[Pkg-samba-maint] r2698 - in trunk/openchange: . doc doc/doxygen doc/doxygen/pictures doc/examples doc/man doc/man/man1 doc/man/man3 libmapi libmapi/conf libmapi/socket libmapi/tests libmapi/util libmapi++ libmapi++/examples libmapi++/impl libmapi++/tests libmapiadmin libocpf libocpf/examples mapiproxy mapiproxy/documentation mapiproxy/documentation/pictures mapiproxy/libmapiproxy mapiproxy/libmapiserver mapiproxy/libmapistore mapiproxy/libmapistore/backends mapiproxy/libmapistore/tests mapiproxy/modules mapiproxy/servers mapiproxy/servers/default mapiproxy/servers/default/emsmdb mapiproxy/servers/default/nspi mapiproxy/servers/default/rfr pymapi python python/openchange python/openchange/tests script setup setup/AD setup/openchangedb setup/profiles swig swig/perl swig/perl/tests testprogs testprogs/blackbox torture utils utils/backup utils/exchange2ical utils/mapitest utils/mapitest/modules utils/mapitrace utils/mapitrace/lib utils/mapitrace/lib/MAPI
jelmer at alioth.debian.org
jelmer at alioth.debian.org
Tue Apr 14 14:39:23 UTC 2009
Author: jelmer
Date: 2009-04-14 14:39:21 +0000 (Tue, 14 Apr 2009)
New Revision: 2698
Added:
trunk/openchange/.bzrignore
trunk/openchange/COPYING
trunk/openchange/ChangeLog
trunk/openchange/Doxyfile.in
trunk/openchange/IDL_LICENSE.txt
trunk/openchange/Mainpage.doxy
trunk/openchange/Makefile
trunk/openchange/README
trunk/openchange/VERSION
trunk/openchange/autogen.sh
trunk/openchange/bin/
trunk/openchange/config.guess
trunk/openchange/config.mk.in
trunk/openchange/config.sub
trunk/openchange/configure.ac
trunk/openchange/doc/
trunk/openchange/doc/doxygen/
trunk/openchange/doc/doxygen/apidocs.css
trunk/openchange/doc/doxygen/footer.html
trunk/openchange/doc/doxygen/header.html
trunk/openchange/doc/doxygen/index.html
trunk/openchange/doc/doxygen/libmapi-concepts.doxy
trunk/openchange/doc/doxygen/libmapi-examples.doxy
trunk/openchange/doc/doxygen/libmapi-mainpage.doxy
trunk/openchange/doc/doxygen/pictures/
trunk/openchange/doc/doxygen/pictures/24px-Cc-by_white.svg.png
trunk/openchange/doc/doxygen/pictures/24px-Cc-sa_white.svg.png
trunk/openchange/doc/doxygen/pictures/CC_SomeRightsReserved.png
trunk/openchange/doc/doxygen/pictures/body_top_bg2.jpg
trunk/openchange/doc/doxygen/pictures/header.jpg
trunk/openchange/doc/doxygen/pictures/middle_bg.jpg
trunk/openchange/doc/doxygen/pictures/nav_tab.gif
trunk/openchange/doc/doxygen/pictures/pixel_grey.gif
trunk/openchange/doc/examples/
trunk/openchange/doc/examples/Makefile
trunk/openchange/doc/examples/fetchappointment.c
trunk/openchange/doc/examples/fetchmail.c
trunk/openchange/doc/examples/mapi_sample1.c
trunk/openchange/doc/howto.txt
trunk/openchange/doc/man/
trunk/openchange/doc/man/man1/
trunk/openchange/doc/man/man1/exchange2ical.1
trunk/openchange/doc/man/man1/exchange2mbox.1
trunk/openchange/doc/man/man1/mapiprofile.1
trunk/openchange/doc/man/man1/mapitest.1
trunk/openchange/doc/man/man1/openchangeclient.1
trunk/openchange/doc/man/man1/openchangepfadmin.1
trunk/openchange/doc/man/man3/
trunk/openchange/doc/man/man3/mapidump.3
trunk/openchange/exchange.idl
trunk/openchange/idl_types.h
trunk/openchange/install-sh
trunk/openchange/libmapi++/
trunk/openchange/libmapi++/Doxyfile.in
trunk/openchange/libmapi++/attachment.h
trunk/openchange/libmapi++/clibmapi.h
trunk/openchange/libmapi++/examples/
trunk/openchange/libmapi++/examples/foldertree.cpp
trunk/openchange/libmapi++/examples/messages.cpp
trunk/openchange/libmapi++/folder.h
trunk/openchange/libmapi++/impl/
trunk/openchange/libmapi++/impl/message.ipp
trunk/openchange/libmapi++/impl/object.ipp
trunk/openchange/libmapi++/impl/session.ipp
trunk/openchange/libmapi++/libmapi++-example.doxy
trunk/openchange/libmapi++/libmapi++-mainpage.doxy
trunk/openchange/libmapi++/libmapi++.h
trunk/openchange/libmapi++/mapi_exception.h
trunk/openchange/libmapi++/message.h
trunk/openchange/libmapi++/message_store.h
trunk/openchange/libmapi++/object.h
trunk/openchange/libmapi++/profile.h
trunk/openchange/libmapi++/property_container.h
trunk/openchange/libmapi++/session.h
trunk/openchange/libmapi++/tests/
trunk/openchange/libmapi++/tests/attach_test.cpp
trunk/openchange/libmapi++/tests/test.cpp
trunk/openchange/libmapi.pc.in
trunk/openchange/libmapi/
trunk/openchange/libmapi/Doxyfile.in
trunk/openchange/libmapi/FXICS.c
trunk/openchange/libmapi/IABContainer.c
trunk/openchange/libmapi/IMAPIContainer.c
trunk/openchange/libmapi/IMAPIFolder.c
trunk/openchange/libmapi/IMAPIProp.c
trunk/openchange/libmapi/IMAPISession.c
trunk/openchange/libmapi/IMAPISupport.c
trunk/openchange/libmapi/IMAPITable.c
trunk/openchange/libmapi/IMSProvider.c
trunk/openchange/libmapi/IMessage.c
trunk/openchange/libmapi/IMsgStore.c
trunk/openchange/libmapi/IProfAdmin.c
trunk/openchange/libmapi/IStoreFolder.c
trunk/openchange/libmapi/IStream.c
trunk/openchange/libmapi/IUnknown.c
trunk/openchange/libmapi/IXPLogon.c
trunk/openchange/libmapi/cdo_mapi.c
trunk/openchange/libmapi/conf/
trunk/openchange/libmapi/conf/build.sh
trunk/openchange/libmapi/conf/mapi-codes
trunk/openchange/libmapi/conf/mapi-named-properties
trunk/openchange/libmapi/conf/mapi-properties
trunk/openchange/libmapi/conf/mparse.pl
trunk/openchange/libmapi/defs_private.h
trunk/openchange/libmapi/dlinklist.h
trunk/openchange/libmapi/emsmdb.c
trunk/openchange/libmapi/emsmdb.h
trunk/openchange/libmapi/freebusy.c
trunk/openchange/libmapi/libmapi.h
trunk/openchange/libmapi/lzfu.c
trunk/openchange/libmapi/mapi_ctx.h
trunk/openchange/libmapi/mapi_id_array.c
trunk/openchange/libmapi/mapi_id_array.h
trunk/openchange/libmapi/mapi_nameid.c
trunk/openchange/libmapi/mapi_notification.h
trunk/openchange/libmapi/mapi_object.c
trunk/openchange/libmapi/mapi_object.h
trunk/openchange/libmapi/mapi_profile.h
trunk/openchange/libmapi/mapi_provider.h
trunk/openchange/libmapi/mapidefs.h
trunk/openchange/libmapi/mapidump.c
trunk/openchange/libmapi/mapidump.h
trunk/openchange/libmapi/nspi.c
trunk/openchange/libmapi/nspi.h
trunk/openchange/libmapi/property.c
trunk/openchange/libmapi/simple_mapi.c
trunk/openchange/libmapi/socket/
trunk/openchange/libmapi/socket/interface.c
trunk/openchange/libmapi/socket/netif.c
trunk/openchange/libmapi/socket/netif.h
trunk/openchange/libmapi/tests/
trunk/openchange/libmapi/tests/locale.c
trunk/openchange/libmapi/tests/locale_codepage.c
trunk/openchange/libmapi/utf8_convert.l
trunk/openchange/libmapi/util/
trunk/openchange/libmapi/util/codepage.c
trunk/openchange/libmapi/util/lcid.c
trunk/openchange/libmapi/utils.c
trunk/openchange/libmapi/x500.c
trunk/openchange/libmapiadmin.pc.in
trunk/openchange/libmapiadmin/
trunk/openchange/libmapiadmin/Doxyfile.in
trunk/openchange/libmapiadmin/libmapiadmin-mainpage.doxy
trunk/openchange/libmapiadmin/libmapiadmin.h
trunk/openchange/libmapiadmin/mapiadmin.c
trunk/openchange/libmapiadmin/mapiadmin_user.c
trunk/openchange/libocpf.pc.in
trunk/openchange/libocpf/
trunk/openchange/libocpf/Doxyfile.in
trunk/openchange/libocpf/examples/
trunk/openchange/libocpf/examples/common_OLEGUID.ocpf
trunk/openchange/libocpf/examples/sample_appointment.ocpf
trunk/openchange/libocpf/examples/sample_task.ocpf
trunk/openchange/libocpf/lex.h
trunk/openchange/libocpf/lex.l
trunk/openchange/libocpf/ocpf-documentation.doxy
trunk/openchange/libocpf/ocpf.h
trunk/openchange/libocpf/ocpf.y
trunk/openchange/libocpf/ocpf_api.c
trunk/openchange/libocpf/ocpf_api.h
trunk/openchange/libocpf/ocpf_dump.c
trunk/openchange/libocpf/ocpf_dump.h
trunk/openchange/libocpf/ocpf_private.h
trunk/openchange/libocpf/ocpf_public.c
trunk/openchange/libocpf/ocpf_write.c
trunk/openchange/mapiproxy/
trunk/openchange/mapiproxy/Doxyfile.in
trunk/openchange/mapiproxy/dcesrv_mapiproxy.c
trunk/openchange/mapiproxy/dcesrv_mapiproxy.h
trunk/openchange/mapiproxy/dcesrv_mapiproxy_nspi.c
trunk/openchange/mapiproxy/dcesrv_mapiproxy_proto.h
trunk/openchange/mapiproxy/dcesrv_mapiproxy_rfr.c
trunk/openchange/mapiproxy/dcesrv_mapiproxy_unused.c
trunk/openchange/mapiproxy/documentation/
trunk/openchange/mapiproxy/documentation/mapiproxy-documentation.doxy
trunk/openchange/mapiproxy/documentation/pictures/
trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_false_nspi.png
trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_true.png
trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_true_custom_nspi.png
trunk/openchange/mapiproxy/documentation/pictures/mapiproxy.png
trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_emsmdb_graph.png
trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_001.png
trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_001_fix.png
trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_002.png
trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_hook_life.png
trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_overview.png
trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_struct.png
trunk/openchange/mapiproxy/documentation/pictures/mpm_cache_case_one.png
trunk/openchange/mapiproxy/documentation/pictures/mpm_cache_case_two.png
trunk/openchange/mapiproxy/documentation/pictures/mpm_pack_pack.png
trunk/openchange/mapiproxy/documentation/pictures/mpm_pack_unpack.png
trunk/openchange/mapiproxy/documentation/pictures/mpm_stack.png
trunk/openchange/mapiproxy/libmapiproxy.pc.in
trunk/openchange/mapiproxy/libmapiproxy/
trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_module.c
trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_server.c
trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_session.c
trunk/openchange/mapiproxy/libmapiproxy/entryid.c
trunk/openchange/mapiproxy/libmapiproxy/libmapiproxy.h
trunk/openchange/mapiproxy/libmapiproxy/mapi_handles.c
trunk/openchange/mapiproxy/libmapiproxy/openchangedb.c
trunk/openchange/mapiproxy/libmapiserver.pc.in
trunk/openchange/mapiproxy/libmapiserver/
trunk/openchange/mapiproxy/libmapiserver/libmapiserver.h
trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcfold.c
trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcnotif.c
trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcprpt.c
trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcstor.c
trunk/openchange/mapiproxy/libmapistore.pc.in
trunk/openchange/mapiproxy/libmapistore/
trunk/openchange/mapiproxy/libmapistore/backends/
trunk/openchange/mapiproxy/libmapistore/backends/mapistore_sqlite3.c
trunk/openchange/mapiproxy/libmapistore/backends/mapistore_sqlite3.h
trunk/openchange/mapiproxy/libmapistore/mapistore.h
trunk/openchange/mapiproxy/libmapistore/mapistore_backend.c
trunk/openchange/mapiproxy/libmapistore/mapistore_errors.h
trunk/openchange/mapiproxy/libmapistore/mapistore_interface.c
trunk/openchange/mapiproxy/libmapistore/mapistore_private.h
trunk/openchange/mapiproxy/libmapistore/mapistore_processing.c
trunk/openchange/mapiproxy/libmapistore/mapistore_tdb_wrap.c
trunk/openchange/mapiproxy/libmapistore/tests/
trunk/openchange/mapiproxy/libmapistore/tests/mapistore_test.c
trunk/openchange/mapiproxy/modules/
trunk/openchange/mapiproxy/modules/mpm_cache.c
trunk/openchange/mapiproxy/modules/mpm_cache.h
trunk/openchange/mapiproxy/modules/mpm_cache_ldb.c
trunk/openchange/mapiproxy/modules/mpm_cache_stream.c
trunk/openchange/mapiproxy/modules/mpm_downgrade.c
trunk/openchange/mapiproxy/modules/mpm_dummy.c
trunk/openchange/mapiproxy/modules/mpm_pack.c
trunk/openchange/mapiproxy/servers/
trunk/openchange/mapiproxy/servers/default/
trunk/openchange/mapiproxy/servers/default/emsmdb/
trunk/openchange/mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.c
trunk/openchange/mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.h
trunk/openchange/mapiproxy/servers/default/emsmdb/emsmdbp.c
trunk/openchange/mapiproxy/servers/default/emsmdb/emsmdbp_object.c
trunk/openchange/mapiproxy/servers/default/emsmdb/oxcfold.c
trunk/openchange/mapiproxy/servers/default/emsmdb/oxcnotif.c
trunk/openchange/mapiproxy/servers/default/emsmdb/oxcprpt.c
trunk/openchange/mapiproxy/servers/default/emsmdb/oxcstor.c
trunk/openchange/mapiproxy/servers/default/nspi/
trunk/openchange/mapiproxy/servers/default/nspi/dcesrv_exchange_nsp.c
trunk/openchange/mapiproxy/servers/default/nspi/dcesrv_exchange_nsp.h
trunk/openchange/mapiproxy/servers/default/nspi/emsabp.c
trunk/openchange/mapiproxy/servers/default/nspi/emsabp_property.c
trunk/openchange/mapiproxy/servers/default/nspi/emsabp_tdb.c
trunk/openchange/mapiproxy/servers/default/rfr/
trunk/openchange/mapiproxy/servers/default/rfr/dcesrv_exchange_ds_rfr.c
trunk/openchange/mapiproxy/servers/default/rfr/dcesrv_exchange_ds_rfr.h
trunk/openchange/missing
trunk/openchange/ndr_mapi.c
trunk/openchange/property.idl
trunk/openchange/pymapi/
trunk/openchange/pymapi/msg_store.c
trunk/openchange/pymapi/object.c
trunk/openchange/pymapi/pymapi.c
trunk/openchange/pymapi/pymapi.h
trunk/openchange/pymapi/session.c
trunk/openchange/python/
trunk/openchange/python/openchange/
trunk/openchange/python/openchange/__init__.py
trunk/openchange/python/openchange/mailbox.py
trunk/openchange/python/openchange/provision.py
trunk/openchange/python/openchange/tests/
trunk/openchange/python/openchange/tests/__init__.py
trunk/openchange/python/openchange/tests/test_mailbox.py
trunk/openchange/python/openchange/tests/test_provision.py
trunk/openchange/script/
trunk/openchange/script/check_exchange
trunk/openchange/script/installman.sh
trunk/openchange/script/installoc.sh
trunk/openchange/script/installsamba4.sh
trunk/openchange/script/mapi_object_init.prop
trunk/openchange/script/mkproto.pl
trunk/openchange/script/mkrelease.sh
trunk/openchange/script/mkversion.sh
trunk/openchange/script/samba4_ver.sh
trunk/openchange/script/uninstallman.sh
trunk/openchange/script/uno.dfn
trunk/openchange/setup/
trunk/openchange/setup/AD/
trunk/openchange/setup/AD/oc_provision_configuration.ldif
trunk/openchange/setup/AD/oc_provision_schema.ldif
trunk/openchange/setup/AD/oc_provision_schema_ADSC.ldif
trunk/openchange/setup/AD/oc_provision_schema_modify.ldif
trunk/openchange/setup/AD/prefixMap.txt
trunk/openchange/setup/AD/provision_schema_basedn_modify.ldif
trunk/openchange/setup/openchange_newuser
trunk/openchange/setup/openchange_provision
trunk/openchange/setup/openchangedb/
trunk/openchange/setup/openchangedb/oc_provision_openchange_init.ldif
trunk/openchange/setup/openchangedb/oc_provision_openchange_mailbox.ldif
trunk/openchange/setup/profiles/
trunk/openchange/setup/profiles/oc_profiles_init.ldif
trunk/openchange/setup/profiles/oc_profiles_schema.ldif
trunk/openchange/swig/
trunk/openchange/swig/perl/
trunk/openchange/swig/perl/Makefile
trunk/openchange/swig/perl/lwmapi.c
trunk/openchange/swig/perl/mapi.i
trunk/openchange/swig/perl/tests/
trunk/openchange/swig/perl/tests/fetchmail.pl
trunk/openchange/testprogs/
trunk/openchange/testprogs/blackbox/
trunk/openchange/testprogs/blackbox/subunit.sh
trunk/openchange/testprogs/blackbox/test_mapiprofile.sh
trunk/openchange/torture/
trunk/openchange/torture/exchange_createuser.c
trunk/openchange/torture/mapi_bookmark.c
trunk/openchange/torture/mapi_common.c
trunk/openchange/torture/mapi_copymail.c
trunk/openchange/torture/mapi_createuser.c
trunk/openchange/torture/mapi_criteria.c
trunk/openchange/torture/mapi_deletemail.c
trunk/openchange/torture/mapi_fetchappointment.c
trunk/openchange/torture/mapi_fetchattach.c
trunk/openchange/torture/mapi_fetchcontacts.c
trunk/openchange/torture/mapi_fetchmail.c
trunk/openchange/torture/mapi_fetchtasks.c
trunk/openchange/torture/mapi_namedprops.c
trunk/openchange/torture/mapi_newmail.c
trunk/openchange/torture/mapi_permissions.c
trunk/openchange/torture/mapi_recipient.c
trunk/openchange/torture/mapi_restrictions.c
trunk/openchange/torture/mapi_sendappointment.c
trunk/openchange/torture/mapi_sendattach.c
trunk/openchange/torture/mapi_sendcontacts.c
trunk/openchange/torture/mapi_sendmail.c
trunk/openchange/torture/mapi_sendmail_html.c
trunk/openchange/torture/mapi_sendtasks.c
trunk/openchange/torture/mapi_sorttable.c
trunk/openchange/torture/mapi_torture.h
trunk/openchange/torture/nspi_profile.c
trunk/openchange/torture/nspi_resolvenames.c
trunk/openchange/torture/openchange.c
trunk/openchange/utils/
trunk/openchange/utils/backup/
trunk/openchange/utils/backup/openchangebackup.c
trunk/openchange/utils/backup/openchangebackup.h
trunk/openchange/utils/backup/openchangemapidump.c
trunk/openchange/utils/exchange2ical/
trunk/openchange/utils/exchange2ical/exchange2ical.c
trunk/openchange/utils/exchange2ical/exchange2ical.h
trunk/openchange/utils/exchange2ical/exchange2ical_component.c
trunk/openchange/utils/exchange2ical/exchange2ical_property.c
trunk/openchange/utils/exchange2ical/exchange2ical_utils.c
trunk/openchange/utils/exchange2mbox.c
trunk/openchange/utils/mapiprofile.c
trunk/openchange/utils/mapitest/
trunk/openchange/utils/mapitest/Doxyfile.in
trunk/openchange/utils/mapitest/mapitest.c
trunk/openchange/utils/mapitest/mapitest.h
trunk/openchange/utils/mapitest/mapitest_common.c
trunk/openchange/utils/mapitest/mapitest_print.c
trunk/openchange/utils/mapitest/mapitest_stat.c
trunk/openchange/utils/mapitest/mapitest_suite.c
trunk/openchange/utils/mapitest/module.c
trunk/openchange/utils/mapitest/modules/
trunk/openchange/utils/mapitest/modules/mapitest.doxy
trunk/openchange/utils/mapitest/modules/module_errorchecks.c
trunk/openchange/utils/mapitest/modules/module_lcid.c
trunk/openchange/utils/mapitest/modules/module_noserver.c
trunk/openchange/utils/mapitest/modules/module_nspi.c
trunk/openchange/utils/mapitest/modules/module_oxcfold.c
trunk/openchange/utils/mapitest/modules/module_oxcfxics.c
trunk/openchange/utils/mapitest/modules/module_oxcmsg.c
trunk/openchange/utils/mapitest/modules/module_oxcprpt.c
trunk/openchange/utils/mapitest/modules/module_oxcstor.c
trunk/openchange/utils/mapitest/modules/module_oxctable.c
trunk/openchange/utils/mapitest/modules/module_oxomsg.c
trunk/openchange/utils/mapitest/modules/module_oxorule.c
trunk/openchange/utils/mapitrace/
trunk/openchange/utils/mapitrace/Makefile.PL
trunk/openchange/utils/mapitrace/lib/
trunk/openchange/utils/mapitrace/lib/MAPI/
trunk/openchange/utils/mapitrace/lib/MAPI/Dump_EcDoRpc.pm
trunk/openchange/utils/mapitrace/lib/MAPI/EcDoRpc.pm
trunk/openchange/utils/mapitrace/lib/MAPI/Graph.pm
trunk/openchange/utils/mapitrace/lib/MAPI/Regression.pm
trunk/openchange/utils/mapitrace/lib/MAPI/Statistic.pm
trunk/openchange/utils/mapitrace/mapitrace
trunk/openchange/utils/openchange-tools.c
trunk/openchange/utils/openchange-tools.h
trunk/openchange/utils/openchangeclient.c
trunk/openchange/utils/openchangeclient.h
trunk/openchange/utils/openchangepfadmin.c
trunk/openchange/utils/openchangepfadmin.h
trunk/openchange/utils/schemaIDGUID.c
Log:
Merge in upstream source.
Added: trunk/openchange/.bzrignore
===================================================================
--- trunk/openchange/.bzrignore (rev 0)
+++ trunk/openchange/.bzrignore 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,66 @@
+aclocal.m4
+config.h
+config.h.in
+config.log
+config.status
+libmapi.pc
+configure
+gen_ndr
+libmapi/mapicode.c
+libmapi/mapicode.h
+libmapi/mapitags.c
+libmapi/mapitags.h
+libmapi/proto.h
+libmapi/utf8_convert.yy.c
+server/dcesrv_proto.h
+torture/torture_proto.h
+libmapi.so.*
+mapicodes_enum.h
+mapitags_enum.h
+bin/exchange2mbox
+bin/locale_codepage
+bin/mapiprofile
+bin/openchangeclient
+bin/schemaIDGUID
+libmapi/proto_private.h
+providers/providers_proto.h
+tags
+*.pc
+*.so.*
+bin/openchangepfadmin
+libmapiadmin/proto.h
+libmapiadmin/proto_private.h
+bin/openchangemapidump
+*.po
+libmapi/mapi_nameid_private.h
+Doxyfile
+libmapi/version.h
+config.mk
+swig/perl/Makefile
+libocpf/ocpf.tab.c
+libocpf/ocpf.tab.c
+libocpf/lex.yy.c
+bin/mapitest
+libocpf/proto.h
+libocpf/proto_private.h
+libocpf/proto_private.h
+libocpf/ocpf.tab.h
+autom4te.cache
+apidocs
+swig/perl/mapi.pm
+swig/perl/mapi_wrap.c
+swig/perl/swig_mapicodes.h
+swig/perl/swig_mapitags.h
+utils/mapitest/mapitest_proto.h
+utils/mapitest/proto.h
+samba4
+tags
+bin/exchange2ical
+libmapi/mapi_namedid.h
+libmapi/mapi_nameid.h
+bin/libmapixx-attach
+bin/libmapixx-test
+libmapi++/examples/foldertree
+libmapi++/examples/messages
+bin/mapistore_test
+_trial_temp
Added: trunk/openchange/COPYING
===================================================================
--- trunk/openchange/COPYING (rev 0)
+++ trunk/openchange/COPYING 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
Added: trunk/openchange/ChangeLog
===================================================================
--- trunk/openchange/ChangeLog (rev 0)
+++ trunk/openchange/ChangeLog 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,4186 @@
+2009-02-24
+ jkerihuel
+ [r1223]
+ - Fix systemfolder value for System/Special folders
+ - Add GetProps support to System/Special folders
+ [r1222]
+ Add auto-generated parser to the ignore list
+ [r1221]
+ - Add auto-generated parser for MAPI property to PidTag mapping
+ - Add some PidTag values
+ - Add a lookup and get property functions on system folders
+ [r1220]
+ - tuple SystemIdx in the dictionnary to workaround the ordering problem
+ - Add ParentFolderId attribute to System Folders
+ [r1217]
+ - Add creation of "Special folders" to mailbox provisioning
+ - Rename fid attribute to PidTagFolderId
+ - Rename name attribute to PidTagDisplayName
+ - Rename ExplicitContainerClass to PidTagContainerClass
+ [r1216]
+ Fix GlobalCount increment
+ [r1215]
+ Fix mailbox provisioning
+ bradh
+ [r1219]
+ Add test for FILETIME structure.
+ [r1218]
+ Update docs for mapiproxy entry.
+ jelmer
+ [r1214]
+ Fix handling of fids.
+2009-02-23
+ jkerihuel
+ [r1208]
+ - Fix openchangedb mailbox hierarchy and introduces subfolders
+ as described in [MS-OXOFOLDS] specifications.
+ - Update openchangedb API to reflect this change.
+ [r1207]
+ Rename private mailbox folder "non_ipm_subtree" to "mailbox_root"
+ to fit with MS-OXOFOLDS specifications.
+ [r1206]
+ - Add provisioning code for GetReceiveFolder defaults
+ - Check if mapistore content repository already exists for the user
+ - Make mailbox creation verbose
+ jelmer
+ [r1213]
+ Fix parentfolder reference.
+ [r1212]
+ Fix syntax error.
+ [r1211]
+ Use recursive call to create folders.
+ [r1210]
+ Simplify list iteration, PEP8, avoid using string exceptions.
+
+2009-02-22
+ jkerihuel
+ [r1204]
+ Fix 'dereferencing type-punned pointer' warnings
+ [r1203]
+ - Add strict-aliasing compiler flags
+ - Fix format string warnings on ubuntu buildbot
+ [r1202]
+ - Add _FORTIFY_SOURCE=2 to the compiler CFLAGS
+ - Fix warnings introduced by -D_FORTIFY_SOURCE
+ bradh
+ [r1201]
+ I might have been a bit hasty with that last commit...
+
+ Need sqlite3.
+ [r1200]
+ Try harder to find sqlite3.
+
+ Seems to be in sqlite.pc on Ubuntu.
+ [r1198]
+ Fix warning on 64-bit arch.
+2009-02-21
+ jkerihuel
+ [r1197]
+ - Add RopGetReceiveFolder (0x27) implementation
+ The function respects should respect the semantics and behavior
+ as described in MS-OXCSTOR specifications. However the python's
+ code modification required: add ExplicitMessageClass attributes
+ to folder records is not yet effective.
+
+ - Add GetReceiveFolder size calculation function to libmapiserver
+ - Add a function to openchangedb API to retrieve the FID/ExplicitMessageClass
+ couple for a given SystemFolder within user's mailbox.
+ [r1196]
+ - Provision scripts: create a mapistore default storage space within ${private}/mapistore/${username}
+ - Provision scripts: add default sqlite:// mapistore URI for system folders
+ - Add mapistore context initialization when calling OpenFolder on SystemFolder
+ - Add mapistore context release for folders in emsmdbp object destructor
+ [r1195]
+ Factorize emsmdbp objects
+ Add emsmdbp_object generic talloc destructor
+ bradh
+ [r1194]
+ Add test for PT_MV_LONG.
+ [r1193]
+ Add tests for PT_I8 and PT_BINARY
+ [r1192]
+ Fix warning about no newline at end of file.
+
+ Remove most recently added tests from "to be done" list.
+ [r1191]
+ Add a couple more mapi_SPropValue tests.
+
+2009-02-19
+ jkerihuel
+ [r1189]
+ - Initialize mapistore within emsmdb provider context
+ - Add destructors for MAPI handles and mapistore contexts
+ - Remove emsmdbp_ctx memory context structure member and
+ allocate directly with emsmdbp_ctx
+ [r1188]
+ I don't see any good reason why we would pad MAPI replies with some bytes.
+ I guess it comes from some prehistoric openchange code.
+ [r1187]
+ Fix systemfolder assignment depending on IsSystemFolder value
+ [r1186]
+ - Initialize OpenFolder server reply
+ [r1185]
+ - Wrap TDB connections to mapistore (code from samba4) so
+ multiple instances can open read/write to the same TDB database
+ - Remove static id_mapping_context (replaced with tdb_wrap calls)
+ - Update mapistore linkage rules so mapistore can be used with exchange_emsmdb server
+ - Link mapistore with exchange_emsmdb
+ [r1183]
+ Fix aclocal warning for AC_DEFINE comparison_fn_t
+ [r1182]
+ Remove useless GetProfilePtr from IProfAdmin interface
+ Closes trac ticket #131
+ [r1181]
+ Add missing script - prevent configure from generating warning vs missing file.
+ [r1180]
+ Remove stamp-h1 file during distclean and add it
+ to the ignore list.
+ [r1179]
+ - Add server-side GetReceiveFolder (0x27) skeleton
+ [r1178]
+ Work around the comparison_fn_t redefinition problem
+ between libocpf and ndr.h
+ [r1177]
+ FreeBSD doesn't have time.h daylight global variable
+ bradh
+ [r1184]
+ start testing mapi_SPropValue_array.
+ This also tests some underlying functions.
+
+2009-02-18
+ jkerihuel
+ [r1175]
+ Add comparison_fn_t support to ndr.h
+ This was the latest change require to make openchange compiles under FreeBSD
+
+ = samba4/openchange FreeBSD support completed =
+
+2009-02-17
+ jkerihuel
+ [r1173]
+ Remove duplicated post_install call
+ [r1172]
+ Add a post_install operation on FreeBSD
+ Make sure pidl is installed properly.
+ [r1171]
+ Patch samba4 tarball so it compiles properly on FreeBSD 7.0
+ Note: this is a dirty hack which needs to be removed in the future
+ [r1170]
+ Install Samba4 correctly although user's PKG_CONFIG_PATH env variable
+ may not be adjusted properly.
+ [r1169]
+ Avoid download samba4 release tarball if already available
+ in current directory.
+ [r1168]
+ - Add test for comparison_fn_t in configure.ac
+ - libocpf auto-generated files include stdlib.h and prevent from
+ having the proper comparison_fn_t typedef. This commit works around this
+ problem and define comparison_fn_t within a private header.
+ [r1165]
+ getline is a stdio GNU_SOURCE extension not available under FreeBSD.
+ Use fgetln instead when it is compiled on this OS.
+ [r1164]
+ FreeBSD doesn't define sighandler_t but sig_t
+ [r1163]
+ Replace open() call with O_DIRECTORY flag (Linux specific) with opendir
+ [r1162]
+ - Add non-default search path /usr/local/{include,lib} to
+ CFLAGS and LDFLAGS when compiling OpenChange under FreeBSD
+ - Make use of LDFLAGS while compiling openchange tools
+ bradh
+ [r1167]
+ A few improvements for property handling.
+
+ Also add unit tests to verify behaviour is correct.
+
+ The implementation for the FlatUID (GUID) structure appears broken. Perhaps I'm not using it correctly.
+ [r1166]
+ Microsoft confirmed the LCID is wrong in the spec, and will be updated in the next rev.
+
+2009-02-16
+ jkerihuel
+ [r1160]
+ Check for Flex version < 2.5.35
+ Make sure users can define the FLEX environment variable
+ [r1159]
+ Add automake scripts for AC_CANONICAL_HOST support
+ Needed for FreeBSD OS detection in configure.ac
+
+2009-02-14
+ bradh
+ [r1153]
+ Fix warnings from lexer output.
+ [r1152]
+ Fixes for warnings on 64-bit architectures.
+ [r1151]
+ Fix warning on 64-bit architecture.
+ jelmer
+ [r1157]
+ Add some more tests for openchange.mailbox.
+ [r1156]
+ Fix creation of new mailbox after provision.
+ [r1155]
+ Always use the same URL when connecting to openchangedb.
+ [r1154]
+ Fix arguments to openchangedb_provision.
+
+2009-02-13
+ jkerihuel
+ [r1149]
+ Fix libmapi 64-bit machine cast warnings mentioned in Brad's devel email
+ bradh
+ [r1148]
+ Warning fix for 64-bit arch.
+
+2009-02-12
+ jkerihuel
+ [r1146]
+ Add doxygen definition for RopRelease
+ [r1145]
+ - Add server-side skeleton implementation for RopOpenFolder and RopRegisterNotification
+ - Add preliminary size calculation functions in libmapiserver for the 2 calls above
+ - Fix size bug for serialized requests
+ - Add skeleton case for RopGetPropertiesSpecific on SystemFolders
+ - Make sure the GetProps reply blob is initialized whatever happen
+ - Add a skeleton emsmdbp folder object init function
+
+2009-02-11
+ jkerihuel
+ [r1143]
+ Remove debug strings for GetPropertiesSpecific Rop
+ [r1142]
+ Enable verbose output in server mode - useful during development
+ [r1141]
+ Implement preliminary server-side RopGetPropertiesSpecific call for mailbox object.
+ [r1140]
+ - Fix GetProps blob for PT_BINARY: use SBinary_short instead of Binary_r
+ - Fix GetProps size: subcontext is not added to the fixed size calculation
+ [r1133]
+ - GetPropsSpecific size calculation function added to libmapiserver
+ - Function to create a GetProps reply property blob added to libmapiserver
+ jelmer
+ [r1139]
+ Add tests for provisioning.
+ [r1138]
+ Several cleanups in python code, add tests for schema use.
+ [r1137]
+ Don't clear PYTHONPATH override.
+ [r1136]
+ Remove unused imports, add extra tests.
+ [r1135]
+ Use member variable for Ldb, rather than subclassing.
+ [r1134]
+ Remove print statements to avoid cluttering test output.
+ [r1130]
+ Add simple and incomplete testcase for OpenChangeDB.
+ [r1129]
+ Move wipe of data to mailbox.py, simplify arguments to add_root_mailbox.
+ [r1128]
+ Move adding a server to mailbox.py.
+ [r1127]
+ Move ldif from oc_provision_openchange.ldif into Python.
+ [r1126]
+ Stop providing setup_path to OpenChangeDB, as it's no longer used.
+ [r1125]
+ Avoid using separate LDIF file when creating folder mailboxes.
+ [r1124]
+ Avoid using separate LDIF file when creating mailboxes.
+ [r1123]
+ Avoid passing full names object.
+ [r1122]
+ Add check-python target.
+
+2009-02-10
+ jelmer
+ [r1120]
+ fix openchange_newuser.
+ [r1119]
+ Use SamDB for actual SAM databases, Ldb otherwise.
+ [r1118]
+ Remove unused parameters, don't make parameters optional if they are mandatory.
+ [r1117]
+ remove unused parameters.
+ [r1116]
+ make mailbox object-oriented, remove creds/lp parameters.
+ [r1115]
+ Fix OpenChangeDB syntax.
+
+2009-02-09
+ jkerihuel
+ [r1113]
+ - Add a systemfolder member to the MAPI handle structure to make a difference
+ between objects managed by mapistore and those stored within openchange.ldb
+ (root mailbox folders).
+
+ - Add opaque functions to set/get private_data and systemfolder to the MAPI
+ handles API.
+ [r1112]
+ Minor doxygen fix/improvement
+ [r1109]
+ Add libmapistore object files to the ignore list
+ [r1108]
+ - Add a very preliminary and light libmapistore implementation.
+ mapistore only supplies init/release and add/del backend contexts.
+ This commit also includes a sqlite3 backend skeleton (open/close sqlite db)
+ - A temporary mapistore testing tool has been added locally for implementation checks.
+ jelmer
+ [r1111]
+ Use convenience function for connecting to openchange.ldb.
+ [r1110]
+ Use standard LDB functions - openchange.ldb is not a SAM database.
+
+2009-02-08
+ bradh
+ [r1106]
+ Implement support the SUMMARY language tag.
+ [r1105]
+ Initial checking of libical based exchange2ical code.
+
+ This has a long way to go, so think of this as more of a checkpoint
+ than a release.
+
+ See http://sourceforge.net/projects/freeassociation/ for the library, or
+ see if your distro has a package.
+ [r1104]
+ Reduce warnings.
+ [r1103]
+ Add missing parameter to API documentation.
+
+ Resolves ticket #130.
+ [r1102]
+ API documentation fixes for OpenEmbeddedMessage()
+ [r1101]
+ Implement OpenEmbeddedMessage ROP (0x46).
+
+ Resolves Ticket #93
+ [r1100]
+ Factor out message creation and message fill actions.
+
+ Also remove GetLastError() where appropriate.
+ [r1099]
+ Add some API documentation.
+
+2009-02-07
+ jkerihuel
+ [r1097]
+ Update openchangepfadmin description
+ Fix tool relying on libmapiadmin
+ bradh
+ [r1096]
+ Minor code tweak.
+
+ Fix ticket #132.
+ [r1095]
+ Add more explanation for README
+ [r1094]
+ Reimplement RTF decompression.
+
+ Add unit tests from MS-OXRTFCP.
+ [r1093]
+ Fix warnings in example code
+ [r1092]
+ Add description for libmapiadmin
+ [r1091]
+ Add description for libmapi / libmapi++
+ [r1090]
+ Start on the directory descriptions.
+ [r1089]
+ doc/ pointers
+2009-02-06
+ bradh
+ [r1088]
+ Add overview. Extracted from API docs.
+ [r1087]
+ Additional docs.
+ [r1084]
+ Outline of README file.
+
+ (also using this to test buildbot without changing real code)
+2009-02-05
+ jkerihuel
+ [r1081]
+ Add Version field - avoid breaking pkg-config --list-all
+ [r1080]
+ Fix warnings (gcc 4.2.4)
+ jelmer
+ [r1083]
+ Use variable for package version rather than hardcoding it.
+
+2009-02-04
+ jkerihuel
+ [r1078]
+ Fix pc file libs
+
+2009-02-03
+ jkerihuel
+ [r1070]
+ - Add an implementation of the MAPI handles management API. The API
+ internally uses an in-memory TDB database to keep object hierarchy
+ and a doubled chained list to associate private data to handles.
+
+ The API currently provides add, search and delete facilities. Note
+ that while untested, the delete operation is designed to recursively
+ delete children of the 'meant to be deleted' handle.
+
+ Finally the API doesn't remove TDB records but mark them as free so
+ they can be reused across MAPI session and prevent from handle counter
+ growing indefinitely.
+
+ - Add a preliminary implementation of the Release call
+ - Add Release size calculation to libmapiserver
+ - Update EMSMDB provider to use MAPI handles API
+ bradh
+ [r1075]
+ Minor api documentation fix.
+ [r1074]
+ Minor API docs fix.
+ [r1073]
+ Minor API docs fix.
+ [r1072]
+ Minor API docs tweak.
+ [r1071]
+ Token commit of tiny API docs fix.
+ jelmer
+ [r1076]
+ Look for GNU make harder (gmake on BSDs).
+
+2009-02-02
+ jkerihuel
+ [r1068]
+ - Add preliminary EMSMDB provider implementation for RopLogon (0xFE)
+ - Add common routines for OpenChange LDB context init and search
+ within libmapiproxy
+ - Add libmapiserver skeleton with size calculation routine for RopLogon
+ - Change DSO linking dependencies for mapiproxy shared libraries
+ - Propagate _GNU_SOURCE change from libmapi.h to mapiproxy
+2009-02-01
+ jkerihuel
+ [r1067]
+ Remove .po and .o objects within libmapiproxy subdirectory
+ [r1066]
+ Move libmapiproxy into its own directory and rebase mapiproxy headers accordingly
+ Fix make uninstall for AD and profiles directories
+ [r1064]
+ doxygen typo fix
+ [r1063]
+ Add python code and ldif files needed to create and populate the experimental
+ openchange dispatcher database.
+ [r1062]
+ Add 5-Minute configuration documentation for OpenChange server mode
+ [r1061]
+ - Rebase ldif files into sub directories:
+ * AD for OpenChange AD modifications
+ * profiles for OpenChange IProfAdmin interface
+ - Makes it easier figuring out LDIF files scope
+ - Prepare setup folder for LDIF openchangedb files integration
+ - Update install/uninstall Makefile rules for ldif files and
+ make sure everything got removed
+ bradh
+ [r1060]
+ Add forgotten file.
+ [r1059]
+ Add support for short language names (e.g. en-AU) for lcid.
+
+2009-01-31
+ jkerihuel
+ [r1057]
+ Delete deprecated libmapi setup Perl script
+ bradh
+ [r1056]
+ Add summary report for tests.
+ [r1055]
+ Make mapitest return the number of failed tests.
+
+2009-01-29
+ jkerihuel
+ [r1052]
+ - Add pkg-config pc file for libmapiproxy
+ - Improve mapiproxy rules so libmapiproxy gets installed and cleaned properly
+ [r1051]
+ Free memory allocated by the fake subcontext in
+ ndr_pull_mapi_response.
+
+ This fix saves 300kb of memory and removes 700 loss records while
+ valgrinding mapitest.
+ [r1050]
+ Fix segfault - Add sanity check - when SPropTagArray is NULL in
+ NspiQueryRows request
+ [r1048]
+ Fix openchange_newuser name typo
+ [r1047]
+ Fix server provisioning command line examples
+ [r1045]
+ Fix several libmapi leaks.
+
+ mapi_response was allocated using emsmdb_ctx->mem_ctx memory context
+ and was not free'd when libmapi function released their
+ context. Furthermore we need to release mapi_response->mapi_repl and
+ mapi_response->handles which are now automatically free'd when
+ mapi_response destructor is called.
+
+ However note that this fix is not perfect: mapi_response memory is not
+ free'd properly when calls exit with an error.
+
+ This commit also make use of talloc_steal where necessary to keep
+ returned fields allocated.
+2009-01-28
+ jkerihuel
+ [r1040]
+ Use named context rather than autofree
+ [r1039]
+ Fix memory leak in emsmdb.c: Use a temporary memory context for
+ request and length allocation in emsmdb_transaction.
+
+ - This removes 827 loss records and approximatively saves 41kb of
+ memory while valgrinding mapitest
+ [r1038]
+ - Fix memory leak in GetDefaultProfile and GetProfileTable.
+ - Save from 10 loss records while valgrinding mapitest
+ - Developers are now responsible from freeing the GetDefaultProfile
+ string the function allocates.
+ - Apply changes to all openchange tools.
+ [r1037]
+ Add blackbox subunit tests for mapiprofile tool
+ bradh
+ [r1043]
+ One more trivial fix.
+ [r1042]
+ Typo fixes.
+
+ (Yep, more trivial changes)
+ [r1041]
+ Fix incorrect LCID for en-CA.
+
+ (OK, its token, I admit).
+ jelmer
+ [r1044]
+ Don't define _GNU_SOURCE unconditionally.
+2009-01-27
+ jkerihuel
+ [r1036]
+ Prevent mapiproxy from multiple init and modules/server register
+ when an smb client connect to the server (e.g. windows browser or smbclient)
+2009-01-26
+ bradh
+ [r1033]
+ According to [MS-OXOCAL] Section 2.2.1.44.1
+ "RecurrencePattern Structure", a monthly recurrence
+ also has a Day specific parameter.
+
+ Add that here.
+ jelmer
+ [r1035]
+ Simply run autogen.sh rather than replicating it inside the Makefile.
+ [r1034]
+ need to run aclocal before autoconf for the pkg-config macros.
+2009-01-25
+ jkerihuel
+ [r1032]
+ Use a autofree context rather than a named one - makes sure memory is free'd when we exit the test.
+ Saves from 4 loss records while valgrind'ing mapitest.
+ [r1031]
+ Use temporary memory context for EcDoConnect.
+ Saves from 20 loss records when valgrind'ing mapitest.
+ [r1030]
+ Free PropertyProblem structures returned by CopyTo.
+ [r1029]
+ Replace deprecated talloc_init calls with talloc_named
+ This commit removes some valgrind loss records talloc_init was responsible for
+ [r1028]
+ Free everything
+ Free everything when running mapitest --list-all.
+ Valgrind however shows a loss record related to talloc_init ...
+ bradh
+ [r1027]
+ Minor Intel C compiler warning fixes.
+ [r1026]
+ Minor apidocs cleanups.
+2009-01-24
+ jkerihuel
+ [r1024]
+ Use double pointer for lp_ctx in GetLoadparmContext assessor
+ [r1023]
+ Fix memory leak in utf8 lexer.
+ [r1022]
+ - Remove custom iconv_convenience from pull_emsmdb_property and use
+ lp_iconv_convenience on loadparm_context argument instead.
+
+ - Change OpenChange libmapi API to reflect this change
+
+ - Introduce a lp_ctx assessor in libmapi/cdo_mapi.c
+ (mostly for mapitest modules). libmapi/mapiproxy developers
+ should never have to make use of it.
+
+ - Remove pointless duplicated call to lp_load_default in MAPIInitialize.
+ [r1021]
+ Free lpProps returned by GetProps, Fix context error in valgrind
+ [r1020]
+ - Fix memory leak bug: release ndr context in pull_emsmdb_property before returning
+ - Terminate SPropValue and SPropTagArray using an element with ulPropTag = 0. This
+ prevent from "invalid read size of 4" messages from valgrind and remove context errors.
+ jelmer
+ [r1025]
+ Don't install mapiproxy if python wasn't found, since
+ we wouldn't know where to install the provisioning scripts or be able
+ to use them.
+2009-01-20
+ jkerihuel
+ [r1018]
+ Merge libmapi-0.8 branch r1015 to 1017 into trunk
+ [r1015]
+ ** Start libmapi-0.9 COCHRANE development **
+ [r1014]
+ Merge libmapi-0.8 branch changes into trunk
+2009-01-18
+ jkerihuel
+ [r1007]
+ Add python install/uninstall rules to provision rather than mapiproxy-servers
+ [r1006]
+ - Remove server Makefile rules
+ - Remove dead code
+
+ Note: server and providers have been merged within mapiproxy,
+ so there is no reason keeping this deprecated code.
+2009-01-17
+ jkerihuel
+ [r1005]
+ Undoing change committed in r1004.
+ [r1004]
+ Use .po files instead of .o files for openchange tools
+ [r1003]
+ Add --version to openchange tools
+ [r1002]
+ Add COPYING file with GPLv3 license
+2009-01-16
+ jkerihuel
+ [r1001]
+ - Add RenameProfile function to IProfAdmin API
+ - Remove pointless CopyProfile from IProfAdmin API
+ - Add --rename option to mapiprofile tool
+ - Update man page to reflect this addition
+
+ (close trac ticket #124)
+ [r1000]
+ Fix libmapi from crashing when mapi_repl is NULL.
+ [r999]
+ Update Samba4 git rev to fix the charcnv segfault met in openchange
+ tools
+ jelmer
+ [r998]
+ Try to find the Samba python modules if they're not installed in the system
+ python directory.
+2009-01-15
+ jkerihuel
+ [r997]
+ - Fix Subscribe semantic bug and add WholeStore boolean parameter
+ - propagate API change to tools/torture callers
+ [r996]
+ - Add assessor functions to set dumpdata and debug level in libmapi
+ (SetMAPIDumpData and SetMAPIDebugLevel)
+ - OpenChange tools modified to use these function rather than set these
+ parameters on their own
+ [r995]
+ - Fix --debuglevel segfault in openchange tools
+ - Enable logging to stdout in MAPIInitialize
+2009-01-14
+ jkerihuel
+ [r994]
+ * OpenChange libmapi function now returns MAPI error instead of -1
+ - use OPENCHANGE_RETVAL_IF instead of MAPI_RETVAL_IF
+ - add doxygen documentation for some missing functions/files
+ [r993]
+ - Missed this event->tevent change in previous commit
+ [r992]
+ - Update openchange to use latest Samba4 master git rev (990491d)
+ - Fix references to tevent_context structures
+ - Fix iconv_convenience init in MAPIInitialize
+ - Remove errorchecks mapitest module warning
+ jelmer
+ [r991]
+ Use tevent_context_init.
+ [r990]
+ Ignore binaries.
+2009-01-13
+ jkerihuel
+ [r989]
+ Some Exchange server (stand-alone) return MAPI_E_LOGON_FAILED when setting EssDN with username rather than
+ using profile's mailbox string directly. This commit fixes the bug.
+ [r988]
+ - Add EcDoConnect and EcDoDisconnect preliminary support to
+ dcesrv_exchange_emsmdb.c
+ - Add internal session management mechanism to EMSMDB server
+ - Add init and unbind modules function to EMSMDB server
+ - Add emsmdbp_context and session to dcesrv_exchange_emsmdb.h
+ bradh
+ [r987]
+ Fix valgrind errors caused by using free'd memory.
+2009-01-12
+ jkerihuel
+ [r986]
+ Implement 'mapiproxy downgrade' behavior in EMSMDB server and force
+ Outlook to use EcDoConnect (0x0) and EcDoRpc (0x2) rather than 0xA and
+ 0xB (opnums using LZ based compression).
+ [r985]
+ - Add Preliminary implementation for RfrGetFQDNFromLegacyDN DS RFR server
+2009-01-11
+ jkerihuel
+ [r984]
+ - Preliminary implementation of NspiGetProps NSPI server function
+ - Makes sure emsabp_tdb_traverse_MId uses the correct dbuf size
+ - Use correct ldb context (users or conf) depending on where MId is
+ located (on-memory or on-disk)
+ - Add PR_EMS_AB_NETWORK_ADDRESS mapping to emsabp_property
+
+ *** Outlook is now able to create MAPI profile using OpenChange Server ONLY! ***
+ [r983]
+ - Preliminary implementation of NspiDNToMId NSPI server function
+ - Add emsabp_search_legacyExchangeDN to search for a record given its
+ legacyExchangeDN attribute.
+ [r982]
+ - Preliminary implementation of NspiQueryRows NSPI server function added
+ - fix a bug in the MID TDB traversal routine: cut dptr to dsize length
+ rather assuming it is NULL terminated
+ - Add support for "referenced" property tags
+ - Add support for PR_MV_STRING8
+ - Add emsabp_search_dn which search for a DN within AD and return the
+ associated LDB message
+ - Add PR_EMS_AB_HOME_MDB and PR_EMS_AB_PROXY_ADDRESSES to
+ emsabp_property array
+ [r981]
+ Prevent from trying to add a NULL element to profile database and segfault on strlen
+ [r980]
+ Prevent x500_get_dn_element from segfaulting when an incorrect DN string parameter is supplied
+ [r979]
+ - Preliminary implementation of NspiGetMatches NSPI server function
+ - Make use of a on-memory TDB database for Ephemeral Entry IDs
+ - Add TDB traversal routines to retrieve DN associated to MId
+ - Move lp_ctx within emsabp_ctx for convenience
+ - Add EphemeralEntryID to Binary_r routine
+ - add emsabp_query (Find attribute matching given property tag and
+ return associated data)
+ - add emsabp_fetch_attrs which builds a SRow array given a MId and
+ requested property tags.
+ - add emsabp_search which searches AD given input search criteria
+ - add a preliminary Property Tag to AD attribute mapping + associated
+ functions in emsabp_property.c
+
+ Note: This NspiGetMatches is limited to MAILUSER which means we only
+ look for users (located within users.ldb). This limitation will be
+ removed when we have a preliminary working emsmdb server, so we can do
+ more extensive NSPI server tests.
+ [r978]
+ Add sanity check to get_SPropValue_SRowSet, prevents the function
+ from segfault when RowSet is NULL (e.g. crafted NspiQueryRows replies)
+ [r977]
+ Prevent IProfAdmin based code from crashing when a crafted NspiGetMatches reply
+ with NULL ppOutMIds is returned.
+
+2009-01-10
+ jkerihuel
+ [r976]
+ - Preliminary NspiGetSpecialTable implementation added to NSPI
+ server/EMSABP provider: Hierarchy Table supported (required during
+ profile creation)
+ - add PT_BINARY support for mapidump_SPropValue
+ - fix a bug when PT_STRING8 or PT_UNICODE pointer is set to
+ MAPI_E_NOT_FOUND
+
+2009-01-06
+ jkerihuel
+ [r974]
+ Add new Display Type values (used by EMSABP provider)
+ [r973]
+ Change DEBUGLEVEL for RfrGetNewDSA
+ [r972]
+ - preliminary implementation of RFR server (RfrGetNewDSA): makes Outlook happy
+ - mapiproxy-servers-install now installs openchange python scripts and ldif file
+2009-01-05
+ jkerihuel
+ [r971]
+ Move auth_serversupplied_info structure from dcesrv_exchange_nsp.h to libmapiproxy.h
+ This structure is required for NTLM_AUTH_IS_OK macro
+ [r969]
+ - Add doxygen comments for all OpenChange server modules
+ - Fix doxygen return value for exchange_nsp
+ [r968]
+ - Add mapiproxy server unbind function and hook in dcesrv_mapiproxy.c
+ - Add exchange handle enum to dcesrv_mapiproxy.h
+ - Add authentication verifier macro to libmapiproxy.h
+ - Add preliminary EMSABP Address Book Provider implementation:
+ * supports initialization, destructor (talloc)
+ * implements user and codepage check routines
+ * retrieve NSPI server GUID
+ - Add NspiBind and NspiUnbind support to dcesrv_exchange_nsp.c
+ - Add internal session mechanism management to NSPI server
+ - Add init and unbind modules function to NSPI server
+ - Add doxygen comments to all dcesrv_exchange_nsp.c functions
+ - Add emsabp_context, session and non-exported Samba structure to dcesrv_exchange_nsp.h
+ [r967]
+ OpenChange configuration schema updated with Addressing schema
+ (Address-Templates, Address-Types and Display-Templates - Exchange 2003 based)
+ [r966]
+ Execute server modules init function when loaded
+ bradh
+ [r965]
+ A few API documentation fixes.
+
+2009-01-04
+ jkerihuel
+ [r963]
+ Add documentation for MAPIProxy 'server mode'
+
+2009-01-02
+ jkerihuel
+ [r961]
+ - Implement mapiproxy server mode architecture
+ - Add server modules management API
+ - Add skeletons for default OpenChange servers (nspi, emsmdb, ds_rfr)
+ - Add temporary provision Makefile rule
+
+2008-12-30
+ jkerihuel
+ [r959]
+ Initial text was correct - rollback
+ [r958]
+ Fix path typo
+ bradh
+ [r957]
+ Ensure that GetLastError() also returns the correct value.
+ [r956]
+ Start changing the MAPI_RETVAL_IF() usage to two new macros:
+ OPENCHANGE_RETVAL_IF() and OPENCHANGE_RETVAL_ERR().
+
+ simple_mapi.c is the only one converted at this stage.
+
+ Also added a set of unit tests that verify at least some initial
+ sanity checks.
+ [r955]
+ Remove unreachable code.
+
+ Partly resolves ticket #124
+
+2008-12-29
+ jkerihuel
+ [r953]
+ Remove references to ldap.h header file - not installed anymore with samba4 git rev openchange uses
+ [r952]
+ mapiproxy documentation update: 3 questions added to FAQ section
+ [r951]
+ Patch from Corentin Chary:
+ - Add PR_CONTENT_FILTER_SCL property to libmapi
+ [r950]
+ - Update openchange to work with samba4 master git rev f308c2f
+ - Replace reference to events.h with tevent.h
+ - Update installsamba4.sh script to reflect latest samba4 compilation changes/requirements
+
+2008-12-27
+ jkerihuel
+ [r948]
+ Fix mapidump date/month when freebusy period covers end of one year - beginning of next year
+ Update openchangeclient to reflect these changes.
+
+2008-12-24
+ jelmer
+ [r946]
+ Export PKG_CONFIG_PATH if it wasn't exported yet. Patch by Metze
+ [r945]
+ Fix PIC object flags for SWIG build. Patch by metze.
+
+2008-12-21
+ bradh
+ [r943]
+ User %u format specifier for unsigned integer.
+ [r942]
+ Make return value match signature.
+ [r941]
+ Miscellaneous minor cleanups. Mainly making return types
+ match signatues, format conversion (%u for unsigned values) and
+ matching up result variable types (bool instead of enum MAPISTATUS).
+ [r940]
+ Return an enum MAPISTATUS, instead of a bool, to match function signature.
+ [r939]
+ Use %u instead of %d for unsigned values.
+
+2008-12-20
+ bradh
+ [r937]
+ Another minor APIdox edit.
+ [r936]
+ API documentation tweak.
+ [r935]
+ API dox fix.
+ [r934]
+ API dox fix.
+ [r933]
+ Minor apidox fixes.
+ [r932]
+ More apidox triviality.
+ [r931]
+ Trivial APIdox edits.
+ [r930]
+ Supplement the user's PKG_CONFIG_PATH rather than
+ overriding it.
+ jelmer
+ [r929]
+ Add bindings for GetBestBody(), GetDefaultFolder(), GetDefaultPublicFolder(), AddUserPermission(), ModifyUserPermission().
+ [r928]
+ Add bindings for create_message, delete_messages, get_message_status, set_read_flags.
+ [r927]
+ Add Python bindings for Unsubscribe(), get_task_status(), get_importance(), get_proptag_name(), get_proptag_value(), DeleteFolder(), CreateFolder(), EmptyFolder(), RemoveUserPermissions(), IsMailboxFolder().
+
+2008-12-19
+ jelmer
+ [r925]
+ Actually use pymapi variables in Makefile.
+ [r924]
+ Add configure flags for building and installing Python MAPI bindings (disabled by default).
+
+2008-12-18
+ bradh
+ [r922]
+ Add namespace prefix to scanner.
+
+2008-12-16
+ jkerihuel
+ [r920]
+ - spnego / gssapi_krb5 authentication now available for mapiprofile
+ - add the --realm | -R option
+ - update mapiprofile man page
+
+2008-12-14
+ bradh
+ [r912]
+ Remove entries for --properties and --priority, which have been removed from the openchangeclient utility.
+
+ Partly fixes #113.
+ [r911]
+ Don't generate / install man3 pages for libmapi++ or mapitest.
+
+ Resolves ticket #121.
+
+ Also don't install man3 pages that are just copies of the C implementation files, or just document bugs / todo items.
+ jelmer
+ [r918]
+ Allow retrieving id and session of MAPI objects.
+ [r917]
+ Add MessageStore and Object Python classes, add bindings for OpenMsgStore, OpenUserMailbox, OpenPublicFolder.
+ [r916]
+ Add stubs for Session class.
+ [r915]
+ Add infrastructure for MAPI python module.
+ [r914]
+ Look for python and python-config binaries.
+ [r913]
+ Remove empty directory.
+2008-12-13
+ jkerihuel
+ [r910]
+ Remove obsolete --properties option and related code
+
+2008-12-10
+ jkerihuel
+ [r908]
+ Fix RecipientRow member's order
+
+2008-12-09
+ jkerihuel
+ [r906]
+ - Update to latest samba4 git master revision (3508a66)
+ - Fix references to samr info24 struct
+ - Add support for assoc_group_id proxy
+ - Add support in mapiproxy for bind/alter connections using assoc_group_id
+ - Update mapiproxy documentation
+
+2008-12-07
+ bradh
+ [r904]
+ Improve building. Partially addresses #94.
+
+ More work required on this as we work on the
+ portability in the future.
+ [r903]
+ Expose the underlying session.
+
+2008-11-30
+ bradh
+ [r901]
+ Remove unused --priority option.
+ [r900]
+ These offsets / values can be negative, so we shouldn't
+ use unsigned int type to represent them.
+
+2008-11-29
+ jkerihuel
+ [r898]
+ Fix Logon problem for users running Exchange 2k7 in a clustered Exchange environment.
+
+ This patch first tries to forge EssDN Logon string from "o" and "ou"
+ attributes stored in the profile. If Logon fails with ecUnknownUser,
+ then try to open the mailbox using the mailbox attribute stored in
+ the profile.
+
+2008-11-28
+ bradh
+ [r896]
+ Document the --label option.
+
+2008-11-26
+ jkerihuel
+ [r893]
+ Make openchange compile and work against latest samba4 master git rev (58db2be)
+ jelmer
+ [r894]
+ Remove check for unused type 'uint_t'.
+
+2008-11-22
+ bradh
+ [r888]
+ More tweaks on the openchangeclient man1 page.
+ [r887]
+ More updates for man1 page for openchangeclient.
+ Still doesn't fully address #113.
+ [r886]
+ Update the openchangeclient man1 page.
+
+ Partly addresses ticket #113.
+
+ There is still some work to do on this.
+ [r885]
+ Fix a typo, and try to make the descriptions more
+ consistent.
+
+2008-11-21
+ bradh
+ [r883]
+ Initial version of man1 page for mapitest
+ [r882]
+ Initial man1 page for exchange2ical utility.
+
+2008-11-14
+ bradh
+ [r879]
+ Update man1 page for openchangepfadmin
+ [r878]
+ Minor updates for the man pages.
+
+2008-11-13
+ jkerihuel
+ [r875]
+ Fix build errors: wrong number of arguments for ocpf_propvalue
+ [r874]
+ Fix warnings when compiling with -Wextra
+ [r873]
+ Fix warnings when compiling with -Wextra
+ [r872]
+ Fix warnings when compiling with -Wextra
+ bradh
+ [r876]
+ Complete initializers here.
+
+2008-11-10
+ bradh
+ [r870]
+ Update to reflect latest state of mapiprofile.
+
+2008-11-09
+ bradh
+ [r868]
+ Prevent segfault when running mapitest. Looks like the we can
+ return MAPI_E_SUCCESS even if one of the property values is
+ MAPI_E_NOTFOUND. That error then get turned into a char*, and
+ strncmp faults.
+
+ Also fix a possible bug relating to operator precedence, and
+ a couple of warnings (one for signed / unsigned comparison, and
+ the other for an unsigned value never being less than zero).
+
+2008-11-08
+ bradh
+ [r866]
+ Enable output to stdout.
+
+ Resolves ticket #106.
+
+ Thanks to raboof for the report and fix.
+
+2008-11-07
+ bradh
+ [r864]
+ Fix missing initialisers (issue #110).
+
+ Also fix some signed/unsigned warnings.
+ [r863]
+ Fix problems with incorrect initialisers (#110) and
+ operator precedence.
+
+ Also fix a couple of places with signed/unsigned confusion.
+ [r862]
+ Partial fix for issue #110, and a couple of very minor cleanups.
+
+2008-11-06
+ bradh
+ [r860]
+ Minor cleanups.
+ [r859]
+ We probably want to return here, not do nothing.
+
+2008-11-05
+ jkerihuel
+ [r855]
+ Fix empty patch function problem: add a retval
+ bradh
+ [r857]
+ Typo fix.
+ [r856]
+ Explain the boost-thread trick.
+ [r854]
+ Minor documentation tweaks.
+
+2008-11-04
+ jkerihuel
+ [r852]
+ - remove usage of global_loadparm in libmapiadmin
+ - make use of session context rather than global_mapi_ctx in libmapiadmin
+ - use local context rather than mapiadmin context in libmapiadmin
+ - libmapiadmin now uses ldb helper rather than raw implementation (ldb async code)
+ - libmapiadmin and openchangepfadmin now works again (user creation/deletion) !! ;-)
+ - remove global_loadparm in torture test and replace it with torture context
+ - fix dcerpc_init to match latest samba4 API
+ - update samba4 version required to build openchange
+ bradh
+ [r850]
+ More API documentation tweaks.
+ [r849]
+ More API documentation tweaks.
+ [r848]
+ Some API dox fixes for libmapi++.
+ jelmer
+ [r851]
+ Remove unnecessary patching of lib/events/events.h.
+
+2008-11-03
+ bradh
+ [r846]
+ Update to a more recent Samba4.
+ jelmer
+ [r845]
+ Remove some usages of deprecated global_loadparm.
+ [r844]
+ Cope with new argument to dcerpc_log_packet().
+
+2008-11-01
+ jelmer
+ [r842]
+ Fix includes for DEBUG(), fix some more warnings.
+ [r841]
+ Use same_net_v4 rather than deprecated same_net().
+ [r840]
+ Fix Samba 4 git revision.
+ [r839]
+ Fix includes - debug.h can only be included once.
+ [r838]
+ Include debug header.
+ [r837]
+ Cope with API changes in Samba functions.
+ [r836]
+ Use new function is_zero_ip_v4 rather than removed is_zero_ip.
+
+2008-10-31
+ jkerihuel
+ [r833]
+ Fix OpenMsgStore binding in swig perl and fetchmail script
+
+2008-10-21
+ jkerihuel
+ [r824]
+ Fix pointless const definition for GetFreeBusyYear return type
+2008-10-20
+ jkerihuel
+ [r823]
+ - Add the IsFreeBusyConflict convenient function which checks if a
+ given date conflicts with existing FreeBusy Busy/OOF events
+
+ - Modify openchangeclient --sendappointment behavior to check whether
+ start or end date conflicts with FreeBusy published data for the
+ user.
+
+ - Add the --force option to openchangeclient to override this behavior
+
+ - Fix a counter bug in mapidump_freebusy_events
+ [r821]
+ Fix doxygen typo error
+ [r820]
+ - Add GetUserFreeBusyData convenient function which retrieves FreeBusy
+ data in public folders for a given user. Note: Ambiguous name is not
+ supported at the moment.
+
+ - Add convenient FreeBusy mapidump routines
+
+ - Add FreeBusy read support to openchangelient
+
+ - Add PT_MV_LONG and PT_MV_BINARY support to pull_emsmdb_property and
+ property.c functions
+
+ - Add OpenUserMailbox which let developers open other mailboxes
+ instead of the default profile one.
+
+ - Add GetABRecipientInfo: convenient function which retrieves Address
+ Book information for a given recipient
+
+2008-10-17
+ jkerihuel
+ [r818]
+ - Add libmapi implementation for DeletePropertiesNoReplicate
+ - Add mapitest test units for DeleteProps and DeletePropertiesNoReplicate
+ [r817]
+ Fix doxygen documentation
+
+2008-10-16
+ jkerihuel
+ [r815]
+ - Implement multisession into libmapi
+ - Update openchange tools and suite to reflect these changes
+ - Fix SRow_addprop behavior
+
+ NOTE: OpenMsgStore, ResolveNames, GetGALTable and RFR functions
+ now take a mapi_session parameter.
+ jelmer
+ [r814]
+ Use my openchange.org email address.
+
+2008-10-09
+ jkerihuel
+ [r812]
+ - Add a session management API for mapiproxy modules. Similar code
+ already existed for mpm_cache module. Common functions are now
+ available to all mapiproxy modules through libmapiproxy
+
+ - replace smbd with samba in mapiproxy documentation
+ [r811]
+ - Cache calendar, contact, journal, note, task and drafts folders IDs
+ when GetDefaultFolder call is performed on one of these folders and
+ keep them until obj_store is released.
+
+ - Add a reverse lookup routine which says whether a given FID belongs
+ to a default folder and which olFolderType it is.
+ [r810]
+ - Remove pointless memory context in GetDefaultFolder
+ - Move entryID to FID code into a separated routine (GetFIDFromEntryID)
+ [r809]
+ Restore install rule for mapi profiles ldif files in
+ libmapi-installscript. Fix the MAPI_E_NO_ACCESS bug when mapiprofile
+ tries to create a new mapi profile store.
+2008-10-08
+ jkerihuel
+ [r808]
+ - Ticket #103 resolved. openchangeclient can now perform custom folder lookup, fetch, mkdir and rmdir.
+ - mapi_object_copy routine added to mapi_object.c
+
+2008-10-06
+ jkerihuel
+ [r806]
+ Fix missing Month field in LogonTime structure
+2008-10-05
+ jkerihuel
+ [r805]
+ propagate IDL warning fix to property.idl
+ jelmer
+ [r804]
+ Add target for building python API documentation.
+2008-10-01
+ jkerihuel
+ [r802]
+ Fix samba4 release and git revision
+ [r801]
+ Fix installsamba4.sh script paths
+ jelmer
+ [r803]
+ Avoid warning.
+ [r800]
+ Install OpenChange python modules.
+ [r799]
+ Check for python dir during configure.
+ [r798]
+ ignore generated files.
+ [r797]
+ Stop installing js files.
+ [r796]
+ Use autoconf cache prefix.
+ [r795]
+ Use newer version of Samba 4.
+2008-09-30
+ jkerihuel
+ [r791]
+ Remove dcesrv_exchange.so from server Makefile rule and
+ move mapiproxy from TOOLS to SERVER.
+
+ dcesrv_exchange and providers Makefile rules are orphan, planned
+ to be removed (with their associated code) when emsabp merge process
+ into mapiproxy is over.
+2008-09-23
+ bradh
+ [r790]
+ Export the Binary_r structure.
+2008-09-22
+ bradh
+ [r789]
+ Use more descriptive variable names in messages example code.
+ [r788]
+ Add a description of messages to libmapi++ API documentation.
+ [r787]
+ Add messages binary to the ignore list.
+ [r786]
+ Add new example showing libmapi++ message handling, and
+ associated API documentation and build system changes.
+2008-09-21
+ bradh
+ [r785]
+ Update the API documentation main page for libmapi++
+2008-09-19
+ jkerihuel
+ [r784]
+ Add foldertree binary to the ignore list
+ [r783]
+ - Add missing Input parameter
+ - Add sanity check on ppNames
+ - Fix ticket #102
+ [r781]
+ - Fix a bug in NspiUpdateStat: make plDelta mandatory and use it for in,out
+ - Add a NspiGetSpecialTable test for Address Creation Template
+ bradh
+ [r780]
+ Fix valgrind-reported error, per ticket #101.
+ [r779]
+ Make sure we clean up after mapitest runs.
+
+ Resolves ticket #84
+2008-09-17
+ jkerihuel
+ [r778]
+ - Add msExchUserAccountControl attribute to extended user record
+ - openchange_newuser can now create/enable/disable an OpenChange account
+ [r776]
+ Exit the test if the WriteStream operation fails
+ [r773]
+ Fix ncacn_ip_tcp binding string for OpenChange server object
+ [r772]
+ With new NSPI IDL, using cValues - 1 is incorrect and lead to errors. Use cValues directly instead
+ [r771]
+ Fix pipe function check and use ndr autogenerated defines rather than static strings
+ Fix calls to NspiDNToMId
+ bradh
+ [r774]
+ Make sure we set the body and body format properties, to
+ ensure that the message is shown correctly with
+ openchangeclient -F.
+2008-09-16
+ jkerihuel
+ [r770]
+ - Fix provisioning
+ - Rename oc_* python scripts to openchange_*
+ - Add Full Exchange 2003 schema (classes and attributes)
+ - Full Exchange 2003 modified classes and attributes support
+ - Add prefixmap OID for some Exchange classes and attributes
+ - Add missing ADSC classes and attributes
+ - Improve configuration LDIF file with new objects
+
+ NOTE: provision.py should find a way to handle firstorg properly
+ NOTE: oc_provision_configuration.ldif is still incomplete
+ bradh
+ [r768]
+ API documentation improvements.
+2008-09-15
+ bradh
+ [r767]
+ Add an example to the libmapi++ documentation, and
+ the right build magic and doxygen linkage.
+ [r766]
+ Minor API documentation fix
+2008-09-14
+ bradh
+ [r765]
+ Add forgotten part of API documentation fixes for mapitest.
+ [r764]
+ Improve mapitest API documentation.
+2008-09-13
+ bradh
+ [r763]
+ Use new DeleteFolder flags to clean up folders on deletion.
+
+ This doesn't completely resolve ticket #84, but it does help.
+ [r762]
+ Ignore API documentation.
+ [r761]
+ Add Doxyfile to ignore list.
+ [r760]
+ Add initial support for Doxygen API documentation
+ for libmapiadmin.
+2008-09-12
+ bradh
+ [r759]
+ Implement the remainder of the standard public folders.
+2008-09-10
+ bradh
+ [r758]
+ Only do header line removal at the start of the file
+ (lines 20 through 40 seems like a good compromise).
+ [r757]
+ libmapi++ is C++, not C, so we should not optimise
+ Doxygen output for C.
+2008-09-09
+ jkerihuel
+ [r755]
+ - Update the Logon_repl IDL (0xFE) and implementation
+ - Add new folders to the mapi_obj_store for PF folders
+ - rename pf_finder to pf_search
+ bradh
+ [r756]
+ Suppress some more unwanted headers.
+2008-09-08
+ jkerihuel
+ [r754]
+ - Add GetStoreState (0x7b) IDL, implementation and mapitest unit
+ [r753]
+ Fix typo error
+ [r752]
+ - Update the EmptyFolder IDL
+ [r751]
+ - Update the SearchFlags enum, GetSearchCriteria and SetSearchCriteria IDL
+ - Add mapitest units for GetSearchCriteria and SetSearchCriteria
+ [r750]
+ Link libmapi++ documentation to main apidocs page
+ [r749]
+ Update GetAttachmentTable IDL and remove the unknown field
+ [r748]
+ - Update DeleteFolder IDL and implementation
+ - It now supports DeleteFolderFlags as input parameter and can return the ParticalCompletion state
+ - Sanity checks added at the beginning of the function
+ [r747]
+ - Rename GetRowCount to QueryPosition
+ - IDL, implementation, documentation and openchange code updated
+ - ActionType enum fields prefixed with 'ActionType_'. Original
+ values were causing conflicts while building Perl bindings with
+ 'i386-linux-thread-multi/CORE/opnames.h where OP_DELETE was already defined'
+ [r746]
+ Change enum SaveFlags to uint8_t for doxygen documentation to be generated properly
+ [r743]
+ - Update SaveChangesMessage IDL and implementation
+ - Add a SaveFlags parameter to SaveChangesMessage function
+ - update openchange code to reflect this change
+ bradh
+ [r745]
+ Build fix / fix for ticket #99.
+ [r744]
+ Filter out some new #include lines.
+
+ This needs to be applied to other modules too.
+2008-09-07
+ jkerihuel
+ [r742]
+ Update SRow and SRowSet IDL
+ [r741]
+ Delete obsolete input_locale and instance_key structures
+ [r740]
+ Fix WStringArray_r IDL
+ [r739]
+ - Move from MV_UNICODE_STRUCT and LPWSTR to WStringArray
+ - LPWSTR structure removed
+ [r738]
+ Rename SDateTimeArray to DateTimeArray_r
+ [r737]
+ Rename SGuidArray to FlatUIDArray_r and fix the IDL
+ [r736]
+ Rename MV_LONG_STRUCT to LongArray_r
+ [r735]
+ Rename SBinary to Binary_r
+ [r734]
+ - Add removal of libmapi++ Doxyfile in make distclean rule
+ - Add Doxyfile to svn:ignore
+ [r733]
+ Rename SShortArray to ShortArray_r
+ [r732]
+ - Move from SLPSTRArray to StringArray_r
+ - LPSTR structure removed
+ [r731]
+ Rename MAPIUID to FlatUID_r
+ [r730]
+ Fix lexer warnings during compilation (ticket #100)
+ [r729]
+ - Update the EcDoConnect IDL (ref. ticket #99)
+ - Add new fields to the emsmdb info structure
+ - Add doxygen comments to libmapi/emsmdb.c
+ bradh
+ [r728]
+ Reduce warnings when compiling with 64-bit arch.
+ [r727]
+ Initial checkin of infrastructure for libmapi++ API documentation.
+2008-09-06
+ jkerihuel
+ [r726]
+ - MAJOR NSPI protocol and libmapi stack update
+ - All NSPI protocol functions implemented
+ - NSPI stack fully documented
+ - NspiGetHierarchyInfo renamed to NspiGetSpecialTable
+ - NspiDNToEph renamed to NspiDNToMId
+ - instance_key removed from nspi_context and set as a parameter to NSPI functions
+ - SPropertyRestriction renamed to PropertyRestriction_r
+ - FlagList structure removed and replaced by a SPropTagArray
+ - MAPI_SETTINGS removed and replaced by a STAT structure
+ - new MAPI property tags added to libmapi/conf/mapi-properties
+ - NSPI module added to mapitest
+ bradh
+ [r725]
+ Clean up on failure.
+ [r724]
+ Clean up on failure.
+ [r723]
+ Minor improvements to ensure cleanup on failure.
+ [r722]
+ API documentation fix
+ [r721]
+ API documentation fix.
+ [r720]
+ API documentation fix.
+ [r719]
+ API documentation fix.
+ [r718]
+ API documentation fixes.
+2008-09-05
+ bradh
+ [r717]
+ API documentation fixes.
+2008-09-04
+ jkerihuel
+ [r716]
+ Fix EMSMDB 0xb function name
+ [r715]
+ - update EcRRegisterPushNotification IDL
+ - update Notify IDL
+ - implement complete MAPI notifications
+ - update libmapi to reflect these changes
+ - make openchangeclient prints a brief summary for each notification found
+ - update ulEventMask used in openchangeclient
+2008-09-03
+ jkerihuel
+ [r714]
+ - Rename Advise MAPI call to RegisterNotification
+ - Update RegisterNotification IDL and implementation
+2008-09-02
+ jkerihuel
+ [r713]
+ - Fix Restrict IDL and implementation
+ - Add a new parameter to the Restrict function
+ - close ticket #32
+ [r712]
+ Add mapi_nameid.h to the ignore list
+ [r711]
+ - Replace libmapi/mapi_nameid.h with a generated mparse file
+ - Add a mapi_nameid.h parser to mparse.pl
+ - Add canonical names for named properties
+ - GetProps and SetProps resolves named properties if they exist
+ - named properties can now be set directly and make mapi_nameid API be
+ optional.
+ - replace named property tags hex value with their canonimal names
+ - replace several use of the mapi_nameid API with smaller code
+ [r710]
+ - Add new IDL file (property.idl) to push/pull structures from binary
+ blobs and not directly related to any MAPI calls. Include the
+ generated property.h file into libmapi.h
+
+ - Add PT_MV_STRING8 support in pull_emsmdb_property (GetProps reply
+ parsing) and mapidump_SPropValue
+
+ - Add functions to property.c to retrieve RecurrencePattern,
+ TimeZoneStruct and GlobalObjectId structures (see property.idl).
+
+ - add a preliminary version of exchange2ical tool. This version only
+ dumps calendar folder appointments into ICS file on standard output.
+2008-08-30
+ jkerihuel
+ [r709]
+ - Update mapi-nameid-properties with a more complete set of properties
+ - Add a header to mapi-nameid-properties for sanity purposes
+ - Move named properties with PT_STRING8 type to PT_UNICODE
+ - update openchange code to reflect these changes
+ - Add PSETID_Attachment to mapidefs.h
+2008-08-28
+ jkerihuel
+ [r707]
+ Add missing check on password for the create command
+ [r706]
+ Fix incorrect usage of realm in mapiproxy
+2008-08-27
+ jkerihuel
+ [r705]
+ Check for provider_rpc_connection retval for RFR functions.
+ [r704]
+ Update Doxyfile to parse mapiproxy/modules files and
+ include documentation on static functions.
+ [r703]
+ - Add NSPI hook on NspiQueryRows and NspiDNToEph and replace the
+ Exchange server name with mapiproxy one.
+ - documentation updated to reflect these changes
+ - new FAQ question added
+ - developer documentation improved
+ [r702]
+ Add the RFR mapiproxy file.
+ [r701]
+ - Implement RfrGetNewDSA DN replacement in mapiproxy
+ - use lp_realm rather than sockaddr in NspiGetProps (FQDN rather than IP address)
+ - update mapiproxy documentation to reflect these changes
+2008-08-26
+ jkerihuel
+ [r698]
+ - Add implementation of the NSPI Referral protocol (exchangeRFR)
+ - update dcesrv_exchange and mapiproxy prototypes for RFR
+ - add references to the RFR pipe in mapiproxy
+ - prefix NSPI client connections with a RfrGetNewDSA call
+ - add RFR functions implementation in libmapi/IMSProvider.c
+ - add a --getfqdn option to mapiprofile
+ - fix a minor mapiprofile option parsing bug
+2008-08-25
+ jkerihuel
+ [r697]
+ Fix mapiproxy dummy module unbind prototype
+ [r696]
+ - Remove flags in EcDoRpc top function, fix compilation vs latest samba4-git version
+ - EcDoRpc indent updated
+2008-08-15
+ clsk
+ [r694]
+ Get rid of initialization order warning
+2008-08-11
+ jkerihuel
+ [r691]
+ - add unbind hook for mapiproxy
+ - add ahead mapiproxy mode
+ - add read ahead in cache module
+ - add synchronization mechanism in cache module
+ - update mapiproxy documentation to reflect these changes
+2008-08-08
+ bradh
+ [r690]
+ Temporarily comment out installation of files removed
+ in r683.
+2008-08-01
+ jelmer
+ [r685]
+ Fix arguments, paths in provision scripts.
+ [r683]
+ Merge python provision/newuser scripts.
+ [r681]
+ Simplify installation of manpages a bit.
+2008-07-29
+ jkerihuel
+ [r679]
+ Add configure check for libboost-thread. Add libmapi++ to the build
+ only if it is available.
+2008-07-27
+ clsk
+ [r678]
+ - session constructor doesn't login to the server anymore, it calls MAPIInitialize().
+ - Created session::login() members.
+ - test applications use default profile.
+2008-07-26
+ jkerihuel
+ [r676]
+ - Import Alan Alvarez work from libmapi++ into trunk
+ - Add a g++ check in configure.ac: don't call libmapi++ rules if g++
+ is missing
+ - Add libmapi++ to the build system
+ - Add a patch function to installsamba4.sh: rename private to
+ private_data in samba4 events.h header file
+ - Change #include directives so it uses <libmapi++ ... rather than
+ relative paths.
+2008-07-24
+ jkerihuel
+ [r674]
+ - Add a statitic function monitoring streams over OpenStream and Last
+ ReadStream operations. Monitoring stream Release is not relevant
+ since Outlook does not close the handle directly after last
+ ReadStream operation. Should put in evidence difference between
+ non-cached(1st retrieval) and cached (further retrieval).
+
+ - Fix a few memory leaks
+2008-07-23
+ jkerihuel
+ [r672]
+ - Commit initial revision for the mapiproxy cache module
+ - Update mapiproxy hook API for the dispatch routine
+ - Introduce the mapiproxy structure for modules to control top-level
+ mapiproxy behavior.
+ - Update mapiproxy documentation to reflect these changes
+2008-07-21
+ jkerihuel
+ [r670]
+ * Fix remaining ByteRead parameter size for ReadStream operations.
+2008-07-20
+ jkerihuel
+ [r669]
+ * Improve/Update Open/Read/WriteStream IDLs
+ * Fix ByteRead parameter size for ReadStream operation.
+2008-07-19
+ jkerihuel
+ [r668]
+ Improve OpenAttach, CreateAttach and DeleteAttach IDL - remove unknown
+ parameters.
+ [r667]
+ Propagate r666 changes to OpenMsgStore and fix build
+ bradh
+ [r666]
+ Minor rename of bitmap value to avoid conflict with
+ Private as a class name.
+2008-07-17
+ jkerihuel
+ [r663]
+ Minor change: remove old debugging string from mapitest
+ [r660]
+ Fix incorrect header
+ [r658]
+ Remove deprecated mapi_handles API
+ bradh
+ [r665]
+ Initial checkin of some uno (static checker) support
+ files.
+
+ There will be a script to run uno with the right options,
+ but that requires more work.
+2008-07-16
+ jkerihuel
+ [r655]
+ Fix OXOMSG-ABORT-SUBMIT return value and return success when expected
+ error values (MAPI_E_UNABLE_TO_ABORT, ecNoDelSubmitMsg) are encountered.
+ [r654]
+ - Call mapi_object_release in GetDefaultFolder
+ - Remove pointless references to mapi_object_t
+ bradh
+ [r656]
+ Fix little memory leak.
+2008-07-15
+ jkerihuel
+ [r653]
+ Fix invalid OpenFolder calls in mapitest modules
+ [r652]
+ Remove references to SaveChanges in doxygen see also statement
+ [r651]
+ - Rename SaveChanges to SaveChangesAttachment (0x25)
+ - Update SaveChangesAttachment IDL
+ - Update references to SaveChanges
+ [r650]
+ - Fix the huge memory leak described in Ticket #91
+ - Rewrite the mapitest NameID test to use the mapi_nameid convenient
+ API
+2008-07-12
+ jkerihuel
+ [r648]
+ - Add mapi_get_errstr auto-generated routine which returns the MAPI
+ retval as a string
+ - Add print routine for MAPI retval in mapitest
+ - Add a color mode (--color) which prints either green or red MAPISTATUS
+ - Update mapitest modules to use these new routines
+ bradh
+ [r647]
+ Minor API documentation fix.
+2008-07-11
+ jkerihuel
+ [r646]
+ Add all MAPI errors
+ [r645]
+ - Add GetOwningServers (0x42) implementation (IDL + libmapi + mapitest)
+ [r644]
+ - Report and make consistent usage of PropertyProblem in the IDL:
+ SetProps, DeleteProps and CopyProperties
+
+ - Remove unknown field in GetProps and GetPropsAll and replace them
+ with the correct IDL mapping.
+
+ - Add IDL for SetPropertiesNoReplicate (0x79) MAPI call
+
+ - Minor typo fix in IMAPIProp.c
+ [r643]
+ Improve CreateMessage request IDL
+ [r642]
+ Improve OpenMessage response IDL
+ [r641]
+ - Add PublicFolderIsGhosted (0x45) MAPI call (IDL + libmapi + mapitest)
+
+ - Improve OpenFolder, CreateFolder and OpenPublicFolderByName response
+ IDL: make these call able to check whether the folder is ghosted or
+ not.
+ [r640]
+ Revert emsmdb pipe version to the hacked one. Makes mapiproxy work with samba4-alpha5 release.
+ [r639]
+ SeekRow and SeekRowBookmark IDL improved
+ [r638]
+ Improve the SetColumns IDL: remove unknown fields
+2008-07-06
+ jkerihuel
+ [r637]
+ Minor code convention fix
+ [r636]
+ Check NTSTATUS return value from dcerpc_ndr_request. Prevent mapiproxy
+ from segfault when invalid dcerpc response is received.
+ [r635]
+ Expose MAPISTATUS error in OXCTABLE-CATEGORY::FreeBookmark.
+ Requires investigation
+ bradh
+ [r634]
+ Implement GetIdFromLongTermId and GetLongTermIdFromId
+ functions (ROP:0x43 and 0x44), and associated mapitest.
+ [r633]
+ Documentation typo fix.
+ [r632]
+ Change the QueryNamesFromIDs() call to match
+ MSDN, including changing the name to QueryNamedProperties().
+
+ Also implement mapitest for QueryNamedProperties(),
+ GetNamesFromIDs() and GetIDsFromNames().
+
+ Update torture test to match.
+2008-07-05
+ jkerihuel
+ [r631]
+ - Build system update: use samba4-alpha5 release with wget method
+ - introduce 'make samba' and 'make samba-git'
+2008-07-04
+ bradh
+ [r630]
+ Make sure we have names[] array large enough.
+
+ Problem identified using default uno run.
+
+ Resolves #87.
+2008-07-03
+ jkerihuel
+ [r629]
+ Fix a small errno bug in GetBestBody
+ Add dump-data and debug options to exchange2mbox
+2008-06-30
+ jkerihuel
+ [r627]
+ - Move emsmdb interface version back to 0.81 (patch applied in samba4 trunk)
+ - remove sed hack, modifications applied in samba4 trunk
+ - update required samba4 git rev required
+ bradh
+ [r628]
+ Typo fix.
+2008-06-25
+ jkerihuel
+ [r626]
+ Minor documentation update: remove deprecated reference to ./bin/smbpython
+ [r625]
+ Fix torture suite entry point name
+ Fix torture module installation path
+ [r624]
+ - Add implementation for the BestBody algorithm
+ - Add MAPI_E_NOT_ENOUGH_MEMORY error code
+ - Remove trailing }}\0 from lzfu code
+ - Update openchange tools to use GetBestBody rather than
+ the initial check on PR_MSG_EDITOR_FORMAT
+ [r623]
+ Add a very basic stat module for mapitest: gives a quick overview
+ of tests which failed at the end of the report.
+ [r622]
+ - Defines a global stream size in mapitest.h
+ - Decrease stream size from 0x4000 to 0x3000
+ Sounds like Exchange 2003 SP2 doesn't support 0x4000, return MAPI_E_CALL_FAILED
+
+2008-06-24
+ jkerihuel
+ [r621]
+ Fix OC_CHECK_SAMBA_VERSION string
+ [r620]
+ - Move samba4_ver.sh from top dir to script
+ - update parts of openchange relying on samba4_ver.sh
+ [r619]
+ Add configure check for lib Z
+
+ [r618]
+ - Temporary fix ldb.pc problem and patch ldb.pc.in
+ - Update samba4 version to the latest revision
+ - Add libmapiproxy to svn:ignore proplist
+ bradh
+ [r617]
+ Try a different git revision, just for now.
+2008-06-17
+ jkerihuel
+ [r614]
+ - Update Samba4 version needed
+ - Change entry point function from init_module to samba_init_module
+ - update documentation
+2008-06-16
+ jelmer
+ [r613]
+ Fix calls of ldb_init() as required by newer versions of Samba.
+ [r612]
+ Avoid bashisms.
+ [r611]
+ Support newer versions of Samba4.
+2008-06-14
+ bradh
+ [r609]
+ Add some other standard GUIDs
+2008-06-11
+ jelmer
+ [r605]
+ Fix silly typo.
+ [r604]
+ Fix linking.
+ [r603]
+ Use version and soversion in mapiproxy library.
+ [r602]
+ Make modules directory overridable.
+2008-06-10
+ bradh
+ [r601]
+ Change API as identified on devel mailing list.
+
+ Here is the email:
+ After some investigation into an error reported by valgrind, I'm proposing an
+ API change for the MoveCopyMessages() function.
+
+ The signature is currently
+ enum MAPISTATUS MoveCopyMessages(mapi_object_t *obj_src, mapi_object_t
+ *obj_dst, mapi_id_t *message_id, bool WantCopy)
+
+ The problem is the message_id array. The subtle part is that it needs to be
+ terminated with a null mapi_id_t*, because of this:
+ for (request.count = 0; message_id[request.count]; request.count++);
+
+ That is a bit error prone - enough so to be wrong in the mapitest.
+
+ Now we could just fix the mapitest and document the requirements, or we could
+ change the signature.
+
+ Two ideas for a different signature:
+ 1. We could add a uint16_t count to the signature, that says how long the
+ array is.
+ 2. We could use a better data structure than mapi_id_t*. I'm suggesting
+ mapi_id_array_t:
+ enum MAPISTATUS MoveCopyMessages(mapi_object_t *obj_src,
+ mapi_object_t *obj_dst,
+ mapi_id_array_t *message_id,
+ bool WantCopy)
+2008-06-09
+ bradh
+ [r600]
+ Add mapitest coverage for CopyTo operations on
+ folders and attachments, and update API docs.
+
+ Also fix one place where we inadvertently used
+ CopyProps instead of CopyTo...
+2008-06-08
+ bradh
+ [r597]
+ Typo fixes in comments.
+ [r596]
+ Minor documentation updates.
+ [r595]
+ Clean up created message for SpoolerLockMessage() test.
+2008-06-07
+ bradh
+ [r594]
+ Update samba4 version test.
+ [r593]
+ typo fix.
+ [r592]
+ Make sure properties are copies into the last valid
+ location in the extended array (i.e. count-1) not the
+ count location.
+
+ Also, make sure we cast the data to a uint8_t for
+ conversion to boolean.
+
+ Also fix compile warning about returning integer instead
+ of pointer.
+ [r591]
+ We may read up to 0x1000 bytes, so ensure there is
+ enough room to add the terminating null.
+ [r590]
+ Minor cleanup of the talloc context for FreeBookmark().
+
+ Also change around some code to protect things a bit
+ better against null pointer inputs.
+2008-06-06
+ bradh
+ [r588]
+ Implement a bit more mapitest for CopyTo (0x39), in
+ support of #83.
+
+ Also make it clean up and report failures properly.
+2008-06-05
+ bradh
+ [r587]
+ Implement the CopyTo operation (0x39), including initial mapitest.
+ JK previously committed the IDL for this.
+
+ Also make CopyProps (0x67) use an appropriate data structure for
+ its IDL and update implementation to match.
+2008-06-04
+ bradh
+ [r586]
+ Minor documentation updates/corrections.
+2008-06-02
+ jkerihuel
+ [r583]
+ Introduce a default case for MAPI Restriction. In some circumstances -
+ while Outlook creates an OOF Rules - it sets a PT_SRESTRICT mapi
+ property tag which value is set to 0xFF. However 0xFF doesn't match
+ any restriction case.
+2008-06-01
+ jkerihuel
+ [r582]
+ - Add IDL for OpenEmbeddedMessage (0x46) MAPI call
+ [r581]
+ - Add IDL for ReloadCachedInformation (0x10) MAPI call
+ [r580]
+ - Add IDL for CopyTo (0x39) MAPI call
+ [r573]
+ - Update the Samba4 GIT revision needed to run openchange properly
+ [r572]
+ - import mapiproxy project from mapiproxy branch
+ - add custom proxypack MAPI call
+ - remove deprecated dcesrv_exchange_remote
+ bradh
+ [r579]
+ Add missing part of mapitest for SetReadFlags
+
+ This should have been part of r578.
+ [r578]
+ mapitest for SetReadFlags
+ [r577]
+ Implement SetReadFlags (operation 0x66).
+
+ Also minor API docs fix.
+ [r576]
+ Move some test infrastructure from the oxctable.c module
+ into the common area.
+ [r575]
+ Fix IDL error for SetReadFlags, and use existing flags
+ define (MSGFLAGS_READ) instead of creating a new set.
+ [r574]
+ Build fix for relocation of mapiproxy/ to be under the
+ top level directory (instead of under the utils/
+ directory)
+2008-05-31
+ jkerihuel
+ [r571]
+ merge from mapiproxy branch:
+ * ndr_push Logon_req manually
+ [r568]
+ merge from mapiproxy branch:
+ * Add IDL and server boiler template for EcDoConnectEx (0xA)
+ EMSMDB RPC function
+
+ * Fix ndr_push_mapi_response code in ndr_mapi.c
+
+ * Add the ndr_push_EcDoRpc_MAPI_REPL function in
+ ndr_mapi.c. Handles special Notify and Pending cases
+
+ * Handle op_MAPI_Pending case properly in
+ ndr_pull_EcDoRpc_MAPI_REPL
+
+ * Add code to ndr_push QueryRows in ndr_mapi.c: Do not push any
+ DATA_BLOB if there is no RowCount
+ [r565]
+ merge from mapiproxy branch:
+ * Fix GetReceiveFolder [out] IDL
+ * Fix some naming convention typo
+ [r564]
+ merge from mapiproxy branch:
+ * Fix SetMessagReadFlag [out] IDL
+ [r563]
+ - Add [flag(NDR_REMAINING)] to SetMessageReadFlag. This is not
+ perfect, but it will prevent mapiproxy from ndr_pull error while
+ setting message read flag on public folders messages.
+ [r562]
+ merge from mapiproxy branch:
+ * Fix CreateMessage [out] IDL
+ [r561]
+ merge from mapiproxy branch:
+ * rename OpenModeFlags to OpenFolder_OpenModeFlags in OpenFolder
+ * rewrite OpenMessage [in] IDL and report changes in
+ libmapi/IStoreFolder.c
+ [r560]
+ merge from mapiproxy branch:
+ * Add IDL for Pending (0x6e) MAPI call
+ * Reorder some MAPI calls in EcDoRpc_MAPI_REPL_UNION
+ [r559]
+ - Add SetReadFlags to EcDoRpc_MAPI_{REQ,REPL}_UNION
+ [r558]
+ merge from mapiproxy branch:
+ * Add IDL for SetSyncNotificationGuid (0x88) MAPI call
+ [r557]
+ merge from mapiproxy branch:
+ * Add IDL for SyncGetTransferState (0x82) MAPI call
+ [r556]
+ merge from mapiproxy branch:
+ * Add IDL for SyncImportReadStateChanges (0x80) MAPI call
+
+ Note: This IDL is temporary and should be improved after completion of
+ the merging process.
+ [r555]
+ merge from mapiproxy branch:
+ * Add IDL for SyncOpenCollector (0x7e) MAPI call
+ [r554]
+ merge from mapiproxy branch:
+ * Add IDL for DeletePropertiesNoReplicate (0x7a) MAPI call
+ [r553]
+ merge from mapiproxy branch:
+ * Add IDL for SyncImportMessageMove (0x78) MAPI call
+ [r552]
+ merge from mapiproxy branch:
+ * Add IDL for SyncUploadStateStreamBegin (0x75) MAPI call
+ * Add IDL for SyncUploadStateStreamContinue (0x76) MAPI call
+ * Add IDL for SyncUploadStateStreamEnd (0x77) MAPI call
+ [r551]
+ merge from mapiproxy branch:
+ * Add IDL for SyncImportDeletes (0x74) MAPI call
+ [r550]
+ merge from mapiproxy branch:
+ * Add IDL for SyncImportHierarchyChange (0x73) MAPI call
+ [r549]
+ merge from mapiproxy branch:
+ * Add IDL for SyncImportMessageChange (0x72) MAPI call
+ [r548]
+ merge from mapiproxy branch:
+ * Add IDL for SyncConfigure (0x70) MAPI call
+ [r547]
+ merge from mapiproxy branch:
+ * Add IDL for RegisterOptions (0x6f) MAPI call
+
+ Note: This call is undocumented in Microsoft documentation, but MSDN
+ RegisterOptions function generates this call on the wire.
+ [r546]
+ merge from mapiproxy branch:
+ * Add IDL for Progress (0x50) MAPI call
+ [r545]
+ merge from mapiproxy branch:
+ * Add IDL for FastTransferSourceGetBuffer (0x4a) MAPI call
+ [r544]
+ merge from mapiproxy branch:
+ * Add IDL for GetPerUserLongTermIds (0x60) MAPI call
+ * Add IDL for GetPerUserGuid (0x61) MAPI call
+ * Add IDL for ReadPerUserInformation (0x63) MAPI call
+ [r543]
+ merge from mapiproxy branch:
+ * Add IDL for LongTermIdFromId (0x43) MAPI call
+ * Add IDL for IdFromLongTermId (0x44) MAPI call
+ [r542]
+ merge from mapiproxy branch:
+ * Add IDL for ModifyRules (0x41) MAPI call
+ [r541]
+ merge from mapiproxy branch:
+ * Add PT_SRESTRICT support in mapi_SPropValue_CTR
+
+ * Add PT_ACTIONS and RuleAction support in mapi_SPropValue_CTR
+
+ * Fix mapi_SNotRestriction NDR push routine - add a wrapper to
+ work around the no-pointer deep recursion pb and remove
+ existing nopull,nopush,noprint code from ndr_mapi.c
+
+ * Fix mapi_SComment_Restriction IDL
+
+ [r540]
+ - Introduce PT_MV_UNICODE support in mapi_SPropValue_CTR (IDL only)
+ - use mapi_LPWSTR for PT_MV_UNICODE
+ - rename mapi_LPWSTR structure to mapi_name in Kind structure and
+ change its field names.
+ [r536]
+ - Fix emsmdb version
+ - Change MAPI opnum enum identation -- Helps to fine down merging from
+ mapiproxy branch
+ bradh
+ [r539]
+ API docs typo fix.
+ [r538]
+ Minor API documentation fixes.
+ [r537]
+ Update label to reflect SetReadFlags -> SetMessageReadFlag
+ renaming.
+
+ This should have been part of r529 - missed it.
+2008-05-30
+ jkerihuel
+ [r535]
+ merging from mapiproxy branch:
+ - Fix MV_UNICODE_STRUCT and unicode strings
+ - Keep LPWSTR for exchange_nsp and move from LPWSTR to
+ mapi_LPWSTR for exchange_emsmdb
+ - Add the NspiGetTemplateInfo IDL
+ - Fix the NspiUpdateStat IDL
+ [r534]
+ Fix build: SetMessageReadFlag function name was not propagated in the
+ module_oxcmsg.c
+ bradh
+ [r529]
+ Initial merge of changes for rename of SetReadFlags to
+ SetMessageReadFlags (op 0x11) and IDL for SetReadFlags
+ (op 0x66).
+ [r528]
+ Use private_data instead of private, for C++ happiness.
+ [r527]
+ Minor cleanup. Using "try" confuses my c++ compiler...
+ [r526]
+ This is really part of r525. It moved to IMAPITable.c
+ [r525]
+ Update the table operations:
+ - implement ExpandRow and CollapseRow
+ - implement GetCollapseState and SetCollapseState
+ - add mapitest coverage for the above, plus the Restrict call
+ - implement ResetTable
+ - implement FreeBookmark
+ - add mapitest coverage for SRowSet parsing code
+ - minor IDL fixes
+ - various API documentation bits
+ jelmer
+ [r533]
+ Use right directory for samba4_ver.sh script.
+ [r532]
+ Use common location for Samba 4 git revision.
+2008-05-27
+ bradh
+ [r522]
+ Use PT_ERROR where appropriate.
+ [r521]
+ Update the SRowSet parser, fixing breakage I introduced.
+2008-05-26
+ bradh
+ [r518]
+ Update examples to reflect recent API changes.
+ jelmer
+ [r520]
+ Don't rely on absolute file paths since the distribution may be installing
+ in other locations.
+ [r519]
+ make scripts executable.
+2008-05-25
+ bradh
+ [r515]
+ Avoid segfaulting if you ask for a specific test or tests and
+ forgot to start the server.
+
+ Here is an example:
+ [bradh at conferta trunk]$ ./bin/mapitest --mapi-calls=OXCTABLE-CATEGORY --mapi-calls=OXCTABLE-RESTRICT --mapi-calls=NOSERVER-LZFU
+ Failed to connect host 192.168.11.77 on port 135 - NT_STATUS_HOST_UNREACHABLE
+ Failed to connect host 192.168.11.77 (192.168.11.77) on port 135 - NT_STATUS_HOST_UNREACHABLE.
+ MapiLogonEx : MAPI_E_RESERVED (0xFFFFFFFF)
+ #############################[mapitest report]#################################
+ [*] Date : Sun May 25 11:45:29 2008
+ [*] Confidential mode : [no]
+ [*] Samba Information : 4.0.0alpha4-GIT-44d8b70
+ [*] OpenChange Information : 0.8-SVN-build-510 (Romulus)
+
+ [*] System Information :
+ Kernel name : Linux
+ Kernel release : 2.6.23.17-88.fc7
+ Processor : x86_64
+ ###############################################################################
+
+
+ [*] NOSERVER-LZFU
+ [TEST] NOSERVER-LZFU
+ ------------------------------------------------------------------------
+ * uncompress_rtf2 : 0x00000000
+ * uncompress_rtf2 : PASSED
+ ------------------------------------------------------------------------
+ [RESULT] NOSERVER-LZFU: [SUCCESS]
+ ========================================================================
+
+ [*] OXCTABLE-RESTRICT
+ Server is offline, skipping test: "OXCTABLE-RESTRICT"
+ [*] OXCTABLE-CATEGORY
+ Server is offline, skipping test: "OXCTABLE-CATEGORY"
+2008-05-24
+ bradh
+ [r510]
+ ignores objects that contain invalid handlers in mapi_object_release().
+
+ Patch by Alan Alvarez. Compile tested, passes mapitest on SBS2003.
+2008-05-23
+ bradh
+ [r507]
+ Fix API documentation to match signature.
+2008-05-20
+ bradh
+ [r504]
+ Update QueryRows IDL and implementation to match
+ msdn documentation.
+
+ The main work here is reworking the SRowSet parsing
+ routine.
+2008-05-18
+ bradh
+ [r501]
+ Typo fix - allow cleanup to work properly.
+2008-05-17
+ bradh
+ [r497]
+ Make sure it has a return value.
+2008-05-11
+ bradh
+ [r495]
+ Rename GetColumns remote operation to GetColumnsAll, and
+ fix up IDL and implementation to match.
+
+ Add some more unit test coverage, and pretty-up the
+ output a little.
+ [r494]
+ Fix up breakage introduced in r493.
+ jelmer
+ [r496]
+ Make sure nagios directory gets created if it didn't exist yet.
+2008-05-10
+ bradh
+ [r493]
+ Refactor the unit tests.
+
+ Extract out the setup and some of the cleanup code.
+2008-05-08
+ jkerihuel
+ [r490]
+ - Update openchange code to work with Samba4 4.0.0alpha4-GIT-44d8b70
+ - Use event_context structure
+ - update installsamba4.sh script to revert to this revision.
+ - update torture modulesdir reference
+ jelmer
+ [r492]
+ Look a little bit harder for the Samba installation.
+2008-05-05
+ jkerihuel
+ [r489]
+ - Add GetLocalReplicaIds MAPI call (IDL + implementation + mapitest)
+ - Add OXCFXICS mapitest module
+2008-05-03
+ jkerihuel
+ [r488]
+ - Fix "the very secret" openchange coding style
+ - Add Copyright for our humble new libmapi developer ;-)
+ bradh
+ [r487]
+ Implement the CopyProperties operation, including
+ a mapitest for this.
+2008-05-02
+ jkerihuel
+ [r485]
+ - Add TransportSend MAPI call (IDL + implementation + mapitest). This
+ code maybe needs some review regarding memory.
+ [r484]
+ - Add the GetTransportFolder MAPI call (IDL + implementation +
+ mapitest)
+ [r483]
+ - Add SpoolerLockMessage MAPI call (IDL + implementation + mapitest)
+ [r482]
+ - Add SetSpooler MAPI call (IDL + implementation + mapitest)
+ [r481]
+ - Add GetRulesTable (IDL + implementation + mapitest)
+ - Add the OXORULE mapitest suite
+ bradh
+ [r480]
+ Typo fix.
+ jelmer
+ [r486]
+ Make sure config.mk is the last file removed during distclean.
+2008-05-01
+ jkerihuel
+ [r479]
+ - Add the Abort MAPI call (IDL + implementation)
+
+ OpenChange doesn't support yet asynchronous operation which explains
+ why no associated mapitest test has been implemented. This should be
+ done in the future.
+ [r478]
+ - Add the MoveFolder MAPI call (IDL + implementation + mapitest)
+ - Fix some typo in mapitest doxygen
+ [r477]
+ - Add MoveFolder MAPI call (IDL + implementation + mapitest)
+ - Fix some doxygen stuff
+ - add a common function within mapitest which looks for a folder name
+ within a container and return the opened folder object on success.
+ [r476]
+ Add auto-generated Doxyfile to the svn ignore list
+ [r475]
+ - Add AbortSubmit MAPI call (IDL + implementation + mapitest)
+ [r473]
+ - Uninitialize MAPI and general memory context at the end of mapitest
+ bradh
+ [r474]
+ Clean up / flush the stream after use.
+
+ Saves a bit more "still reachable" in valgrind too.
+2008-04-30
+ jkerihuel
+ [r470]
+ - Rename CopyMessages to MoveCopyMessages
+ - Improve IDL + implementation and mapitest added
+ bradh
+ [r471]
+ Make sure the version shown for mapitest documentation
+ is automatically set to match the package version.
+ [r468]
+ complete the rest of the API documentation autonumbering.
+ jelmer
+ [r472]
+ Remove duplicate use of $(SHLIBEXT).
+ [r469]
+ Avoid parallel builds for now.
+2008-04-29
+ jkerihuel
+ [r467]
+ Fix GetContentsTable binding in perl swig
+ [r466]
+ - Improve the GetHierarchyTable and GetContentsTable IDL and public
+ IDL implementation (new parameters in,out)
+ bradh
+ [r465]
+ Initial part of automatic list numbering for doxygen comments.
+
+ This doesn't work correctly with the current apidocs.css, which
+ turns the list numbers into bullet points for reasons I don't
+ understand.
+2008-04-28
+ jkerihuel
+ [r464]
+ - Improve the DeleteMessages IDL request
+ [r463]
+ - Update libmapi version from 0.7 to 0.8
+
+ - Public API change for the GetReceiveFolder function; now takes a
+ message class as 3rd parameter.
+ [r458]
+ - Improve GetSearchCriteria request IDL (unknown removed)
+ - update libmapi copyright headers 2007 -> 2007-2008.
+ [r457]
+ - Improve the SubmitMessage IDL
+ - minor indentation fixed in IMessage.c
+ [r456]
+ - Add CopyToStream MAPI call (IDL + implementation + mapitest)
+ [r455]
+ - Add SeekStream MAPI call (IDL + implementation + mapitest)
+ - Add SetStreamSize MAPI call (IDL + implementation + mapitest)
+ [r454]
+ - Add CommitStream MAPI call (IDL + implementation + mapitest)
+ - Add GetStreamSize MAPI call (IDL + implementation + mapitest)
+ - refactor the stream test to include all stream related operations
+ - add a common function which generates a random ASCII blob of data
+ bradh
+ [r453]
+ Add doxygen support for the mapitest examples.
+ jelmer
+ [r459]
+ Allow cleaning individual parts.
+2008-04-27
+ jkerihuel
+ [r452]
+ - Add GetStatus call (IDL + implementation + mapitest)
+ [r451]
+ - Fix format string problem in mapitest headers
+ [r450]
+ Run offline suites by default.
+ [r449]
+ - Introduce the online/offline mode for suite
+ - Fix Exchange headers print bug when server is offline
+ - reset errno to 0 before running new test
+ bradh
+ [r447]
+ Install the libmapiadmin.h header.
+ [r446]
+ Fix a compile-time warning on amd64, for the second
+ argument to the getline() call - incompatible pointer
+ type.
+
+ I'm assuming that size_t is equivalent to uint32_t
+ on a 32-bit architecture, but not on a 64-bit arch.
+
+ A quick test showed no difference in actual output.
+ jelmer
+ [r448]
+ Remove bashisms in installsamba4.sh
+2008-04-26
+ jkerihuel
+ [r445]
+ - Add ReadRecipients MAPI call (IDL + implementation + mapitest)
+ - Improve some ModifyRecipients and Recipients structure naming
+2008-04-25
+ jkerihuel
+ [r444]
+ - Add RemoveAllRecipients call (IDL + implementation + mapitest)
+ [r443]
+ - Add OpenPublicFolderByName call added (IDL and implementation).
+
+ - Note: the reply IDL doesn't handle Server and ServerCount yet.
+
+ - Note: this call only refers to NNTP folders (e.g: folders located
+ within "Internet Newsgroups". If developers use this call within "All
+ Public Folders", then the call with return MAPI_E_NOT_FOUND.
+
+ - Call not added to mapitest cause it require RightsAuthor permissions
+ on Internet Newsgroups which is not the case by default.
+
+ - dump-data and debug options added to mapitest
+ - FOLDER suite renamed to OXCFOLD (naming convention)
+ [r441]
+ Rename module folder to oxcfold
+ [r440]
+ Replace the existing mapitest tool with a new implementation. It is
+ less complete but more modular.
+ jelmer
+ [r442]
+ Add proto headers to ignore file.
+2008-04-20
+ jkerihuel
+ [r438]
+ OpenFolder request: replace unknown field with OpenModeFlags
+ [r437]
+ - Rename 0xFE opnum from OpenMsgStore to Logon
+ - Update the Logon request IDL
+ bradh
+ [r439]
+ Add BEGIN_DECLS for private_proto.h.
+ [r436]
+ Add forgotten part of rev435.
+ [r435]
+ Add unit test framework for compressed RTF decoding.
+
+ Refactor lzfu.c to improve testability.
+2008-04-19
+ jkerihuel
+ [r434]
+ Fix openchangeclient --mailbox --pf with wasn't launched anymore due
+ to some incorrect sanity check tests.
+ [r433]
+ - Remove deprecated fuzzer_msgstore torture test
+ - replace mapi_flags with logon_id in EcDoRpc_MAPI_REQ
+2008-04-16
+ bradh
+ [r432]
+ A couple of minor fixes to make it read better.
+ jelmer
+ [r431]
+ properly clean up sofiles
+ [r430]
+ Import exchange nagios check script by Bill Edmunds.
+ [r429]
+ Add support for creating libocpf soname symlink.
+ [r428]
+ Use standard include for uint64_t definition.
+ [r427]
+ Cleanup talloc and tdb before building samba4.
+2008-04-14
+ jkerihuel
+ [r426]
+ Check for ocpf_set_Recipients retval (MAPI_E_NOT_FOUND)
+ [r425]
+ - Reset ocpf to NULL after release so the ocpf_init/release couple can be called more than once.
+ - Sanity check on recipient, avoid parsing if no recipient is set. Return MAPI_E_NOT_FOUND instead.
+ [r424]
+ Add reference to the ocpf lib within the pc file.
+2008-04-09
+ jelmer
+ [r423]
+ Remove duplicate SWIG instructions (already covered by stdint.i).
+ [r422]
+ Ignore files created by swig.
+ [r421]
+ Use config.mk in swig/perl/Makefile.
+ [r420]
+ Allow sambaprefix and prefix to be different. Allow building with unknown
+ Samba git revisions (will still warn though).
+ [r419]
+ Add --with-samba argument to configure so samba and openchange can be installed in different directories.
+2008-04-08
+ jkerihuel
+ [r418]
+ Add domain to the mapiprofile dump output.
+ [r417]
+ Fix OpenMessage IDL and GetRecipientTable fetched data
+
+ -This line, and those below, will be ignored--
+
+ _M trunk
+ M trunk/exchange.idl
+ M trunk/libmapi/IStoreFolder.c
+ M trunk/libmapi/emsmdb.c
+ M trunk/libmapi/IMessage.c
+2008-04-07
+ jelmer
+ [r416]
+ Fix typo, change samba-config -> samba-hostconfig.
+2008-04-06
+ jkerihuel
+ [r415]
+ - Add openchangepfadmin to make install
+ - Add openchangemapidump and locale_codepage to make clean
+2008-04-05
+ jelmer
+ [r413]
+ Merge the samba4-latest branch.
+2008-04-03
+ jkerihuel
+ [r408]
+ Revert so version number to 0.7
+ [r407]
+ Fix Perl bindings: update mapidump_message
+ [r405]
+ ** Start libmapi-0.8 ROMULUS development **
+ [r402]
+ Add ChangeLog and apidocs to the releases
+ [r400]
+ - Delete unmaintained regression suite
+ - Fix typo error in torture-clean rule
+ [r399]
+ Add modified release script originally from abartlett/samba4
+ [r398]
+ - Check for specific Samba4 git revision in configure.ac
+ - Prefix locale functions with lcid and make them _PUBLIC_
+ bradh
+ [r406]
+ API documentation update.
+ jelmer
+ [r403]
+ Fix some typos.
+2008-04-02
+ jkerihuel
+ [r397]
+ Add installation script for samba4
+ [r396]
+ - Apply the nspi pointer patch - make openchange works with
+ samba4-alpha3 git 41309dc
+
+ - update howto.txt
+ bradh
+ [r390]
+ Move the top level API documentation to an "overview"
+ section and add a redirect to that overview.
+
+ This keeps the doxygen output more nicely separated for
+ packaging.
+
+ Also, generate the man pages where the install expects
+ to find them.
+2008-04-01
+ jkerihuel
+ [r388]
+ - Fix strsep bug in openchangeclient
+ - Add RECIPIENT support to libocpf
+ [r383]
+ - escape/unescape strings support added
+ - PT_MV_STRING8 type added to OCPF write API
+2008-03-31
+ jkerihuel
+ [r382]
+ - return MAPI_E_NOT_FOUND if NspiGetMatches doesn't return any results
+ (based upon patch from lofi at mountproc.org)
+ - makes the workstation parameter of mapiprofile optional (use
+ gethostname if not defined by the user on command line)
+ [r381]
+ - Fix an allocation memory problem in cast_SPropValue
+ - update svn:ignore proplist
+2008-03-30
+ jkerihuel
+ [r380]
+ Update the documentation build so it keeps generating an embedded
+ website in with apidocs/html as root directory.
+ [r378]
+ - Add support for PT_UNICODE and PT_SHORT to libocpf
+ - Initial implementation of the libocpf write API
+ - Update libocpf documentation
+ - add --ocpf-dump option in openchangeclient
+ - Fix realdistclean rules for server
+ - add cast_SPropValue function to libmapi/property.c which cast
+ mapi_SPropValue to SPropValue
+ bradh
+ [r379]
+ Split API documentation into two separate sections - one
+ for libmapi and one for libocpf.
+
+ Also add in a top level intro page.
+2008-03-27
+ jkerihuel
+ [r376]
+ New build system which gathers a list of things that can be built with
+ the libraries/utilities the user has installed and build that when
+ "make all" is run.
+2008-03-26
+ jkerihuel
+ [r375]
+ Add missing allocation for OLEGUID
+ [r373]
+ --ocpf-syntax doesn't require MAPI to be initialized. Furthermore
+ makes ocpf-syntax "exclusive" (quit after performing the operation).
+ bradh
+ [r372]
+ r371 was bad. What was I thinking with that nonsense!
+
+ Revert to something sane.
+ [r371]
+ Make the ./bin/ directory if it doesn't exist.
+
+ This should resolve ticket #33.
+2008-03-23
+ bradh
+ [r370]
+ Improve language handling when creating profiles.
+
+ You can now get a list of valid languages and use either
+ the language code ID or the language name to specify what
+ language later versions of Exchange should reply with.
+ [r369]
+ Typo fix - duplicate ; at the end of the structure.
+ [r368]
+ Match format to unsigned int argument.
+ [r367]
+ Make the format specifier match the unsigned argument.
+2008-03-22
+ jkerihuel
+ [r366]
+ propset svn:ignore update
+ [r365]
+ Update propset svn:ignore on doc/examples and libocpf targets
+ [r364]
+ - Fix ticket #29: http://trac.openchange.org/ticket/29
+
+ - use access(2) to see if the database already exists
+ - test if the profile already exists prior trying to add it
+ - add descriptive error messages
+ - catch CTRL-C signal and run a profile deletion routine
+ bradh
+ [r363]
+ Update API documentation for ocpf_nproperty_add().
+ [r362]
+ Typo fix.
+2008-03-16
+ jkerihuel
+ [r361]
+ Fix mapidump_message call parameters
+2008-03-13
+ jkerihuel
+ [r360]
+ Add fid/mid parameters to mapidump_message and changed
+ openchangeclient_fetchitems to reflect these changes.
+ [r359]
+ Patch from Brad Hards <bradh at frogmouth.net>:
+ updates the OCPF doxygen file.
+ [r358]
+ Patch from Brad Hards <bradh at frogmouth.net>:
+ adds the doc/examples into the build system and enables make examples.
+ [r357]
+ Patch From Brad Hards, <bradh at frogmouth.net>:
+ API documentation update and minor fix for the error value change.
+2008-03-09
+ jelmer
+ [r355]
+ Update bzr ignores.
+2008-03-06
+ jkerihuel
+ [r354]
+ - Add PT_BINARY property support to OCP
+ - Add stream support to OCPF for large PT_BINARY blobs.
+ - Fix a bug which prevented from having no/empty PROPERTY or NPROPERTY
+ sections.
+2008-03-05
+ jkerihuel
+ [r353]
+ - Prevent from assigning a value which type doesn't match with
+ the property one.
+ - Add missing substitution variable support for some named properties
+ declaration
+ - Improve sample_appointment.ocpf example
+ - Add PT_MV_STRING8 keyword to the list of supported property type
+ identifiers.
+2008-03-04
+ jkerihuel
+ [r352]
+ Improve OCPF PT_MV_STRING8 support.
+ [r351]
+ - Initial revision for libocpf and its documentation
+ - YACC support added to the build system
+ - custom lid and string support in mapi_nameid
+ - lookup functions added for OOM, lid and string
+ - OCPF commands added to openchangeclient (ocpf-file, ocpf-syntax,
+ ocpf-sender)
+ - PR_FID displayed in openchangeclient --mailbox
+ - PT_MV_STRING8 support added to cast_mapi_SPropValue
+2008-03-02
+ jkerihuel
+ [r350]
+ Patch from Brad Hards <bradh at frogmouth.net>:
+ updates code to build with current API
+ [r349]
+ Patch from Brad Hards <bradh at frogmouth.net>:
+ little update for some API dox
+2008-02-21
+ jkerihuel
+ [r348]
+ - Add --update option to openchangeclient and allow users to modify
+ existing messages (calendar, task, contact, note)
+ - Add --delete option to openchangeclient and allow users to delete
+ existing messages (calendar, task, contact, note)
+ - Add some folder/message unique ID to mapidump outputs and send*
+ openchangeclient functions.
+ - Fix a bug in set_SPropValue: add sanity check on unicode
+ string. Thanks to Suman Manjunath for this patch.
+ - Fix mapidump_task function and identifiers of named properties used.
+2008-02-19
+ jkerihuel
+ [r347]
+ Fix missing sanity check on priority
+ [r346]
+ Fix a bug in openchangeclient when tasks are created without body
+ [r345]
+ private flag added to openchangeclient appointments
+ [r344]
+ Fix folder IDs problem for Exchange 2007 SP1
+2008-02-09
+ jkerihuel
+ [r343]
+ Fix names IDL against Samba4 4.0.0alpha3-GIT-41309dc
+2008-01-24
+ jkerihuel
+ [r342]
+ - Fix a bug in IStoreFolder.c:OpenMessage which was also affecting
+ GetRecipientTable. We were extending SPropTagArray prior calling
+ emsmdb_get_SRow. This was causing ndr_pull_error in OpenMessage_repl
+ and erroneous data to be inserted in the SRow.
+
+ - Fix libmapi/socket/interface.c:
+ - Use the latest version from Samba4 which removes reference to
+ global_loadparm.
+ - Moves struct interface declaration to netif.h
+ - Report changes to emsmdb.c notification functions.
+
+ - Change GetGALTable prototype to match general libmapi policy. Remove
+ the usage of bool and replace it with uint8_t. Possible values added
+ to mapidefs.h
+2008-01-22
+ jkerihuel
+ [r341]
+ - Improve NspiQueryRows IDL and implementation
+ - Add GetGALTable implementation: fetch all the Global Address List
+ recipients
+ - Add --userlist option to openchangeclient
+ - Add a convenient and basic dumping function for Global Address List
+ recipients.
+ [r340]
+ - Improve OpenMessage reply IDL
+ - Fetch mapi recipients from OpenMessage reply
+ - Add GetRecipientTable convenient function
+ - Add OPENCHANGE-MAPI-RECIPIENT torture test to test
+ GetRecipientTable implementation.
+ - Add convenient SPropTagArray_add function
+ - Add internal emsmdb_get_SRow routine
+2008-01-21
+ jkerihuel
+ [r339]
+ Patch from Suman Manjunath <msuman at novell.com>:
+
+ - Adds named-properties which define recurrence patterns for
+ appointment and task.
+ - Adds named properties for appointment timezone
+ [r338]
+ - Fix the SNotRestriction IDL and write custom push,pull,print
+ functions
+ - Add 2 new MAPI calls to the IDL:
+ * GetSearchCriteria,
+ * SetSearchCriteria
+ - add sample {Get,Set}SearchCriteria torture test
+ - add convenient mapi_id_array implementation
+ - add GetDefaultFolder support for CommonView and Finder folders
+2008-01-20
+ jelmer
+ [r337]
+ Make sure directory exists.
+2008-01-18
+ jkerihuel
+ [r336]
+ - Fix tiny 'nail down samba4 version' bug
+ - update the minimal Samba4 required version
+ [r335]
+ - Add FindRow call to the IDL
+ - Improve mapi_Restriction support
+ - Remove deprecated ndr_print_QueryRows function
+ - Add a print function for fuzzyLevel
+ - Add preliminary FindRow implementation test to MAPI-RESTRICTIONS
+ torture test
+ - Add couple of new MAPI tags to mapi-properties
+ - change initial bookmark index to 3
+2008-01-16
+ jkerihuel
+ [r334]
+ - Add 2 new MAPI calls to the IDL and mapitest:
+ * SetReceiveFolder
+ * GetReceiveFolderTable
+
+ - Fix a bug in the SortTable test when no messages are returned by
+ QueryRows
+ [r333]
+ - Add SeekRowApprox to the IDL and mapitest
+ - Fix some doxygen typo
+ [r332]
+ - New calls added to the IDL, torture suite and mapitest:
+ * CreateBookmark
+ * SeekRowBookmark
+ - Internal mapi_object_bookmark_t implementation added to
+ mapi_object_table_t
+ - SBinary_short default ndr_print function changed to custom
+2008-01-14
+ jkerihuel
+ [r331]
+ Temporary fixes unexpected segfault in SortTable test. Emails sent
+ during the Submit test have sometimes not yet been dispatched when the
+ SortTable test begins. This fix adds a sleep(1) and an arbitrary
+ number of attempts (5).
+ [r330]
+ Add 2 new MAPI calls to the IDL and libmapi:
+ * AddressTypes
+ * SortTable
+
+ Tests for SortTable added to mapitest and the torture suite
+ Test for AddressTypes added to mapitest.
+2008-01-13
+ jkerihuel
+ [r329]
+ Fix perl bindings and fetchmail test
+ [r328]
+ 2 new MAPI call added to the IDL and mapitest:
+ * GetMessageStatus
+ * SetMessageStatus
+2008-01-11
+ jkerihuel
+ [r327]
+ - Add DeleteAttach MAPI call
+ - Add new mapi unit tests:
+ * QueryColumns
+ * CreateAttach
+ * SaveChanges
+ * GetAttachmentTable
+ * DeleteAttach
+ - Update mapitest README
+ - Add some convenient functions to mapitest_common.c
+2008-01-10
+ jkerihuel
+ [r326]
+ Add a preliminary draft of the mapitest standalone MAPI test suite.
+2008-01-05
+ jkerihuel
+ [r324]
+ Add missing files
+ [r323]
+ - Fix the build with the latest Samba4 version.
+
+ - Add a basic libmapi/version.h auto-generated
+ file (based on Samba4 one)
+ - Remove some warnings when compiling the utf8
+ lexer
+ - Add a emsmdb_info structure to fetch some
+ information from the Exchange server
+
+ WARNING: Please note that EMSABP is definitely broken and
+ requires a review and update.
+ jelmer
+ [r325]
+ DESTDIR should never get into any source files, that would defeat its purpose.
+2008-01-04
+ jkerihuel
+ [r322]
+ Fix the torture suite.
+2007-12-28
+ jelmer
+ [r321]
+ provide extra required argument.
+ [r320]
+ Store a loadparm context in the global mapi context.
+ [r319]
+ Deal with samba version.h's that don't contain the Subversion revision.
+2007-12-15
+ jelmer
+ [r318]
+ Use SWIG-provided typemaps for stdint.
+2007-11-29
+ ali
+ [r317]
+ Fix Content-Type field in exchange2mbox
+ Reported by Yuriy Filatov <yuriy.filatov at gmail.com>
+2007-11-28
+ jkerihuel
+ [r316]
+ - Improve the CreateMessage IDL
+ - Add new parameters to IMAPIFolder CreateMessage libmapi function
+ - Add --mkdir --rmdir options to openchangeclient
+ - Update the CreateFolder API and openchangeclient documentation
+ - Fix CreateFolder calls in openchange tools and torture suite
+ - Fix gendb_search warning
+2007-11-25
+ jkerihuel
+ [r315]
+ Add new PSETID_Address named properties
+ [r314]
+ Fix a few code convention typos
+
+ Patch from Suman Manjunath <msuman at novell.com> applied:
+ converts a 'struct timeval' to 'NTTIME'.
+ minor extension of 'set_SPropValue_proptag', used while setting PT_SYSTIME properties.
+2007-11-21
+ jkerihuel
+ [r313]
+ update Samba4 first revision to 26100
+ jelmer
+ [r312]
+ Cope with ndr updates.
+2007-11-12
+ jkerihuel
+ [r311]
+ Patch from Brad Hards: Fix possible Heap overflow in lzfu code
+2007-11-07
+ jkerihuel
+ [r310]
+ Fix profile creation in a clustered Exchange 2007 environment.
+2007-11-02
+ jkerihuel
+ [r309]
+ Fix QueryColumns req size.
+2007-11-01
+ jkerihuel
+ [r308]
+ ** Start libmapi-0.7 PHASER development **
+
+ add --dump-data option to mapiprofile for debugging purpose
+2007-10-31
+ jkerihuel
+ [r306]
+ openchangepfadmin (1) man page added
+ [r305]
+ Store messageID in the object when SaveChangesMessage is called
+ [r304]
+ Nail down Samba4 version for libmapi-0.6
+2007-10-30
+ jkerihuel
+ [r303]
+ - Add PR_MSG_EDITOR_FORMAT property to the sendmail operation
+ - Fix body dump bug when PR_MSG_EDITOR_FORMAT property is missing (default set to PLAINTEXT)
+ - Continue to process the mailbox when a problem is encountered with mesage contents (not attachment)
+ - Fix a typo bug in openchangeclient body help string
+ [r302]
+ Update doxygen section
+2007-10-29
+ jkerihuel
+ [r301]
+ - Add doxygen man (3) pages to installman and uninstallman rules
+ - do not run doxygen if apidocs already exists
+2007-10-28
+ jkerihuel
+ [r300]
+ Move documentation to doxygen
+2007-10-25
+ jkerihuel
+ [r299]
+ Add convenient date related functions for implementors:
+ returns a timeval struct matching a PT_SYSTIME property
+ for improved date manipulation in 3rd party softwares
+2007-10-24
+ jkerihuel
+ [r298]
+ Fix build to work with latest Samba4 revision (4.0.0alpha2-SVN-build-25722)
+ [r297]
+ Fix make realdistclean when swig perl is enabled
+ [r296]
+ Fix swig perl bindins compilation: move *.o to *.po
+ [r295]
+ use talloc_memdup to copy const data in the body DATA_BLOB
+ Should only provide valid pointer to talloc_free
+2007-10-23
+ jkerihuel
+ [r294]
+ Fix the DeleteMessages [out] IDL.
+
+ The remaining bytes were not part of DeleteMessages but
+ MAPI notification (0x2a)
+2007-10-22
+ jkerihuel
+ [r293]
+ - Add RTF support in exchange2mbox
+ - Use openchange-tools public functions
+ - Replace GetPropsAll calls with GetProps
+ [r292]
+ - fetchmail:
+ * Use GetProps rather than GetPropsAll for message dump
+ * Rely on PR_MSG_EDITOR_FORMAT to select the type of body
+ * Open a stream for PR_BODY and PR_HTML if the size exceeds max property size
+
+ -This line, and those below, will be ignored--
+
+ M trunk/Makefile.in
+ A trunk/utils/openchange-tools.c
+ M trunk/utils/openchangeclient.c
+ M trunk/utils/openchange-tools.h
+ M trunk/utils/openchangeclient.h
+ M trunk/libmapi/mapidefs.h
+2007-10-20
+ jelmer
+ [r291]
+ Fix ignores.
+2007-10-19
+ ali
+ [r290]
+ Remove useless svn:ignore
+ jkerihuel
+ [r289]
+ Add WrapCompressedRTFStream function for PR_RTF_COMPRESSED content.
+
+ Original lzfu decompress routine fetched from libpst-0.5.2
+ [r288]
+ make enum MAPISTATUS variables naming uniform in libmapi
+2007-10-16
+ jkerihuel
+ [r287]
+ Add PT_CLSID case to get_SPropValue_data
+ [r286]
+ Add/Fix pull property support for PT_UNICODE and PT_CLSID (used by GetProps)
+ [r285]
+ Patch from Brad Hards <bradh at frogmouth.net>:
+ Fix compilation for x86_64 platforms.
+2007-10-14
+ ali
+ [r284]
+ More svn:ignore updates
+ [r283]
+ Update of svn:ignore
+2007-10-10
+ jkerihuel
+ [r282]
+ added the IDL license
+ [r281]
+ Convert OpenChange to GPLv3
+ [r280]
+ - Add .po files to make clean
+ - Fix a couple of warnings in the utf8 conversion lexer
+ - Prefer long filenames to truncated one for attachments in openchangeclient
+2007-10-09
+ jkerihuel
+ [r279]
+ Prevent exchange2mbox from segfault when PR_MESSAGE_DELIVERY_DATE is unset
+ [r278]
+ Add PT_CLSID and PT_MV_CLSID support to the IDL
+ [r274]
+ - Add new named properties
+ - Convenient function for MNID_STRING props lookup added
+ jelmer
+ [r277]
+ Make .po a recognized suffix.
+ [r276]
+ Fix compile error.
+ [r275]
+ Use -fPIC for library objects.
+2007-10-08
+ jkerihuel
+ [r273]
+ - Rename GetAllNamesFromIDs to QueryNamesFromIDs (better naming)
+ - fix SPropValue_CTR boolean to uint8_t in the IDL and emsmdb.c
+
+ - add mapi_nameid convenient interface and headers
+ - mapi-named-properties populated, parser added to mparse.pl, file
+ added to the build system
+
+ - remove any incorrect reference to named properties in openchange
+ tree
+
+ - remove deprecated libmapi/mapi.h file
+ - remove unused ulFlag parameter from IProfAdmin functions
+ - remove unused memory context from libmapi/x500.c
+
+ - support sendnote operation in openchangeclient
+ - optimize check/list oc_element functions in openchangeclient
+
+ - update swig interface
+2007-10-05
+ jkerihuel
+ [r272]
+ - New MAPI calls: Named properties support
+ * GetNamesFromIDs
+ * GetIDsFromNames
+ * GetAllNamesFromIDs
+
+ - Modified MAPI calls:
+ * OpenMessage
+ * SaveChanges
+ These calls now have more granularity in libmapi with flags support
+
+ - sample mapi-named-properties file introduced in libmapi/conf
+
+ - Torture test suite:
+ * suite temporary fixed (import torture_rpc_* functions from
+ Samba4)
+ * torture_namedprops test added
+
+ - SWIG Perl bindings fixed according to changes described above
+ - minor improvements in libmapi/mapidump.c
+2007-10-02
+ jkerihuel
+ [r271]
+ - Decrease MAX_READ_SIZE to 0x1000
+ - Clean-up Read/WritreStream related code
+ - add dump-data option to openchangepfadmin (debugging purpose)
+2007-10-01
+ jkerihuel
+ [r270]
+ Fix build:
+ - remove reference to core/nterr.h
+ - add global_loadparm reference where missing
+ - add reference to core/error.h where needed
+ jelmer
+ [r269]
+ Improve output during build.
+ [r268]
+ Fix lp_load().
+ [r267]
+ Pass loadparm contexts, should fix the build with newer Samba revisions.
+2007-09-28
+ jkerihuel
+ [r266]
+ - WriteStream API changed: now returns the number of bytes written
+ - WriteStream man page updated
+ - 16 bytes extra-data bug fixed when sending attachments in openchangeclient
+ - Set open mode to 0600 when attachments are stored on the filesystem
+
+2007-09-19
+ jkerihuel
+ [r265]
+ Fix preliminary Perl bindings so it works with Samba4 alpha2
+ and latest libmapi revision.
+ [r264]
+ Patch from Andrew Gaylard <ag at computer.org>:
+
+ - When calling openchangeclient with the --dump-data switch, it will
+ dump core, since the global_mapi_ctx pointer isn't initialised yet.
+ The fix is to wait until it's set before accessing it.
+ [r263]
+ Patch from Andrew Gaylard <ag at computer.org>:
+ - Leaving any blank lines before .TH directives appears to cause a blank page
+ to be output when converting man pages to DVI files (which is a step to converting
+ them to PDF). The following patch remove the blank line above the .TH in each man page file.
+
+ - mapiprofile doesn't understand the -A switch, as mentioned in it's man page.
+ It should be -I.
+2007-09-13
+ jkerihuel
+ [r262]
+ - Add objectClass to the object: container, message or attachment
+ - Rename content to message in openchangebackup functions
+ - add objectClass parameter to ocb_record_init
+2007-09-12
+ jkerihuel
+ [r261]
+ - Move debug options to their correct location (after MAPIInitialize)
+ - Improve code related to LDB transactions
+ - Add convenient error checking macros
+2007-09-11
+ jkerihuel
+ [r260]
+ - Add preliminary openchangemapidump draft
+ - Fix lp_parm_* 1st parameter in the torture suite
+ - New functions in property.c for MAPI data retrieval
+2007-09-09
+ jelmer
+ [r259]
+ Use configure definition for mandir.
+2007-09-08
+ dan
+ [r258]
+ Activate debugs this time
+ [r257]
+ Replaced remaining gotos with MAPI_RETVAL_IF so errno is set correctly
+ [r256]
+ MAPI_RETVAL_IF missing ";" could cause surprises ;-)
+ [r255]
+ Add error check for samr call.
+ set errno with MAPI_RETVAL_IF.
+2007-09-06
+ dan
+ [r254]
+ Make required packaged more clear (LinuxMagazin input)
+2007-09-05
+ jelmer
+ [r253]
+ Remove invalid comment.
+2007-09-04
+ jkerihuel
+ [r252]
+ - Clean-up function prototypes
+ - Dump email when NEWMAIL notification is received
+2007-08-31
+ jelmer
+ [r251]
+ Proper dependencies.
+ [r250]
+ Don't regenerate proto headers unless necessary.
+ [r249]
+ Add 'make check'.
+ [r248]
+ Use install for installing files/directories.
+ [r247]
+ Actually use replacement variable for libmagic.
+2007-08-30
+ jkerihuel
+ [r246]
+ Remove forgotten BOOL
+ [r245]
+ Remove mapi_session pointer in mapi_objects
+ Add public function to IProfAdmin: retrieve default ldif path location outside the OC tree
+2007-08-28
+ jkerihuel
+ [r244]
+ Prevent users from creation of *undeletable* folders in Outlook and
+ perform sanity check on dirclass + display possible values.
+ [r243]
+ Provides a way to modify Default and Anonymous permissions for a given folder.
+ [r242]
+ Fix errno in getdir function + add sanity check on opt_rmdir
+ [r241]
+ - Fix a memory related bug in mapiadmin_add_user
+ - Add latest howto.txt modifications from Dan
+ [r240]
+ - Fix bug in *UserPermission function: return when user is not found
+ - Add sanity checks to mapi_object API functions
+ - mapi_object_release reset errno to 0: need to release object
+ after displaying the potential error message.
+ [r239]
+ Fix a mapidump_appointment bug
+ Add PF folder support to fetch-items operation
+2007-08-27
+ jkerihuel
+ [r238]
+ openchangeclient now support send/read/delete operation on custom PF directories.
+ [r233]
+ - Add libmapiadmin library draft: Add/Remove Exchange user
+ - openchangepfadmin tool added: Public Folders management
+ - Add Sanity check to CreateFolder
+ jelmer
+ [r237]
+ Update ignore list.
+ [r236]
+ Fix last references to BOOL, True and False.
+ [r235]
+ Fix more references to BOOL, False and True.
+ [r234]
+ Use standard type and values for booleans since Samba no longer exports
+ BOOL, True and False.
+2007-08-21
+ jkerihuel
+ [r232]
+ - Add OpenPublicFolder function to libmapi, Open Public Folder store
+ - change torture suite API to match latest Samba4 pidl changes
+ - utf8_convert regexp improved
+ - minor changes: printf to DEBUG
+ - howto.txt patch from Dan included
+ - Samba4 torture code related to user account creation included in the
+ torture suite.
+2007-08-06
+ jkerihuel
+ [r231]
+ Fix segmentation fault when running update prior populating the database.
+2007-07-31
+ jkerihuel
+ [r230]
+ Remove obsolete file from the torture suite
+ [r229]
+ - Add Exchange Administration test to the torture suite: Create Exchange user
+ [r228]
+ Dan update on howto.txt
+2007-07-10
+ jkerihuel
+ [r227]
+ - Add Exchange ACLs support to MAPI library
+ - Add 2 new MAPI opnum: GetTable and ModifyTable
+ - Improve mapidump functions
+2007-07-04
+ jkerihuel
+ [r226]
+ - Improve aclocal check in autogen.sh
+ - Fix flex binary detection in configure.ac
+2007-06-22
+ jkerihuel
+ [r225]
+ Same player ...
+ [r224]
+ Fix libmapi symlink
+ [r223]
+ Create libmapi.so symlink
+2007-06-21
+ jkerihuel
+ [r222]
+ Fix mandir installation path
+ Add ldconfig intructions to openchange installation documentation
+ [r221]
+ Fix build.
+2007-06-20
+ jkerihuel
+ [r220]
+ RES_AND and RES_OR preliminary implementation.
+2007-06-19
+ jkerihuel
+ [r218]
+ - doc patch from Brad Hards
+ - rename PROFILE_NOPASSWORD to OC_PROFILE_NOPASSWORD
+ - fix a warning in property.c
+2007-06-16
+ jelmer
+ [r210]
+ Add some 'const' (fixes compile warnings).
+ [r209]
+ Use sonames (required for the Debian packages).
+ [r208]
+ Add .bzrignore file.
+ [r207]
+ Update version number and use globally defined version number in libmapi.pc.
+2007-06-15
+ jkerihuel
+ [r205]
+ - Add IDL implementation for restrictions Content, Property,
+ CompareProps, Bitmask, Size, Exist.
+ - Add Restrict MAPI call handling the restrictions above
+ - OPENCHANGE-MAPI-RESTRICTIONS torture test added to the suite.
+ - convenient sendmail function added to mapi_common.c
+ - get property size function for mapi_SPropValue added to property.c
+
+ test --This line, and those below, will be ignored--
+
+ M Makefile.in
+ M exchange.idl
+ M torture/openchange.c
+ A torture/mapi_restrictions.c
+ M torture/mapi_common.c
+ M libmapi/property.c
+ M libmapi/IMAPITable.c
+2007-06-11
+ jkerihuel
+ [r204]
+ Documentation update: Perl bindings installation
+2007-06-10
+ jkerihuel
+ [r203]
+ - Add mapitags and mapicode support to Perl SWIG bindings
+ - SPropTagArray support
+ - SRowSet preliminary support
+ - new constructor/destructor for mapi objects
+2007-06-09
+ jkerihuel
+ [r202]
+ - IProfAdmin patch applied: having password outside of the profile
+
+ - Perl bindings draft added to the trunk and to the build system:
+ --enable-swig-perl=yes
+
+ - datarootdir fixed in libmapi.pc.in
+2007-06-06
+ jkerihuel
+ [r201]
+ - Add CopyMessages IDL and COPYMAIL torture implementation
+ - Fix man page install dir according to latest Samba4 changes
+ - Add datarootdir var to libmapi.pc.in and fix configure warning
+2007-06-01
+ jkerihuel
+ [r199]
+ convenient function which retrieve a value from a SPropValue array
+ given its property tag name, otherwise NULL
+2007-05-31
+ jkerihuel
+ [r198]
+ Patch from Brad Hards <bradh at frogmouth.net>:
+ openchangeclient man page updated
+ [r197]
+ - Add Windows UTF8 to classic UTF8 conversion through a lexer
+ - openchangeclient --mailbox option changed to use it
+ - flex and bison support added to configure.ac
+ - windows_to_utf8 function added: wrapper over yyparse_utf8 routine
+2007-05-29
+ jkerihuel
+ [r196]
+ - features added to openchangeclient:
+ * --send-appointment
+ * --send-contact
+ * --send-task
+ * custom parameters
+ - openchangeclient man page updated
+ - new properties added to mapi-properties
+ [r195]
+ - Add man pages for simple_mapi.c functions:
+ * GetDefaultFolder
+ * GetFolderItemsCount
+ [r194]
+ - Remove deprecated functions from IMsgStore.c
+ - Update man pages documentation
+ [r193]
+ Fix install rule in Makefile: add missing headers
+ Move callback retval from uint32_t to int
+ [r192]
+ Fix notification callback retval
+ [r191]
+ - Advise opnum added to the IDL
+ - Parts of the Notify response IDL implementation
+ - Add Notification support to libmapi
+ - Add --notifications option to openchangeclient
+2007-05-28
+ jkerihuel
+ [r190]
+ Patch from Brad Hards <bradh at frogmouth.net>:
+ - PR_BUSINESS_FAX_NUMBER
+ - improves the information provided on a contact by
+ mapidump_contact()
+2007-05-25
+ jkerihuel
+ [r189]
+ - Fix the release call in,out
+ - Call Release from mapi_release_object
+ - Add sanity check to OpenMsgStore
+ - clean up parts of the mapi_newmail test
+ [r188]
+ EcDoDisconnect code now sounds to work properly
+ Tested against Exchange 2000 / Exchange 2003
+ [r187]
+ - Fix SpropValue property pull problem when GetProps layout is set
+ - Add a dumpdata boolean to mapi_ctx_t so tools can dump hex data
+ - Add PR_CONTAINER_CLASS fetch to openchangeclient --mailbox
+ - Add debuglevel and dumpdata options support to openchangeclient
+2007-05-24
+ jkerihuel
+ [r186]
+ - Remove useless memory allocation in mapidump.c
+ - Improve mapidump_appointment
+ - Add sample mapidump_note
+ - Add --fetchitems option to openchangeclient:
+ This command offers an easy way to fetch calendar, contacts,
+ tasks, notes and mails from the Exchange server.
+ - Add IPF container class defines to mapidefs.h
+ - Add and Fix property tags
+2007-05-22
+ jkerihuel
+ [r185]
+ - Commit the EcDoRpc max_data patch proposed on the devel list
+ - Clean up folders related functions from the torture suite
+ (GetDefaultFolder makes this code obsolete)
+2007-05-21
+ jkerihuel
+ [r184]
+ Add the --mailbox option to openchangeclient which recursively
+ lists the full mailbox folder hierarchy
+ [r183]
+ - Add PT_SYSTTIME support to get_SPropValue_data
+ - Add mapidump_SPropValue_date dumping function
+ - Add PT_SYSTIME support to mapidump_SPropValue
+ [r182]
+ - Add multi-valued SBinary_short support to mapi_SPropValue_CTR in the
+ IDL
+
+ - Add GetDefaultFolder implementation to simple_mapi.c. This function
+ provides a convenient way to retrieve default folders ID. const
+ olFolder values are stored in libmapi/mapidefs.h
+
+ - Modify the torture test suite to reflect these changes.
+
+ - OpenMsgStore now decodes all the fid returned in the response
+
+ - fix a bug size in libmapi/property.c
+2007-05-18
+ jkerihuel
+ [r181]
+ - Fix SMTP recipient in libmapi
+ - Add SMTP recipient support to openchangeclient
+ and the torture test suite
+ - Fix a bug in SRow_addprop
+2007-05-17
+ jkerihuel
+ [r180]
+ - OpenMessage IDL changed: we have a permission field.
+ It is now set by default to 0x3 (read/write) until we
+ change OpenMessage prototype.
+
+ - Add a sanity check to MAPIInitialize when no profdb
+ is specified
+2007-05-15
+ jkerihuel
+ [r179]
+ Remove remaining MAPISTATUS and replace them with enum MAPISTATUS
+ [r178]
+ - SetReadFlags IDL and implementation added to libmapi
+ - Warning fixed in emsabp.h
+ [r177]
+ Fix a bug in openchangeclient when attachments are using
+ PR_ATTACH_LONG_FILENAME rather than PR_ATTACH_FILENAME to store
+ attachment filename.
+ [r176]
+ Patch supplied by Brad Hards <bradh at frogmouth.net> which renames
+ private structure member to private_data for C++ compatibility.
+ [r175]
+ Add libmapi/simple_mapi.c designed to hold convenient
+ functions for application development.
+
+ - GetFolderItemsCount added which returns the number of
+ total and unread messages for a given folder.
+2007-05-14
+ jkerihuel
+ [r174]
+ - Fix a body openchangeclient bug which now prevent openchangeclient
+ from segfault when no body is specified.
+ - Add GetDefaultProfile call to exchange2mbox for the default
+ operation.
+ - Improve fuzzer_msgtore output
+2007-05-13
+ jkerihuel
+ [r173]
+ Add a fuzzer torture test on OpenMsgStore which
+ test all the possible max_data value.
+
+ Should help to understand if libmapi fails because
+ of max_data or not.
+2007-05-12
+ jkerihuel
+ [r171]
+ exchange2mbox improved:
+ - tdb dependency removed
+ - message-id are now stored in the profile database
+ - it now mirrors deletion operation from the mbox file back to the
+ Exchange server.
+ - man page updated to reflect these changes
+ [r170]
+ - GetProfileAttr function prototype modified. It now returns the
+ results count for the given attribute and store values in a string
+ array.
+ - GetProfileAttr man page updated to reflect these changes
+ - Fix mapiprofile attribute search command
+ - migrate from open/write calls to stream ones in exchange2mbox
+ texane
+ [r172]
+ newmail torture + notifications implementation
+
+ -- texane
+2007-05-11
+ jkerihuel
+ [r169]
+ Fix the SambaXP live demo segfault: When an ambiguous recipient is
+ specified, it now skips the name properly and maintain a correct
+ SRowSet.
+ [r168]
+ - Fix a bug when storing attachments into mbox
+ - Add default path support to exchange2mbox
+2007-05-10
+ jkerihuel
+ [r167]
+ - Update libmapi version according to the roadmap
+ - Fix nspi_resolvenames to use default profile database and profile
+2007-05-09
+ jkerihuel
+ [r166]
+ - Add default profile database and profile support in the torture suite.
+ - Fix a bug in mapidump_task
+2007-05-08
+ jkerihuel
+ [r165]
+ - Change MAPILogonEx to MAPILogonProvider and avoid potential
+ emsmdb endpoint related problem
+ - add sanity check on global session pointer
+2007-05-06
+ ali
+ [r164]
+ Merged MAILOOK-branch changes r64:163 into the trunk.
+2007-03-04
+ jkerihuel
+ [r79]
+ Remove ChangeLog, use svn log instead ;p
+2007-02-13
+ jkerihuel
+ [r63]
+ - libmapi includes moved from libmapi/include to libmapi
+ - Remove arguments from prototype definitions generation in mkproto.pl
+ - __BEGIN_DECLS __END_DECLS support in header files
+ - united libmapi/libmapi.h header file
+ - openchange.h header removed
+ - PIDL generated files moved to gen_ndr
+ - compilation rule for libmapi header installation added
+ - useless torture tests removed
+
+ jkerihuel.
+2007-02-12
+ jkerihuel
+ [r62]
+ Replace OpenProperty and ReadAttach calls with OpenStream and ReadStream call
+ Add GetAttachmentTable call
+
+ jkerihuel.
+2007-02-09
+ jkerihuel
+ [r58]
+ Remove -Werror CFLAGS until I figure out how to fix
+ our problem definitively.
+
+ Remove static from dcesrv_exchange.c functions definition
+
+ jkerihuel.
+ texane
+ [r61]
+ . reimplement GetProps
+ . retrieve attachment size
+ . modify fetchmail and fetchattach torture
+
+ -- texane
+ [r60]
+
+ . add GetPropList to exchange.idl
+ . add GetPropList implementation to IMAPIProp.c
+ -- texane
+ [r59]
+ - Add fetchattach torture; Attachment size is not yet
+ defined and 42 is used.
+ - add 3 new EcDoRpc opnums:
+ - OpenAttach
+ - ReadAttach
+ - OpenProperty
+
+ -- texane
+2007-02-08
+ jkerihuel
+ [r57]
+ Forgot to add IMAPISession.c
+
+ jkerihuel.
+2007-02-07
+ jkerihuel
+ [r56]
+ Remove spurious warnings at compile time and
+ add -Werror -Wstrict-prototypes to CC.
+
+ jkerihuel.
+ [r55]
+ Dispatch libmapi functions into filenames matching
+ the MAPI interface they belong to.
+
+ jkerihuel.
+ [r54]
+ Fix the attach issue by value and add torture test to
+ the openchange torture suite.
+
+ jkerihuel.
+ texane
+ [r53]
+ attachment torture test implementation
+
+ -- texane
+2007-02-06
+ jkerihuel
+ [r52]
+ Add a null element at the end of MAPI_REQ array
+ so we can exit from the loop in ndr_print_mapi_request
+
+ jkerihuel.
+ [r49]
+ - Add the DeleteMessages IDL
+ - New torture tests added:
+ * OPENCHANGE-MAPI-SENDMAIL
+ * OPENCHANGE-MAPI-DELETEMAIL
+
+ These are experimental implementation
+
+ jkerihuel.
+ texane
+ [r51]
+ subject option for delete message torture test
+
+ -- texane
+ [r50]
+ added (recipients == null) check
+ added default body
+ added default subject
+ -- texane
+2007-02-03
+ jkerihuel
+ [r48]
+ Add NspiResolveNames and the associated torture test.
+
+ jkerihuel.
+2007-02-01
+ jkerihuel
+ [r47]
+ Fix nspi decoding problem due to the usage of
+ a hyper instead of a dlong.
+
+ jkerihuel.
+ [r46]
+ - Add a preliminary NspiUpdateStat IDL
+ - Fix the new server code convention naming
+ (function prefixed with dcesrv_)
+ - Fix a security bug in emsabp provider code
+
+ jkerihuel.
+ [r45]
+ Fix the allocation memory for the EcDoRpc_{MAPI_REQ,MAPI_REPL} pointer.
+
+ jkerihuel.
+ [r44]
+ Add SetProps [out] support.
+
+ Temporary allocation pb fixed in ndr_pull_mapi_response.
+ Final fix in next commit.
+
+ jkerihuel.
+2007-01-31
+ jkerihuel
+ [r43]
+ Fix the SetProps [in] IDL
+
+ New mapi call support added:
+ - ModifyRecipients [in,out]
+ - SubmitMessage [in,out]
+
+ jkerihuel.
+ [r42]
+ Add IDL support for the following mapi calls:
+
+ [in] CreateMessage
+ [in] SetProps
+
+ The SetProps IDL is still experimental and the
+ content blob should be decoded more than the current
+ IDL does.
+
+ jkerihuel.
+2007-01-30
+ jkerihuel
+ [r41]
+ Fix the align problem in QueryRows reply blob
+ Add some printing output and clean useless DEBUG.
+
+ jkerihuel.
+2007-01-29
+ jkerihuel
+ [r40]
+ Fix the OpenMessage IDL and add ndr_print support
+ to the MAPI-FETCHMAIL torture test so we can
+ read information.
+
+ jkerihuel.
+ [r39]
+ Commit of the first experimental but working implementation
+ of the MAPI-FETCHMAIL torture test able to retrieve mails
+ from an Exchange Server.
+
+ jkerihuel.
+ [r38]
+ - Add a preview implementation of cached data system for multi MAPI calls requests
+ - Add SetColumns and QueryRows calls to mapi.c + mapi_fetchmail torture test
+ - Enhance some MAPI calls IDL
+ - Fix some pull/print functions according to error_code and row_count values
+
+ jkerihuel.
+2007-01-28
+ jkerihuel
+ [r37]
+ Manual handling of EcDoRpc_MAPI_REPL pull and print function.
+ When a mapi call returns an error_code different from MAPI_E_SUCCESS,
+ we have to stop processing the function IDL since no parameters follow.
+
+ jkerihuel.
+ [r36]
+ add MAPISTATUS to EcDoRpc_MAPI_REPL
+ add mapi library code for:
+ - OpenFolder
+ - Release
+ - GetContentsTable
+ - GetReceiveFolder
+
+ add mapi calls described above to MAPI-FETCHMAIL torture test
+
+ jkerihuel.
+ [r35]
+ add mapi_response to emsmdb_transaction so we can get the results
+ check the mapi call error core in OpenMsgStore
+
+ jkerihuel.
+ [r34]
+ Add MAPISTATUS field in each mapi calls
+ Add new MAPICODE (MAPI_E_CALL_FAILED)
+
+ jkerihuel.
+ [r33]
+ Fix the mapi_request push function
+ Add a first approach to the MAPI client side library
+ Add a first approach of the MAPI-FETCHMAIL torture test
+ Fix the smb.conf.example with new fields and remove Samba4 unused ones
+
+ jkerihuel.
+2007-01-27
+ jkerihuel
+ [r32]
+ Initial mapidump commit
+ OpenMessage IDL fixed
+
+ jkerihuel.
+2007-01-24
+ jkerihuel
+ [r31]
+ Unused and dummy code removed
+
+ jkerihuel
+ [r30]
+ - Remove the MAPI decoding TDR layer and associated functions
+ - Add MAPI decoding in exchange.idl at NDR layer
+ - mapi_request / mapi_response pull/print ok
+ - implement subcontext for async response decoding in
+ some EcDoRpc IDLs.
+ - new MAPITAGS added related to Message envelope properties
+ - clean up the code and remove unused files
+
+ - Add new MAPI opnums and associated IDL:
+ * [in] Release (opnum=0x1)
+ * [in,out] OpenFolder (opnum=0x2)
+ * [in,out] OpenMessage (opnum=0x3)
+ * [in,out] GetContentsTable (opnum=0x5)
+ * [in,out] GetProps (opnum=0x7)
+ * [in,out] Secolumns (opnum=0x12)
+ * [in,out] QueryRows (opnum=0x15)
+ * [in,out] GetReceiveFolder (opnum=0x27)
+ * [in,out] OpenMsgStore (opnum=0xFE)
+
+ ** WARNING **
+
+ 1. Assumption
+ ==============
+ For IDL with unknown fields followed the IDL may
+ change and the mapping of these unknown bytes incorrect.
+ It's just based on assumptions and results of the different
+ wireshark captures.
+
+ 2. Broken Code
+ ==============
+ - The mapi_request / mapi_response pull function
+ - emsmdb torture tests and libmapi/emsmdb.c
+
+ All this code is currently broken and will be fixed
+ when we start writing the new emsmdb torture suite
+ using the new API.
+
+
+ jkerihuel
+2007-01-22
+ jkerihuel
+ [r29]
+ Fix ndr_pull_MAPI_DATA function
+
+ jkerihuel.
+ [r28]
+ - Add new mapi opnums
+ - Add a first IDL implementation for OpenMsgStore out
+
+ jkerihuel.
+ [r27]
+ - Enhance the handles id support in MAPI_DATA
+ - Remove unused code
+
+ EMSMDB encoding/decoding is currently broken.
+ It will be fixed when we start the client side
+ mapi library implementation.
+
+ jkerihuel.
+2007-01-21
+ jkerihuel
+ [r26]
+ - Change IMAPISession.idl to mapi.idl
+ - enhance mapi content payload decoding (multiple calls supported)
+ - add sub EcDoRpc opnums and IDL for setcolumns (in)
+
+ jkerihuel
+ pkhun
+ [r25]
+
+ - memory leak fixed
+ - new function on emsabp provider for entry id generation
+
+ pkhun
+2006-12-27
+ jkerihuel
+ [r24]
+ Old mapitables code deleted and merge of the samdb
+ code used in openchange (emsabp_result_guid function).
+
+ The following revision compiles and work fine with
+ Samba4 revision 20341
+
+ jkerihuel.
+2006-12-17
+ pkhun
+ [r23]
+
+ Instance keys management changed (we now use struct instance_key and uint32_t instead of an array of 4 uint8_t)
+
+ pkhun
+2006-12-15
+ jkerihuel
+ [r22]
+ - Fix compilation warnings based on patches provided
+ by Stefan Huehner <stefan at huehner.org>
+ - Fix the DSO issue for x64 platforms
+ - Add the evolution plugin in the compilation process
+ - remove the mapidump code (obsolete and replaced with ndrdump usage)
+
+ jkerihuel.
+2006-12-13
+ jkerihuel
+ [r21]
+ evolution plugin moved into client/evolution for
+ a correct and extensible naming convention.
+
+ EcDoRpc IDL modified:
+ - opnum are now 8 bits
+ - action enum added
+ - EcDoRpc ndrdump output enhanced
+
+ IMAPISession IDL modified:
+ - Change OpenMsgStore function name to MAPI_RPC_LOGON
+ for the 0xFE opnum operation.
+
+ Fix warnings in the code.
+
+ jkerihuel.
+2006-12-09
+ loic
+ [r20]
+ Openchange-Evolution plugin commit
+ I reorganized openchange evolution plugin source tree.
+ Now we have one directory for the camel-openchange provider, and one for the openchange eplugin.
+ Everything can be found in the oc-evolution directory.
+ This is code a minimalist implementation of the camel provider for evolution.
+ It will make appears an openchange server type in the server list handled by evolution.
+ Still have to fix the ./configure to create a Makefile though.
+2006-12-05
+ jkerihuel
+ [r19]
+ Fix the memory allocation problems in the emsmdb torture test
+2006-12-03
+ jkerihuel
+ [r17]
+ Removed ascstr and directly add it to the IDL
+ [r16]
+ Fix the NspiQueryRows response where strings
+ containing the user email address have to be
+ NULL terminated.
+
+ The EMSABP provider is working ;-)
+ pkhun
+ [r18]
+
+ The emsabp provider is now able to return multiple users
+ when searching for part of a username.
+
+ pkhun
+2006-11-30
+ jkerihuel
+ [r15]
+ Fix the networkAddress binding strings for the
+ Exchange object in the configuration db. The
+ SERVER variable based on exchange:server had
+ been added while we needed the NETBIOSNAME one
+
+ Fix a segmentation fault in emsabp.c due to an
+ unchecked pointer res->msgs. This was causing
+ smbd to segfault when the supplied legacyExchangeDN
+ sent by the user wasn't present in the database.
+
+ jkerihuel
+2006-11-27
+ jkerihuel
+ [r14]
+ Remove unused files and directory.
+ Update Makefile.in and remove storedb compilation
+ rules.
+ pkhun
+ [r13]
+
+ Fixed :
+ - NspiQueryRows
+ - NspiDNToEph
+ - NspiGetProps
+ - provisioning (for the legacyExchangeDN of the server entry)
+2006-11-26
+ jkerihuel
+ [r11]
+ Fix the build and remove dynconfig samba lib
+ dependency.
+
+ jkerihuel
+ pkhun
+ [r12]
+ Unused ldif files removed + Schemas definitions updated
+
+ pkhun
+ [r10]
+ Provisionning fixed (old ldif files cleaned)
+
+ pkhun
+2006-11-22
+ jkerihuel
+ [r9]
+ add tags rules to the Makefile
+
+ jkerihuel.
+ [r8]
+ add the \\pipe\\protected_storage named pipe
+ to exchange_nsp bindings
+
+ jkerihuel.
+2006-11-21
+ jkerihuel
+ [r7]
+ Add a dcerpc_server module in charge of the
+ exchange interfaces registration. When this module
+ is loaded prior the remote endpoint, it let us proxify
+ the exchange_nsp and exchange_emsmdb ones.
+
+ Change the exchange_nsp ncacn_np binding string to
+ reflect how Exchange server is currently using it.
+
+ Conform the IDL with latest pidl requirements and
+ move the MAPI_DATA structure from exchange_nsp to
+ exchange_emsmdb.
+
+ jkerihuel
+2006-11-14
+ jkerihuel
+ [r6]
+ Create the $prefix/modules/{dcerpc_server,torture}
+ directories.
+
+ This fix openchange make install rule.
+
+ jkerihuel.
+ [r5]
+ This commit conforms openchange with the Samba4
+ trunk and fix the autotools checks.
+
+ I've modified the openchange torture file to
+ match the current smbtorture API and the
+ OPENCHANGE-NSPI-PROFILE test was successful.
+
+ The NSPI ndrdump suite has fully been tested and
+ works correctly.
+
+ jkerihuel.
+2006-11-05
+ jkerihuel
+ [r3]
+ This commit fix the build system:
+ - add the -ldynconfig dependency to LDFLAGS
+ - add header checks in configure.ac. We need them
+ for the moment cause Samba4 doesn't install some headers
+ required by openchange core
+ - fix the make install
+
+ - remove autotools generated files and definitively
+ ignore them with the .svnignore file
+
+ - keepref keyword removed from exchange_nsp interface
+
+ jkerihuel.
+ pkhun
+ [r4]
+ + aclocal.m4 removed from repository
+ + provisionning fixed
+
+ pkhun.
Added: trunk/openchange/Doxyfile.in
===================================================================
--- trunk/openchange/Doxyfile.in (rev 0)
+++ trunk/openchange/Doxyfile.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1274 @@
+# Doxyfile 1.5.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = OpenChange
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = apidocs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = .
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.doxy
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = *_private.h
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = *.yy.c *_private.h
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = doc/doxygen/pictures/
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER = "sed \
+ -e 's/.*\<libmapi\/proto_private.h\>//' \
+ -e 's/.*\<gen_ndr\/ndr_exchange.h\>//' \
+ -e 's/.*\<param.h\>//' \
+ -e 's/.*\<core\/error.h\>//' \
+ -e 's/.*\<credentials.h\>//' \
+ -e 's/.*\<ldb.h\>//' \
+ -e 's/.*\<ldb_errors.h\>//' \
+ -e 's/.*\<libmapi\/dlinklist.h\>//' \
+ -e 's/.*\<libmapi\/mapi_nameid.h\>//' \
+ -e 's/.*\<libmapi\/mapi_nameid_private.h\>//' \
+ -e 's/.*\<libocpf\/proto_private.h\>//' \
+ -e 's/.*\<libocpf\/ocpf_api.h\>//' \
+ -e 's/.*\<libocpf\/ocpf.tab.h\>//' \
+ -e 's/.*\<libgen.h\>//' \
+ -e 's/.*\<time.h\>//' \
+ -e 's/.*\<sys\/*\>//' \
+ -e 's/_PUBLIC_//'"
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html/overview
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER = doc/doxygen/header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = doc/doxygen/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET = doc/doxygen/apidocs.css
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = _PUBLIC_
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen will always
+# show the root nodes and its direct children regardless of this setting.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
Added: trunk/openchange/IDL_LICENSE.txt
===================================================================
--- trunk/openchange/IDL_LICENSE.txt (rev 0)
+++ trunk/openchange/IDL_LICENSE.txt 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,9 @@
+The IDL files in this directory are made available by the OpenChange Team
+under the following license:
+
+ Permission to use, copy, modify, and distribute these interface
+ definitions for any purpose is hereby granted without fee.
+
+ This work 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.
Added: trunk/openchange/Mainpage.doxy
===================================================================
--- trunk/openchange/Mainpage.doxy (rev 0)
+++ trunk/openchange/Mainpage.doxy 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,43 @@
+/** @mainpage The OpenChange Library API Reference
+
+This is the online reference for developing with the OpenChange client
+libraries.
+
+Among other things, the OpenChange client libraries provide:
+- MAPI client library (<a href="../libmapi/index.html">libmapi</a>)
+- MAPI administration libraries (<a href="../libmapiadmin/index.html">libmapiadmin</a>)
+- OpenChange Property Files (<a href="../libocpf/index.html">libocpf</a>)
+- A regression test framework (<a href="../mapitest/index.html">mapitest</a>)
+- MAPIProxy project (<a href="../mapiproxy/index.html">mapiproxy</a>)
+- C++ bindings for libmapi (<a href="../libmapi++/index.html">libmapi++</a>)
+
+<h2>OpenChange Project Goals</h2>
+
+The OpenChange Project aims to provide a portable Open Source
+implementation of Microsoft Exchange Server and Exchange
+protocols. Exchange is a groupware server designed to work with
+Microsoft Outlook, and providing features such as a messaging server,
+shared calendars, contact databases, public folders, notes and tasks.
+
+The OpenChange project has three goals:
+
+- To provide a library for interoperability with Exchange
+protocols, and to assist implementors to use this to create
+groupware that interoperates with both Exchange and other
+OpenChange-based software.
+
+- To provide an alternative to Microsoft Exchange Server which uses
+native Exchange protocols and provides exactly equivalent
+functionality when viewed from Microsoft Outlook clients.
+
+- To develop a body of knowledge about the most popular groupware
+protocols in use commercially today in order to promote development
+of a documented and unencumbered standard, with all the benefits that
+standards bring.
+
+<h2>More information</h2>
+
+Visit the <a href="http://www.openchange.org">OpenChange web site</a> for
+other useful information.
+
+*/
Added: trunk/openchange/Makefile
===================================================================
--- trunk/openchange/Makefile (rev 0)
+++ trunk/openchange/Makefile 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1477 @@
+# Makefile for OpenChange
+# Written by Jelmer Vernooij <jelmer at openchange.org>, 2005.
+
+default: all
+
+# Until we add proper dependencies for all the C files:
+.NOTPARALLEL:
+
+config.mk: config.status config.mk.in
+ ./config.status
+
+config.status: configure
+ ./configure
+
+configure: configure.ac
+ ./autogen.sh
+
+samba:
+ ./script/installsamba4.sh all
+
+samba-git:
+ ./script/installsamba4.sh git-all
+
+ifneq ($(MAKECMDGOALS), samba)
+ifneq ($(MAKECMDGOALS), samba-git)
+include config.mk
+endif
+endif
+
+#################################################################
+# top level compilation rules
+#################################################################
+
+all: $(OC_IDL) \
+ $(OC_LIBS) \
+ $(OC_TOOLS) \
+ $(OC_TORTURE) \
+ $(OC_SERVER) \
+ $(SWIGDIRS-ALL) \
+ $(PYMAPIALL)
+
+install: all \
+ installlib \
+ installpc \
+ installheader \
+ $(OC_TOOLS_INSTALL) \
+ $(OC_SERVER_INSTALL) \
+ $(OC_TORTURE_INSTALL) \
+ $(SWIGDIRS-INSTALL) \
+ $(PYMAPIINSTALL) \
+ installnagios
+
+installlib: $(OC_LIBS_INSTALL)
+installpc: $(OC_LIBS_INSTALLPC)
+installheader: $(OC_LIBS_INSTALLHEADERS)
+
+uninstall:: $(OC_LIBS_UNINSTALL) \
+ $(OC_TOOLS_UNINSTALL) \
+ $(OC_SERVER_UNINSTALL) \
+ $(OC_TORTURE_UNINSTALL) \
+ $(SWIGDIRS-UNINSTALL) \
+ $(PYMAPIUNINSTALL)
+
+distclean:: clean
+ rm -rf autom4te.cache
+ rm -f Doxyfile
+ rm -f libmapi/Doxyfile
+ rm -f libmapiadmin/Doxyfile
+ rm -f libocpf/Doxyfile
+ rm -f libmapi++/Doxyfile
+ rm -f mapiproxy/Doxyfile
+ rm -f config.status config.log
+ rm -f stamp-h1
+ rm -f utils/mapitest/Doxyfile
+ rm -f intltool-extract intltool-merge intltool-update
+ rm -rf apidocs
+ rm -rf gen_ndr
+ rm -f tags
+
+clean::
+ rm -f *~
+ rm -f */*~
+ rm -f */*/*~
+ rm -f doc/examples/mapi_sample1
+ rm -f doc/examples/fetchappointment
+ rm -f doc/examples/fetchmail
+
+re:: clean install
+
+#################################################################
+# Suffixes compilation rules
+#################################################################
+
+.SUFFIXES: .c .o .h .po .idl
+
+.idl.h:
+ @echo "Generating $@"
+ @$(PIDL) --outputdir=gen_ndr --header -- $<
+
+.c.o:
+ @echo "Compiling $<"
+ @$(CC) $(CFLAGS) -c $< -o $@
+
+.c.po:
+ @echo "Compiling $< with -fPIC"
+ @$(CC) $(CFLAGS) -fPIC -c $< -o $@
+
+
+
+#################################################################
+# IDL compilation rules
+#################################################################
+
+idl: gen_ndr gen_ndr/ndr_exchange.h gen_ndr/ndr_property.h
+
+exchange.idl: mapitags_enum.h mapicodes_enum.h
+
+gen_ndr:
+ @echo "Creating the gen_ndr directory"
+ mkdir -p gen_ndr
+
+gen_ndr/ndr_%.h gen_ndr/ndr_%.c: %.idl %.h
+ @echo "Generating $@"
+ @$(PIDL) --outputdir=gen_ndr --ndr-parser -- $<
+
+gen_ndr/ndr_%_c.h gen_ndr/ndr_%_c.c: %.idl %.h
+ @echo "Generating $@"
+ @$(PIDL) --outputdir=gen_ndr --client -- $<
+
+gen_ndr/ndr_%_s.c: %.idl
+ @echo "Generating $@"
+ @$(PIDL) --outputdir=gen_ndr --server -- $<
+
+
+
+#################################################################
+# libmapi compilation rules
+#################################################################
+
+LIBMAPI_SO_VERSION = 0
+
+libmapi: idl \
+ libmapi/version.h \
+ libmapi/proto.h \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+libmapi-install: libmapi \
+ libmapi-installpc \
+ libmapi-installlib \
+ libmapi-installheader \
+ libmapi-installscript
+
+libmapi-uninstall: libmapi-uninstallpc \
+ libmapi-uninstalllib \
+ libmapi-uninstallheader \
+ libmapi-uninstallscript
+
+libmapi-clean::
+ rm -f libmapi/*.o libmapi/*.po
+ rm -f libmapi/tests/*.o, libmapi/tests/*.po
+ rm -f libmapi/socket/*.o libmapi/socket/*.po
+ rm -f libmapi/util/*.o, libmapi/util/*.po
+ rm -f libmapi/version.h
+ifneq ($(SNAPSHOT), no)
+ rm -f libmapi/utf8_convert.yy.c
+ rm -f libmapi/mapicode.c libmapi/mapicode.h
+ rm -f libmapi/mapitags.c libmapi/mapitags.h
+ rm -f libmapi/mapi_nameid.h libmapi/mapi_nameid_private.h
+ rm -f libmapi/proto.h
+ rm -f libmapi/proto_private.h
+ rm -f mapicodes_enum.h
+ rm -f mapitags_enum.h
+endif
+ rm -f gen_ndr/ndr_exchange*
+ rm -f gen_ndr/exchange.h
+ rm -f gen_ndr/ndr_property*
+ rm -f gen_ndr/property.h
+ rm -f ndr_mapi.o ndr_mapi.po
+ rm -f *~
+ rm -f */*~
+ rm -f */*/*~
+ rm -f libmapi.$(SHLIBEXT).$(PACKAGE_VERSION) libmapi.$(SHLIBEXT).$(LIBMAPI_SO_VERSION) \
+ libmapi.$(SHLIBEXT)
+
+clean:: libmapi-clean
+
+libmapi-distclean::
+ rm -f libmapi.pc
+
+distclean:: libmapi-distclean
+
+libmapi-installpc:
+ @echo "[*] install: libmapi pc files"
+ $(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig
+ $(INSTALL) -m 0644 libmapi.pc $(DESTDIR)$(libdir)/pkgconfig
+
+libmapi-installlib:
+ @echo "[*] install: libmapi library"
+ $(INSTALL) -d $(DESTDIR)$(libdir)
+ $(INSTALL) -m 0755 libmapi.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)
+ ln -sf libmapi.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)/libmapi.$(SHLIBEXT)
+
+libmapi-installheader:
+ @echo "[*] install: libmapi headers"
+ $(INSTALL) -d $(DESTDIR)$(includedir)/libmapi
+ $(INSTALL) -d $(DESTDIR)$(includedir)/libmapi/socket
+ $(INSTALL) -d $(DESTDIR)$(includedir)/gen_ndr
+ $(INSTALL) -m 0644 libmapi/dlinklist.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/libmapi.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/proto.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/nspi.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/emsmdb.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/mapi_ctx.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/mapi_provider.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/mapi_id_array.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/mapi_notification.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/mapi_object.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/mapi_profile.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/mapi_nameid.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/mapidefs.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/version.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/mapicode.h $(DESTDIR)$(includedir)/libmapi/
+ $(INSTALL) -m 0644 libmapi/socket/netif.h $(DESTDIR)$(includedir)/libmapi/socket/
+ $(INSTALL) -m 0644 gen_ndr/exchange.h $(DESTDIR)$(includedir)/gen_ndr/
+ $(INSTALL) -m 0644 gen_ndr/property.h $(DESTDIR)$(includedir)/gen_ndr/
+
+libmapi-installscript:
+ $(INSTALL) -d $(DESTDIR)$(datadir)/setup/profiles
+ $(INSTALL) -m 0644 setup/profiles/oc_profiles* $(DESTDIR)$(datadir)/setup/profiles/
+
+libmapi-uninstallpc:
+ rm -f $(DESTDIR)$(libdir)/pkgconfig/libmapi.pc
+
+libmapi-uninstalllib:
+ rm -f $(DESTDIR)$(libdir)/libmapi.*
+
+libmapi-uninstallheader:
+ rm -rf $(DESTDIR)$(includedir)/libmapi
+ rm -f $(DESTDIR)$(includedir)/gen_ndr/exchange.h
+ rm -f $(DESTDIR)$(includedir)/gen_ndr/property.h
+
+libmapi-uninstallscript:
+ rm -f $(DESTDIR)$(datadir)/setup/profiles/oc_profiles*
+ rm -rf $(DESTDIR)$(datadir)/setup/profiles
+
+libmapi.$(SHLIBEXT).$(PACKAGE_VERSION): \
+ libmapi/IABContainer.po \
+ libmapi/IProfAdmin.po \
+ libmapi/IMAPIContainer.po \
+ libmapi/IMAPIFolder.po \
+ libmapi/IMAPIProp.po \
+ libmapi/IMAPISession.po \
+ libmapi/IMAPISupport.po \
+ libmapi/IStream.po \
+ libmapi/IMAPITable.po \
+ libmapi/IMessage.po \
+ libmapi/IMsgStore.po \
+ libmapi/IStoreFolder.po \
+ libmapi/IUnknown.po \
+ libmapi/IMSProvider.po \
+ libmapi/IXPLogon.po \
+ libmapi/FXICS.po \
+ libmapi/utils.po \
+ libmapi/property.po \
+ libmapi/cdo_mapi.po \
+ libmapi/lzfu.po \
+ libmapi/mapi_object.po \
+ libmapi/mapi_id_array.po \
+ libmapi/mapitags.po \
+ libmapi/mapidump.po \
+ libmapi/mapicode.po \
+ libmapi/mapi_nameid.po \
+ libmapi/emsmdb.po \
+ libmapi/nspi.po \
+ libmapi/simple_mapi.po \
+ libmapi/util/lcid.po \
+ libmapi/util/codepage.po \
+ libmapi/freebusy.po \
+ libmapi/x500.po \
+ ndr_mapi.po \
+ gen_ndr/ndr_exchange.po \
+ gen_ndr/ndr_exchange_c.po \
+ gen_ndr/ndr_property.po \
+ libmapi/socket/interface.po \
+ libmapi/socket/netif.po \
+ libmapi/utf8_convert.yy.po
+ @echo "Linking $@"
+ @$(CC) $(DSOOPT) -Wl,-soname,libmapi.$(SHLIBEXT).$(LIBMAPI_SO_VERSION) -o $@ $^ $(LIBS)
+
+
+libmapi.$(SHLIBEXT).$(LIBMAPI_SO_VERSION): libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ ln -fs $< $@
+
+libmapi/version.h: VERSION
+ @./script/mkversion.sh VERSION libmapi/version.h $(PACKAGE_VERSION) $(top_builddir)/
+
+libmapi/utf8_convert.yy.c: libmapi/utf8_convert.l
+ @echo "Generating $@"
+ @$(FLEX) -Plibmapi_utf8_convert_ -t $< > $@
+
+# Avoid warnings:
+libmapi/utf8_convert.yy.o: CFLAGS=
+
+libmapi/proto.h libmapi/proto_private.h: \
+ libmapi/nspi.c \
+ libmapi/emsmdb.c \
+ libmapi/cdo_mapi.c \
+ libmapi/simple_mapi.c \
+ libmapi/mapitags.c \
+ libmapi/mapicode.c \
+ libmapi/mapidump.c \
+ libmapi/mapi_object.c \
+ libmapi/mapi_id_array.c \
+ libmapi/mapi_nameid.c \
+ libmapi/property.c \
+ libmapi/IABContainer.c \
+ libmapi/IProfAdmin.c \
+ libmapi/IMAPIContainer.c \
+ libmapi/IMAPIFolder.c \
+ libmapi/IMAPIProp.c \
+ libmapi/IMAPISession.c \
+ libmapi/IMAPISupport.c \
+ libmapi/IMAPITable.c \
+ libmapi/IMSProvider.c \
+ libmapi/IMessage.c \
+ libmapi/IMsgStore.c \
+ libmapi/IStoreFolder.c \
+ libmapi/IUnknown.c \
+ libmapi/IStream.c \
+ libmapi/IXPLogon.c \
+ libmapi/FXICS.c \
+ libmapi/freebusy.c \
+ libmapi/x500.c \
+ libmapi/lzfu.c \
+ libmapi/utils.c \
+ libmapi/util/lcid.c \
+ libmapi/util/codepage.c \
+ libmapi/socket/interface.c \
+ libmapi/socket/netif.c
+ @echo "Generating $@"
+ @./script/mkproto.pl --private=libmapi/proto_private.h --public=libmapi/proto.h $^
+
+libmapi/emsmdb.c: libmapi/emsmdb.h gen_ndr/ndr_exchange_c.h
+
+libmapi/mapitags.c libmapi/mapicode.c mapitags_enum.h mapicodes_enum.h: \
+ libmapi/conf/mapi-properties \
+ libmapi/conf/mapi-codes \
+ libmapi/conf/mapi-named-properties \
+ libmapi/conf/mparse.pl
+ @./libmapi/conf/build.sh
+
+#################################################################
+# libmapi++ compilation rules
+#################################################################
+
+libmapixx: libmapi libmapixx-tests libmapixx-examples
+
+libmapixx-installpc:
+
+libmapixx-clean: libmapixx-tests-clean
+
+libmapixx-install: libmapixx-installheader
+
+libmapixx-uninstall: libmapixx-uninstallheader
+
+libmapixx-installheader:
+ @echo "[*] install: libmapi++ headers"
+ $(INSTALL) -d $(DESTDIR)$(includedir)/libmapi++
+ $(INSTALL) -m 0644 libmapi++/attachment.h $(DESTDIR)$(includedir)/libmapi++/
+ $(INSTALL) -m 0644 libmapi++/clibmapi.h $(DESTDIR)$(includedir)/libmapi++/
+ $(INSTALL) -m 0644 libmapi++/folder.h $(DESTDIR)$(includedir)/libmapi++/
+ $(INSTALL) -m 0644 libmapi++/libmapi++.h $(DESTDIR)$(includedir)/libmapi++/
+ $(INSTALL) -m 0644 libmapi++/mapi_exception.h $(DESTDIR)$(includedir)/libmapi++/
+ $(INSTALL) -m 0644 libmapi++/message.h $(DESTDIR)$(includedir)/libmapi++/
+ $(INSTALL) -m 0644 libmapi++/message_store.h $(DESTDIR)$(includedir)/libmapi++/
+ $(INSTALL) -m 0644 libmapi++/object.h $(DESTDIR)$(includedir)/libmapi++/
+ $(INSTALL) -m 0644 libmapi++/profile.h $(DESTDIR)$(includedir)/libmapi++/
+ $(INSTALL) -m 0644 libmapi++/property_container.h $(DESTDIR)$(includedir)/libmapi++/
+ $(INSTALL) -m 0644 libmapi++/session.h $(DESTDIR)$(includedir)/libmapi++/
+ $(INSTALL) -d $(DESTDIR)$(includedir)/libmapi++/impl
+ $(INSTALL) -m 0644 libmapi++/impl/* $(DESTDIR)$(includedir)/libmapi++/impl/
+
+libmapixx-uninstallheader:
+ rm -rf $(DESTDIR)$(includedir)/libmapi++
+
+
+libmapixx-tests: libmapixx-test \
+ libmapixx-attach
+
+libmapixx-tests-clean: libmapixx-test-clean \
+ libmapixx-attach-clean
+
+libmapixx-test: bin/libmapixx-test
+
+libmapixx-test-clean:
+ rm -f bin/libmapixx-test
+ rm -f libmapi++/tests/*.o
+
+clean:: libmapixx-tests-clean
+
+bin/libmapixx-test: libmapi++/tests/test.cpp \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking sample application $@"
+ @$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)
+
+clean:: libmapixx-test-clean
+
+libmapixx-attach: bin/libmapixx-attach
+
+libmapixx-attach-clean:
+ rm -f bin/libmapixx-attach
+ rm -f libmapi++/tests/*.o
+
+bin/libmapixx-attach: libmapi++/tests/attach_test.cpp \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking sample application $@"
+ @$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)
+
+clean:: libmapixx-attach-clean
+
+
+libmapixx-examples: libmapi++/examples/foldertree \
+ libmapi++/examples/messages
+
+libmapixx-foldertree-clean:
+ rm -f libmapi++/examples/foldertree
+ rm -f libmapi++/examples/*.o
+
+libmapixx-messages-clean:
+ rm -f libmapi++/examples/messages
+ rm -f libmapi++/examples/*.o
+
+libmapi++/examples/foldertree: libmapi++/examples/foldertree.cpp \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking foldertree example application $@"
+ @$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)
+
+clean:: libmapixx-foldertree-clean
+
+libmapi++/examples/messages: libmapi++/examples/messages.cpp \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking messages example application $@"
+ @$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)
+
+clean:: libmapixx-messages-clean
+
+#################################################################
+# libmapiadmin compilation rules
+#################################################################
+
+LIBMAPIADMIN_SO_VERSION = 0
+
+libmapiadmin: libmapiadmin/proto.h \
+ libmapiadmin.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+libmapiadmin-install: libmapiadmin-installpc \
+ libmapiadmin-installlib \
+ libmapiadmin-installheader
+
+libmapiadmin-uninstall: libmapiadmin-uninstallpc \
+ libmapiadmin-uninstalllib \
+ libmapiadmin-uninstallheader
+
+libmapiadmin-clean::
+ rm -f libmapiadmin/*.o libmapiadmin/*.po
+ifneq ($(SNAPSHOT), no)
+ rm -f libmapiadmin/proto.h
+ rm -f libmapiadmin/proto_private.h
+endif
+ rm -f libmapiadmin.$(SHLIBEXT).$(PACKAGE_VERSION) libmapiadmin.$(SHLIBEXT).$(LIBMAPIADMIN_SO_VERSION) \
+ libmapiadmin.$(SHLIBEXT)
+
+clean:: libmapiadmin-clean
+
+libmapiadmin-distclean::
+ rm -f libmapiadmin.pc
+
+distclean:: libmapiadmin-distclean
+
+libmapiadmin-installpc:
+ @echo "[*] install: libmapiadmin pc files"
+ $(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig
+ $(INSTALL) -m 0644 libmapiadmin.pc $(DESTDIR)$(libdir)/pkgconfig
+
+libmapiadmin-installlib:
+ @echo "[*] install: libmapiadmin library"
+ $(INSTALL) -d $(DESTDIR)$(libdir)
+ $(INSTALL) -m 0755 libmapiadmin.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)
+ ln -sf libmapiadmin.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)/libmapiadmin.$(SHLIBEXT)
+
+libmapiadmin-installheader:
+ @echo "[*] install: libmapiadmin headers"
+ $(INSTALL) -d $(DESTDIR)$(includedir)/libmapiadmin
+ $(INSTALL) -m 0644 libmapiadmin/proto.h $(DESTDIR)$(includedir)/libmapiadmin/
+ $(INSTALL) -m 0644 libmapiadmin/libmapiadmin.h $(DESTDIR)$(includedir)/libmapiadmin/
+
+libmapiadmin-uninstallpc:
+ rm -f $(DESTDIR)$(libdir)/pkgconfig/libmapiadmin.pc
+
+libmapiadmin-uninstalllib:
+ rm -f $(DESTDIR)$(libdir)/libmapiadmin.*
+
+libmapiadmin-uninstallheader:
+ rm -rf $(DESTDIR)$(includedir)/libmapiadmin
+
+libmapiadmin.$(SHLIBEXT).$(PACKAGE_VERSION): \
+ libmapiadmin/mapiadmin_user.po \
+ libmapiadmin/mapiadmin.po \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) $(DSOOPT) -Wl,-soname,libmapiadmin.$(SHLIBEXT).$(LIBMAPIADMIN_SO_VERSION) -o $@ $^ $(LIBS) $(LIBMAPIADMIN_LIBS)
+
+libmapiadmin/proto.h libmapiadmin/proto_private.h: \
+ libmapiadmin/mapiadmin.c \
+ libmapiadmin/mapiadmin_user.c
+ @echo "Generating $@"
+ @./script/mkproto.pl -private=libmapiadmin/proto_private.h --public=libmapiadmin/proto.h $^
+
+
+
+#################################################################
+# libocpf compilation rules
+#################################################################
+
+LIBOCPF_SO_VERSION = 0
+
+libocpf: libocpf/proto.h \
+ libocpf.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+libocpf-install: libocpf-installpc \
+ libocpf-installlib \
+ libocpf-installheader
+
+libocpf-uninstall: libocpf-uninstallpc \
+ libocpf-uninstalllib \
+ libocpf-uninstallheader
+
+libocpf-clean::
+ rm -f libocpf/*.o libocpf/*.po
+ifneq ($(SNAPSHOT), no)
+ rm -f libocpf/lex.yy.c
+ rm -f libocpf/ocpf.tab.c libocpf/ocpf.tab.h
+ rm -f libocpf/proto.h
+ rm -f libocpf/proto_private.h
+endif
+ rm -f libocpf.$(SHLIBEXT).$(PACKAGE_VERSION) libocpf.$(SHLIBEXT).$(LIBOCPF_SO_VERSION) \
+ libocpf.$(SHLIBEXT)
+
+clean:: libocpf-clean
+
+libocpf-distclean::
+ rm -f libocpf.pc
+
+distclean:: libocpf-distclean
+
+libocpf-installpc:
+ @echo "[*] install: libocpf pc files"
+ $(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig
+ $(INSTALL) -m 0644 libocpf.pc $(DESTDIR)$(libdir)/pkgconfig
+
+libocpf-installlib:
+ @echo "[*] install: libocpf library"
+ $(INSTALL) -d $(DESTDIR)$(libdir)
+ $(INSTALL) -m 0755 libocpf.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)
+ ln -sf libocpf.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)/libocpf.$(SHLIBEXT)
+
+libocpf-installheader:
+ @echo "[*] install: libocpf headers"
+ $(INSTALL) -d $(DESTDIR)$(includedir)/libocpf
+ $(INSTALL) -m 0644 libocpf/ocpf.h $(DESTDIR)$(includedir)/libocpf/
+ $(INSTALL) -m 0644 libocpf/proto.h $(DESTDIR)$(includedir)/libocpf/
+
+libocpf-uninstallpc:
+ rm -f $(DESTDIR)$(libdir)/pkgconfig/libocpf.pc
+
+libocpf-uninstalllib:
+ rm -f $(DESTDIR)$(libdir)/libocpf.*
+
+libocpf-uninstallheader:
+ rm -rf $(DESTDIR)$(includedir)/libocpf
+
+libocpf.$(SHLIBEXT).$(PACKAGE_VERSION): \
+ libocpf/ocpf.tab.po \
+ libocpf/lex.yy.po \
+ libocpf/ocpf_public.po \
+ libocpf/ocpf_dump.po \
+ libocpf/ocpf_api.po \
+ libocpf/ocpf_write.po \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) $(DSOOPT) -Wl,-soname,libocpf.$(SHLIBEXT).$(LIBOCPF_SO_VERSION) -o $@ $^ $(LIBS)
+
+libocpf.$(SHLIBEXT).$(LIBOCPF_SO_VERSION): libocpf.$(SHLIBEXT).$(PACKAGE_VERSION)
+ ln -fs $< $@
+
+libocpf/proto.h: libocpf/ocpf_public.c \
+ libocpf/ocpf_dump.c \
+ libocpf/ocpf_api.c \
+ libocpf/ocpf_write.c
+ @echo "Generating $@"
+ @./script/mkproto.pl --private=libocpf/proto_private.h \
+ --public=libocpf/proto.h $^
+
+libocpf/lex.yy.c: libocpf/lex.l
+ @echo "Generating $@"
+ @$(FLEX) -t $< > $@
+
+libocpf/ocpf.tab.c: libocpf/ocpf.y
+ @echo "Generating $@"
+ @$(BISON) -pocpf_yy -d $< -o $@
+
+# Avoid warnings
+libocpf/lex.yy.o: CFLAGS=
+libocpf/ocpf.tab.o: CFLAGS=
+
+
+
+#################################################################
+# torture suite compilation rules
+#################################################################
+
+torture: torture/torture_proto.h \
+ torture/openchange.$(SHLIBEXT)
+
+torture-install:
+ @echo "[*] install: openchange torture suite"
+ $(INSTALL) -d $(DESTDIR)$(TORTURE_MODULESDIR)
+ $(INSTALL) -m 0755 torture/openchange.$(SHLIBEXT) $(DESTDIR)$(TORTURE_MODULESDIR)
+
+torture-uninstall:
+ rm -f $(DESTDIR)$(TORTURE_MODULESDIR)/openchange.*
+
+torture-clean::
+ rm -f torture/*.$(SHLIBEXT)
+ifneq ($(SNAPSHOT), no)
+ rm -f torture/torture_proto.h
+endif
+ rm -f torture/*.o torture/*.po
+
+clean:: torture-clean
+
+torture/openchange.$(SHLIBEXT): \
+ torture/nspi_profile.po \
+ torture/nspi_resolvenames.po \
+ torture/mapi_restrictions.po \
+ torture/mapi_criteria.po \
+ torture/mapi_copymail.po \
+ torture/mapi_sorttable.po \
+ torture/mapi_bookmark.po \
+ torture/mapi_fetchmail.po \
+ torture/mapi_sendmail.po \
+ torture/mapi_sendmail_html.po \
+ torture/mapi_deletemail.po \
+ torture/mapi_newmail.po \
+ torture/mapi_sendattach.po \
+ torture/mapi_fetchattach.po \
+ torture/mapi_fetchappointment.po \
+ torture/mapi_sendappointment.po \
+ torture/mapi_fetchcontacts.po \
+ torture/mapi_sendcontacts.po \
+ torture/mapi_fetchtasks.po \
+ torture/mapi_sendtasks.po \
+ torture/mapi_common.po \
+ torture/mapi_permissions.po \
+ torture/mapi_createuser.po \
+ torture/exchange_createuser.po \
+ torture/mapi_namedprops.po \
+ torture/mapi_recipient.po \
+ torture/openchange.po \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $(DSOOPT) $^ -L. $(LIBS)
+
+torture/torture_proto.h: torture/mapi_restrictions.c \
+ torture/mapi_criteria.c \
+ torture/mapi_deletemail.c \
+ torture/mapi_newmail.c \
+ torture/mapi_fetchmail.c \
+ torture/mapi_sendattach.c \
+ torture/mapi_sorttable.c \
+ torture/mapi_bookmark.c \
+ torture/mapi_copymail.c \
+ torture/mapi_fetchattach.c \
+ torture/mapi_sendmail.c \
+ torture/mapi_sendmail_html.c \
+ torture/nspi_profile.c \
+ torture/nspi_resolvenames.c \
+ torture/mapi_fetchappointment.c \
+ torture/mapi_sendappointment.c \
+ torture/mapi_fetchcontacts.c \
+ torture/mapi_sendcontacts.c \
+ torture/mapi_fetchtasks.c \
+ torture/mapi_sendtasks.c \
+ torture/mapi_common.c \
+ torture/mapi_permissions.c \
+ torture/mapi_namedprops.c \
+ torture/mapi_recipient.c \
+ torture/mapi_createuser.c \
+ torture/exchange_createuser.c \
+ torture/openchange.c
+ @echo "Generating $@"
+ @./script/mkproto.pl --private=torture/torture_proto.h --public=torture/torture_proto.h $^
+
+#################################################################
+# mapiproxy compilation rules
+#################################################################
+LIBMAPIPROXY_SO_VERSION = 0
+LIBMAPISERVER_SO_VERSION = 0
+
+.PHONY: mapiproxy
+
+mapiproxy: idl \
+ libmapiproxy \
+ libmapiserver \
+ libmapistore \
+ mapiproxy/dcesrv_mapiproxy.$(SHLIBEXT) \
+ mapiproxy-modules \
+ mapiproxy-servers
+
+mapiproxy-install: mapiproxy \
+ mapiproxy-modules-install \
+ mapiproxy-servers-install \
+ libmapiproxy-install \
+ libmapiserver-install \
+ libmapistore-install
+ $(INSTALL) -d $(DESTDIR)$(SERVER_MODULESDIR)
+ $(INSTALL) -m 0755 mapiproxy/dcesrv_mapiproxy.$(SHLIBEXT) $(DESTDIR)$(SERVER_MODULESDIR)
+
+mapiproxy-uninstall: mapiproxy-modules-uninstall \
+ mapiproxy-servers-uninstall \
+ libmapiproxy-uninstall \
+ libmapiserver-uninstall \
+ libmapistore-uninstall
+ rm -f $(DESTDIR)$(SERVER_MODULESDIR)/dcesrv_mapiproxy.*
+ rm -f $(DESTDIR)$(libdir)/libmapiproxy.*
+ rm -f $(DESTDIR)$(includedir)/libmapiproxy.h
+
+mapiproxy-clean:: mapiproxy-modules-clean \
+ mapiproxy-servers-clean \
+ libmapiproxy-clean \
+ libmapiserver-clean \
+ libmapistore-clean
+ rm -f mapiproxy/*.o mapiproxy/*.po
+ rm -f mapiproxy/dcesrv_mapiproxy.$(SHLIBEXT)
+
+clean:: mapiproxy-clean
+
+
+mapiproxy/dcesrv_mapiproxy.$(SHLIBEXT): mapiproxy/dcesrv_mapiproxy.po \
+ mapiproxy/dcesrv_mapiproxy_nspi.po \
+ mapiproxy/dcesrv_mapiproxy_rfr.po \
+ mapiproxy/dcesrv_mapiproxy_unused.po \
+ ndr_mapi.po \
+ gen_ndr/ndr_exchange.po
+
+ @echo "Linking $@"
+ @$(CC) -o $@ $(DSOOPT) $^ -L. $(LIBS) -Lmapiproxy mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+mapiproxy/dcesrv_mapiproxy.c: gen_ndr/ndr_exchange_s.c gen_ndr/ndr_exchange.c
+
+
+###############
+# libmapiproxy
+###############
+
+libmapiproxy: mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+libmapiproxy-install:
+ $(INSTALL) -m 0755 mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)
+ ln -sf libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)/libmapiproxy.$(SHLIBEXT)
+ $(INSTALL) -m 0644 mapiproxy/libmapiproxy/libmapiproxy.h $(DESTDIR)$(includedir)/
+ $(INSTALL) -m 0644 mapiproxy/libmapiproxy.pc $(DESTDIR)$(libdir)/pkgconfig
+
+libmapiproxy-clean:
+ rm -f mapiproxy/libmapiproxy/*.po mapiproxy/libmapiproxy/*.o
+ifneq ($(SNAPSHOT), no)
+ rm -f mapiproxy/libmapiproxy/openchangedb_property.c
+endif
+ rm -f mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION)
+ rm -f mapiproxy/libmapiproxy.$(SHLIBEXT).$(LIBMAPIPROXY_SO_VERSION)
+
+libmapiproxy-uninstall:
+ rm -f $(DESTDIR)$(libdir)/libmapiproxy.*
+ rm -f $(DESTDIR)$(includedir)/libmapiproxy.h
+ rm -f $(DESTDIR)$(libdir)/pkgconfig/libmapiproxy.pc
+
+libmapiproxy-distclean:
+ rm -f mapiproxy/libmapiproxy.pc
+
+distclean::libmapiproxy-distclean
+
+mapiproxy/libmapiproxy/openchangedb_property.c: libmapi/conf/mapi-properties libmapi/conf/mparse.pl
+ @./libmapi/conf/mparse.pl --parser=openchangedb_property --outputdir=mapiproxy/libmapiproxy/ \
+ libmapi/conf/mapi-properties
+
+mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION): mapiproxy/libmapiproxy/dcesrv_mapiproxy_module.po \
+ mapiproxy/libmapiproxy/dcesrv_mapiproxy_server.po \
+ mapiproxy/libmapiproxy/dcesrv_mapiproxy_session.po \
+ mapiproxy/libmapiproxy/openchangedb.po \
+ mapiproxy/libmapiproxy/openchangedb_property.po \
+ mapiproxy/libmapiproxy/mapi_handles.po \
+ mapiproxy/libmapiproxy/entryid.po \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @$(CC) -o $@ $(DSOOPT) -Wl,-soname,libmapiproxy.$(SHLIBEXT).$(LIBMAPIPROXY_SO_VERSION) $^ -L. $(LIBS)
+
+mapiproxy/libmapiproxy.$(SHLIBEXT).$(LIBMAPIPROXY_SO_VERSION): libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION)
+ ln -fs $< $@
+
+
+#################
+# libmapiserver
+#################
+
+libmapiserver: mapiproxy/libmapiserver.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+libmapiserver-install:
+ $(INSTALL) -m 0755 mapiproxy/libmapiserver.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)
+ ln -sf libmapiserver.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)/libmapiserver.$(SHLIBEXT)
+ $(INSTALL) -m 0644 mapiproxy/libmapiserver/libmapiserver.h $(DESTDIR)$(includedir)/
+ $(INSTALL) -m 0644 mapiproxy/libmapiserver.pc $(DESTDIR)$(libdir)/pkgconfig
+
+libmapiserver-clean:
+ rm -f mapiproxy/libmapiserver/*.po mapiproxy/libmapiserver/*.o
+ rm -f mapiproxy/libmapiserver.$(SHLIBEXT).$(PACKAGE_VERSION)
+ rm -f mapiproxy/libmapiserver.$(SHLIBEXT).$(LIBMAPISERVER_SO_VERSION)
+
+libmapiserver-uninstall:
+ rm -f $(DESTDIR)$(libdir)/libmapiserver.*
+ rm -f $(DESTDIR)$(includedir)/libmapiserver.h
+ rm -f $(DESTDIR)$(libdir)/pkgconfig/libmapiserver.pc
+
+libmapiserver-distclean:
+ rm -f mapiproxy/libmapiserver.pc
+
+distclean:: libmapiserver-distclean
+
+mapiproxy/libmapiserver.$(SHLIBEXT).$(PACKAGE_VERSION): mapiproxy/libmapiserver/libmapiserver_oxcstor.po \
+ mapiproxy/libmapiserver/libmapiserver_oxcprpt.po \
+ mapiproxy/libmapiserver/libmapiserver_oxcfold.po \
+ mapiproxy/libmapiserver/libmapiserver_oxcnotif.po
+ @$(CC) -o $@ $(DSOOPT) -Wl,-soname,libmapiserver.$(SHLIBEXT).$(LIBMAPIPROXY_SO_VERSION) $^
+
+mapiproxy/libmapiserver.$(SHLIBEXT).$(LIBMAPISERVER_SO_VERSION): libmapiserver.$(SHLIBEXT).$(PACKAGE_VERSION)
+ ln -fs $< $@
+
+
+################
+# libmapistore
+################
+
+libmapistore: mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION) \
+ $(OC_MAPISTORE) \
+ mapistore_test
+
+libmapistore-install: $(OC_MAPISTORE_INSTALL)
+ $(INSTALL) -m 0755 mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)
+ ln -sf libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION) $(DESTDIR)$(libdir)/libmapistore.$(SHLIBEXT)
+ $(INSTALL) -d $(DESTDIR)$(includedir)/mapistore
+ $(INSTALL) -m 0644 mapiproxy/libmapistore/mapistore.h $(DESTDIR)$(includedir)/mapistore/
+ $(INSTALL) -m 0644 mapiproxy/libmapistore/mapistore_errors.h $(DESTDIR)$(includedir)/mapistore/
+ $(INSTALL) -m 0644 mapiproxy/libmapiserver.pc $(DESTDIR)$(libdir)/pkgconfig
+
+libmapistore-clean: $(OC_MAPISTORE_CLEAN)
+ rm -f mapiproxy/libmapistore/*.po mapiproxy/libmapistore/*.o
+ rm -f mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION)
+ rm -f mapiproxy/libmapistore.$(SHLIBEXT).$(LIBMAPISTORE_SO_VERSION)
+
+libmapistore-uninstall: $(OC_MAPISTORE_UNINSTALL)
+ rm -f $(DESTDIR)$(libdir)/libmapistore.*
+ rm -rf $(DESTDIR)$(includedir)/mapistore
+ rm -f $(DESTDIR)$(libdir)/pkgconfig/libmapistore.pc
+
+libmapistore-distclean: libmapistore-clean
+ rm -f mapiproxy/libmapistore.pc
+
+distclean:: libmapistore-distclean
+
+mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION): mapiproxy/libmapistore/mapistore_interface.po \
+ mapiproxy/libmapistore/mapistore_processing.po \
+ mapiproxy/libmapistore/mapistore_backend.po \
+ mapiproxy/libmapistore/mapistore_tdb_wrap.po
+ @$(CC) -o $@ $(DSOOPT) -Wl,-soname,libmapistore.$(SHLIBEXT).$(LIBMAPISTORE_SO_VERSION) $^ -L. $(LIBS)
+
+mapiproxy/libmapistore.$(SHLIBEXT).$(LIBMAPISTORE_SO_VERSION): libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+#####################
+# mapistore backends
+#####################
+
+mapistore_sqlite3: mapiproxy/libmapistore/backends/mapistore_sqlite3.$(SHLIBEXT)
+
+mapistore_sqlite3-install:
+ $(INSTALL) -d $(DESTDIR)$(libdir)/mapistore_backends
+ $(INSTALL) -m 0755 mapiproxy/libmapistore/backends/mapistore_sqlite3.$(SHLIBEXT) $(DESTDIR)$(libdir)/mapistore_backends/
+
+mapistore_sqlite3-uninstall:
+ rm -rf $(DESTDIR)$(libdir)/mapistore_backends
+
+mapistore_sqlite3-clean:
+ rm -f mapiproxy/libmapistore/backends/mapistore_sqlite3.o
+ rm -f mapiproxy/libmapistore/backends/mapistore_sqlite3.po
+
+clean:: mapistore_sqlite3-clean
+
+mapistore_sqlite3-distclean: mapistore_sqlite3-clean
+ rm -f mapiproxy/libmapistore/backends/mapistore_sqlite3.so
+
+distclean:: mapistore_sqlite3-distclean
+
+mapiproxy/libmapistore/backends/mapistore_sqlite3.$(SHLIBEXT): mapiproxy/libmapistore/backends/mapistore_sqlite3.po
+ @echo "Linking mapistore module $@"
+ @$(CC) $(SQLITE_CFLAGS) -o $@ $(DSOOPT) $^ -L. $(LIBS) $(SQLITE_LIBS) \
+ -Lmapiproxy mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+#######################
+# mapistore test tools
+#######################
+
+mapistore_test: bin/mapistore_test
+
+bin/mapistore_test: mapiproxy/libmapistore/tests/mapistore_test.o \
+ mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) -lpopt
+
+mapistore_clean:
+ rm -f mapiproxy/libmapistore/tests/*.o
+ rm -f bin/mapistore_test
+
+clean:: mapistore_clean
+
+####################
+# mapiproxy modules
+####################
+
+mapiproxy-modules: mapiproxy/modules/mpm_downgrade.$(SHLIBEXT) \
+ mapiproxy/modules/mpm_pack.$(SHLIBEXT) \
+ mapiproxy/modules/mpm_cache.$(SHLIBEXT) \
+ mapiproxy/modules/mpm_dummy.$(SHLIBEXT)
+
+mapiproxy-modules-install: mapiproxy-modules
+ $(INSTALL) -d $(DESTDIR)$(modulesdir)/dcerpc_mapiproxy/
+ $(INSTALL) -m 0755 mapiproxy/modules/mpm_downgrade.$(SHLIBEXT) $(DESTDIR)$(modulesdir)/dcerpc_mapiproxy/
+ $(INSTALL) -m 0755 mapiproxy/modules/mpm_pack.$(SHLIBEXT) $(DESTDIR)$(modulesdir)/dcerpc_mapiproxy/
+ $(INSTALL) -m 0755 mapiproxy/modules/mpm_cache.$(SHLIBEXT) $(DESTDIR)$(modulesdir)/dcerpc_mapiproxy/
+ $(INSTALL) -m 0755 mapiproxy/modules/mpm_dummy.$(SHLIBEXT) $(DESTDIR)$(modulesdir)/dcerpc_mapiproxy/
+
+mapiproxy-modules-uninstall:
+ rm -rf $(DESTDIR)$(modulesdir)/dcerpc_mapiproxy
+
+mapiproxy-modules-clean::
+ rm -f mapiproxy/modules/*.o mapiproxy/modules/*.po
+ rm -f mapiproxy/modules/*.so
+
+clean:: mapiproxy-modules-clean
+
+mapiproxy/modules/mpm_downgrade.$(SHLIBEXT): mapiproxy/modules/mpm_downgrade.po
+ @echo "Linking $@"
+ @$(CC) -o $@ $(DSOOPT) $^ -L. $(LIBS) -Lmapiproxy mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+mapiproxy/modules/mpm_pack.$(SHLIBEXT): mapiproxy/modules/mpm_pack.po \
+ ndr_mapi.po \
+ gen_ndr/ndr_exchange.po
+ @echo "Linking $@"
+ @$(CC) -o $@ $(DSOOPT) $^ -L. $(LIBS) -Lmapiproxy mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+mapiproxy/modules/mpm_cache.$(SHLIBEXT): mapiproxy/modules/mpm_cache.po \
+ mapiproxy/modules/mpm_cache_ldb.po \
+ mapiproxy/modules/mpm_cache_stream.po \
+ ndr_mapi.po \
+ gen_ndr/ndr_exchange.po
+ @echo "Linking $@"
+ @$(CC) -o $@ $(DSOOPT) $^ -L. $(LIBS) -Lmapiproxy mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+mapiproxy/modules/mpm_dummy.$(SHLIBEXT): mapiproxy/modules/mpm_dummy.po
+ @echo "Linking $@"
+ @$(CC) -o $@ $(DSOOPT) $^ -L. $(LIBS) -Lmapiproxy mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+
+####################
+# mapiproxy servers
+####################
+provision-install: python-install
+ $(INSTALL) -d $(DESTDIR)$(datadir)/setup/AD
+ $(INSTALL) -m 0644 setup/AD/oc_provision* $(DESTDIR)$(datadir)/setup/AD/
+ $(INSTALL) -m 0644 setup/AD/prefixMap.txt $(DESTDIR)$(datadir)/setup/AD/
+ $(INSTALL) -d $(DESTDIR)$(datadir)/setup/openchangedb
+ $(INSTALL) -m 0644 setup/openchangedb/oc_provision* $(DESTDIR)$(datadir)/setup/openchangedb/
+
+provision-uninstall: python-uninstall
+ rm -f $(DESTDIR)$(datadir)/setup/AD/oc_provision_configuration.ldif
+ rm -f $(DESTDIR)$(datadir)/setup/AD/oc_provision_schema.ldif
+ rm -f $(DESTDIR)$(datadir)/setup/AD/oc_provision_schema_modify.ldif
+ rm -f $(DESTDIR)$(datadir)/setup/AD/oc_provision_schema_ADSC.ldif
+ rm -f $(DESTDIR)$(datadir)/setup/AD/prefixMap.txt
+ rm -rf $(DESTDIR)$(datadir)/setup/AD
+ rm -rf $(DESTDIR)$(datadir)/setup/openchangedb
+
+mapiproxy-servers: mapiproxy/servers/exchange_nsp.$(SHLIBEXT) \
+ mapiproxy/servers/exchange_emsmdb.$(SHLIBEXT) \
+ mapiproxy/servers/exchange_ds_rfr.$(SHLIBEXT)
+
+mapiproxy-servers-install: mapiproxy-servers provision-install
+ $(INSTALL) -d $(DESTDIR)$(modulesdir)/dcerpc_mapiproxy_server/
+ $(INSTALL) -m 0755 mapiproxy/servers/exchange_nsp.$(SHLIBEXT) $(DESTDIR)$(modulesdir)/dcerpc_mapiproxy_server/
+ $(INSTALL) -m 0755 mapiproxy/servers/exchange_emsmdb.$(SHLIBEXT) $(DESTDIR)$(modulesdir)/dcerpc_mapiproxy_server/
+ $(INSTALL) -m 0755 mapiproxy/servers/exchange_ds_rfr.$(SHLIBEXT) $(DESTDIR)$(modulesdir)/dcerpc_mapiproxy_server/
+
+mapiproxy-servers-uninstall: provision-uninstall
+ rm -rf $(DESTDIR)$(modulesdir)/dcerpc_mapiproxy_server
+
+mapiproxy-servers-clean::
+ rm -f mapiproxy/servers/default/nspi/*.o mapiproxy/servers/default/nspi/*.po
+ rm -f mapiproxy/servers/default/emsmdb/*.o mapiproxy/servers/default/emsmdb/*.po
+ rm -f mapiproxy/servers/default/rfr/*.o mapiproxy/servers/default/rfr/*.po
+ rm -f mapiproxy/servers/*.so
+
+clean:: mapiproxy-servers-clean
+
+mapiproxy/servers/exchange_nsp.$(SHLIBEXT): mapiproxy/servers/default/nspi/dcesrv_exchange_nsp.po \
+ mapiproxy/servers/default/nspi/emsabp.po \
+ mapiproxy/servers/default/nspi/emsabp_tdb.po \
+ mapiproxy/servers/default/nspi/emsabp_property.po
+ @echo "Linking $@"
+ @$(CC) -o $@ $(DSOOPT) $^ -L. $(LIBS) -Lmapiproxy mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+mapiproxy/servers/exchange_emsmdb.$(SHLIBEXT): mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.po \
+ mapiproxy/servers/default/emsmdb/emsmdbp.po \
+ mapiproxy/servers/default/emsmdb/emsmdbp_object.po \
+ mapiproxy/servers/default/emsmdb/oxcstor.po \
+ mapiproxy/servers/default/emsmdb/oxcprpt.po \
+ mapiproxy/servers/default/emsmdb/oxcfold.po \
+ mapiproxy/servers/default/emsmdb/oxcnotif.po
+ @echo "Linking $@"
+ @$(CC) -o $@ $(DSOOPT) $^ -L. $(LIBS) -Lmapiproxy mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION) \
+ mapiproxy/libmapiserver.$(SHLIBEXT).$(PACKAGE_VERSION) \
+ mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+mapiproxy/servers/exchange_ds_rfr.$(SHLIBEXT): mapiproxy/servers/default/rfr/dcesrv_exchange_ds_rfr.po
+ @echo "Linking $@"
+ @$(CC) -o $@ $(DSOOPT) $^ -L $(LIBS) -Lmapiproxy mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION)
+
+#################################################################
+# Tools compilation rules
+#################################################################
+
+###################
+# openchangeclient
+###################
+
+openchangeclient: bin/openchangeclient
+
+openchangeclient-install: openchangeclient
+ $(INSTALL) -d $(DESTDIR)$(bindir)
+ $(INSTALL) -m 0755 bin/openchangeclient $(DESTDIR)$(bindir)
+
+openchangeclient-uninstall:
+ rm -f $(DESTDIR)$(bindir)/openchangeclient
+
+openchangeclient-clean::
+ rm -f bin/openchangeclient
+ rm -f utils/openchangeclient.o
+ rm -f utils/openchange-tools.o
+
+clean:: openchangeclient-clean
+
+bin/openchangeclient: utils/openchangeclient.o \
+ utils/openchange-tools.o \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION) \
+ libocpf.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) -lpopt
+
+
+##############
+# mapiprofile
+##############
+
+mapiprofile: bin/mapiprofile
+
+mapiprofile-install: mapiprofile
+ $(INSTALL) -d $(DESTDIR)$(bindir)
+ $(INSTALL) -m 0755 bin/mapiprofile $(DESTDIR)$(bindir)
+
+mapiprofile-uninstall:
+ rm -f $(DESTDIR)$(bindir)/mapiprofile
+
+mapiprofile-clean::
+ rm -f bin/mapiprofile
+ rm -f utils/mapiprofile.o
+
+clean:: mapiprofile-clean
+
+bin/mapiprofile: utils/mapiprofile.o \
+ utils/openchange-tools.o \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) -lpopt
+
+
+###################
+#openchangepfadmin
+###################
+
+openchangepfadmin: bin/openchangepfadmin
+
+openchangepfadmin-install: openchangepfadmin
+ $(INSTALL) -d $(DESTDIR)$(bindir)
+ $(INSTALL) -m 0755 bin/openchangepfadmin $(DESTDIR)$(bindir)
+
+openchangepfadmin-uninstall:
+ rm -f $(DESTDIR)$(bindir)/openchangepfadmin
+
+openchangepfadmin-clean::
+ rm -f bin/openchangepfadmin
+ rm -f utils/openchangepfadmin.o
+
+clean:: openchangepfadmin-clean
+
+bin/openchangepfadmin: utils/openchangepfadmin.o \
+ utils/openchange-tools.o \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION) \
+ libmapiadmin.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) $(LIBMAPIADMIN_LIBS) -lpopt
+
+
+###################
+# exchange2mbox
+###################
+
+exchange2mbox: bin/exchange2mbox
+
+exchange2mbox-install: exchange2mbox
+ $(INSTALL) -d $(DESTDIR)$(bindir)
+ $(INSTALL) -m 0755 bin/exchange2mbox $(DESTDIR)$(bindir)
+
+exchange2mbox-uninstall:
+ rm -f $(DESTDIR)$(bindir)/exchange2mbox
+
+exchange2mbox-clean::
+ rm -f bin/exchange2mbox
+ rm -f utils/exchange2mbox.o
+ rm -f utils/openchange-tools.o
+
+clean:: exchange2mbox-clean
+
+bin/exchange2mbox: utils/exchange2mbox.o \
+ utils/openchange-tools.o \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LIBS) $(LDFLAGS) -lpopt $(MAGIC_LIBS)
+
+
+###################
+# exchange2ical
+###################
+
+exchange2ical: bin/exchange2ical
+
+exchange2ical-install: exchange2ical
+ $(INSTALL) -d $(DESTDIR)$(bindir)
+ $(INSTALL) -m 0755 bin/exchange2ical $(DESTDIR)$(bindir)
+
+exchange2ical-uninstall:
+ rm -f $(DESTDIR)$(bindir)/exchange2ical
+
+exchange2ical-clean::
+ rm -f bin/exchange2ical
+ rm -f utils/exchange2ical/exchange2ical.o
+ rm -f utils/exchange2ical/exchange2ical_utils.o
+ rm -f utils/exchange2ical/exchange2ical_component.o
+ rm -f utils/exchange2ical/exchange2ical_property.o
+ rm -f utils/openchange-tools.o
+
+clean:: exchange2ical-clean
+
+bin/exchange2ical: utils/exchange2ical/exchange2ical.o \
+ utils/exchange2ical/exchange2ical_component.o \
+ utils/exchange2ical/exchange2ical_property.o \
+ utils/exchange2ical/exchange2ical_utils.o \
+ utils/openchange-tools.o \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LIBS) $(ICAL_LIBS) -lpopt
+
+
+###################
+# mapitest
+###################
+
+mapitest: libmapi \
+ utils/mapitest/proto.h \
+ bin/mapitest
+
+mapitest-install: mapitest
+ $(INSTALL) -d $(DESTDIR)$(bindir)
+ $(INSTALL) -m 0755 bin/mapitest $(DESTDIR)$(bindir)
+
+mapitest-uninstall:
+ rm -f $(DESTDIR)$(bindir)/mapitest
+
+mapitest-clean:
+ rm -f bin/mapitest
+ rm -f utils/mapitest/*.o
+ rm -f utils/mapitest/modules/*.o
+ifneq ($(SNAPSHOT), no)
+ rm -f utils/mapitest/proto.h
+ rm -f utils/mapitest/mapitest_proto.h
+endif
+
+clean:: mapitest-clean
+
+bin/mapitest: utils/mapitest/mapitest.o \
+ utils/openchange-tools.o \
+ utils/mapitest/mapitest_suite.o \
+ utils/mapitest/mapitest_print.o \
+ utils/mapitest/mapitest_stat.o \
+ utils/mapitest/mapitest_common.o \
+ utils/mapitest/module.o \
+ utils/mapitest/modules/module_oxcstor.o \
+ utils/mapitest/modules/module_oxcfold.o \
+ utils/mapitest/modules/module_oxomsg.o \
+ utils/mapitest/modules/module_oxcmsg.o \
+ utils/mapitest/modules/module_oxcprpt.o \
+ utils/mapitest/modules/module_oxctable.o \
+ utils/mapitest/modules/module_oxorule.o \
+ utils/mapitest/modules/module_oxcfxics.o \
+ utils/mapitest/modules/module_nspi.o \
+ utils/mapitest/modules/module_noserver.o \
+ utils/mapitest/modules/module_errorchecks.o \
+ utils/mapitest/modules/module_lcid.o \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) -lpopt
+
+utils/mapitest/proto.h: \
+ utils/mapitest/mapitest_suite.c \
+ utils/mapitest/mapitest_print.c \
+ utils/mapitest/mapitest_stat.c \
+ utils/mapitest/mapitest_common.c \
+ utils/mapitest/module.c \
+ utils/mapitest/modules/module_oxcstor.c \
+ utils/mapitest/modules/module_oxcfold.c \
+ utils/mapitest/modules/module_oxomsg.c \
+ utils/mapitest/modules/module_oxcmsg.c \
+ utils/mapitest/modules/module_oxcprpt.c \
+ utils/mapitest/modules/module_oxctable.c \
+ utils/mapitest/modules/module_oxorule.c \
+ utils/mapitest/modules/module_oxcfxics.c \
+ utils/mapitest/modules/module_nspi.c \
+ utils/mapitest/modules/module_noserver.c \
+ utils/mapitest/modules/module_errorchecks.c \
+ utils/mapitest/modules/module_lcid.c
+ @echo "Generating $@"
+ @./script/mkproto.pl --private=utils/mapitest/mapitest_proto.h --public=utils/mapitest/proto.h $^
+
+#####################
+# openchangemapidump
+#####################
+
+openchangemapidump: bin/openchangemapidump
+
+openchangemapidump-install: openchangemapidump
+ $(INSTALL) -d $(DESTDIR)$(bindir)
+ $(INSTALL) -m 0755 bin/openchangemapidump $(DESTDIR)$(bindir)
+
+openchangemapidump-uninstall:
+ rm -f bin/openchangemapidump
+ rm -f $(DESTDIR)$(bindir)/openchangemapidump
+
+openchangemapidump-clean::
+ rm -f bin/openchangemapidump
+ rm -f utils/backup/openchangemapidump.o
+ rm -f utils/backup/openchangebackup.o
+
+clean:: openchangemapidump-clean
+
+bin/openchangemapidump: utils/backup/openchangemapidump.o \
+ utils/backup/openchangebackup.o \
+ utils/openchange-tools.o \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) -lpopt
+
+
+###############
+# schemaIDGUID
+###############
+
+schemaIDGUID: bin/schemaIDGUID
+
+schemaIDGUID-install: schemaIDGUID
+ $(INSTALL) -m 0755 bin/schemaIDGUID $(DESTDIR)$(bindir)
+
+schemaIDGUID-uninstall:
+ rm -f $(DESTDIR)$(bindir)/schemaIDGUID
+
+schemaIDGUID-clean::
+ rm -f bin/schemaIDGUID
+ rm -f utils/schemaIDGUID.o
+
+clean:: schemaIDGUID-clean
+
+bin/schemaIDGUID: utils/schemaIDGUID.o
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LIBS)
+
+
+##################
+# locale_codepage
+##################
+
+locale_codepage: bin/locale_codepage
+
+locale_codepage-install: locale_codepage
+ $(INSTALL) -m 0755 bin/locale_codepage $(DESTDIR)$(bindir)
+
+locale_codepage-uninstall:
+ rm -f bin/locale_codepage
+ rm -f $(DESTDIR)$(bindir)/locale_codepage
+
+locale_codepage-clean::
+ rm -f bin/locale_codepage
+ rm -f libmapi/tests/locale_codepage.o
+
+clean:: locale_codepage-clean
+
+bin/locale_codepage: libmapi/tests/locale_codepage.o libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) -lpopt
+
+###################
+# python code
+###################
+
+pythonscriptdir = python
+
+pymapi: $(pythonscriptdir)/mapi.$(SHLIBEXT)
+
+pymapi/%: CFLAGS+=`$(PYTHON_CONFIG) --cflags` -fPIC
+
+$(pythonscriptdir)/mapi.$(SHLIBEXT): $(patsubst %.c,%.o,$(wildcard pymapi/*.c)) libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)
+ $(CC) -o $@ $^ `$(PYTHON_CONFIG) --libs` $(DSOOPT)
+
+pymapi-install::
+ $(INSTALL) -d $(DESTDIR)$(PYCDIR)
+ $(INSTALL) -m 0755 $(pythonscriptdir)/mapi.$(SHLIBEXT) $(DESTDIR)$(PYCDIR)
+
+pymapi-uninstall::
+ rm -f $(DESTDIR)$(PYCDIR)/mapi.$(SHLIBEXT)
+
+PYTHON_MODULES = $(patsubst $(pythonscriptdir)/%,%,$(shell find $(pythonscriptdir) -name "*.py"))
+
+python-install::
+ @echo "Installing Python modules"
+ @$(foreach MODULE, $(PYTHON_MODULES), \
+ $(INSTALL) -d $(DESTDIR)$(pythondir)/$(dir $(MODULE)); \
+ $(INSTALL) -m 0644 $(pythonscriptdir)/$(MODULE) $(DESTDIR)$(pythondir)/$(dir $(MODULE)); \
+ )
+
+python-uninstall::
+ rm -rf $(DESTDIR)$(pythondir)/openchange
+
+EPYDOC_OPTIONS = --no-private --url http://www.openchange.org/ --no-sourcecode
+
+epydoc::
+ PYTHONPATH=$(pythonscriptdir):$(PYTHONPATH) epydoc $(EPYDOC_OPTIONS) openchange
+
+check-python:
+ PYTHONPATH=$(pythonscriptdir):$(PYTHONPATH) trial openchange
+
+check:: check-python
+
+###################
+# nagios plugin
+###################
+
+nagiosdir = $(libdir)/nagios
+
+installnagios:
+ $(INSTALL) -d $(DESTDIR)$(nagiosdir)
+ $(INSTALL) -m 0755 script/check_exchange $(DESTDIR)$(nagiosdir)
+
+###################
+# libmapi examples
+###################
+examples:
+ cd doc/examples && make && cd ${OLD_PWD}
+
+examples-clean::
+ rm -f doc/examples/mapi_sample1
+ rm -f doc/examples/fetchappointment
+ rm -f doc/examples/fetchmail
+
+clean:: examples-clean
+
+examples-install examples-uninstall:
+
+manpages = \
+ doc/man/man1/exchange2mbox.1 \
+ doc/man/man1/mapiprofile.1 \
+ doc/man/man1/openchangeclient.1 \
+ doc/man/man1/openchangepfadmin.1 \
+ $(wildcard apidocs/man/man3/*)
+
+installman: doxygen
+ @./script/installman.sh $(DESTDIR)$(mandir) $(manpages)
+
+
+uninstallman:
+ @./script/uninstallman.sh $(DESTDIR)$(mandir) $(manpages)
+
+doxygen:
+ @if test ! -d apidocs ; then \
+ echo "Doxify API documentation: HTML and man pages"; \
+ mkdir -p apidocs/html; \
+ mkdir -p apidocs/man; \
+ $(DOXYGEN) Doxyfile; \
+ $(DOXYGEN) libmapi/Doxyfile; \
+ $(DOXYGEN) libmapiadmin/Doxyfile; \
+ $(DOXYGEN) libocpf/Doxyfile; \
+ $(DOXYGEN) libmapi++/Doxyfile; \
+ $(DOXYGEN) mapiproxy/Doxyfile; \
+ $(DOXYGEN) utils/mapitest/Doxyfile; \
+ cp -f doc/doxygen/index.html apidocs/html; \
+ cp -f doc/doxygen/pictures/* apidocs/html/overview; \
+ cp -f doc/doxygen/pictures/* apidocs/html/libmapi; \
+ cp -f doc/doxygen/pictures/* apidocs/html/libmapiadmin; \
+ cp -f doc/doxygen/pictures/* apidocs/html/libmapi++; \
+ cp -f doc/doxygen/pictures/* apidocs/html/libocpf; \
+ cp -f doc/doxygen/pictures/* apidocs/html/mapitest; \
+ cp -f doc/doxygen/pictures/* apidocs/html/mapiproxy; \
+ cp -f mapiproxy/documentation/pictures/* apidocs/html/mapiproxy;\
+ rm -f apidocs/man/man3/todo.3; \
+ rm -f apidocs/man/man3/bug.3; \
+ rm -f apidocs/man/man3/*.c.3; \
+ fi
+
+etags:
+ etags `find $(srcdir) -name "*.[ch]"`
+
+ctags:
+ ctags `find $(srcdir) -name "*.[ch]"`
+
+swigperl-all:
+ @echo "Creating Perl bindings ..."
+ @$(MAKE) -C swig/perl all
+
+swigperl-install:
+ @echo "Install Perl bindings ..."
+ @$(MAKE) -C swig/perl install
+
+swigperl-uninstall:
+ @echo "Uninstall Perl bindings ..."
+ @$(MAKE) -C swig/perl uninstall
+
+distclean::
+ @$(MAKE) -C swig/perl distclean
+
+clean::
+ @echo "Cleaning Perl bindings ..."
+ @$(MAKE) -C swig/perl clean
+
+.PRECIOUS: exchange.h gen_ndr/ndr_exchange.h gen_ndr/ndr_exchange.c gen_ndr/ndr_exchange_c.c gen_ndr/ndr_exchange_c.h
+
+test:: check
+
+check:: torture/openchange.$(SHLIBEXT) libmapi.$(SHLIBEXT).$(LIBMAPI_SO_VERSION)
+ # FIXME: Set up server
+ LD_LIBRARY_PATH=`pwd` $(SMBTORTURE) --load-module torture/openchange.$(SHLIBEXT) ncalrpc: OPENCHANGE
+ ./bin/mapitest --mapi-calls
+
+# This should be the last line in the makefile since other distclean rules may
+# need config.mk
+distclean::
+ rm -f config.mk
Added: trunk/openchange/README
===================================================================
--- trunk/openchange/README (rev 0)
+++ trunk/openchange/README 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,138 @@
+This is the README file for OpenChange
+
+ABOUT OPENCHANGE
+
+The OpenChange Project aims to provide a portable Open Source
+implementation of Microsoft Exchange Server and Exchange
+protocols. Exchange is a groupware server designed to work with
+Microsoft Outlook, and providing features such as a messaging server,
+shared calendars, contact databases, public folders, notes and tasks.
+
+The OpenChange project has three goals:
+* To provide a library for interoperability with Exchange protocols, and
+to assist implementors to use this to create groupware that
+interoperates with both Exchange and other OpenChange-based software.
+
+* To provide an alternative to Microsoft Exchange Server which uses
+native Exchange protocols and provides exactly equivalent
+functionality when viewed from Microsoft Outlook clients.
+
+* To develop a body of knowledge about the most popular groupware
+protocols in use commercially today in order to promote development of
+a documented and unencumbered standard, with all the benefits that
+standards bring.
+
+
+DOCUMENTATION
+
+There are two sources of documentation - text files in the doc/
+directory, and API documentation generated from the source files using
+doxygen. You can create the API documentation yourself (using "make
+doxygen" at the top level) or you can refer to the copy on the
+OpenChange web site at
+http://apidocs.openchange.org/overview/index.html
+
+doc/howto.txt contains instructions on how to install and set up
+client libraries, client utilities and the server / proxy parts of
+OpenChange.
+doc/man/ contains man(1) pages for several OpenChange utilities. Note
+that man pages for programming (i.e. the parts that would appear in
+man3) are generated by doxygen, and will be found in apidocs/ if you
+generate the documentation yourself.
+doc/doxygen/ provides static content used as part of the doxygen API
+documentation generation process.
+doc/examples/ provides programming examples for libmapi.
+
+
+STRUCTURE
+[TODO: add description of each directory]
+- bin/ This directory is created during the build process. It
+contains the binaries (executable programs) that are compiled during
+the "make" step. The source for most of these is in the utils/
+directory, described below.
+
+- doc/ This directory contains documentation - see description above
+(in DOCUMENTATION) for the various contents of this directory.
+
+- gen_ndr/ This directory contains routines for handling the Network
+Data Representation (NDR) for various Exhange RPC calls. The contents
+of this directory are generated (using Samba's pidl IDL compiler) at
+build time. The main input file is exchange.idl (see top level
+directory).
+
+- libmapi/ This directory contains the main client-side library,
+called libmapi. libmapi closely reflects the underlying protocol
+operations (Exchange RPC) being performed between the client and the
+server. For more information, consult the API documentation (either
+build yourself, or online at
+http://apidocs.openchange.org/libmapi/index.html)
+
+- libmapi++/ This directory contains C++ bindings for libmapi. It is
+not a replacement for libmapi, but is intended to provide easier
+access to many libmapi functions for C++ programmers. For more
+information, consult the API documentation (either build yourself, or
+online at http://apidocs.openchange.org/libmapi++/index.html)
+
+- libmapiadmin/ This directory contains client-side library functions
+for administering OpenChange or Exchange servers. For more
+information, consult the API documentation (either build yourself, or
+online at http://apidocs.openchange.org/libmapiadmin/index.html). If
+you are looking for a program you can run, instead of library
+functions to write your own program, "openchangepfadmin" might be of
+interest.
+
+- libocpf/ This directory contains library functions for the
+OpenChange Property Files (OCPF). This allows building of mail
+messages, address book entries, appointments and similar objects from
+text files. For more information, consult the API documentation
+(either build yourself, or online at
+http://apidocs.openchange.org/libocpf/index.html)
+
+- mapiproxy/ This directory provides an Exchange RPC proxy. You can
+use this to provide transparent proxying, or to change / monitor
+connections between the client and server. For more information,
+consult the API documentation (either build yourself, or online at
+http://apidocs.openchange.org/mapiproxy/index.html)
+
+- pymapi/ This directory contains hand-written python bindings for
+libmapi functions. There are also SWIG generated bindings - see the
+swig/ directory below.
+
+- python/ This directory contains python scripts used to set up
+("provision") the server side. They are not required for the client
+side.
+
+- samba4/ This directory will be created during the build process if
+you call "make samba" or execute the ./script/installsamba4.sh
+script. It is used to build samba4, if required.
+
+- script/ This directory contains a range of scripts useful for
+development or use of OpenChange. [TODO: document the scripts -
+perhaps write script/README?]
+
+- setup/ This directory contains data for setting up ("provisioning")
+the server.
+
+- swig/ This directory contains support for SWIG
+(http://www.swig.org/) bindings generation.
+
+- testprogs/ This directory contains developer test tools
+
+- torture/ This directory contains modules to test openchange
+functionality using the Samba "smbtorture" framework. This is partly
+obsoleted by the standalone "mapitest" suite - see utils/mapitest/ below.
+
+- utils/ This directory contains the source code for a range of
+applications / utilities that can be used to interact with an exchange
+server. They include:
+ - utils/backup/ backup and restore tools
+ - utils/exchange2ical/ converts Exchange calendar into an ICal file
+ - utils/exchange2mbox two way conversion between Exchange mail and mbox
+ - utils/mapiprofile set up client side profiles (login information)
+ - utils/mapitest/ test tools for libmapi functionality
+ - utils/mapitrace/
+ - utils/openchangeclient command line client for Exchange RPC
+ - utils/openchangepfadmin Public Folders admin tools and
+ administration of Exchange users (add/del)
+ - utils/schemaIDGUID
+For more information on these tools, refer to the man(1) pages in doc/man/man1
Added: trunk/openchange/VERSION
===================================================================
--- trunk/openchange/VERSION (rev 0)
+++ trunk/openchange/VERSION 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,29 @@
+########################################################
+# OPENCHANGE Version #
+# #
+# script/mkversion.sh #
+# will use this file to create #
+# libmapi/version.h #
+# #
+########################################################
+
+########################################################
+# To mark SVN snapshots this should be set to 'yes' #
+# in the development BRANCH, and set to 'no' only in #
+# the release BRANCH #
+# #
+# <MAJOR>.<MINOR>[...]-SVN-build-xxx #
+# #
+# e.g. OPENCHANGE_VERSION_IS_SVN_SNAPSHOT=yes #
+# -> "0.7-SVN-build-199" #
+########################################################
+OPENCHANGE_VERSION_IS_SVN_SNAPSHOT=yes
+
+
+#############################################################
+# This is for specifying a release nickname #
+# #
+# e.g. OPENCHANGE_VERSION_RELEASE_NICKNAME=Nicky Nickname #
+# -> "0.7 (Nicky Nickname)" #
+#############################################################
+OPENCHANGE_VERSION_RELEASE_NICKNAME=Cochrane
Added: trunk/openchange/autogen.sh
===================================================================
--- trunk/openchange/autogen.sh (rev 0)
+++ trunk/openchange/autogen.sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+# Run this script to build openchange from SVN
+
+## insert all possible names (only works with
+## autoconf 2.x
+TESTAUTOHEADER="autoheader autoheader-2.53 autoheader2.50 autoheader259 autoheader253"
+TESTAUTOCONF="autoconf autoconf-2.53 autoconf2.50 autoconf259 autoconf253"
+TESTACLOCAL="aclocal aclocal19"
+
+AUTOHEADERFOUND="0"
+AUTOCONFFOUND="0"
+ACLOCALFOUND="0"
+
+##
+## Look for autoheader
+##
+for i in $TESTAUTOHEADER; do
+ if which $i > /dev/null 2>&1; then
+ if test `$i --version | head -n 1 | cut -d. -f 2 | tr -d [:alpha:]` -ge 53; then
+ AUTOHEADER=$i
+ AUTOHEADERFOUND="1"
+ break
+ fi
+ fi
+done
+
+##
+## Look for autoconf
+##
+
+for i in $TESTAUTOCONF; do
+ if which $i > /dev/null 2>&1; then
+ if test `$i --version | head -n 1 | cut -d. -f 2 | tr -d [:alpha:]` -ge 53; then
+ AUTOCONF=$i
+ AUTOCONFFOUND="1"
+ break
+ fi
+ fi
+done
+
+##
+## Look for aclocal
+##
+for i in $TESTACLOCAL; do
+ if which $i > /dev/null 2>&1; then
+ ACLOCAL=$i
+ ACLOCALFOUND="1"
+ break
+ fi
+done
+
+
+##
+## do we have it?
+##
+if test "$AUTOCONFFOUND" = "0" -o "$AUTOHEADERFOUND" = "0"; then
+ echo "$0: need autoconf 2.53 or later to build samba from SVN" >&2
+ exit 1
+fi
+
+if test "$ACLOCALFOUND" = "0"; then
+ echo "$0: aclocal not found" >&2
+ exit 1
+fi
+
+
+rm -rf autom4te*.cache
+rm -f configure include/config.h*
+
+echo "$0: running $ACLOCAL"
+$ACLOCAL || exit 1
+
+echo "$0: running $AUTOHEADER"
+$AUTOHEADER || exit 1
+
+echo "$0: running $AUTOCONF"
+$AUTOCONF || exit 1
+
+
+rm -rf autom4te*.cache
+
+echo "Now run ./configure and make"
+exit 0
Property changes on: trunk/openchange/autogen.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/config.guess
===================================================================
--- trunk/openchange/config.guess (rev 0)
+++ trunk/openchange/config.guess 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1464 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-08-03'
+
+# This file 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/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per at bothner.com>.
+# Please send patches to <config-patches at gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi at noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee at wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel at ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes at openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf at swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green at stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green at stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ *86) UNAME_PROCESSOR=i686 ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches at gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Property changes on: trunk/openchange/config.guess
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/config.mk.in
===================================================================
--- trunk/openchange/config.mk.in (rev 0)
+++ trunk/openchange/config.mk.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,109 @@
+# Mode (Release or snapshot?)
+SNAPSHOT=@OPENCHANGE_VERSION_IS_SVN_SNAPSHOT@
+
+# Binary
+CC=@CC@
+CXX=@CXX@
+BISON=@BISON@
+FLEX=@FLEX@
+PIDL=@PIDL@
+PERL=@PERL@
+DOXYGEN=@DOXYGEN@
+INSTALL=@INSTALL@
+PYTHON=@PYTON@
+PYTHON_CONFIG=@PYTHON_CONFIG@
+SMBTORTURE=@SMBTORTURE@
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+modulesdir=@modulesdir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+includedir=@includedir@
+mandir=@mandir@
+top_builddir=@builddir@
+pythondir=@pythondir@
+
+sambaprefix=@sambaprefix@
+
+DSOOPT=-shared -fPIC
+CFLAGS=@CFLAGS@ -I. -O3 -Wall -Wmissing-prototypes -Wstrict-prototypes -g3 -Wp,-D_FORTIFY_SOURCE=2 \
+ -fstrict-aliasing -Wstrict-aliasing=3 \
+ -DDEFAULT_LDIF=\"$(datadir)/setup/profiles\" \
+ -DMAPISTORE_BACKEND_INSTALLDIR=\"$(libdir)/mapistore_backends\" \
+ -DMAPISTORE_MAPPING_PATH=\"$(prefix)/private/mapistore\"
+
+# This value should be determined by configure at some point
+SHLIBEXT=so
+PACKAGE_VERSION=@PACKAGE_VERSION@
+
+# Portability hack...
+CFLAGS+=-Duint_t="unsigned int"
+
+CFLAGS+=@SAMBA_CFLAGS@ @LDB_CFLAGS@ @TALLOC_CFLAGS@
+LIBS+=@SAMBA_LIBS@ @LDB_LIBS@ @TALLOC_LIBS@
+LDFLAGS+=@LDFLAGS@
+
+# Assign CFLAGS to CXXFLAGS
+CXXFLAGS=@CFLAGS@ -I. @SAMBA_CFLAGS@ @LDB_CFLAGS@ @TALLOC_CFLAGS@
+
+# OPENCHANGE LIBRARIES
+OC_IDL=@OC_IDL@
+OC_LIBS=@OC_LIBS@
+OC_LIBS_INSTALL=@OC_LIBS_INSTALL@
+OC_LIBS_UNINSTALL=@OC_LIBS_UNINSTALL@
+OC_LIBS_INSTALLPC=@OC_LIBS_INSTALLPC@
+OC_LIBS_INSTALLHEADER=@OC_LIBS_INSTALLHEADER@
+OC_LIBS_INSTALLLIB=@OC_LIBS_INSTALLLIB@
+LIBMAPIADMIN_LIBS+=@SAMR_LIBS@
+LIBMAPIADMIN_CFLAGS=@SAMR_CFLAGS@
+
+
+# TORTURE
+OC_TORTURE=@OC_TORTURE@
+OC_TORTURE_INSTALL=@OC_TORTURE_INSTALL@
+OC_TORTURE_UNINSTALL=@OC_TORTURE_UNINSTALL@
+SAMBA_MODULESDIR=${sambaprefix}/modules/
+TORTURE_MODULESDIR=${SAMBA_MODULESDIR}torture/
+SERVER_MODULESDIR=${SAMBA_MODULESDIR}dcerpc_server/
+
+# TOOLS
+OC_TOOLS=@OC_TOOLS@
+OC_TOOLS_INSTALL=@OC_TOOLS_INSTALL@
+OC_TOOLS_UNINSTALL=@OC_TOOLS_UNINSTALL@
+MAGIC_LIBS=@MAGIC_LIBS@
+ICAL_CFLAGS=@ICAL_CFLAGS@
+ICAL_LIBS=@ICAL_LIBS@
+
+# SERVER
+OC_SERVER=@OC_SERVER@
+OC_SERVER_INSTALL=@OC_SERVER_INSTALL@
+OC_SERVER_UNINSTALL=@OC_SERVER_UNINSTALL@
+
+# MAPISTORE BACKENDS
+OC_MAPISTORE=@OC_MAPISTORE@
+OC_MAPISTORE_CLEAN=@OC_MAPISTORE_CLEAN@
+OC_MAPISTORE_INSTALL=@OC_MAPISTORE_INSTALL@
+OC_MAPISTORE_UNINSTALL=@OC_MAPISTORE_UNINSTALL@
+
+SQLITE_CFLAGS=@SQLITE_CFLAGS@
+SQLITE_LIBS=@SQLITE_LIBS@
+
+# SWIG
+SWIGDIRS-ALL=@SWIGDIRSALL@
+SWIGDIRS-INSTALL=@SWIGDIRSINSTALL@
+SWIGDIRS-UNINSTALL=@SWIGDIRSUNINSTALL@
+
+SWIG=@SWIG@
+
+PERL5DIR=@PERL5DIR@
+
+# Python
+PYMAPIALL=@PYMAPIALL@
+PYMAPIINSTALL=@PYMAPIINSTALL@
+PYMAPIUNINSTALL=@PYMAPIUNINSTALL@
+
+PYCDIR=@PYCDIR@
+
Added: trunk/openchange/config.sub
===================================================================
--- trunk/openchange/config.sub (rev 0)
+++ trunk/openchange/config.sub 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1577 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-07-08'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file 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/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches at gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | ms1 \
+ | msp430 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m32c)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | ms1-* \
+ | msp430-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ m32c-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Property changes on: trunk/openchange/config.sub
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/configure.ac
===================================================================
--- trunk/openchange/configure.ac (rev 0)
+++ trunk/openchange/configure.ac 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,580 @@
+# Simple configuration script for OpenChange
+# Written by Jelmer Vernooij <jelmer at openchange.org>
+
+AC_PREREQ(2.57)
+AC_INIT(openchange, 0.8, [openchange at openchange.org])
+AC_CONFIG_HEADER([config.h])
+AM_INIT_AUTOMAKE
+AC_DEFINE(_GNU_SOURCE, 1, [Use GNU extensions])
+
+PKG_PROG_PKG_CONFIG([0.20])
+
+dnl #################################################################
+dnl Check for OS dependent options
+dnl #################################################################
+AC_CANONICAL_HOST
+
+case "${host}" in
+ *freebsd*) BUILD_FOR_FREEBSD=yes ;;
+esac
+
+#
+# OC_CHECK_SAMBA_PATH([PATH],[action-if-found],[action-if-not-found])
+# -------------------------------------------------------------------
+AC_DEFUN([OC_CHECK_SAMBA_PATH],
+[
+ old_PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
+ PKG_CONFIG_PATH="$1/lib/pkgconfig"
+ export PKG_CONFIG_PATH
+ PKG_CHECK_EXISTS([samba-hostconfig], [found=1], [found=0])
+ PKG_CONFIG_PATH="$old_PKG_CONFIG_PATH"
+ if test $found = 1; then
+ ifelse([$2],[], [echo -n ], [$2])
+ ifelse([$3],[],[],[else
+ [$3]])
+ fi
+])
+
+AC_MSG_CHECKING([for samba 4])
+
+AC_ARG_WITH(samba,
+[AC_HELP_STRING([--with-samba], [Override location Samba is installed])],
+[
+ sambaprefix="$withval"
+],[
+ for p in "$prefix" /usr/local/samba /usr/local /usr
+ do
+ OC_CHECK_SAMBA_PATH($p, [sambaprefix="$p"])
+ done
+])
+AC_SUBST(sambaprefix)
+OC_CHECK_SAMBA_PATH($sambaprefix,[], AC_MSG_ERROR(Samba 4 not found))
+AC_MSG_RESULT($sambaprefix)
+PKG_CONFIG_PATH="$sambaprefix/lib/pkgconfig:$PKG_CONFIG_PATH"
+PATH="$sambaprefix/bin:$PATH"
+
+#
+# OC_SETVAL([NAME])
+# -----------------
+AC_DEFUN([OC_SETVAL],
+[
+AC_ARG_VAR([NAME], [var name])
+if test x"$enable_$1" = x""; then
+ enable_$1="no"
+fi[]
+])
+
+#
+# OC_CHECK_SAMBA_VERSION([RELEASE],[VERSION], [action-if-found],[action-if-not-found],
+# [action-if-cross-compiling])
+# ------------------------------------------------------------------------------------
+AC_DEFUN([OC_CHECK_SAMBA_VERSION], [
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <samba/version.h>
+int main() { if (!strcmp(SAMBA_VERSION_STRING, "$1") || !strcmp(SAMBA_VERSION_STRING, "$2")) {return 0; } else { return -1;} }
+]])],[$3],[
+ ifelse([$4],[],[AC_MSG_WARN([The Samba4 version installed on your system doesn't meet OpenChange requirements ($1 or $2).])],[$4])],[$5])
+])
+
+#
+# OC_RULE_ADD([NAME], [TYPE])
+# ---------------------------
+AC_DEFUN([OC_RULE_ADD],
+[
+AC_ARG_VAR([NAME], [rule name])
+AC_ARG_VAR([TYPE], [rule type])
+if test "x$1_set" != "xset"; then
+ case "$2" in
+ LIBS)
+ OC_$2+=" $1"
+ OC_$2_INSTALL+=" $1-install"
+ OC_$2_UNINSTALL+=" $1-uninstall"
+ OC_$2_INSTALLPC+=" $1-installpc"
+ OC_$2_INSTALLHEADER+=" $1-installheader"
+ OC_$2_INSTALLLIB+=" $1-installlib"
+
+ AC_SUBST(OC_$2_INSTALLPC)
+ AC_SUBST(OC_$2_INSTALLHEADER)
+ AC_SUBST(OC_$2_INSTALLLIB)
+ ;;
+ TOOLS|TORTURE)
+ OC_$2+=" $1"
+ OC_$2_INSTALL+=" $1-install"
+ OC_$2_UNINSTALL+=" $1-uninstall"
+ ;;
+ SERVER|MAPISTORE)
+ OC_$2+=" $1"
+ OC_$2_CLEAN+="$1-clean"
+ OC_$2_INSTALL+=" $1-install"
+ OC_$2_UNINSTALL+=" $1-uninstall"
+ ;;
+ esac
+
+ AC_SUBST(OC_$2)
+ AC_SUBST(OC_$2_CLEAN)
+ AC_SUBST(OC_$2_INSTALL)
+ AC_SUBST(OC_$2_UNINSTALL)
+
+ enable_$1="yes"
+
+fi[]
+])
+
+dnl ###########################################################################
+dnl FreeBSD installs some libraries such as libpopt in the non default
+dnl search path /usr/local/{include,lib}. This nasty hack ensures
+dnl configure.ac will find the library if available and additional
+dnl flags be correctly added while compiling.
+dnl ###########################################################################
+if test x"$BUILD_FOR_FREEBSD" = x"yes"; then
+ CFLAGS+=" -I/usr/local/include"
+ LDFLAGS+=" -L/usr/local/lib"
+fi
+
+dnl ----------------------------------------------------------------------------
+dnl Check for comparison_fn_t
+dnl ----------------------------------------------------------------------------
+AC_CHECK_TYPE(comparison_fn_t,
+[AC_DEFINE(HAVE_COMPARISON_FN_T, 1,[Whether or not we have comparison_fn_t])])
+
+
+dnl ###########################################################################
+dnl libmapi and required dependencies
+dnl ###########################################################################
+
+dnl ---------------------------------------------------------------------------
+dnl Check for CC
+dnl ---------------------------------------------------------------------------
+AC_PROG_CC
+
+dnl ---------------------------------------------------------------------------
+dnl Check for install
+dnl ---------------------------------------------------------------------------
+AC_PROG_INSTALL
+
+dnl ---------------------------------------------------------------------------
+dnl Check for Perl
+dnl ---------------------------------------------------------------------------
+. `dirname $0`/VERSION
+AC_SUBST(OPENCHANGE_VERSION_IS_SVN_SNAPSHOT)
+
+AC_PATH_PROG(PERL, perl)
+
+if test x"$PERL" = x""; then
+ AC_MSG_WARN([No version of perl was found!])
+ AC_MSG_ERROR([Please install perl http://www.perl.com])
+fi
+AC_SUBST(PERL)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for Pidl
+dnl ---------------------------------------------------------------------------
+AC_PATH_PROG(PIDL, pidl)
+
+if test x"$PIDL" = x""; then
+ AC_MSG_WARN([No version of pidl was found!])
+ AC_MSG_ERROR([Please install pidl])
+fi
+AC_SUBST(PIDL)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for Python
+dnl ---------------------------------------------------------------------------
+
+AC_PATH_PROG(PYTHON,python)
+AC_PATH_PROG(PYTHON_CONFIG,python-config)
+
+AC_MSG_CHECKING(python library directory)
+pythondir=`$PYTHON -c "from distutils import sysconfig; print sysconfig.get_python_lib(1, 0, '\\${prefix}')"`
+AC_MSG_RESULT($pythondir)
+
+AC_SUBST(pythondir)
+
+dnl ----------------------------------------------------------------------------
+dnl Check for Flex
+dnl Flex version < 2.5.35 is fine but 2.5.4 beta is not. This is the
+dnl default version provided under FreeBSD or RHL5
+dnl ----------------------------------------------------------------------------
+if test x"$OPENCHANGE_VERSION_IS_SVN_SNAPSHOT" = x"yes"; then
+ AC_ARG_VAR([FLEX], [Location of the flex program.])
+ AC_CHECK_PROG([FLEX], [flex], [flex])
+
+ if test x"$FLEX" = x""; then
+ AC_MSG_WARN([No version of flex was found!])
+ AC_MSG_ERROR([Please install flex])
+ else
+ V=`$FLEX --version | awk '{print $NF}'`
+ W=`echo $V | awk -F. '{if (((($1*100 + $2)*100 + $3) > 20535) || $3 == 4) print "no"}'`
+ if test "x$W" != x ; then
+ AC_MSG_WARN([Adjust your FLEX environment variable])
+ AC_MSG_ERROR([Flex version 2.5.35 or below is needed. You have $V])
+ fi
+ fi
+
+ AC_SUBST(FLEX)
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Samba4 modules
+dnl ---------------------------------------------------------------------------
+PKG_CHECK_MODULES(TALLOC, talloc)
+PKG_CHECK_MODULES(SAMBA, dcerpc ndr samba-hostconfig)
+PKG_CHECK_MODULES(LDB, ldb)
+
+dnl ---------------------------------------------------------------------------
+dnl Check a particular Samba4 git revision
+dnl ---------------------------------------------------------------------------
+
+oc_save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS `$PKG_CONFIG --cflags-only-I samba-hostconfig`"
+AC_CHECK_HEADER([samba/version.h],, AC_MSG_ERROR([Could not find Samba4 headers. Re-run ./configure with --with-samba=XXX where
+ XXX is the prefix that Samba4 was installed to.]))
+
+. `dirname $0`/script/samba4_ver.sh
+
+OC_CHECK_SAMBA_VERSION([$SAMBA4_RELEASE],[$SAMBA4_GIT_VER-GIT-$SAMBA4_GIT_REV])
+CPPFLAGS="$oc_save_CPPFLAGS"
+
+dnl ---------------------------------------------------------------------------
+dnl Finally add libmapi to the library list
+dnl ---------------------------------------------------------------------------
+OC_RULE_ADD(libmapi, LIBS)
+
+dnl nasty hack: only compile IDL if we have a library
+dnl libraries require libmapi and libmapi require IDL
+OC_IDL="idl"
+AC_SUBST(OC_IDL)
+
+dnl ###########################################################################
+dnl libmapi++ dependencies
+dnl ###########################################################################
+
+dnl ---------------------------------------------------------------------------
+dnl Check for g++
+dnl ---------------------------------------------------------------------------
+AC_CACHE_CHECK([C++ compiler availability], [ac_cv_libmapixx_gxx_works],
+ [
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE([int main() { return 0; }],
+ [ac_cv_libmapixx_gxx_works=yes],
+ [ac_cv_libmapixx_gxx_works=no])
+ AC_LANG_POP([C++])
+ ])
+
+dnl ---------------------------------------------------------------------------
+dnl Check for boost-thread
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_VAR([BOOST_LIB_SUFFIX], [Boost library name suffix])
+
+AC_CACHE_CHECK([for boost_thread$BOOST_LIB_SUFFIX library], [ov_cv_boost_thread],
+ [
+ ov_cv_boost_thread=no
+ ov_save_LIBS=$LIBS
+ LIBS="-lboost_thread$BOOST_LIB_SUFFIX $LIBS"
+ AC_LANG_PUSH([C++])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <boost/thread.hpp>]],
+ [[boost::thread t]])],
+ [ov_cv_boost_thread=yes])
+ AC_LANG_POP([C++])
+ LIBS=$ov_save_LIBS
+ ])
+
+
+if test x"$ac_cv_libmapixx_gxx_works" = "xyes"; then
+ if test x"$ov_cv_boost_thread" = "xyes"; then
+ AC_PROG_CXX
+ OC_RULE_ADD(libmapixx, LIBS)
+ fi
+fi
+
+
+dnl ###########################################################################
+dnl libocpf dependencies
+dnl ###########################################################################
+
+dnl ---------------------------------------------------------------------------
+dnl Check for Bison
+dnl ---------------------------------------------------------------------------
+if test x"$OPENCHANGE_VERSION_IS_SVN_SNAPSHOT" = x"yes"; then
+ AC_ARG_VAR([BISON], [Location of the bison program.])
+ AC_PATH_PROG([BISON], [bison], [bison])
+
+ if test x"$BISON" != x""; then
+ OC_RULE_ADD(libocpf, LIBS)
+ AC_SUBST(BISON)
+ fi
+else
+ OC_RULE_ADD(libocpf, LIBS)
+fi
+
+
+
+dnl ###########################################################################
+dnl libmapiadmin dependencies
+dnl ###########################################################################
+PKG_CHECK_EXISTS([ dcerpc_samr ],
+ [
+ enable_libmapiadmin="yes"
+ ], [
+ enable_libmapiadmin="no"
+ ])
+
+if test x"$enable_libmapiadmin" = x"yes"; then
+ PKG_CHECK_MODULES(SAMR, dcerpc_samr)
+ OC_RULE_ADD(libmapiadmin, LIBS)
+fi
+
+
+
+dnl ##########################################################################
+dnl tools dependencies
+dnl ##########################################################################
+
+dnl --------------------------------------------------------------------------
+dnl Check for libical
+dnl --------------------------------------------------------------------------
+PKG_CHECK_MODULES([ICAL], [libical], [have_libical="yes"], [have_libical="no"])
+AC_SUBST(ICAL_CFLAGS)
+AC_SUBST(ICAL_LIBS)
+
+dnl --------------------------------------------------------------------------
+dnl Check for popt
+dnl --------------------------------------------------------------------------
+
+AC_CHECK_LIB([popt], [poptFreeContext],
+ [
+ AC_DEFINE(HAVE_LIBPOPT, 1, [Define if you want to use libpopt])
+ enable_libpopt="yes"
+ ],
+ [
+ AC_MSG_WARN([libpopt is missing - can't build openchange tools])
+ enable_libpopt="no"
+ ])
+
+if test x"$enable_libpopt" = x"yes"; then
+ if test x"$enable_libmapiadmin" = x"yes"; then
+ OC_RULE_ADD(openchangepfadmin, TOOLS)
+ OC_RULE_ADD(mapitest, TOOLS)
+ fi
+
+ if test x"$enable_libocpf" = x"yes"; then
+ OC_RULE_ADD(openchangeclient, TOOLS)
+ fi
+
+ if test x"$have_libical" = x"yes"; then
+ OC_RULE_ADD(exchange2ical, TOOLS)
+ fi
+
+ OC_RULE_ADD(mapiprofile, TOOLS)
+ OC_RULE_ADD(openchangemapidump, TOOLS)
+ OC_RULE_ADD(schemaIDGUID, TOOLS)
+ OC_RULE_ADD(locale_codepage, TOOLS)
+fi
+
+dnl --------------------------------------------------------------------------
+dnl Check for libmagic
+dnl --------------------------------------------------------------------------
+AC_CHECK_LIB([magic], [magic_open],
+ [
+ AC_DEFINE(HAVE_LIBMAGIC, 1, [Define if you want to use libmagic])
+ MAGIC_LIBS="-lmagic -lz"
+ enable_libmagic="yes"
+ ],
+ AC_SUBST(MAGIC_LIBS)
+ [
+ AC_MSG_WARN([libmagic is missing - can't build exchange2mbox])
+ enable_libmagic="no"
+ ])
+
+if test x"$enable_libmagic" = x"yes"; then
+ AC_CHECK_LIB([z], [gzopen], [],
+ [
+ AC_MSG_ERROR([Z library not found, please install zlib-devel.], [1])
+ ])
+ if test x"$enable_libpopt" = x"yes"; then
+ OC_RULE_ADD(exchange2mbox, TOOLS)
+ fi
+fi
+
+
+dnl ##########################################################################
+dnl libmapistore backends dependencies
+dnl ##########################################################################
+
+dnl --------------------------------------------------------------------------
+dnl Check for sqlite3
+dnl --------------------------------------------------------------------------
+PKG_CHECK_MODULES(SQLITE, sqlite3, SQLITEFOUND=yes, [SQLITEFOUND=no])
+AC_SUBST(SQLITE_CFLAGS)
+AC_SUBST(SQLITE_LIBS)
+
+if test x"$SQLITEFOUND" = x"yes"; then
+ OC_RULE_ADD(mapistore_sqlite3, MAPISTORE)
+fi
+
+
+dnl ##########################################################################
+dnl torture dependencies
+dnl ##########################################################################
+AC_PATH_PROG([SMBTORTURE], [smbtorture], no)
+
+if test x"$SMBTORTURE" != x""; then
+ TORTURE_MODULESDIR=`$PKG_CONFIG --variable=modulesdir torture`
+ AC_SUBST(TORTURE_MODULESDIR)
+ OC_RULE_ADD(torture, TORTURE)
+fi
+
+
+dnl ##########################################################################
+dnl mapiproxy server
+dnl ##########################################################################
+if test x$PYTHON != x; then
+ OC_RULE_ADD(mapiproxy, SERVER)
+fi
+
+AC_ARG_WITH(modulesdir,
+[AS_HELP_STRING([--with-modulesdir], [Modules path to use])],
+[modulesdir="$withval"; ],
+[modulesdir="\${prefix}/modules"; ])
+
+AC_SUBST(modulesdir)
+
+dnl ##########################################################################
+dnl Swig bindings dependencies
+dnl ##########################################################################
+AC_ARG_ENABLE(swig-perl, AC_HELP_STRING([--enable-swig-perl],
+ [build SWIG interfaces for Perl]),
+ enable_perlswig="$enableval")
+if test "x${enable_perlswig}" = xyes; then
+ AC_PATH_PROG(SWIG, swig)
+
+ if test -z "$SWIG"
+ then
+ AC_MSG_ERROR(Please install swig)
+ fi
+
+ SWIGDIRSALL+="swigperl-all"
+ SWIGDIRSINSTALL+="swigperl-install"
+ SWIGDIRSUNINSTALL+="swigperl-uninstall"
+fi
+
+PERL5DIR=`$PERL -e 'use Config; my $dir = $Config{sitelib}; print $dir'`
+AC_SUBST(PERL5DIR)
+
+AC_SUBST(SWIGDIRSALL)
+AC_SUBST(SWIGDIRSINSTALL)
+AC_SUBST(SWIGDIRSUNINSTALL)
+
+dnl ##########################################################################
+dnl Python bindings dependencies
+dnl ##########################################################################
+AC_ARG_ENABLE(pymapi, AC_HELP_STRING([--enable-pymapi],
+ [build Python bindings for libmapi]),
+ enable_pymapi="$enableval",
+ enable_pymapi=no)
+if test "x${enable_pymapi}" = xyes; then
+ PYMAPIALL+="pymapi"
+ PYMAPIINSTALL+="pymapi-install"
+ PYMAPIUNINSTALL+="pymapi-uninstall"
+fi
+
+PYCDIR=`$PYTHON -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1, prefix='\\$(prefix)')"`
+AC_SUBST(PYCDIR)
+
+AC_SUBST(PYMAPIALL)
+AC_SUBST(PYMAPIINSTALL)
+AC_SUBST(PYMAPIUNINSTALL)
+
+dnl ##########################################################################
+dnl Documentation dependencies
+dnl ##########################################################################
+AC_PATH_PROG(DOXYGEN, doxygen)
+if test x"$DOXYGEN" = x""; then
+ AC_MSG_WARN(doxygen)
+ enable_doxygen="no"
+else
+ enable_doxygen="yes"
+ AC_SUBST(DOXYGEN)
+fi
+
+
+
+dnl ***********************
+dnl Makefiles
+dnl ***********************
+AC_CONFIG_FILES([config.mk libmapi.pc libmapiadmin.pc libocpf.pc mapiproxy/libmapiproxy.pc
+ mapiproxy/libmapiserver.pc mapiproxy/libmapistore.pc Doxyfile libmapi++/Doxyfile
+ libocpf/Doxyfile libmapiadmin/Doxyfile libmapi/Doxyfile mapiproxy/Doxyfile
+ utils/mapitest/Doxyfile])
+AC_OUTPUT
+
+
+dnl ##########################################################################
+dnl Print configuration info
+dnl ##########################################################################
+
+OC_SETVAL(libmapi)
+OC_SETVAL(libmapiadmin)
+OC_SETVAL(libocpf)
+OC_SETVAL(libmapixx)
+
+OC_SETVAL(openchangeclient)
+OC_SETVAL(mapiprofile)
+OC_SETVAL(openchangepfadmin)
+OC_SETVAL(exchange2mbox)
+OC_SETVAL(exchange2ical)
+OC_SETVAL(mapitest)
+OC_SETVAL(openchangemapidump)
+OC_SETVAL(schemaIDGUID)
+OC_SETVAL(locale_codepage)
+OC_SETVAL(mapiproxy)
+
+OC_SETVAL(torture)
+OC_SETVAL(doxygen)
+OC_SETVAL(perlswig)
+
+AC_MSG_RESULT([
+
+===============================================================
+OpenChange Configuration (Please review)
+
+ * Install:
+ - prefix: $prefix
+
+ * OpenChange MAPI library: $enable_libmapi
+
+ * OpenChange Libraries:
+ - libmapi++: $enable_libmapixx
+ - libmapiadmin: $enable_libmapiadmin
+ - libocpf: $enable_libocpf
+
+ * OpenChange Server:
+ - mapiproxy: $enable_mapiproxy
+
+ * OpenChange mapistore backends:
+ - sqlite3: $enable_mapistore_sqlite3
+
+ * OpenChange Tools:
+ - openchangeclient: $enable_openchangeclient
+ - mapiprofile: $enable_mapiprofile
+ - openchangepfadmin: $enable_openchangepfadmin
+ - exchange2mbox: $enable_exchange2mbox
+ - exchange2ical: $enable_exchange2ical
+ - mapitest: $enable_mapitest
+ - openchangemapidump: $enable_openchangemapidump
+ - schemaIDGUID: $enable_schemaIDGUID
+ - locale_codepage: $enable_locale_codepage
+
+ * OpenChange Torture Suite: $enable_torture
+
+ * OpenChange Documentation: $enable_doxygen
+
+ * OpenChange Bindings:
+ - Perl: $enable_perlswig
+ - Python: $enable_pymapi
+
+===============================================================
+
+])
+
Added: trunk/openchange/doc/doxygen/apidocs.css
===================================================================
--- trunk/openchange/doc/doxygen/apidocs.css (rev 0)
+++ trunk/openchange/doc/doxygen/apidocs.css 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,758 @@
+/*
+** WEBSITE
+**
+*/
+
+BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+}
+BODY,TD {
+ font-size: 90%;
+}
+H1 {
+ text-align: center;
+ font-size: 160%;
+}
+H2 {
+ font-size: 19px;
+ font-weight: bold;
+ color: #3E93D5;
+}
+H3 {
+ font-size: 100%;
+}
+
+P {
+ text-align: justify;
+}
+
+LI {
+ li-style-type: square;
+ li-style-position: outside;
+ display: list-item;
+}
+
+CAPTION { font-weight: bold }
+DIV.qindex {
+ width: 100%;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.nav {
+ width: 100%;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.navtab {
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+TD.navtab {
+ font-size: 70%;
+}
+A.qindex {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D;
+}
+A.qindex:visited {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D
+}
+A.qindex:hover {
+ text-decoration: none;
+ background-color: #ddddff;
+}
+A.qindexHL {
+ text-decoration: none;
+ font-weight: bold;
+ background-color: #6666cc;
+ color: #ffffff;
+ border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+ text-decoration: none;
+ background-color: #6666cc;
+ color: #ffffff;
+}
+A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
+A.el { text-decoration: none; font-weight: bold }
+A.elRef { font-weight: bold }
+A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
+A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
+A.codeRef:link { font-weight: normal; color: #0000FF}
+A.codeRef:visited { font-weight: normal; color: #0000FF}
+A:hover { text-decoration: none; background-color: #f2f2ff }
+DL.el { margin-left: -1cm }
+.fragment {
+ font-family: monospace, fixed;
+ font-size: 95%;
+}
+PRE.fragment {
+ border: 1px solid #CCCCCC;
+ background-color: #f5f5f5;
+ font-size: 11px;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ margin-left: 2px;
+ margin-right: 8px;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+}
+DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
+
+DIV.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ margin-bottom: 6px;
+ font-weight: bold;
+}
+DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
+BODY {
+ background: white;
+ color: black;
+ margin-right: 20px;
+ margin-left: 20px;
+}
+TD.indexkey {
+ background-color: #e8eef2;
+ font-weight: bold;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TD.indexvalue {
+ background-color: #e8eef2;
+ font-style: italic;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TR.memlist {
+ background-color: #f0f0f0;
+}
+P.formulaDsp { text-align: center; }
+IMG.formulaDsp { }
+IMG.formulaInl { vertical-align: middle; }
+SPAN.keyword { color: #008000 }
+SPAN.keywordtype { color: #604020 }
+SPAN.keywordflow { color: #e08000 }
+SPAN.comment { color: #800000 }
+SPAN.preprocessor { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral { color: #008080 }
+.mdescLeft {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.mdescRight {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.memItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplParams {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ color: #606060;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.search { color: #003399;
+ font-weight: bold;
+}
+FORM.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+INPUT.search { font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #e8eef2;
+}
+TD.tiny { font-size: 75%;
+}
+a {
+ color: #1A41A8;
+}
+a:visited {
+ color: #2A3798;
+}
+.dirtab { padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #84b0c7;
+}
+TH.dirtab { background: #e8eef2;
+ font-weight: bold;
+}
+HR { height: 1px;
+ border: none;
+ border-top: 1px solid black;
+ margin-bottom: 50px;
+}
+
+/* Style for detailed member documentation */
+.memtemplate {
+ font-size: 80%;
+ color: #606060;
+ font-weight: normal;
+}
+.memnav {
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+.memitem {
+ padding: 4px;
+ background-color: white;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #ccc;
+ -moz-border-radius: 8px 8px 8px 8px;
+ margin-bottom: 30px;
+}
+.memname {
+ white-space: nowrap;
+ font-weight: bold;
+ font-size: 12px;
+ margin: 10px 10px 10px 10px;
+}
+
+.memname EM {
+ color: #45417e;
+}
+
+.memdoc{
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+.memdoc EM, TD {
+ font-size: 12px;
+}
+
+.memproto {
+ background-color: #e9e9f4;
+ width: 100%;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #ccc;
+ font-weight: bold;
+ -moz-border-radius: 8px 8px 8px 8px;
+}
+.paramkey {
+ text-align: right;
+}
+.paramtype {
+ white-space: nowrap;
+}
+.paramname {
+ color: #602020;
+ font-style: italic;
+ white-space: nowrap;
+}
+/* End Styling for detailed member documentation */
+
+/* for the tree view */
+.ftvtree {
+ font-family: sans-serif;
+ margin:0.5em;
+}
+.directory { font-size: 9pt; font-weight: bold; }
+.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; }
+.directory > h3 { margin-top: 0; }
+.directory p { margin: 0px; white-space: nowrap; }
+.directory div { display: none; margin: 0px; }
+.directory img { vertical-align: -30%; }
+
+
+#website {
+ width: 820px;
+ height: 100%;
+ margin-left: auto;
+ margin-right: auto;
+ text-align: left;
+
+
+ /* IE hack */
+ * position: absolute;
+ * left: 50%;
+ * margin-left: -410px;
+}
+
+/*
+** HEADER
+**
+*/
+
+.header {
+ height: 200px;
+ background: url(header.jpg) no-repeat top center;
+}
+
+body {
+ background: #fff url(body_top_bg2.jpg) top left repeat-x;
+ font-family: Arial, Trebuchet MS, Tahoma, Verdana, Helvetica, sans-serif;
+ font-size: 11px;
+ line-height: 17px;
+ color: #444;
+ color: #3a3a3a;
+ fdpadding-top: 15px;
+ text-align: center;
+ background-color: #fbfbfb;
+}
+
+h1 {
+ font: 24px bold Trebuchet MS, Arial;
+ color: #FFF;
+ padding: 0;
+ margin: 0;
+}
+
+/*
+** MIDDLE SIDE
+**
+*/
+
+#middle_side {
+ display: block;
+ height: 100%;
+ width: 800px;
+ margin-top: 7px;
+ backsground: url(middle_bg.jpg) top left repeat-x;
+ background-color: #fbfbfb;
+}
+
+/* left and right side */
+
+#left_side {
+ background-color: #fff;
+ clear: both;
+ margin-bottom: 10px;
+ border-bottom: 1px solid #eee;
+ border-left: 1px solid #eee;
+ border-right: 1px solid #eee;
+ -moz-border-radius: 0 0 8px 8px;
+ height: 29px;
+}
+
+
+/*
+** MENU HORIZONTAL
+**
+*/
+
+/************ Global Navigation *************/
+
+DIV.tabs {
+ float : left;
+ width : 100%;
+ background : url("tab_b.gif") repeat-x bottom;
+ margin-top : 10px;
+ margin-bottom : 4px;
+}
+
+DIV.tabs ul {
+ margin : 0px;
+ padding-left : 10px;
+ list-style : none;
+}
+
+DIV.tabs li {
+ display : inline;
+ margin : 0px;
+ padding : 0px;
+}
+
+DIV.tabs A {
+ float : left;
+ background : url("tab_r.gif") no-repeat right top;
+ border-bottom : 1px solid #84B0C7;
+ font-size : x-small;
+ font-weight : bold;
+ text-decoration : none;
+}
+
+DIV.tabs A:link, .tabs A:visited,
+DIV.tabs A:active, .tabs A:hover
+{
+ color: #1A419D;
+}
+
+
+DIV.tabs SPAN
+{
+ float : left;
+ display : block;
+ background : url("tab_l.gif") no-repeat left top;
+ padding : 5px 10px;
+ white-space : nowrap;
+}
+
+DIV.tabs TD
+{
+ font-size : x-small;
+ font-weight : bold;
+ text-decoration : none;
+}
+
+
+
+/* Commented Backslash Hack hides rule from IE5-Mac \*/
+DIV.tabs SPAN {float : none;}
+/* End IE5-Mac hack */
+
+DIV.tabs A:hover SPAN
+{
+ background-position: 0% -150px;
+}
+
+DIV.tabs LI.current A
+{
+ background-position: 100% -150px;
+ border-width : 0px;
+}
+
+DIV.tabs LI.current SPAN
+{
+ background-position: 0% -150px;
+ padding-bottom : 6px;
+}
+
+
+DIV.nav
+{
+ background : none;
+ border : none;
+ border-bottom : 1px solid #84B0C7;
+}
+
+
+#right_side_home {
+ font-family: "Lucida Grande", Arial, Verdana, sans-serif;
+ background-color: white;
+ padding: 0px 20px;
+ border: 1px solid #ebebeb;
+ border: 1px solid #ddd;
+ -moz-border-radius: 10px 10px;
+
+ width: 750px;
+
+
+ * width: 800px;
+ * margin-left: 0px;
+ padding-bottom: 10px;
+}
+
+#right_side_home td {
+ line-height: 17px;
+ margin: 0 0 5px 0;
+ padding: 10px 0 15px 7px
+ display: table-cell;
+ border-spacing: 2px 2px;
+ vertical-align: middle;
+ text-align: left;
+ border-bottom: 1px solid #EEEEEE;
+}
+
+#right_side_home td h2, a.anchor {
+ font-size: 19px;
+ font-weight: bold;
+ color: #3E93D5;
+}
+
+#right_side_home td.indexkey {
+ border-bottom: none;
+}
+
+#right_side_home li {
+ list-style-position: inside;
+ valign: middle;
+}
+
+
+TD.indexkey {
+ background-color: #e8eef2;
+ font-size : 12px;
+ font-weight : bold;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border : 1px solid #CCCCCC;
+}
+TD.indexvalue {
+ background-color: #e8eef2;
+ font-style : italic;
+ font-size : 12px;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border : 1px solid #CCCCCC;
+}
+TR.memlist {
+ background-color: #f0f0f0;
+}
+
+.mdescLeft {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.mdescRight {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.memItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplParams {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ color: #606060;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+
+code {
+ display: block;
+ width: 100%;
+ border: 1px solid #ccc;
+ background-color: #e8edf3;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ padding-left: 5px;
+ padding-right: 5px;
+ margin-bottom: 10px;
+ margin-top: 10px;
+}
+
Added: trunk/openchange/doc/doxygen/footer.html
===================================================================
--- trunk/openchange/doc/doxygen/footer.html (rev 0)
+++ trunk/openchange/doc/doxygen/footer.html 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,18 @@
+</div>
+<br/>
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#f8f8f8; border:2px solid #e0e0e0; padding:5px;">
+<tr>
+<td>
+ <img alt="Creative Commons License" src="CC_SomeRightsReserved.png" width="90" height="30" border="0" /><br />
+ <img alt="Creative Commons Attribution icon" src="24px-Cc-by_white.svg.png" width="24" height="24" border="0" />
+ <img alt="Creative Commons Share Alike icon" src="24px-Cc-sa_white.svg.png" width="24" height="24" border="0" />
+</td>
+<td> <i><strong class="selflink">This content</strong> is licensed under the Creative Commons<br />
+Attribution ShareAlike License v. 3.0:<br />
+<a href="http://creativecommons.org/licenses/by-sa/3.0/" class="external free" title="http://creativecommons.org/licenses/by-sa/3.0/" rel="nofollow">http://creativecommons.org/licenses/by-sa/3.0/</a></i>
+</td></tr></table>
+<br/>
+</div>
+</div>
+</body>
+</html>
Added: trunk/openchange/doc/doxygen/header.html
===================================================================
--- trunk/openchange/doc/doxygen/header.html (rev 0)
+++ trunk/openchange/doc/doxygen/header.html 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,11 @@
+<html>
+ <head>
+ <title>$projectname $projectnumber API Documentation</title>
+ <link href="doxygen.css" rel="stylesheet" type="text/css"/>
+ <link href="apidocs.css" rel="stylesheet" type="text/css"/>
+ </head>
+ <body>
+ <div id="website">
+ <div class="header"></div>
+ <div id="middle_side">
+ <div id="right_side_home">
Added: trunk/openchange/doc/doxygen/index.html
===================================================================
--- trunk/openchange/doc/doxygen/index.html (rev 0)
+++ trunk/openchange/doc/doxygen/index.html 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>OpenChange API Documentation</title>
+ <meta http-equiv="refresh" content="0;URL='overview/index.html'" />
+ </head>
+ <body>
+ <p>Redirecting you to the OpenChange <a href="overview/index.html">API documentation
+ overview</a>.</p>
+ </body>
+</html>
Added: trunk/openchange/doc/doxygen/libmapi-concepts.doxy
===================================================================
--- trunk/openchange/doc/doxygen/libmapi-concepts.doxy (rev 0)
+++ trunk/openchange/doc/doxygen/libmapi-concepts.doxy 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,55 @@
+/**
+\page mapiconcepts MAPI Concepts
+
+<h2>MAPI objects</h2>
+
+Almost any MAPI data you access, read or edit is associated with an
+object. No matter whether you intend to browse mailbox hierarchy, open
+folders, create tables or access items (messages, appointments,
+contacts, tasks, notes), you will have to initialize and use MAPI
+objects: <em>object understanding and manipulation is
+fundamental</em>.
+
+- When developing MAPI clients with Microsoft framework, instantiated
+objects inherit from parent classes. As a matter of fact, developers
+know which methods they can apply to objects and we suppose it makes
+their life easier.
+- In OpenChange, objects are opaque. They are generic data structures
+which content is set and accessed through MAPI public
+functions. Therefore, Linux MAPI developers must know what they are
+doing.
+
+An example of MAPI object manipulation is shown below:
+\code
+ mapi_object obj_store;
+
+ [...]
+
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(&obj_store);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("OpenMsgStore", GetLastError());
+ exit (1);
+ }
+ mapi_object_release(&obj_store);
+\endcode
+
+<h3>MAPI Handles</h3>
+
+Beyond memory management considerations, understanding MAPI handles
+role in object manipulation provides a better understanding why
+mapi_object_release() matters.
+
+Handles are temporary identifiers returned by Exchange when you access
+or create objects on the server. They are used to make reference to a
+particular object all along its session lifetime. They are stored in
+unsigned integers, are unique for each object but temporary along MAPI
+session. Handles are the only links between objects accessed on the
+client side and efficiently stored on the server side.
+
+Although OpenChange MAPI makes handles manipulation transparent for
+developers, mapi_object_release() frees both the allocated memory
+for the object on client side, but also releases the object on the
+server.
+
+*/
Added: trunk/openchange/doc/doxygen/libmapi-examples.doxy
===================================================================
--- trunk/openchange/doc/doxygen/libmapi-examples.doxy (rev 0)
+++ trunk/openchange/doc/doxygen/libmapi-examples.doxy 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,110 @@
+/** \example mapi_sample1.c
+
+This example shows a very basic MAPI program, including setup, login,
+and teardown.
+
+The first MAPI library function called is MAPIInitialize(). As its
+name suggests, this function initializes MAPI library: It creates the
+MAPI global context, opens the profile database store (database path
+passed as function parameter) and initialize Samba4 transport
+layer. This function must be called prior any other MAPI
+library operations.
+
+Once MAPI is initialized, we need to create a connection to Exchange and
+open MAPI sessions with the user credentials. This is the purpose of
+MapiLogonEx() which needs to be executed prior doing any effective
+code. This function takes a pointer on a mapi_session structure,
+the profile username and an optional password in case you decided to
+store it outside the profile. In the example above, we retrieve the
+default profile name from the database using GetDefaultProfile()
+Note that MapiLogonEx() opens connections to both the EMSMDB and
+EMSABP store providers. If you intend to interact with a single
+provider, use MapiLogonProvider() instead.
+
+Finally we call MAPIUninitialize() prior to leaving the
+function. This opaque function will clean up the memory allocated
+during the session and stored within the global MAPI context.
+
+*/
+
+/** \example fetchmail.c
+
+This example shows how to fetch mail from the server.
+
+We initialize MAPI library with the profiles database path, retrieve
+the default profile name and open connections to both the Exchange
+message store provider (EMSMDB) and Exchange Address Book provider
+(EMSABP).
+
+\section ex-fetchmail-openstore Open the message store
+
+Now we have
+opened a connection to the Exchange message store provider, we can
+open the user mailbox store with OpenMsgStore() This function
+will return a set of pre-defined folder unique IDs (stored on double
+values) and a \em pointer to the upper object we can access in MAPI
+hierarchy.
+
+\section ex-fetchmail-openinbox Opening the Inbox folder
+
+We now open the Inbox folder. Since OpenMsgStore() returns a set
+of \em common folders identifiers we store in the message store
+object (obj_store), we can retrieve them using the convenient
+GetDefaultFolder() function. This function doesn't generate any
+network traffic, but returns the folder identifier associated with the
+constant passed as argument (here olFolderInbox).
+
+We could have used MAPI tables and GetHierarchyTable() function to
+find Inbox folder identifier. We would have had to retrieve the
+Top Information Store hierarchy table, customize the view with
+PR_FID (Folder ID MAPI property) and PR_DISPLAY_NAME, find the
+IPM_SUBTREE folder identifier, open it, retrieve the Hierarchy Table,
+call SetColumns() with PR_FID and finally browse table rows until
+we found the Inbox folder.folders to store emails within
+IPM_SUBTREE folder hierarchy.
+
+\section ex-fetchmail-retrievecontentstable Retrieve contents table
+
+Once the Inbox folder is opened, we can call GetContentsTable() to
+create the view needed to list all the children objects. In the
+current example we suppose we will only retrieve IPM.Post objects
+(emails).
+
+\section ex-fetchmail-customview Customizing the MAPI view
+
+We now customize the MAPI view and set the columns with the property
+tags we want to access: PR_FID (Folder Identifier) and
+PR_MID (Message identifier). MAPI uses unique and permanent
+identifiers to classify objects. These identifiers are double values
+(8 bytes) and never change until you move the object to another
+location.
+
+We now enter the last step of the fetching process:
+
+- Call QueryPosition() to retrieve the current cursor position in the
+ contents table. The function returns the approximate fractional
+ position with a Numerator and Denominator. Denominator is the total
+ number of rows in the table.
+- Recursively call QueryRows() with the TBL_ADVANCE flag to fetch table rows.
+- Iterate through QueryRows results
+- Retrieve columns values for each row with the convenient find_SPropValue_data()
+- Open the message given its folder and message ids.
+- Call GetPropsAll() rather than GetProps() to retrieve all properties associated with a given object
+- Call one of OpenChange mapidump API function to display nice messages dump on standard output.
+
+We finally release mapi objects and clean up the MAPI library before returning
+*/
+
+/** \example fetchappointment.c
+
+This example shows how to fetch an appointment from the server.
+
+This is very similar to the fetchmail.c example, except two minor changes:
+- We change the default folder constant from olFolderInbox to
+olFolderContact so any further operations are performed on a child of
+the calendar folder.
+- We use mapidump_appointment() rather than mapidump_message() to dump
+appointments on standard output.
+
+*/
+
Added: trunk/openchange/doc/doxygen/libmapi-mainpage.doxy
===================================================================
--- trunk/openchange/doc/doxygen/libmapi-mainpage.doxy (rev 0)
+++ trunk/openchange/doc/doxygen/libmapi-mainpage.doxy 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,79 @@
+/**
+\mainpage Opening Exchange to a wider world
+
+<h2>OpenChange Project Goals</h2>
+
+The OpenChange Project aims to provide a portable Open Source
+implementation of Microsoft Exchange Server and Exchange
+protocols. Exchange is a groupware server designed to work with
+Microsoft Outlook, and providing features such as a messaging server,
+shared calendars, contact databases, public folders, notes and tasks.
+
+The OpenChange project has three goals:
+
+- To provide a library for interoperability with Exchange
+protocols, and to assist implementors to use this to create
+groupware that interoperates with both Exchange and other
+OpenChange-based software.
+
+- To provide an alternative to Microsoft Exchange Server which uses
+native Exchange protocols and provides exactly equivalent
+functionality when viewed from Microsoft Outlook clients.
+
+- To develop a body of knowledge about the most popular groupware
+protocols in use commercially today in order to promote development
+of a documented and unencumbered standard, with all the benefits that
+standards bring.
+
+<h2>MAPI Overview</h2>
+
+MAPI is the glue between Exchange and Outlook, but a common
+misconception is to consider it as a network protocol. MAPI, an
+acronym for Messaging Application Programming Interface, refers to a
+proprietary set of function call interfaces developed by Microsoft
+before Microsoft Exchange existed. By purchasing licenses to
+Microsoft's proprietary and Windows-only MAPI libraries, anyone can
+create message services that communicate using these functions. A mail
+server implemented in this way is what Microsoft calls a MAPI Service
+Provider. Any protocol could be used as a transport for these MAPI
+communications.
+
+When Microsoft Exchange 5.5 was developed in 1997, the decision was
+taken to create a proprietary transport protocol for MAPI which
+closely matches the MAPI calling interface. This protocol is called
+ExchangeRPC and used in Outlook-Exchange communications. ExchangeRPC
+is the only transport OpenChange supports, and in practice is the only
+transport of interest today. Most of the world is being forced to use
+Microsoft Exchange servers, so that defines the transport that
+matters.
+
+When OpenChange team members first looked at the network network
+traffic these generated by calling MAPI functions on Windows operating
+systems, we noticed blobs of data first either compressed or
+obfuscated, then encapsulated by an RPC transport protocol function
+(EMSMDB) and finally pushed on the wire. Transporting
+memory-image blobs on the wire is not good protocol design, however
+for a number of reasons the result now works quite reliably.
+
+<h2>Looking at a MAPI Conversation</h2>
+
+A high-level view of a MAPI conversation follows. We also introduce
+important terminology:
+- MAPI applications call MAPI providers, using the API to pass data
+(eg a mail message body) or MAPI conversation requests and responses
+(eg 'search for this address').
+- MAPI providers pack the client or server MAPI information in a
+blob. There are only two really important providers, one for data
+destined for what is somewhat strangely termed the Message Store
+(although it handles more than just messages), and the other for data
+to be sent to the Address Book. These are called the EMSMDB and
+EMSABP providers, respectively.
+- ExchangeRPC protocol is used to transport the MAPI information over
+the wire, encapsulating inside it one of two MAPI-specific protocols:
+the EMSMDB Message Store Protocol, or the NSPI Addressbook Protocol.
+- The store provider on the server side associated with the protocol
+used (either EMSMDB or EMSABP) extracts the MAPI blob from RPC
+protocol functions, analyzes its content and performs operations
+embedded within it.
+
+*/
Added: trunk/openchange/doc/doxygen/pictures/24px-Cc-by_white.svg.png
===================================================================
--- trunk/openchange/doc/doxygen/pictures/24px-Cc-by_white.svg.png (rev 0)
+++ trunk/openchange/doc/doxygen/pictures/24px-Cc-by_white.svg.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,30 @@
+PNG
+
+
+IHDR °çá» bKGDÿÿÿÿÿÿ X÷Ü pHYs H H FÉk>
+ IDATXýXmPU¾veY pW$gQH%ãËc*$åÃIkFmiØttrêC öa3 cD$ e¬±X,«@³ Â.ÈîõþyuÓ÷·÷úóÌçÜϹîëºçÜç<þxHØNÛNÛN½+zWô® ._,¿X|»æÛ5ß®Q(C`4F#p×ý®û]w at qRqRqðÿÎÿ;ÿï°caÇÂIÅIÅIÅ@$L&Ämâ6qÛòÀÄ-í-í--ùVë[oµ<.
+¡B¨øS RT(*I$æHs¤9¤SSSð>°Ï÷ôô$Óôiú4=Ù2Ú2Ú2JZV¥Uù`^û9À3<Ã3À7ýßôÓl?Ø~°¸ªºªºª
+6Øp x&õÔgR000ÀMá¦pS B©P*õõõ@²GÙ£ªªª¦mMÛ¶#êõðj÷j÷jöeïËÞ
+äÎäÎäÎ Ò^i¯´÷að£ýȳégÓϦK{ö,í±+¦êRu©ºÈÎÎNòöÔí©ÛSë£sñsñsñd{^{^{u%ëJÖÒÅÛÅÛÅIERÔìÕìÕì%ÇSÇSÇS~gAuuu¤|µ|µ|5)øJðà+rGË-äÀ±cÇþsÂå)ËS§ÈÒ-¥[J·»=w{î&µZA-÷BÞy/³£³£³£$psäæÈÍR¨JT%Úßñýïw|OÌ&³Éü¿'þWXÖFòÔ§<õ$é6â6â6Bºæ»æ»æÕÕÕ÷&°û¹<p(áPxxQxQxyëÀ·üóÄÿùçÿÔ®Ô®Ô®´óx.â¹çÈÁÎÁÎÁN7Ü8rã¹æÙ5Ï®ytww'+++ÿÿÄÿãqÀH¿üzðë¤(H$
+"4E"
+)
+ø0àÃ:³ñÌÆ3··7à é é pNwNwN¦º¦º¦ºZS©Ö\K¹r-èÎíÎíÎggg OgOgOgÀbL1¦ õâzq½XÒ·¤oI SÊ2%033TÿQýGõh§h§h'àëëkßdÜÜÝÜÝÜsç&Î
+õ
+õ
+õÀ¸iÜ4n°uÕÖU[WÙ-*4©õ^^^r¹Ãrå¤SSSéêêJºMºMºM»rwåîÊ%ûûûIE¤"RIîÙ¼góÍäÜƹsÉý'öØ'ÊådÛ¶-m[îïN£Óè4¤ÇÛo{¼Mä"¹HN
+{]z]z] Ñ:Ñ:Ñ:@¥T)UÊE¶Û!q¸k¾k¾k2e²LÐÛÛ¤½ö~ÚûÀ¥ÉK&ÿVÿVÿV c.c.c¨Ê®]+»K>|.ÔDj"5@[t[t[4 _ª_ª_ºpýÕΫW;>Y>Y>YõwëïÖߧÄSâ)R'ÄÍ7o6ß\¨Ál0̤¼SÞ)ï$RRRÈ3_Î|9ô³øYü,dÒ¤I7HÅÏâGöÕôÕôÕAùAùAù¤Ä 1HdÈùó!çɲÀ²À²@R\".Å?ÿTüÓÂõïîîÈ(×(×(W{Åç:æ:æ: ¡£ÐQèÒDi¢´E: Aª U
+L©§ÔSj`$a$a$pLvLvL¶mÚVVV~~~À®_wýºëWÀrÄrÄrÈPf(3ÀóåÏ?_|ôÉG|ô ·!nCÜEo4Q¨(Tj*Åb`V2+ o·Å{±
+5Ôj
+ÒéÖt+P¡þBý ðzáõÂë@÷+ݯt¿èôú{x`c`c`#à~Úý´ûi À`°K>_òùϵ«ÚUí
+È5r\³È!2Ïg˦ççÃïy}9úrôe»%%×K®\_¤ú}>R!UHRò1Ç|ó!ãZãZãZIe´2ZM.»³ìβ;d{{{¿=¾á7Þ =.x\ð¸@Ö)ëuJ²¥¥¥\öȲG=B~úqêÇz²{²{²Iß}¾û|÷ÝSBª¯U_«¾¶'ÔTßTßTÌý6÷ÛÜoöqéyéyéyàÅÒK_,ÔoªßT¿ xj=µZ F#'kOÖ¬B2B2B2ìñò+ò+ò+ÀK^ÚôÒ&@Þ!ïw 2³Ì,3¿Düñ ($
+ÉBt't't'ÁÍ7+V6lÐÜÜL>Gñ(Hï×¼_ó~¼úóÕ¯þ|5¬a
+iK±¥ØRH[-À@Ú²mÙ¶l{¸{þ¦#íænî&mkmkmkIÆ1q$ýéOÒ*°
+¬Òö¥íKÛö°2ùpòáäÃvås
+r
+r
+H½Ì^f/r[Ö¶¬mYö Y]Y]Y]¤ùóæþávû7¨\W¹®r)ÏgH>[}¶º]®äÃ\K]K]KéuÉë×%Rü©øSñ§di|i|i<iµYmVÛÿ¸^§×éuä;ØùÄN»°Ú.m¶´
ÚBm¡÷$`½m½m½M8:qt6
+
¤çaÏÃÉSI§N%ó5ó5ó5ÿñîÐîÐîPòé/þâé/ìÄcÆ9J;;;Úç/¸LzMzMzããã¤0Q(L$eU²*YY0\0\0LÖÖÖãÇþ{Â3Ûg¶Ïl'+'*'*'È ³AgÎÚMÁ&²#³#³#saü}ïÄã±ã±ã±dÞÞ¼½y{I©³ÔYêL
+
+28-8-8|Göì©»¬»¬»L½7öÞØ{ä´ÿ´ÿ´?9]5]5]ENEOEOEW
+¯^%ËÊÊÈäMÉ7Ï$I>#FQ`$c¼b¼b¼È;.Þ_^êg3f3f3Èʵk+×êUêUêU¤ÃråËIÇq'=4
+¹~lýØú12*+*+*ÍÍÍ'Ueª2Uéû®ï»¾ï!!!v¥W[FjõZ½VO'''<ØÁþ+ñ'È¢²¢²¢22\®×2ÌNèAOßbßbßb2Ç%Ç%Ç
Ôéuzx>ÿ^5¡ü+^ :tEXtComment Created with Inkscape (http://www.inkscape.org/) ã+ld IEND®B`
\ No newline at end of file
Added: trunk/openchange/doc/doxygen/pictures/24px-Cc-sa_white.svg.png
===================================================================
--- trunk/openchange/doc/doxygen/pictures/24px-Cc-sa_white.svg.png (rev 0)
+++ trunk/openchange/doc/doxygen/pictures/24px-Cc-sa_white.svg.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,25 @@
+PNG
+
+
+IHDR °çá» bKGDÿÿÿÿÿÿ X÷Ü pHYs H H FÉk>
+ IDATXÃX}LÓW>¿
+´.Ôb±"Cèê(lS9ÉuN&n Ź¹,+&+à&3[a`Ë$ãs3Ö¨L(X¸Åñá¬EÄ4ElK¡åyÿy÷¼µ/¾çÜssûÓ{·þmô¶ðÃÂ?¬Y3²èBý
úõD7\ÞpyÑpâpâp"Ñh4DóÏÌ?3ÿQPmPmP-QØoa¿
ýFw"îDÜ ¢ÊÊJ¢8n7KäwÃïߧeCDxJ3MÅÀgW?»úÙU `"Ä
+bý# À>Ê>Ê>
+p¸ÜWÀ+à Ë3g,Ï èú¾q¯Ø°%`=== è&tº ÀétE.ÍñVÁ!ºxçâw>5|jøÔ@Ô#ëõÈ|Ç|Ç|Ç^,z±èÅ"¢m»·íÞ¶(Çãùùù±x,G4;;K499IÔÞÚÞÚÞJÔ¾§}Oû"s9Á@$4
+BQa~a~a>Ñ!Û!Û!o7Ây
+¬Çz¬ßi|§ñ`ÕЪ¡UCnÅdý²~Y?ÐÔ×Ô×ÔLÍLÍLÍ<mÝ622TA(®+®+®@N '`óØ<6PVV,»-»-»=ãxl@Û§íÓö¢pQ¸(`~a~a~ru¹º\0zbôÄèÿðR6ûòì˳/ÕiÕiÕiÀÊV~°ò9ÇcΪªªcÂ1áxÂîïïYº,]îV<÷ZîµÜkÀCûCûC»wÖ ëu0D¢Q@]i]i])Pý¸úqõc áZõkÀ-í-í--0ÏÌ3ógW«ÍÕÞtzÓéM¿ÙßìoVYqdÅ ©µ©µ©uñ>ÂGø8¶ãØc;ÜÄãËãËãËS©ÈTäxÏ®]=»Wv^Ùy´
+Z SÏÔ3õ~Ü&¶mÄ_¿
+;v(05MÍqÝÎng7P¼¶xmñZw^éõ^îõÝë»×Ð`é`é`)°áµ
+¯mx
+X²<ey
+ÐÕÕåøõS×O]?<7ñÜÄsîÿߢ·è-ÙÆlc¶$%)Iù(TEª"U&§ÉégÔ8j5 {#{#{#P®,W+ª¸Uq«â@ÝÔMÝÀæªÍU«©´©´©4϶mÛ>äeò2y'ñA B ØJl%6 nUݪºU*ZÄÄÄ<qMôÌ[__ï^°.a]Â:2C3C3CÝ£ö£ö£OèuÑetn<¸ñ çóÄyn'ÅÉCCC¼W®áÇ~¸9Ün¿ºpuáêBàfðÍàÁ8½R¯Ô+/¾ø`Ø"¶`pF8#"v4;M$EÊ"=[Ä"±H*j*j*jîß¾ûþm·ébº."û#û#û#ïgêåÔË©¤Bºèö¹t?é~Q¥ÇÒcñÄ
ûûû+Á
+"×××"òññ¸Û¹Û¹Û»w;îzWðêÙ«g¯ÂËÂ˵P>Ïä3å[Ë·o½ãq·qØkÝkÝkõl¥ÏÕ«?W{Â?~<$®H\¸Â½Þg®w®w®³³³ÍÎfgQuQ§¯È_¿"'Ò5fHë¯õ×úûëØ_Çþ"âïçïçïÿß.ëi='ò©õ©õ©õtϧϧϧ{Î3LÓAIJ¥l)éHG:"VPePeP%ëà:¸D³³³ÞóOØ'ìv¢Õ©«SW§åìËÙ³È,7ËÍr"G
£ÂQá?77G4ùóäÏ?{ú\WÀõ_P-¨TDÖxk¼5~ckçÖÎîTýQõGÕÞ;à|Öù¬óY@ÀÉ'Þ:Þ:Þ:@&N§cccÞñÝnA· ý$úIô;/?ÍtºAÝN¡¡ü¡ü¡| ¤0¤0¤pQë}RôIÑ'³¾Îúp9ÆO 2Z3Z3ZÄ9sгw%ïJ޴ŶŶÅwDwDwDÀÅ÷/¾ñ}`Ëw[¾Ûò'îÍóoó<`}×ú®õ]ϼgfÏÌXZ¥Ö¶¯m_ÛP¤CÒ!$ ~ø!ÐógÏ=zW²V]«®U:N§n¡(¢(À?Ê?Ê?
+Í Í Íx
gñ$ê
+u
º®³]g»Îzæ±UÙªlU¼D^"/Yto¨ÔjìB»Ð.ö(ö(ö(Üý~E?`ï²wÙ»<;¡ChÞм¡y±D,ë 7ò¬V+Ø»)wS.pI}I}Ií]¨æèæèæhÀÏægó³ÁÁÁ¾J_¥¯Zô1§Óê´:- ¼"¼"¼ø}ï÷½ß÷@uJuJu
+àZp-¸<8wþîü0ì7ì7ìJ5¥R
+ùwæßÛÓ·§oOÞî|»óíNàññýý~@ÄìÙ³Ï- at qqq?° ].HmÀ5årMǧOXm¬6V°²deÉÊàtÆéÓóWç¯Î_½'FZÐ8ßs¾ç|+++\®WILbÒ;ü¦ô¦ô¦ØÜ°¹asxÒñ¤ãIÇñeãËƹ×{¼ ¥F©Qj V:+ð[ø-ü@=®W÷ÎÝ;wïÜÒ2[-Ç4O7O7O76nlt<<<zózózó<ñ^ßÄdK²%PVVx¾<_/À\b.1 I¶$[
+|Éÿÿ%Ðwê;õÀdÅdÅd`
+³Yà kµÅÚÌlÙ:³>0|`ø P¯®W׫ù«òWå¯Ü:n·`1IÂ$aè½Ð{¡÷w|Ô;ö:ö:öÍÏ7?ßü<
+ø}Ä>b4¤!
+ P(ØÉØÉØI Q¨HT ÉG$d5²Y
+r2ädÈIÀç|^p+½&nMÜ8 x x x ß1¾c|ÇÒ|ê%þ±±gÇ{(¯)¯)¯âõñúx=àÃ÷áûð>
þC*C*C*N§èôúÀâLq¦<=YΧÑéÈ :tEXtComment Created with Inkscape (http://www.inkscape.org/) ã+ld IEND®B`
\ No newline at end of file
Added: trunk/openchange/doc/doxygen/pictures/CC_SomeRightsReserved.png
===================================================================
--- trunk/openchange/doc/doxygen/pictures/CC_SomeRightsReserved.png (rev 0)
+++ trunk/openchange/doc/doxygen/pictures/CC_SomeRightsReserved.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,29 @@
+PNG
+
+
+IHDR Z ¬a x pHYs tIMEÕÌIð bKGD ÿ ÿ ÿ ½§ ·IDATx^íiUEÇû¾{ßÚÝ6ë"²@ !`DÇ¡Ä "2 ×%Æ(êD£ñ1¨â@P¢HezX¦é¶~¯ßrç÷ïÜêyV¼1íVòçÔz«þuêÔ¹÷9%¿Nr@$Bd\ºP¤Ç¤KÒHDÈ|² Èh,Ò=
+l)ÒÍøí´2$Ù"ír«,n¤
Õ?À+B¸4d¤à `dÞvL_h×&By#Äl
+,OHIÚyû¤Ø°N¤g¡èä ÒùnÑ0gKë!íi6IÁ¶dË
bÉFÝ?-Ú°áÙeÈO&g}vä-[¦8qâ\.7çÌ3Ó÷ìÙ3áý÷ß¿büøñÝdÉÅÅb©Ç{lÐ÷ßÿãÇÏ ÏÜæææ¿8p`ÎòåË+§LÒËz
+{®ö½´Ú?Åcݦ[eâ²áÃw]¶lÙ´¾}ûBfxrçfÞ_|±»bÅ!
+*ÿ}]xÍÒVOï ¤{.¸XrìO>ù!yûöí
+7ß|óêT*õwÊÖ<óÌ3ûN<S]±%Óg!yóæÍM7ÞxãÚÒÒÒ¥lÀâW^yeÝéÓ§3ª3Ï q5nHÞÎWXV
+½Ä/¾øâè|p¢Ø·o_ãСC¿J§ÓÁÊ>ûì³^ziµÚÍ?¿âÕW_í!}çΧG¹9ÉüÄZ9%.}*{öì¹ð,kK»¬p>Z´s£[å6\ÉÊÊÊ¡f_~ù_±#½{÷:|ÈlÒ·ÞÚÁôyþùç Ù³ýð¶mÛÒ¼È
+ýG2$ïXhäµ?Ñá°7£O>ÝÍ øéc¶»Q+êp±úé³råÊûb³78¶1Ë@Îï8ڱɷõb²ñÑqÓøÈ#9Ûê`ÜI²¢¢¢mîÇioÉ
+ß\#C²óÐuè>µÃU´L÷îÝcöÆXäy Ååè>;wöl²Î<'l
+íî:|ßïÐ^mܸÑûâ/R555£G&!#ÉÍjiiI$~4ÍfS<3U(ù|>!YWW÷Ã%\ÒScÜvÛm=Þyçã´ñ"À´a¤<²y×®]±Ñ£G»êsÓM7¥/^|0γD"qd©)D£Ñëº>(ñ<Ï!ïÁDKÄâ^pÁ^×®]½þýûGG»æk²íå£hÿì&t¯ºêªDÇSç/ü1ÁDBCr²È/ñï¾û®Ú=oÞ¼Á«VÚ»l ýnݺ9o½õVçIË}ùå.Uz¨ÓºuëWsvIï/ýõ×õÒò7ò|P"ãñx+ÉDB$srª¢½{÷:êtåI¿§VKqöÆç>8dF°4Y³èä©S§â'xÃK at r\0d¸ÈfÑ©×^{m
+. \ãa_¸paÍ
+2eee¥×]w]§Ù³gwÁÚ´GÔF$}øá{õêå)_UUuúÍ7߬ٺuë:uÊO8±ãÔ©SB^ÿ+äf »b3¡:@x=
+Ùiü~¦Cé.]º¤ÙØQN3ýE´cz.ûtÑã 'ôÜwÒCűæ8¯Ã²è丬ZRD$Çò²êaXûî»od
ÎÜ÷Kn¸áÈV]Àêܧ~ºë
^;[»îºk!¤Aò\ÂÑ`#ÓllVa61S`Nz8ܧzêrë±Ñ%amÛâE`)$¤°$H±¨VÿMqEJÒYdî¯]»¶§ØÿP¨¯¯ÏàN¾ñÆGñë9Ú°´zvÍ5M¸,ãéÓØØx7ÌÚ?þx#d·@bIyy¹X¯ "Pç"=ê$]¤GY4#Ût3ÆG;ç°3þ9>>Ä´$DuAZ×!b£"%G%!$J[å¥{HwQ©
+ôKQÒEF°´¶èEV
+òëׯo¤_=$çØì2+ g±È,® Æ°yÅ £
+e¾Ñ 6/Ê<cl¤@ ±d»Ü¤zCô/ö=öt{ËBQuëÇXlD°#b£ê!
+¹Q]Ò3ä[sÐK(ó>I?%&)hî£ëtt´^~ä}lõë¹ä[A>áQ uZZ@òlȧÒPÂmiÝ1àp_äí¤Êb<*²Ñ$[HÑÊ»"2%
+Éå!URd;"8X³¤Aää{$/QDIr³Áüäzb¤2«r
g#ÖÒC91á]
UîôIaÖlN^£+ÕÊÛFò&/ÐN1´¤±nG©ØªacÝH§ØºE0R¹²æ"/=t?´¡`.ÄM:«±àDæÎ;[ÎsÏ=7©O¿~ýî ³oûh#Øåy6mêÅGÞ¯{T¦~Lêµ½þúë')o ±^N})9ï Þüî»ï*ÔJ¦HcÇä¢Ià³Ë¯ tÅÇû¡V1.¢èôéÓ/G÷Ûo¿}0Ò%Vî?cÆA?üpß%Kt&Bé/¯Ï&JP[éJÖ¼ûî»þùç=xN-~íµ×þ¡±<çwÃK/½4²Ê÷Þ{oëÓ<g]yåSo¹å?Bt¹Öéó/ºè¢?ÃË:ùÄú3ùbÐý÷ß?fòäÉjp0Kñ2ñf_}õÕS<ØCå:Ki2cˤóð>úèÞξ¥s
+eKu¤¦M¶öJW;AþLõÒ
+L×°pn¹ü1WCBèá«Ã¯¡,W]]ý-ñmý#<rxÓ§~º(ai;õy¾/Wñ¦ùoélø!Ð÷1ßüêÕ«÷s îU9¡°[í1*µã
f'ÄgwìرEãë|]Ïs×ñæú
+cdùçf
+¡èª¦¦¦'ó]¡yuh}µqUÆî[°`ÁHÞùM{ý¦ïèYã~évjæCùer¿ë¤ITǺj78R~CCv«Dºúc«ús/:®A¼ëзÖì³IerêÆÉ(
¨/¼ðÂêÃ
+SûDàÅ®°:Sîña?ËßTwÞyç)Êü zli© TØYPeļT_àûvcêÇ 9B}^³¶ò mÁ¬ÃèƦ´®Á:ó7Yù£>zTܨê]ª)ãù)Þ./.Þüõ×_ïâm*˳²Ê£ó Ü|°wÑ¢E²¦¶zHΰÓÊÛàRÛ*ÿ©yì¼*^`ªd¼Ììfü<ñî>\×q^:²lÈA¬þ ãØ"H¯=ÌPý
+K.=¦·?¢^yÕ¤Z¾RÌiiâ
+µ«Ý¯2æÁ5àÌ.>V3FÒªpaÛ5Oêµl1ëÓéxüñÇkUÆÿUãÆ;;Ép¯l ã@Ùèý úÉ'l5kÖIÞós¼Åê=zäT/BL;£WÊ[¨D*ǹ;@ãÖæRúa&zȯg¬ßEØ£ÒqeÇ8ÒÒ% Iظ33gÎLKW½ú©þ»gæÉ7ñ±ò:=bkGíO<q5´É¬Å¬Oyq²Í~ÚíÇ r|ljV½Í]ÆZȤ·º\òÀ8É2þiÎaá¿riåUï,wa¹ð¤(`ÄI6P_÷:rüä
+ñ¨ÀeTqï½÷f<eúqA%m=8þ Í>%ñ}CãÙQQ mEõLzÏÌ«LÏ4m!ÚçBup)½ä ´Å¬¿ÃÊÇá.è<fÌ<Ï¥ù³|²·ß~;Î=W0®Ãçvô9¦>7±ÏÅáCÏDýÝ»wûJøÈVië,ºµí9s|;Ùí¹©}.a>dû,ÆçHZ}Btk¾çöL{®öv}ø8Òq¡¡²!Cø&Lðq]¾DÿÊé7üFôÿÿj|w%& IEND®B`
\ No newline at end of file
Added: trunk/openchange/doc/doxygen/pictures/body_top_bg2.jpg
===================================================================
--- trunk/openchange/doc/doxygen/pictures/body_top_bg2.jpg (rev 0)
+++ trunk/openchange/doc/doxygen/pictures/body_top_bg2.jpg 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,3 @@
+ÿØÿà JFIF d d ÿì Ducky d ÿî Adobe dÀ ÿÛ ÿÀ ÿÄ h
+ að¡qQáR¢ ð!1aQÿÚ ? Ô¢±Õ|W¼ í|ua³Dbeh*ø
+VÁ&ÅrV¹´,¸^Â-~TbÁÐéÊ=©xj䮤*ÿ Rb²r %7Lñܶ5ø¦èªÞV¶ ÿÙ
\ No newline at end of file
Added: trunk/openchange/doc/doxygen/pictures/header.jpg
===================================================================
--- trunk/openchange/doc/doxygen/pictures/header.jpg (rev 0)
+++ trunk/openchange/doc/doxygen/pictures/header.jpg 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,612 @@
+ÿØÿà JFIF d d ÿì Ducky d ÿî Adobe dÀ ÿÛ ÿÀ Í4 ÿÄ û
+
+ a!Qqð1A¡¢d ±"Ô%UÕVÖWÑñ#EÁá2DT·BR3C$uµ&g(8xS£³4
6¦hbc¤´ÅG§)
+
+ !1AQq"ÓTÔUa2¡Ò#³´u6±BRVÁÑb²3$v'7ðár&ñ¢CS%Âs£4Dct¤5ef(ÿÚ ? ýAîÊåSñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pìSpvPnÊñMÁÙB8v)¸;(GÅ7eáئàì¡;Ü#b²pì__gÓâ£êE~²O\VݪÏãà
·#÷Á?NcÏ´ÔôÛ£¾!àÞÖ²x¬.c;s÷<%Íåå+ÝÁ¾ºckO¦£Êcq0}ç)sµµi®W¶6׳SÈpo×'üßÆWí¬?þ«[7ð¿áÜï¨]ù¥øócûëëvþqkúßÿ øÇñåõ¥?á2ÿ ùßP»óHøócûçëpyůëvþoc/Ç¿Ö¿Ëÿ ç=BëÍ#ãÍïWÁçýn¿ÍÜeøî×úÒá2¿Ã¹ÏPºóIüy²=óõ¸<â×õ·7qã»_ëJ?Êÿ ç=BëÍ#ã½ïWÁçýlÂÿ ÍÌiøê×úÒðÇ?áÜç¨]y¤|w²=óõ¸<â×õ¯ÿ 6ñ§ã«cë:?<Êÿ ç=BëÍ#ã½ïWÁç¿XcùµÛYÑü1æOø{9ê^iì|â½n8§ëNþlãoÇ6ÏÖt¹þÎz×GÇ{#ß8¯[Î-Z0×óg~8¶~³£øeÌðösÔn¼Ò>:Ù>ùÅzÜqkúÏÿ ßñųõ/á2?ÃÙ¿QºóHøëdûçëpyÅ?Y°à÷²¾8üom}gGðËáìߨÝy¤þ:Ù>ùÅzÔqkúÍøãñ½µõÃ>d³~£uæñÖÉ÷Î+Ö ó~²áßæ¶9ümm}eGðÏÿ áìߨÝy¤|u²}óõ¨<â×õ5q×ãkoë*_ÃNcÿ ó~£uæñÎÊ÷Æ+Ö ó_Ö<?üÔÇ_m¿¬¨þsü?õ¯4vW¾1~µSõÿ Êxïñ·õÃNcó~£uæñÎÊ÷Æ/Ö ó_ÖCüÓÇ-Ϭhþóü?õ¯4vW¾1~µZþ°b/æ<üin}cKøkÌ_ðþkÔn¼Òì¯|býj8§êþ"þhãßÆvçÖ4
+¹þÍz×GÇ;/ß¿ZÎ-W±óGþ3·~±£ømÌ_pf½FëÍ#ãï_Aç¿«¸ù¿[¿XÑü6æ/¸3^£uæñÆË÷Æ/Ö ó~®b_æ~?üenýcKømÌOpf½FëÍ#ãï_Aç¿«ùÿ ÛßXQü7æ'¸3^¥uæñÆË÷Æ/Ö ó_Õ¼OüÍ°?ÛßXQü7æ¸3^¥sæñÆË÷Æ/Ö ó~bæmøÂÞúÂðã~àÍzÏOã}ï|_Aç¿«8§ù`þ/·þ°£øqÌ?pf½JçÍ#ã}ï|_Aç¿«§ùa~/·þ°£øqÌ?pf}JçÍ#ã}ï|_AçýWÅ_Ì«ñ}¿õ
Ãa{3êW>iìÏ{âýj8µýVÅÌñtÃéy
îÏ©\ù´|o³=ïõ¨<⪸°{Ù&Äü]ðú?<Â÷gÔ®|Ú>6Ù¾÷ÆzÔqkú©/âØÑü9æ¸s>¥sæÑñ¶Í÷¾3Ö ó_ÕL[üDZÀü>á×0}Ãõ+6ÆÛ7ÞøÏZÎ)ú§¿ö7âÈÑü:æ¸s>¥sæÑñ¶Í÷¾3Ö ó_Õ,_üƱ¿A|:ðïâÌzÏGÆÛ7ÞøÏZÎ-Tq÷²-?þëøuþ`{1êW>mìß{ã=j8§ê1þbYà¾GðïâÌzÏGÆ»;ÞøÏZÎ-SñóÈüUðê?{ÿ ÜYR¹óhø×g{ßëPyÅ?SñóÉüUðê_ÃÍÿ î,Ç©\ù´þ5ÙÞöÆzÌqkúÿ VWâ?Qü<ßþâÌzÏGÆ»;ÞØÏYÎ-Sq ÷²ø¦á´w÷¸³§sæÑñ®Î÷¶3Ö`ó~¦c_æ
+ø¢á´w÷¸³§sæÑñ¦Î÷¶3Öaó_Ô¼müÀ²ÿ B|6áîþ÷cÔî|Ú>4ÙþöÆzÌ>qOÔ¬müÀ³?Â|6ð÷{/êw>mlÿ {c=fËZþ¤ã¿öoâx_Ñü>ß¾ãËúÏGÆ?ÞØÏYòÔýIǬßÄп
+£ø}¿}Çõ;66½±¾³åR1ÏßÛ;ñ4/Ã(þoßqåýNçÍ£ãMïlo¬Ãùk_Ô|s÷öÎüK
+ðÊ_Ãýûî<¿©Üù´þ3ÙþöÆúÌ?§ê6:ûùgþ%øeÃýùî<¿©Üy´|g´=íõ-kúþýÙÿ a¾Gðÿ ~{/êwmí{c}fËSõýû´?Cü27ß¹2þ§qæÑñÐ÷¶7Öaüµ¯ê&<ûõh~$øe/7ß¹2Þ§qæÑñÐ÷®7Öaüµ?Pñïß«Gñ?Ã)ü¾ýÉõ;6ö½q¾³åPñ÷ßGñGÂé|¾ýÉõ;6¶½q¾³å©ú
¾üZ_â>GÀ;ïÜoS¸óiüe´}ëõ-kúþüZ_¢>GÀ;ëÜoS¸ói|e´}ëõ-OÔ÷ÞÓüEðº_ ï¯re½RãͧñÑ÷®7Öaüµ¯ê÷ÚÓüCðº>ß>åËz¥ÇGÆ[GÞ¸ßYòÔû`ýöµ?Äü.·×¹2Þ©qæÑñÑ÷®7Öaüµ¯Ûëï©ø'át|¾}ËõK6v½q¾³å©öúÂûëjþ øUorå½RãÍ£ã£ï\o¬Ãùk_·¶ßKWñW¨ø|û-êmízã}fËSíå÷ÒÖú~+áT¾ßåÊú¥ÇGÆ;KÞ¸ïYòÖ¿o,?¾·Óñ_
+£à=ñî\¯ª\y´|c´½ëõ-O·v'ß;_éø¯
Qð&ø÷.WÕ.<Ú>1Ú^õÇzÌ?µûwbýòµþøUïrå}RãͧñÒ÷®;Öaüµ>ÝX¿|§¢þGÀ{ãܹ_T¸óhøÇi{×ë0þZn¬o¾6ÇÓÑ
+£àMñî\¯ª\y´|a´½ëõ-köæÆûãl}=ðª>ÞþåÊú¥ÇGÆOÞïYòÔûqcýð¶~øM/7¿¹²¾©qæÑñÒ÷¦;Öaüµ¯Ûï
³ôìgÂhø{û+êmm?zc½fËSíÅ÷ÂÙúv3á4|½ýÍõK66½1Þ³å©öÞÈûßm}9ð>ÞÞæÊú¥ÇGÆOÞïYòÔûodýﶾøMïose}RãÍ£ã
+§ïLw¬Ãùk_¶ÖOÞëkéÈÏÑð.÷÷6WÕ.<Ú>/Ú~ôÇzÄ?§Ûk+ïu·ôÜoÂhø{{+êmm?zc½fËZýµ²¾÷[MÆü&w·¹²¾©qæÑñ~Ó÷¦;Ö!üµ>ÚÙ_{m¿¦ã~Kàmíîl¯ª\y´þ/Ú~ôÇzÄ?§Û[/ïm¹ôÜoÂhø{{)êm/6½1Þ±å©öÒËûÛn}7ð>ÞÞæÊz¥ÇGÆOÞïYòÔûieýí·>øMoose=RãÍ£ã
+§ïLw¬Ãùj}´²þöÛMÆü&··¹²©qæÑñÓ÷¦;Öaüµ>ÚY{mϦã~GÀÛÛÜÙOT¸óhøÃiûÓë0þZm,¿½¶çÓq¿ £àmíîl§ª\y´|a´ýéõ-O¶_ÞÛsé¸ßÑð6ö÷6SÕ.<Ú>0Ú~ôÇzÌ?§ÛK/ïm¹ôÜoÂhø{{)êmm?zc½fËSí¥÷¶Üún7á4|
+½½ÍõK66½1Þ³å©öÒËûÛn}7ð>ÞÞæÊz¥ÇGÆOÞïYòÔûieýí·>øMoose=RãÍ£ã
+§ïLw¬Ãùj}´²þöÛMÆü&··¹²©qæÑñÓ÷¦;Öaüµ>ÚY{mϦã~GÀÛÛÜÙOT¸óhøÃiûÓë0þZm,¿½¶çÓq¿ £àmíîl§ª\y´|a´ýéõ-O¶_ÞÛsé¸ßÑð6ö÷6SÕ.<Ú>0Ú~ôÇzÌ?§ÛK/ïm¹ôÜoÂhø{{)êmm?zc½fËSí¥÷¶Üún7á4|
+½½ÍõK66½1Þ³å©öÒËûÛn}7ð>ÞÞæÊz¥ÇGÆOÞïYòÔûieýí·>øMoose=RãÍ£ã
+§ïLw¬Ãùj}´²þöÛMÆü&··¹²©qæÑñÓ÷¦;ÖaüµÈ[.Õâ)8há'(,Ed"©,¥¦ªJLEPS ¡ZÜðMk;í®ctw1¼µìp-s\ÓG5Í4-sH P¬ô3Eqn-Þ×Àö5Í!ÍsH¨s\ AÄ/£³éñWÔ¹+ô©Ùôø¨ú_¥bï¼JÆàXññ¶Èe\D[G2NJ&CC6*ä1ORöêÜ 6¾ñÈîKÞsS,û«×>
+§hð'¿jGÐ8A<H/uð«ònió6Û`ãÛ«Y.á¸i10ý7£½xtÖ¡£§Æ¯oL
xäi¥®Òá¸$Ö1÷T|¹ÌDÎmïFhV±í?ä¤sk_§[khmÍn'mYÃidÐ*Ðò8jÿ jG·<Õð¶sqf·-ó²9Ën.[ýV7ì±£© .(
+uV|µb*ë©ÓDêªmÓÜþ;SªPS¸)P&
+PSn½=úÔU()ÕRZª©ANº)Õ)UÛã¤GjuJ
+wM`¥*u÷jKSªPSnÞ*Ôê¨ÓN
UL
+íñÒ¢uJU:½ÊR}SªR©·ÇPZRORuLUzüJ©Õ)TÛ§OzN©ANà¨-L ¦ÝjUU)Tê÷*tÁL
+XRN½J¦Þ¡¥¤'T §UAjuJ
+uÔ§T¥So½SBª©AOëè¤{Mºûµ%¡:¥*t©-N©AJÔêªmñÒ¡N©ANò
MªR©×ÑH´&
+R©¶ µ:¥*KUÛ¯MMN©ANò
*'T §^ЩÒRjKSªPS¸*S)TÛ®Á©¥ª@S¤<´ª`S¯¢uH
+m©-N©@üõ©ªsPÔ§T §pRâRu¥@RU%©Õ(yõ©-Nªà~ªÔêQ:¤N<)Õ()J§T}µ%©×ëH)Õ 9ô©-N© ãÓSDU 9ôé¥Ç:¤ÒàSW
-)Ô¤=Iju~z)ñWs
+I¨ª@?8x©S±5p?0ÿ M.=iÔ¤ÑÀ£¸)Q:p5M¨ëWÒÒ\SBö«<4¨ª¸<5:SVs
+.!UÀÂT'^Õp?pQNÄS±\
+JÔ®´¨
`0ôÒ¢t
+À`è¥E4ZÒIkB¡
+P
(B!J¥R)B¡
+P
(B!J¥R,®Áw¹f"Éc 8±K^ð$Óþ@è§_ûç÷Û1ûVïôò/»¶î/öu·èX²?³îÒµo¶/À§gÝ¥
~px»e®ÜõK¹2ǽni57fÞ*ÙuD¦ ÑL}4ÞPÆ0ò×ì?%0V.U` Ç°5³ãmî^zÝ-ÌMGÒ|g+ÐÐ@ó{[¼¶ÿ ÊËxíF+é hêÀ÷DÀ;<ViÒI=%th)Ï^£Jt-©
+¦Þª^êî
+¥*u÷jKSªPSn%ªª¨§buJU6øéSµ:¥:º)PêÛ¯»RZRtîñT§T ¥Nt'T¥So¦©Õ()Ò¨
+uJ
+uôT§T ¦ÚÕUJ
+TéìN©¦Ýi'T¥SnP© )Õ()Ü%©ªm¨-N©J§UM
+ RN¿ ÒE
+b©·ÇS¤êê©-UT¥S® µ:¥*¢¤RÁJتm×È5%©Õ)Tê©-N©ANzÕUJUvøêhSªR©ÒP¥Dêëè©-N©J¦ÚÔêî
+ÔêÛ¯O~¦
:¥6t÷©QURÁRZRMµ%©Õ()ÕÑPZ)AN÷jhBuJU6éÓJ:¥)iìN©J¦ÚÔêêè©-N©N÷jhBuHU6éÓÞ¥áN©AN१±:¥*ÃÝÍPZRÁRZRuéîÖ§MªPSªêë© N© áHµ:ýiNºÔê·NïIjª¥÷M)Ф*ÃÕG
:¥Ò = Õ jKS¯j@?=IjuìWó%©Õ(ÉSNÄÕÀüÃã¥áN©@ô¨
+ÀáÝÉHµ:
+ at 8ÿ ]Iju
+àpðÔéN© ãàjHNªà~~JT#¡ üÃKÂUÀôPpH
+TUR®z" «ùêt§ÅXá¥DU\!·¦¦5p8xy)P¦®Ì:Ò© Ô
p8ÑÁôQìWë¥DêGJ¶´¨AVÞTJ]à¥B
+µ$¡
+P
(B!J¥R)B¡
+P
(B!J²Wõ,éßyÿ ¯=~ooßlÇí[¿ÓȾîÚºx¿ÙÖß¡bËË`÷uV®¶À§e°{º¨Gà_è}3~dl«ÃÅwK~¿hùXðÇn~ÁÇþ©
+üÊߧÿ =f¿k^~±"êàSh¹[ÙjÕjëÚ%¨ªR©¶ µURô¨SªPSo»Zv§T §WE-5N©AN¾ÔêÛÝîT§T ¥MèN©J¦ßv´©ÚR!ÑKMSªPS¯¢ µ0RMµ%©Õ()QCÔS»ué¥DêªmÓÊAN©ANà©-T
+R©¶ µ:¥*U4)è%Mªb©·¨iÕ:ö¥;¤µ:¥*u¨-UT¥SnåM
+uJU?¬*h)¦Ýz{ôSªPSª µ:¥*KSªR«·ÇSBR]4 Õ0)Ð4SªR©¶ µURÁRZRMºôÔÑ:¥*D<¡J:¦?¬*KS)TÛPZR]%ªL
+tjhSªR©·ÇJ:¥*KSªR©·ZÔêêè©-N©AN¾êÛã¥@RôSªPSnµ©Õ )Òªªë÷iP¢©J¦Þ¡¥Dêç©ÓØ)AMµ%©Õ )ÕÑPZ¨¥Sn¾íM(Rt¥áN©AJTHÛHµ:¥óÔ¦
+@?0鲤µ:¥9ü4)¤*ÃÕþ*^ꥧ±:¤ó
+"ÔëÚÏQ¥:¤óUIojuHçòR¡êM {º)xSª@?=*Фí¤BuíHÔÁìWEM
+uH}jKBuWE*Ðna¥^ÔëÚ®¢ô'àW Ò¢u=jàa¤T+ùêt§Å\iQWMM¥p8tR¡V¥^ÔêUÀôpGp0QDqêV¥DëÚ¬Ì4¨½ÏJQX¡ZÒIJ¥R)B¡
+P
(B!J¥YGÃjz¤üyß»ÿ ׿7·Ïï¶cößéä_wmÝ<_ìëoбeçb;|«NÄvù(Bü³ç£nçLÐí2ÎFá0ûOʶÿ Ë
+·ûú¤+ó#üõýyúĪÁJÞèµ:ýINª\zÓJ
+t*Û§MIjª¥óÔ¦
+B©¶¤µ:¥*hSªPSn½4¨ªPSnå"Ôêî
+ÔÁHU6Ô§T ¥M
+uL
+mצ;SªPSnåN§T §pT¦
+R©¶ µURNªêèTN©AMºtÔéªuíJ
+wIjuJ
+mÖ µ:¥*U4)Õ()ܸ&
+b©·ÇHµ:¤:ªUU0)×PZR]¾>õ*êªXTÐ'TÅSn¾íIjuJ
+mÒ¤µ:¥*SªR©·]Jªé(TÒ©Õ0)×ÑRZRMµ%©Õ()ÕÑQ¥:¥:È4¨RM½CR at N½©ANà¤ZRMºÔ§T¥SnåAjª¦:ú)'T ¦ßMuJ
+uR-N©ANºÔêªsçôT§T §pT¦bR©·Çߥ@RU%©Õ()×PZª©
+§0éÝâ©-N©ANà¥Å:¥*|u4ªPSªjª¥6ëPZRU%©Õ((=54¢uH
+mÓ¦
:¥óÒ =ª@?0ÔªªP?=Nê§æ¡¨-N©Nz\SªPSn½Þ:\:ÐKObuHÛRZ~¤~zÔêÌ:ôÔ§T~~JT#¡4
?0ëKÂ{RéR½¯b@?0÷tT{UÀýu%©×±\ú
+"ª@8ôÔiNªàpèé£OÀ4¸u¢½ªàz( ¦×µ\4@§R¸<<:S©Væ;Sª¸|<´´¦®})P+{Sª¸à¬
+(#¡_ZTOWjÔiQ>[{¢¶ 4¢ÖJP
(B!J¥R)BYðÒ¨<;ï\ùU0ø«ó{|þûf?jÝþE÷vÐýÒÅþζý`ö;<«T-þÝ*v;<T#þÝ+òÍ»shkÞ˹$4Í~Öò¨Êý·ûú¤+óü÷ýyúÄ©ýU¾N©@ýu%©Õ )·JÔê'T ¦Ý;¼TxSJçÿ MRuH
+mêÔêçä©-N©
+¦ÝjSªû6y éQí\½xààv¬ÐUËÔ0èTÑAUNo ×ÒÇfYÜÖBÑRç ¤[ùÀ\ãÐOàYKcðoïTÐr[IKyú®n5>/W³0@bRªø©Ã@2e
+5¯7ÌókcaÜcuÛg¿ÕÇãÙ«z»|+mÆì}ËðÛ=±5p§¯Â<+¸à2èdçnEÛ ©XGª)¦.I¯½Qs 1¬TÄ ¼¢<ªÅÎìMäÝÕ»HÔáS@]Ð:*ÐOJÊÍ°o,ÁûãÈ¡¡£M:iÓÆ´<;*¶ÙÚ±)ÿ çÒ¡È.b©ïhôÆn7Cx{ýí9DC½]«~kÈÿ tiû2ý=«í á;ª[HºÆàá®àrá«Y¦.\ JKº
+²b²~å#%5KCrD
+` Ö¶+`cîãl¯FÆâE{(iÄ#¾#¤®ÆÔ²F®Úñ кVn͹mÓÆQª0HGEÐäå×}=t^PïVÝiÇÞÌH5£À¬Î6ö×%½£\dëò
+dhB©MºtÒ-N½©AJÕ@¥*u©-N©J§UM
+uL
+uÒ N©J¦ßIjuJ
+uT§T §]AjuJU6éîTЧUÚ¸kßÛ!@ã\{YuS(ºÞ6&9¸S÷TôH¸Ô5:§C¦E9mcwîÌ&ÈÀO¸óòì UïyàÈão
+Oyà 8¹ÅpÎíͽÝ9x°¸vk¼õ5iï=MhâOzÖ»ogg1Qø¯ÉÒWîF~Å'«Ú±on&äû@ûfÃ2sñQ«".å¤IÈDAÔ
ùÝç3nd0ã¶ûZÙØziãKroxà\Èb%WIú5ü¹åNÆ
o[¹/sh&6:FýXà!íiè@Ò)Ð>7{,ø·]K/ dIÜQÝ$¸Á@Ê>ºAÓåÐ)tôxlåó[°¦L¦TÌã%Sz ÇÌ8î¹üÃrèòµ¶ÊàZGxö² ?ÿ Õ¬0,.´q* ØüÞÙm©æÇåÈ:]!$ô'.véPúTðy¡Ä>¿¸gÉ1ÖAj¨dFFÛ¸ v@¨±ÑBZ)U CDÅ7
+ÑfËJmJ$9þ¢å÷0°ÆÁ37qkÓ,N§y©cÀémxñ^Þ"¼6n_eeÊ4MQÈß±++@æÄv9§OÒÅWn½5½PN©J§W)Pêëè©-N©
+¦ßAjuL
+TéUT¥W¯È54N©J¦Ý:{Ô¨ªPS¸*KSªb©·ZÔêªuTé)Õ0+Éà%Mz=í á×pÛgá«´ÓW×ùçK4iy¥Pc¢Çz*j¦@o¢²k¦º5|ÏÉ.iîmñËÙn7Àè,û¾ëDaÆ|5 ðcWºsO``¶¦7u
l¢[}æ·±N8¸¯9ÐpUS*
C ×ÒbÃÏB¾S®j*ªsçôTé)Õ0)ýaI0{Mºûµ:BuJ
+uT§T §]AjuHU6øêtªª`S«hRERMºû´¨ª@Sn%ªª¨-N©AM¾:)Õ()Ïã
+ÁìJU6ëîÒ N©ANªE©Õ )×PZRt÷?¢¤µ:¤9ùv
M
+uJU6õ
+/
+uJ
+sÒÓØRù¤µ:¤÷AjuJ
+>½5:Sª@SªÒúépERÂ궤µ:ýJàpè©-N©@ãÏAjuWõyiP§T qç×ËKjàz4ö'^Äna©!íHç©-M\
+Ì:TRÇÃËS¥5p8séÓKN© ãGpëWÒ¢~p7pR!:ö«Ç¦¤µp8R¡N¥\>©#µ:«ù§Jjà`ðÒ⬢½©×µ\ÝÞ¢ÀÛ|tQB¶´¨¥`0ÔÑ>[{¢×]hIkI%(B!J¥YÃ"Zµt:wݸý!¼5ù½¾}³µnÿ X}Ý´?tñ³¿BŽvµªNÇ»Z¿%Bów´Ì90<W¬ØWí*ÿ +¶ßìê¯Ì-üóÞoö½çë.£oZG (¸õ§T §]*êÚ!îR-N© ý}©Õ mIjuúÒõ4=IÕ)TÛKÂ͸,ÉMÉ¢ù
+jcÔvR7¤U#ÄÁéMmæB)UÚaïL}â7Hâ1÷½àù3¹Ã·9qlaýë<æÕí R½Üt4ôBâ8N+Ñv?.3[Òq$_ÅãLàxÓ¤FÞÈí¨h< ¯úÆ<$`Îà
+Þj¼â¢Õ£h©J\²K¸U4@@æ 2(²ý%"] F¾ÜÕÞ¼Á½q½¸sl§£«!` ®t¸Þ+ê¬7/6®Òµos_thä£äq$'¡ ¹}Ë?EHݲ`}4
+5
+t!OÈ!ÑXuÍÓ¤q¯ÖJÉß^[[4Ð ¹2í:ïf%#"ÂÌHwGMS¼Q§Æاÿ Q2"Ôë¢*ÚNA
+ 4¯IÛx±?~sKûÈÙAQ¤;CxW à áCÒ¼ßqÞýêcbÑ7¸.-Ö>QRxÔt.¸ÁÔ`9p¬rU¶ªö/»BRò¥3cx¥þ¾ÁtW}ÔMÀ;
[Bþ׬ý+L=Áµïß##Ä
+Wé TÃ%0z«u1lªNY±lGGP§Uºí[z:E1A¹;!U°
+aÐ ÄÝï¡Y[qq]ops^ò@¨TõÐÖ¾õÃmËZHkæ´H$)NÒà6tT»uÐ(£¤À@éiÛ4PL'2Jö§HU
+DtÝ0w³Ög>õô8vOè\ca êêðý
bÍ×;~áó3e%¸²ÌôìÚÉ2LT]©:r ¼¡èÍé÷hÃåÖûZÑÕâYôöÓéâ:ºV§}¶ÅËÜÖQõ§ÛðýKæ¡¥íÉâæY,Åësn¨ÀÈ S¦r P("^ÈYå-ÅÍÃã=#è#¤-òÊæÂcËK_øm¥Sª»ÄÕªPS¯¢¦:¥6ø颩ANªÕUJ
+uÔ§T¥Sn¨Sª`Sú¦0Ru÷i§Uï²ù!á*åcòJÜgv¤(,6Æ/²P¾d2T¥¦ì&¨Q:SäÔ¡¯Â¿Íýæâßø\A!m¤'tw×sºÝ®pë1±o`Üxõw!í-°ÛC/½ef«wéîíâ8Ø÷:´°v/ÎmËv^yÊÿ ¹ò
+ñ0îjáºæMLÉ:Pç3oDcfÙ=Ô¢MA2HR}7ÀÚYØÁÆF!Æ[FØã`àZ)õÒç.q.$Jð¼¾Zâæê\óÌó¼½î=$è .Ml-ò>bAìTÜCÖR±Îg!'ºnØ¿bñ¹ÓpÕë7ID!r bl·vÖæÙöÓµ¯F¹® µÍp!Í ð B
+ÁøfÏ$cA¡è :èPâCÙ}¸I±¯Ë[BFj] w/¤npýþÙºiãxé¼È=ôtôìŲ`<ølþÈìkg8bî¬k 'ÅýîÜô¹ÕN§µõ>ùt[ã6[®pÓÅÔh¿îóØ×IGPti¯ø<àñ¹jô²îtç®I^ËM~߶F.e:zvñVúnKÛ® "Ì
+¤÷Ìþyo=̶müD1]â´E¶ýÝdYXàƶ¯§{ éhÔàAÔj[;gtlgfr2Éo¼µÑ7´¸7ìjq $P(f\ÞÇ®øÂÑ°y I)Gmm|Å55|FÛSo\¹nÖÉǬñÚ
!Vun3(}ÒjjÆå2ßÍ?ýÕ5æ<@Àe}q[>HØÑW0àMtù:'ïXc¹y|Üv×gnß$ÍcÜMá( ®·k;h8¬Aã[ü%eVV¹dNØ×SÀñ""ùvlÜ´¿bMTU ²©,V$*
+)ûw'ymÌý¾ë¹£m¾rÙâ;ÚIn¢*Ù#©'»P8×5í«Cå|Êåôû0-£{¦ÅNÒø^áãP9 [ "5ÔÒ3^ßá#°Ì`ã®beåÃw3BbÈG²Ì×AUZðA½¾â2nRàbÐå3õÌõk%Næ0¦ª¾9ç/0÷þë¸Ûd1c- ^ÊÖ8:ÓÞVPøÙ¢9&ú©¬ô¼_,önÐÛðçyéd¾¸E«öÒ£VFZ÷HÑöÝ°5&vã±W³Ö'¾pXs0Ê"æy5"õÓDTI°É:»o(yèvΦUÒjõ 9Na)?ÊÄe¹Ï~U]Ãß²ÍmÉ$s¢dl -(-ßÈK¥ñ=~Êå70-ä²ÚͺÆfÂæ¹ï$tUÌYöEC$cÅA<:p7á"¯ÅÍ·Ã[báºÍò¶eÞÊ9éÛ*ªh$åB:~RýE$á²ÀPíT¦ÓßWÐ;µÜªºß»RFýÀO {A ÞM$µÍ¯:à¶{Ì}£¸àß½÷RT MZîÇpsM8´Ö½!Íü;{:øC¹ÔÎ7Ï4Òàd̶f{qºi);IHYy±håúG#uWxÁ{#¦Qp®¥OæýµÍyóÛ¥½Ä/qýñ±±Ô²&6FICH.
+I
+A:ÅÞÙåç*6Uñ»Ï¾âhdhî÷Ò4,sBêö0PôqÛî¸á~÷â²Ï[/±IçÓvÔ¤ÂøÔNภf#îYçì¦Fß\X®ÉâV01)Äæ2Y]½Í¾gìÎ`ZìÞh¾»KçÆÖLÆDÂÞõÝÜr1в&º>ðÈÙ#®Pt3<ºØ{gÜnmÙ®m÷:7:GjîÛì{e|Ñã1Ìyi45%¸YÁw¼[_îaV
+ǵڳ¾nVȦáÓ6VU(Øh¤Õ3UÁªIYcN̨©îÙæ¥,öã2"6Üfnæ[BI
+s|#w¦êqsu·Ê¹yËû½óu³2Ý¡ÓÈHÖ0ßGi'C\â
+]ÕËì
ÃW¢ä¶/ËÞfAXø½åb!ä[jÓɺ½ÖÏÔbࢿź!V)Ñ ð¬~SùÜXѸo¬l¦`+gÅl×½§CCíåsCßLÓJEW¬^cù
½8k[«©ãv'l9pàK&:î¢pEEñµÂ±áì\Å®U®ì
+È°RN¥ æ%üÌZ×!lÙ²2ðif{b'"¢aÜQOGäç8o·ÅÖÖÝ6ÛwØêÖ[#XáÉa$²XÞ@ é:mZÝ'|µµÚðÛç¶ô®mÝÓIqsæ´j jcÙRÃMB:¦úÇ$áî÷ÇG#ñ=ÝØ8·|ñìdYÍó;sCÛCÛ«7Aü¢bB.u[±j£ÅRÔÄQ¹QbüË}É»0ùÌ/eZ6ç;
+s¾Ä,òHàK[ýqG=Áð!ä£7¾näñV7û¦àÁ´a%ûR¹íf4]ýSPÖÐZ#0¾1öjñÎî°8½1ÎA<Ó7Ò·r²Å*íëx»íº æbI¼n´w¹ pP(§¾Uë9®`së2Úå·eÅC,¡cc2´'»/dcËCã¶5¡ióÌ^Ïåûã·a¹²ËG ç>RêT
+a²K+Ðâî<¨#ÍÜ]®|ÄppÞ.F\ñ÷½Éh\²eIWlâ³U$ñI7i¹ÛÆH®É¾Mð0}5æ>'Ëçó 5ÒXH¦:¹î0E<té@:F£C¦Âq;'#Þ-ÙÅÁBæH¤} kDZ»ÇѬ%££AQUè&agì¾á2wô·%Zy7-dÌT¸RB1gÍ|Ý)C0½±Í´
+&° Ü«(j aåùÛ¹¿aZüG
½Æâ°²¹ÝÓ_z\âÒY®ÞêbºZ ´e°<ٷܹK[ÜR0;Ç6GÕ¤@vã
+ ñ_HáÛ
|×Ã
+ÛÄÏKÍÁ!L¿¹I µªÅ {®2Q½ÆþbR.z:ßpYNÕÚ® £Úé÷v·69¶7í¶Ææyå®ccWDö¤7F×´ñ¯Cº»{+?´'ݽÖsÜ÷
+F¤k{ðìòÒ8S#§½Xñ-ußñY¼³Æõ³+òÊÅ(GNåÑQYDSPU ¢
ðòÖ÷ÏbîÇßm§ÂÙ®n^Ç÷ZÍBN=kQåÊÃnüå¦q²:( k¡å¥Ô5#§íÛ;ÙÃLÂøÏ/K]y#G¼2sëmÍÌHIø+º¬@ع-ÆiyGut="MêJà¯fqìKçñîÏæ}B3»cî|XY#at6LÐÌã«¥®Ód§Pñäý»ÉÝ¥)Äç¾óʵÔÌ2Fköi¬jàZp^9xgÅøËÆùëJ9{2c¨öh´Yó©Vl?¥ÅjÉÂHH¥däNG§:È,Bøö»íæÞàÜÙKͽØÆî;&¹Ááa~÷r²F·óaìsC
+sIñF»Ìþ]a°V»j¹Ç t@Ð\^ãsê¿CÚPòKM8øÔw
+)c»£\<Kq:êÝÃé*ÁeܱR}§ ÒFMëÖi)#ñPHêųv ½&áJ·'5¹·Äî9}Ëè>ìN·¸µLcZâ¯Gçù?7t$Î>^òçÃM¼·nëKKL
+ç8í¼Fµ;ßP åvDz»<Üñ¥ × akªJa»v~~Npw#ÑpÅ$êjî¾"¥.&Ò+²Æ8Pâ"
TÉÚ
ösùÙ¶ÎÍe'°ËØ2"d8âÕ¡«éï%'A q--×É]Ï;qvÞco ïðm_,ÍÝPÇ H¥} wpÝ,{/#(Õ
Ãbâv¼¢é® ÍôT4»
+ÐøøkÐ9Ì<îûÀÝßn7D븯;¶h``ÑݱÜ@<N§+Mæ¾ËÄíµ½¦²6ÚKmnÖâó«[ÛÀªÁd'ü7ðÓ ²¿ÒÎgn²&h|kòQªèª«R½B!¼|Äë6Ç).g#¨pDNa(®ææýß[}·Ê6C:Ô%äc¨t÷>6Dâ¢7Ë èZÝ¿Ë¡´ð1fùé$½¸%³Å*+¢½Ïí¸½°5&wÛñϳëÆSvÊ^x(ÄŹgq:~ñËDTI¸È8º.ظîIgÊcn¿Ês¼±ºÿ y¾Ï/·ä1α°jtµñÃãy é2Dö=û
+ʽùo%ØmÎ72Æ4=Ïq#¢¥¯V½ PÉñÓÀ/0o[js_V<ºËg̼nCï¢+µ>ºj ¢»íÌEÐS@íP¦Ó¾ªÛÙìvæÃÛæñÕes^Úð ¸u9¦pêp#©|ûÃÞà²Sb¯Û¦ê N±Ú(ZzÁl`¦Ú̬]Rõ%©Õ()·ÇQ¥:ö¥:BuJU:éP'T¦ÚÔê©-N©J¦Þ¡¨-N½©N%*ÁìJU6ëJ:¤ÒÒRÇü5©×êHÔê×SDê\zÓª@S®éª¯Ö5¨¨WEIjª¤MNU :)qN© ýt¸&iN¥ ÃRZ¸§J¤na©#µWóù*tö&¥Ät§Up?=Á )iOR¸¨ëWMNü
+à`UX!ÞD'Up?8xªt¦® ÷tR⮢½©×µ\E;AÔ¬ÛJ©
+ÚÒ¢u
+Àaé¥Dè
+¶ðtR¢TZÒIkBJP
¼/¥«%ÇNûÆq¯ÍÝóûíý«wúyÝÛC÷Oû:Ûô,YØì%jËbS±Ø>J¿"EwLî^AÓ2äðñ^óûmÊ^Ví¯Øÿ Õ!_;üÿ çÌßí{ÏÖ$]:}+}-ZRǦ¤µ:«Ãü%©Ô¥¦ª@Sª
4 §_»J©:¤íÓ`÷iRZV}p'ÁܧײÒÓÈ®ÏYÎP5Èü¦;aúBË'E(.Ñí^*MN} ºBxo;9³mËl3ml_¹®Ú{ô÷lè38uÐðwO}?{ãzd4Â{r´ÖãÄF
+ ¥^EHoG
+ýOÚöE³íèfáã3lÕdB Æ¢ÑtÀÙ7* 'A"9@0F¿2²yw%%õã-ËÞ\çÈKËOð$ý<P_qãñVx&ZÛÈÚÐX@ ph Ãô®ÉRmÙ26oÌòÎÑ(n¬¼,Î(«êºkG*ûýGUÓ7+rÛØ·ºÍ×Ré&~ ÆQϧPÔâÆðþËjÕ³Xb¼À²&kpë/}ZÀGI£Cÿ ¬Ò°Ç%ܳnÓ21Ò±=ªÄIwÒëè"©8ERa0ê¥{ÙÆØDðû¸åÈÅ\HãØkà^G¹2ykÚEc¦8I£ç^.
+óÿ (Ý rN¾É¬u¹&ÞÛwMQh."£[î.ýuMªc¨¡¸Q( W¿m«ëo
+¾)ú#·´p:µW¼Ô4P¸öñ5â¼Ö÷\×ËutÇÈ纮0=#WWàà´KÙè¸ï`3¦poܧïùDp»dÞ ººÖjò×--Ö±i`ÁÒ5½ 9ÞÑoÜÚ>wÿ
ßåqY¶Ü1NíIdM!8©Í®ø¬fG\á¨Rh6W}Ü÷8ÍGK$8¯NÐ[pxtU®ÿ %h¹ 2|ù
+Ï $S1;6ÇRHñVLM¡²RÌ$s¦ è Bòë aß·¬ -9¢ãSâê ÿ êýwºmÙï8}`E£ÌI¢Ý\q²úìÝ©K²ìǹ0ª`C9ng
+©ÄNQÓPä÷_û[²FØÊÉcpã¸8pã@hïĹMûæ{
+ÃÇ´ý¡Ðxý ò}|Çr
+LfØO(Bo71Duôg ª¡,nC
+å/½ÔµÖÁenðwBXxÛ»í0iÄ~?ɳ·ÊÀbAö\:ùâüKß³{õÄ|u¼j ¦»u¸¡
+ Aïä1G¼br
+{¥
í¾JÕ·VƱ»ñ°¼²öÎko8£AíD/ê®ÑjëU()×Q¥:¥*¢;SªPS¸)P'T ¦Ýz{õ%©Õ()ÕRZRu{ª÷¯ÙâÑ,ÙÀ/ü>D²är<\{EìÉ8ÑË>AÁÌ©@¡öÐj;©P
+u÷ÚüüȶM³Î]¿¼gÔ1Õ¹.¥xÚܹÓ4pÿ åHÃÛãpê_[òL³9Ë<ÆÚI¾×0è¶'?üÆ?èñWçfÄh´y2|ÕvRÜ.Ñë7h¨ÝÛGm2.9n±Hª¬A)ÈpÀ !¨WÙûxÅ-³fFáPAxàAAæ\À9Ìr×´Ð(A ÐGEe~Aµaj½Ã⥠`¯bõ¥.Â:äÈ
+XL££]êÔeî\¨læáÈDÉ8a àªû¢É¸mÈ?8¶oæ!Æ%
£æ«ÛöK!µÀõ<´:A¨à¾ÃÉ[»mòÓ|.îzC¥ÝÔZÀA +®1rË°Ë35O|q\f$¡@@wNĦð%wwHÕüÍãôxÿ Vup¾#ÿ ÿ Óļ&³Ý²(mý7mDSwÀ@C¾ÅÆâÙ45Bù²úùÑËFp¢ý5ûDÈÒköÌZõ;ɼã¢îWoÑ2¾.¸S±~Öí$]B®ªd3ùNBè:WÁ¢|]Îõn XÛiñkECÑÀWIì%}qÌh¢¿k«ä½YpãG÷]åGÓýaô.Sí0KÙKóEñ
rÝ©6ÖÒweDج¥AþdèÊ?]V6eÆJ.ò94Õ(¬C(¤"@ÉË®hZbo?ö¶ZÉrÑ3¦-ÖÖxã4g@$p"®w¡æ]¾Ã¸È[|a=ÜS²Ûqnïðþ1- ñè
+à±ÝþÈ^²E©1ÞdÎ-î«AÃǹ]±pcØyrMÇmtÍät©¡@Ú
+z~æÆÿ 0[³>/Ä}ÃZ¥ñ.kÚærêæ
+ÑpwÜÛÙx²øëì¼ÝLyiÔÒÒ ¨\<3Î(ÏÞÖü;ð¼ËÛRåb¡&ýÔ½¼à×$#¤Ög2Ý£¥Ìdk0*ÀÄС¨F²X=Áµ?ì¾ÞÜ1î¢rÖ¶A¡ò5â
ã9ü+ZÔõ®ÎW¸9ÃÌá_o$T¹[Xæ OÆ¥RèÏlC5$xîne cðïÍé < &0HÖoùq·3òþ¾Oþ°X¾uÊ"Þ»¯îÑAYíì®J/þ.Ûw»YUAå&ñ±¼±;£ÉïPç +ù´m¦ÿ Ûa.kOÿ Ôµm¸7C6]ÐïÐ9|>ÉiGÐüqauÛÂb^Q.¯ã]62ûÒ qRrvà©(U Pt±îNch:içémï16å
ÿ ,8³GÝi§µ ×
]ÞPk³3Wv/Cä ²Þ¬ü&I_»NK
Êï_ª¢¦UCçPÂsÆ0Æ1¨Æ0ê"<µö>6Ä]÷ýóMõ×p4·¥väܦF´Þ_פ¥è£jI]í¨Ï@ID|_éò±l½
+LD»4ÙÂÐB¸Û´qVye,mã¿}uJØØÙ¨ÕÚjEMOÒ©Û!sdÛ©æ}i¦7=ŧFZ(:(8ìo¶ù¹Å!·ÝÞ`1m» DD»Ã§6£_.±w»<ÞºÅúI×Óé~>%ÝTýHKûíÔc8rô£ªÄwzb#ÌyHÃå-zó-bÛ~YE(ûG% ÿ òæZ#®Ý6ú>¡c/úñ.«Æ¹+4{I³¾5Æ2Î`®lÍVáIëèä-Ø6O×xò8Åvd Qp²D=òY
+»¹ðK69ÃgÇE·¤EyG5¡k]âÔº§ì^x4®kÜ\Í»Æab½öjÈÀI{oÂíÒVReLìÔáÊèqÄ~XËÙ¿0¦Vn.¸¸ÎÌf«,͹Ð+ÂÆbÌ«Q!ÊÙÜë¤DH" A á÷G:wÍ°Èìü~7¶Ü\!tPã]:«®£S-ÚÂkÖ
+Ü2XWíIÍä¼¾ÈfÀëXMA R´¦:]3:¨³GÙ~dø,â¹Ï öíßmY¨Z¹H[Åg¾^ç.'2á©ÎÏ|TfåÐ oÞ÷Â>[½÷Õ·1°mßÚÏïmf Dzè4?V£ÐxS߶´ÛN};F+¬»¹ÃĤ_Üt½ü4Ó¬q¯ÃÇÊ<½3ha0ÆÓQ×ûý@ÿ zó9!~×ÄWÓ$ý^Ègò4ôf®¼\,¦/«½G*à7,àñDDej"""""5ôvß²ûŬZº;¦ªæn»4ô÷þ½ÈâíG{$¸lTLvW.4dÀ¤&CßZ§¢e!Dl®wQ¶
+´þb³EÀ5·ë/
ÇðOô/{Ürºã¸©$âI~Êâr^1ÞÞöGpôÚÜt¢,nìI¢·Ð©»<¨þènçtBÝHAð© ÷ñI.ÿ ,ÕÅàÄr_ÒelL#ÿ Ááÿ ÞÝlm¿'1pÛBöZê êÒ8ÿ /ð]¨Ý{ç=XwÞÑT{ûÅ7ø+ëL¶9Û7Ò;í}Îcÿ å¹|ë½ss¶·£ïQýö¯_½¥ãd=¡Çͤm£æwÈeSøÞeo 'H c(ODTú DÁÉ_'rV[~Xn:ýéåÌ¡§Û0[Ç«8¯¡ù£oÜ,4û»ßøMÉüUYíOéçFqi2¯4
ªýÍe4^hÇ
+#$ùc²´n&³¶)¦¨v¤?bZMÑ+<ɵÅÝümc-«î%tÅ¡úϼeaÒ«Ç¥mÆcÜd-þ-î9Ù îÛqnïðãQ Ç 7Å,5uû(pFAµòs;{Ó]ÚñǸ2pkÈÍ$£`5QËGlªÈ ÷ W¤n,w=÷FlW6¥ñ.ii7ÐA¡ZN÷¬Yl}î@]ÂM55å¦- $OZÂÞ2óÖ6Î\UÜYH8´ç-ËE³'1p»J%ÙÖe,Ù«½äZ³A >àÄL4×JõJás[jEδ2ê9¥!¡Íx
+{Ë
IIq¥zJó®idñ[pÉÄ»U»âæ·I¨p tu.´M]JQäå ½Ö*¼©ÁMºt÷©Sµ:¥;êªm©-N©ANà¨-N©AMºô÷êhBuJU:½Ê^êî
+T¡:¤*jKSªPS µ:¥6øûµ©-N©N~J\SªR©·_v¦:¤
"Ôêë©-N© áÑRZRǦ¢èN©MºtÑáN©@ô¨BuHzÔê5%©×± 9ô©-N© ãÓSNÄêútÒãÖ¤.4p¤ZO
yêKS¨W§J|UÀÜÃRB*Î*TìM\Ì4¸õ§Tz8pW
"©Wm©¢ujà~zZS⮩¡EUÀÂjhª¸<4´¦®Ì4¸T
`8ÑÁ:µp?pQDS±\
+JÔ®´¨¬TN[x)QM
+ÎÞTy×T|f~noßlÇí[¿ÓȾîÚºx¿ÙÖß¡bÌþÃg+V[Ï P
øòâDÛ¼EgÀïf¦+æt+öãþVí¯øú¤+òûÿ >fëï{ÏÖ$]2
+sÖýÅj5ìHæ(ð§áH륧±:¤ó¤µ:¤óù*Sª@>Þïr¤µ:ýk|·â\sQp1ɯe^ ɹwL`®p&ù #¸DLm< 5׺¸ÒÝ÷SEK
+®{x]q3`í8Óþÿ ©~½¸c¶m<l{R%©A`fÔæjHéiyUP;éG)ÅÕ/h±À@
+]wJZü§æmþSzoÛìË¿4á¨ñk#`!¬oê´4t¸zI_kòÎêô!6Öáò¸5q$ç@]C@ Sä̾ò,îq:CxöÏdShúG~f(è"(]¦gæDß16ðNÿ ÚÚ1]²(49¬.<C5$ðÒÓ§QÂ5]ÝÉ»¦¶Ü²Ý5
+ êH&h:Ü5PUÚXMx8ù{eË¥IøÔý
+àU¼ó+=3ê>r²A²ZxÖ¨¨@& c2 yké¼&ÏÅlÎ2ÛmÚÐØèàÀI5{'ñEI¯Bð»ýÁw5ç}od<e}$Õ uQ¬Sàw\»WNnÎï[1UÁD¹TäP¥n±;Q8oæ(j j5ÄYËBY¦îat:ià5à +4¸þ!´tÒ½]$ÜËuZ3*Îá~× w¬áÁ$%èF"åò&3%*: pÝW°cÙui9ÐÃ÷C××IuHà°óG ¶£ªI§ <<W¾³%¢Ì¶¼TKÎTCWJ@±fE@÷ÉtÙ¾ »TQ ߬¦êúàÜË+Zàzi¨Ó^$ôcÌзc©ÿ ó¬~ýJl¹³Ðà&£¹é t$cÊ Jèï¿HÅÔu VÄìeÑ´ÏFô?¦§ñ¨þßù]ÕbçB̤Ú)¢æb?3påòjǸpO$ªnÓW|Ì¢EĺZÓ³8&¾xdWK(ap§Pa§¶£G²¼i0F£¸ÄMD¶ia íEmÿ EX0Gɸ@"¡DCÑÌd»@LDàrÄÂPäÞõv]·¦
+5©¯ôð\
+»¤Ó ôv7Ðs¢©\E¨4b²çQ7Éh¾úIH-ز· LNn &(ïÖ¯u´®-åu^jÑÑÛP;xh~£Áf#È°W
:ÇôýKò]¤ËTdÐUߣ*{ÀM0¹£ÇIÌs¢(`UÓd5ÞOBA@@r[hË´úG8´©=dvW¯ÃÇ¡c³7!¶ÿ ·h%¦j#ðuÙTÛÔ5èÞ t$:¶
*U0SMºûµ%©Õ )·JÔê©¥:ªR«·ÇJ©Õ()ÕÑJ§U|'ñYupäHf\ÄO²G Ø·¸¢¥XÑU
+¢
+§¡\2XÅä0]]|<³°ænÖv&r"ÉBîòÚjTÇ õä+Ú> \ƯBå¾ø»ØÙá,¤&´ÖÊÖ£¨=Æað·\åéÍñ}|vÎHæÄu·rMÒ'¾lë!ªöy]Õ_ÊLcÙùËfUËb=xâ-ÒÚ®PYS(ªß+í~`s¬nÙÜøI²¸Hd¿ÅgCZËã`Y¬l!-h
+o¾ç¶.yóÁe#Çå%ñ¤cÃx»¤B÷ÆàãÐç±å>7I.ú¬n¸áMã<«ÄoJ=ºdåáìÆ*¡õû1:ÈKBvﺯpEt@ÄA""Øç
+ÕÓQ1Spó§¼Çµ~ÜØzëà²K¹ík¸LøàÞ Ð¸<,s]B±ønXòëeNÜÖìÌ[ß>È@hipâ+_,P4´p^RûB¸ãã{*C#n°Ä6½ic@?:a ùËó ·dúm«rJÊ¢I¤N©¶LSçXêz7(yW/±NW6|ýÑk®%h:@mtE4:RKî$ hnÌ]ÿ .ñÈ £k¢Ä[!cÔkö¤}8ju Ñ@I.'Øþ-Ì?5즻í|ù>½§¦nKª&î¹8]¢öñdnË}¬4ÂnjøuÄ«EDë"«RupQC´
+ðqKÆsþÞãkÄ'ÎÃiâCôÃ!{%µÕx !Ü|BEë¶}Ê ¡ÏHbÄÉq+^ðH,¬
+u at 4£ô ·ûCMWGbÿ fß6
+ÊÊû¾8Î÷¦]É´¶#]\°È,ÅÊK£xHÄ·v®»AYGd"u
+d÷¿æzÝàßÁm¾î òÙØEØÎå¯/oÖ¿KXhçíVß^ß*ܶ[;e.ÝÂBÐX×HÐjçw¥¡§qmK
CCIa?´ßXÎ*3ÅÏ?yúk
SxÚɸç<Èçss6Ë$Ýã&<+$b`M¯l%LVɳrW÷;3oÌÌës";*#¡Á kG½ÒiWiÁ¡ÇÍ
+ùæËÆìS1V@BÒ÷¤ @ñZ7Uu£mãÂoµg
+XæXÊþâ{£Ú4}8´\rK=lÙ¥À#i×ñ,¯.êYO=³ä¥#WE=MÙAuä'nïÞAn»¬MÙ]tî8èk,k3D f·0Ç &¤hôoï£ÍÜù¸ñû¦Òí#Æ è-Dò´5Áì q :øîà»nfÍüFñ#2ª6ÜdÉmË »;rZ6QÛ¶.cÌämG2÷<å(FN-¢Ð´rb®e³)ËÜÜÉæ2ìµv>!tÏg{rçH×4Nô2&BÍCÆ{KÛVDvdlítwéËYÞÚîîÖ88E{²é+¨|V×QÄð¨Á¼1±®BöÙyµ¬
±²¹5høÓý´-JØV.%WjH¸÷ohW/TÞìý-ÁÀ`Ý0úÎghe1|¾Û}ÎW<,ð$Y¥|Ü©Ik+¡¢
çÍÇaÍ\ë Ý´Èã6³H.#KM58ôjqâQ{Q/Ë'!ñ¹%qãûÆÖ¾ÓØV3"OY×MÏ
+wº#¶
vù¶1Lß o W_ùyÄåpÛ*,ŵťèºæñ<áBXð×Põqê\ÜäÈØd÷DXÙḵ6ñ øÞÙP
+F¦*:ÅVsû<ræ+°8iâ~ýÉúÉg$X¾ó·-¹)³)aJ3L±fd:1ݨT±!õPÀ_òJÕ?Ý·¸rûão^âl/n¬ác{É!YûÃ]ã¹sYâññáÇ¡lÍá±ÛW3k»¶·¹ÇC$sÿ 2áâµÎÜxpË2`8`¼.Kc%b\ m¦åAG¡hOÆÒ1· $²î¡Wg ³y"C-ÙöJ§ì;3çyÓÊëíû·áÉ`;^XÂt÷Ѻ
ñ x-¸ÒºQ«PÄòÃ~ZíĶYbFð49ÃvöÔ5äq%¤8µôãM'Åömp×s^oï9Æ,Ä<´m󿵧\ZÌ©énb!&ÞQí^0fetÝ ÝfH¬eÎCÚfÞçöóÛÁÜjúãpBÀÍ`KÀP:FàOâÒàóRÐÀ@6cg5|r8|å¤8y\]§Äy`<KXá+A-Q®öñÂÔ]§xqá²&͹d÷vX; ·¡ÝÀ°¹cuî§ò'[ã GÈ(-TX©TÆX©m¼Åsæï·Îýî'ßwÍK¥ìÒwyµî¡Ã[Z]PÐ]®s;!³Æ.ÓiíÞÛ]íÓÍOîØXÖwh29Õ×#ÁÒ]¦ÕÀrÿ kþ]ÅY"ÁáU;ÉúýsuyyÛKÈ@se¢ÜeÛAÉ>^4,ÕR¶)7Ì5O 6îàÂçóRæ¬o,ãÑh3Ã$AôbtÐê ¥hí[O83X|¦2îÚåñ5¥d
µd`jqÓRM:bàþË;öÈǹùiûþòµlhÆ7;¼nf _8¶TAIM<dÏÒM¹ÌD÷÷ÌR@ kÕ?ì6_7Ëh¬ð¶·7# ò¼4G0.-®vH©¥"½+@ä¦Oß\äî ¶¶6R·\¯lmÔ_SÈ4$
+ÔÐö-£
+ñ=°Çµ6åYY¶ô¿²U´êò¶Ü#pŵ¹çyuǸQÒRðÈ?luÔËYC¢UNR¦}'-°³{§[~Ö'Ƕµ¶°Èn/:'Xò×84:Xhqh%ÃhÇnì^ßæ¥ÖbâF¿=ÄñXCÚ#ªÙmu49$¶§I% ÈÌýìøÃAæ;«;X¼hbHû7"Ë9»¦XËÉÛó*Á9~B;<lµgì{Q:AɨРCîÇMÚ<ÛÜ[O oµó;o#-ýBhlÖâ´9®Å®¥su!¢´[.ãåÖpå&Ïc3vQÙÝ<ÈýEÒ]ÅÚ\$h#¤í%£'¥d:¹xáë"°Ö.â/OM¸³2JSÒ×5õmÂÈ_·Ä¾6Yc#È´F^0ÈfmÑ2Å»uܦOsÙs;uïÜFåÜk«kNúß»8d{`=óÃIkë©ïït;IÐÆ
±`nv&ÞÚ9'÷=ÔÚÞùÓ4®i 9´ÒÖ÷z
E59Õ+ýy7c[¯-?È×ýãä,ÈFÑïo{ª
+ÔhùÊ3*«vng_°EÊé$;Æ!Æ)yD4¯Tþa°9¼æÚÅDz»¼;¹É)kL`á\Z à ªóþLåñXåûò·VöÌ}»L²20âR^EHB«Ëø)/vÝ+ ªk ½Á0²+¤rªÉ+ àéª"¨A)DP¯¤vÃËXðCm" øç\q#Ai{©N¾'õÇL£%ýX'Ää;Rþºl¶DuÛ öïA«KØ®¶H+4ÉÆv(e(T&ºo¿3à¶þzÓùÍf.¬nãÄJÙ´Nødl/« ¦KCZQÆ´4è+ÜòÙMÇ'±xÛ{«gäctZâl¬26Zê`qsiQZJÕÍxU̸à£Ý<nFÑ0í¬Sw¬ØÉõ¦ö2bLíâ~ØÑ¡ãY¹ä#À¤eëX^dí
+ײwû9´m_wa/<lÅ®-Ñ(sW÷r·Ç àÉ*]J3VSdn=½ºv{¶ã¸mµÜ~,Oq
+hv¸Ë\ê7\nñK ì «©É0×|8ðãwZ7^fâBÂÉ«¥wBFc¼gzÝÝwKÙv¬m³ÈÇ#90ýÓd¤\"u)Åîbw3üàß;Ço\à¶êÁ¦ÖG]]L]Ha&PÇØÖ¸´85Ä*#]Þ®#ÛSlæ`Ën,¬[Äd¸Ë·8â m¡{ôÔöÏȹâ¸bº_4Ä_3rÅ59o}Üê·]#¢²@br´¿ãl_ÛÊ¢}ù1ÐG<Þø³ÖFH{mt%yxC]÷G>Óü=bÛÙ;%ÀàÞ$l$Ϋ7s
+Æ°MIM[7N!¼Ûئ7ms(Ñ7`ųääã@cd8ºÕÞüÝ78«)r{6åßÔÔ|@If²Æ¸Å4`ksrh*@fÀ2ûWø È]Ga¹àÖ ñ¨ô#}5iax]Çpÿ Ü"p
*¦fâ\Y·c¥ËoÙ5·å#¤Ý:dá
+°æV㻤ÍÑ
»d\V2ÙÅÊî>aï¾bÙ·llÌ%ý¥{;Û:F¹ êw²ÔxÎ/%í«CF¢C ³6˹9íÏ´»µÚ!
+cWAsÝ#¨|V×QÄðªò+äÛ[2çÛ!Ú6\=
mMH »iÂFEIJbÖ*8ª³nÞ<²O[²/0¥ÐÆ._JlÛwk¼¸òþ&ög¹Î/Î.uÉv¥ã¤
+WïÄy¬¼ù+hYmg#ÐÖ4¶¡
+D
+N§õ¡_I¡J
++Òx-¼SM´Sª@S«¢ µ0RSBªPSn=ÚR¢uJ
+sÒÓØRjSªPS«¢¤µ:¥:êhSªPSn4¼)Õ()S§±:¤*jKSªP?pTª!TÛ¯MM(¥:BUJ
+uôTÐU m"Ôëõ¤õÔ§T}ºwxªKSªP??¦©:¤9
+uJ¥@zª@?0Ô§^ÔzÔëØÌ:l©-N© üþJTìM {¿ÃKÂRùéP+Ãju) ãRZGR¸<5:Sª@8óëRZUÀüü¨GB¹{S¯j¸ ÁJªUÀÚxjHEB¸§J|UÀÀ=á¥DUX!¶¦5p8tR¡M\n´ªBu*àq£8+"À4¨Hé^p¨ôYNú-~lï¯ß|Ïí[¿Ö$_víÝ<_ìëoбfa³ÍÕÅE;
+hÐ/Ưæ â?÷´Í¹X<WÜõ~Þòʽ³ÿ ã¿S
~]ó Ó~fÿ kÞ~±"é`8ôÖü@ZUÀáÑRZ) ãà'^Ô§=.)øùWµ ÉKJk&xiYõØIWE8I1QóV+v˸;_JPás¦[C
Ô·uÌPã$f¹ÑhÇ<v
+ZA ^I-iâ¶m¿jù®GMt=gé< §jý¯y¶²lH£¿UIÛñ³·%Æ»GF| ¾ÌíÊ*¥¬åª¯´D{R197t¯ÎÓ;¸¥e°yu̱CstÏ8<P×øº~Ó\¯£,²
+§ýÙM$:®ctðé ¼RC\ÒÞ¢¼÷igyë)£¸Çÿ Î?r¯ló¸~6mÔ;#}"*ÆH
'½ÐD¡ô%æиËGç^Øï&k»¸öQ¥Î 6§óHƤñà
+óh¤¾ÜWMl,
ÕsÈ$ñ©úh8Ø,ªÛ½EGNªÙX¶H¢¹ËgEQ3@P(í9«"ë[VÈè1îÐ<V±î'
HצVµ¡\Ð4ë p
GÑß
È,H$ez«gNtÌÆ& £§`¨©ß(Àn@ åÎ×j_]mòÇ8i-áXõ<S¨
+4ë¨âWQ·Íí®+8¥O
u½ñ¸¸·®ûj)½Á ñ¼¨ñó
+.ÏyűMB& P0è5¾ÙËAl²\\ÄâXó¤1Âñ|jÔÏ5äw=ãåCOPéð®¥ÈÏcÂY7yxÎ϶EÌìÈ°jħ2SÓ8PìÀÙS9Í o
+lväùÚnîÛozC8øC_G±RÜã(#bñ¥lC˧ö^XfÉð²H\iS xÂÕxÓGTM¹LkÚ»ÚrVÓ=¦m·¹¸d¶|5öÒàãô.`ãö8øUlòÆN"£¤÷@âù£*õXÉ4uè
+TG>9Ê@
+ó ßi¯jòÙºàÖ88p=-5±c,bg5jèýÔ¾»ûÓa¥ÎÉP;£2@ñÖ*B¡æu"V]Cr\Êp×@=«¨î¬>ðâwSJöþ4¯"+¡ß
ÆmÉåI2ª·ìÙ9;6.Ö§!¸.C³n¡{6JEH"tôï×ýÕ£".Hõ4ëP=á}*íY+Ýèêtp¡èãÕÒ»ÊÖR5{_ Ã9go$±¤XJLöq-Ù&#£ó¤ìL@Ý¢(ÞQéËZ®FLtÒ6ç 7n ÚM#¡Ôé¥WJÊÛÃsLw-W¦Ôq¨Â·BÜ®kË5«3p½íV(*ÝTõåÝ:'ÿ (w·,LϹ°c¥¾+ao¢e mµóÚÏönñÿ ßTeSmdV:©ANzêªmק»Z\ª@S«Ê´Õ:¥:ú*KS)TÛPZUÄÀrLPYQCШ8 ®/iµ~aU0ÜPyuAÖ°×xç:Ò²vùÅâ
°Èpcnc5ïj=êÆÿ qÉÐOÜþôe* ªæpÓXÀ@Ê£§~²v¸øÓèÜ_¾nKÙh{³>1ÉV~F<^?{xÛoyÔÈV{ÔÔaj/"Iç;6Ê*s ¤ô¢!òùÛ[oæZÇ9
ã°M0ë¦o3H3÷`@¡wI¤¯£¶¦o$.ñR]Û7*é^D&V H3FAk5 ³Ð ê^Û¢®B(bQ ¯¦¬q/M%xeÞA¬
v,¨z²ýNþ¦åk5id[ºV.ã éFз²èbø èÏwå´ë\V÷Ô.2À;±û=ÉäÒ°ÇúÒ§JÉz7¦W5·[Æ¢b Á ÖNÛÈJq]ï_3«Ôí¤Q~/ü¡6õq·ÖÍÞõÕS¯è»µ¿ÊGI° ~PÐÉ]a<z
+áàÂý]kåA@@7O®¡Ò׷Dz&QsKvé«qÉ.e¦&}ï'ecn0ÁÏÕ»±dÈnq_LUDNb¡¼:Ño~·ñ)K.nô-íͬÝÃ×ÓNÏM k\c báùÍaojåbÔ§eè¿ìw7|WqÐvºÂR$×Ö¶Ûa»5P^Ó]uÛt!Ʋ7v®ÜÎx õ-¦JÇ"îÃs #¨îòr÷ë¥q~¶p+³H±º]Ð,H(}4Q®×ö× ÊiâÕËØÛh´`,ËþH:ïÇlp÷C¡u_zçÉÞ/¾
+(Äÿ d:øéÛX¶ÜÔ)èÌæ RPªJ =ê«Üâf@½^á¬Üf®¤¸lÌæÆo.·3 3,½¹gC\È-qÁíµõ"Õ¸b¡Â-ÓOPUä~é9Ç~Wæ46núzm³}Úohï,[,Ï7»§n×8ºó$c-K ×ïû
+çaîm¦ý¯
®:.MàÉL@%Íÿ fæ9à¹
+&§O6Áü
+ð§ÂÅÿ og|ÃÆ3¼blGéÝ6¥»¥¿ÚFf?u̺¨¡vÝSêEº;AsaPÎQHâ©Ó)Ò>¹9¾wÎ&m¶våõ´÷mî¥Ýãô±ÜÊ¢da¬säuKHpÛ0{iíLYüînÒxÝ®6
+
+ÔáÅ®á$~ã1µÔ©Ì3øoŧY&«¶Öd$Tebñ;7ÊZ°¤^' ñóeff%Þ½Gß GLÂ& û_(ö<»'nø-vAï3N[Å¢GÐzÃÖ2¿Ö-$p+Ëyº£Ý9r0Û6°G<¡¤Hê.sêuCкÆRÜm,Ô
P §.µí·¸`í/,íð¾ ð\8,ÀÛ±û-{ÚòiX¿îgÖ:Wûͧ«çöõºÞºNQQÖ²V¶·+£qvé
ÌJ§UwWV©ANòR¢uJ
+mêT Õ()RZRu¨-N©J¦Ý*KSªPS¯¢¦
:¥*zuJ
+uT§T ¦ÝjKSªR©ÕPZª©AN¾T(ªB©·¨iP'T §=NÄêÛÝîÔ§T~®ÕUJ
+Á©¥T ¦Ý)xUU()Jô"© û{½ÊÕUHç©-ERüÃÔ5%ªªçòTТ©NaÖ´ÒéiìN½@üÃRZ{UÀüõ%©Õ zªKSª@??èM!OÌ4¼)Õ èE{ù ×µ zjKS±\$ê=5%¡:«Ã¢M yéxQ^Õp=¯B~p7w¦Ôõ«ÇHpêWóÔéO¸0Ò¢*®-N¸:)PÕiU:èÏ ÉoCtï¾0¯Íõûïý«wúÄîí¡û§ýmú,Úì6y+U[Ï%_'
+»Ä§¥æÎ9d<Wìøw¼ûÊoúW¶áüwêp¯Ë®`WãÜÝ=ïyúĤ@üÃ[ÿ ¨×µ zi§àW>%¨ª@8ôÔéNªàpèé¤ZRƦÔ,ºÀ²ní°s®î¹êFYé²Px9 7mÓ¼£9)D·vÑ&{ÅÉu= ¢D5Ò÷;,ïíÍûÚÌcf¸ÿ ã2&6ÿ hx²½Òq;£Q![Ö"9mìc÷Ť´ÿ d¸Â;Òõbâ¾,¢ZSØ®!bÏ02nc·`÷ã çOdä]H¹xåc*(î Ó å,ðÙÙ3po9|Y¥¿ûÏǽº"kXƱhZÝU¡è[ìw°Eg&66-GÀôõ¹Î$I4&à±êÃOcI+fÁô)ËÊJBkµX±æ`Ì¢éI4gÔC&]æL"";Îç¾rn(ò¹ím2ØéÝ3V³À¸¹Ïw ñkAÂu1ï8ëSmdiª¤ýcBßM+Ú±[+ÚºÅUäD¢AAtäRNc³ªÄXÇIjMÑÞÞß2¯x~Âgv´÷ÝÙéÒ-% 7M $þ%¼°»kìãÓÇ£²µXH³"Oª¢·
+ÈѲ+˪V+Ò©DD=ñp£a ;ï½ü3Õ±ZÈ!¦¯u%¥¢wz½»v´ÈÊaíkqÂŶĤÔc6
AÊ»PÊw5Ð4Þ×½ÉZùÍÀö[#Z$Ô ÒãSð,£E§Ü¦kÞtpâ8¥Æ®; 2¶mEfßM̵E»øÒ¼·n¨¶äUÂnÜ<1Ýx¥ÌàSéÈ`(ià¬Øq\Êö°C¨#[xPtb½+ÿ ¦·ûnH\Y¸bÙÂÛ±³í`Ý%ÎÌW v
)þN4`å×RuõsniÃSîÓý ªeÍ>Í»^>»
+f~Þ"Ù´4pDníffRM3i8tÔGG¾Ð½ÆI+÷«IOÔ?Ì»L¿ ÅÞÊTW:Ü-´½¸ª×1m§O"Z,»¸RÊ¡'èm½<ȶ(ɦAtQT8{+·q6RÙß{~Ûº*hhMkÙõ®Åíëû÷ËÓV´ô
+V!b¬ÓsK¨ç³ÌkªíMÙ<Zr#öú¦Å°4n.CQ> öZÖháqÑïºÝ'qúÇêXæß]HÆ»¾&¿WÔ¶ÛàNï4¡4ÂnNÉùݱtäȱ"ï cvÀ:Q@ß05åÛ]KhÙ÷'21¡ÌsÑNâ÷.Ôã/.i
+wOhãÓÚ»/¸{öpÌ÷¢ä´ASDª·UC¹HÔGû$Êp&¥8sVW÷eþ½ø¨íô,&áN±©§ê5°ANºÎÐ-f©M¾>í)§T ~%AjuìJ
+s
+IjuH
+TЧTÀ§]*êÛ§¹Hµ:¥÷AjuJU9¤µ:¥*hSªÙeâ(úò
+t/,Ûr(WnÚäÀVáÌÈ%ä
+»ka4
3Ìev¢·Sú¹ËW
+RMµªªê©¡N©AN¿%*'T ¦ßNê©-N©J¦ÝjSªR©·Or¤SÖ¨RM¾:E©Õ()ÕPZª©ANºÔêªmñÔЧTÀ§WE*ÁJU:Ý©-N©J¦Ý*KSªPS¸*4§UµËF!*¤§. <¾}Úê\Ú¶á\»\:T.¾= A5L ÷G½`Ý
p4i:VU¹0EHâ¹½k¶þÓ@2íu®ý¦5ü¬º7¯Rç%S@Ъ²«¥T §UNRäTN©A]¾:êç©-N©J¦ÝjUU)TÛ§¹S¤§T §^ÐþIªmñ÷êhªPSªjuJ
+uÔ§T¥SnçôT§T §pRLÄ¥Sn¾í*êê©-N©ANºÔêªmÓÜ©-UT §?ú)qLÄ ¦ÝzjhT §U"ÕUJ
+mÖ µ:¤6éRZRu4!:¤*téîÒ
:¥)R½ Õ(jKQT~zÕUH
+s»ZÔêçä¥Å:¥6ëKZ*´§R·ü5%©×êH
+NêÌ:ô÷kRZRùù)P¦·^ï%.iÕ ;^Änaîè©!:ö«úêKS¯b¸<¥I Õ zjt¦®8ê4¸"½© ôS±?¸¦×µ\=5$#À®
+-)Ô«ó
+I©ÕzcÂ:[Ði9J>2kóW}þüfjÝþ±"ûÃgþébÿ g[~
7ûÖÇé[Ghãô¡~'8¢6LñQöuËɲÿ ¸¿p¹LßùU¶áüwêp¯Ë~`þþç?kÞ~±"èÐ0·ò£R4¨B¸øõ$s
+.íWóù)iM\Ò¤ê»âؾ$¬·ökæïå±R)á»nnÖUË9-Y®DÀP6ìТUDÁ¾dÌÐy5üU¶V) {éèK:A8}!Óô¯B³ñXC§ Æßõ?γ/[ úäºÌ»,Æß<cÀT®ÔAJ8v"Ä) ¼pÝÔt
+C_,ÝÙh4AaÒÒ$=¬âàíD£xIáÅf,âx°iO§¬J³Ö4dtSÕnÒRUÌ[9$a ðWmY.ÉÒâFn bûÐ
+4èÜÛÛe^Ùços)cuññâHèãQà@ñpWâ"ôt¦¹§`dÝòkB A"h¸V=_ÑjíM»5+fËä\LQÝ ëÞÐk±»ÈÚ¶â:(kôý*î^çÙ½ßH^9J_×d°&WÓÏb³`*zÆ0î±=Ãî 5ïÑÅ
+%¢T|{ràrw(:¼¬¨]ÝvÊi*»ÅN-Ù Òqõ¸TÆ1(=nPÓAäO?³Ä¸d£¢$ «z:øÁeq°ºêBMêqükÐw
è<{iÙw½'p«z1ZZKûv±ÍØ=IÄ<!Nô°fÄ0§¿Ú kÍ.÷¥íÕÔPw¶*ihûEÜCý=|*JÏÛØ[CF88Ð(?ùø/²úáL0RÄlÆuÙßCʦ,õ;`dá2ʤªÆ8 ÙAîa¹-¼ýR79ã-ñ»xpë5ê¢á½ÇE8ÿ w£à§þßø«%hA¢Òa£Iº:8M%@)L"dr
+!¡@÷µ®n½Äì½ï{bçÇ ãâ;þñ¶?uhg´ÿ Û©c׸ÁÕд¤Z¯Ð%è©á»§ª$dÐ*IÀ IêPÔG¶¾^f,¸eóØ ÒOH`Á
-¦<:
+z
+ÄXî/éåFÑm2`W
+§&¡7"uQÞóvmèäpVÉ/Nüc_ 6¥baÆÝé¤ÒÖx.áÂÏ[¶ã^R]»r ÏlB tJ²®u$IU¼
+°YLDÈÛrÈòírð'W
+µ£¢Ë¾(#k]#êàÐ(>¥p+µ3)EnvM¤ÛÆÌÅÜpÕ`.;¥WUPPÇïAþµÛ¯{îdä9Ñ°´Ð\uôWÔ°»´²ü@t´ Óñ..
+mÒ¶ÒÕ¥U()SNÄêªmÒ
4 §pR êL
SoPÔ§^Ô §UIjuJU6ëPZWzYü5ñ[äºì®id³YÈ+äM08b¶:RÂQLCF¨ïh]5Ò²ÜÆØ8+óÌæ±vÙhèå¹
a4ûm/?×ÓÃBÙñû3wemþ7=d9®èÚ;£úµ]E%' ò&f=ôL¬s
ZHFI´pÂA´L$Y³ÆnIÃg 41R£È![e½Åµäº´ÚÈÐæ½cz×4Aê Ð~hf¶Ö÷tw4s\\Ò:AÖªùM½C\¥«©AJÔÁJU9 µ:¥:©P§T §@ÔÐ'T ¦ß"Ôê¨-UUÝgù÷!Áý¦±°ÎN»-Ñ36MÃ#ðSíRG¾nÀíäHÉS bé`lLï÷no1µÈuÇ-ÄL{kJkiuX
+x ©l¸Ýºòö¿}Åão§³ê|pÈæÝ$6§XmHúÂêéX¹{~Mì,ô\Ìkµdæ6J=Òc¢0z.¸LGßBÁá
+Ùínoíyc,sÙÈÐæ=cz\ÒZàz$,ŽŤñÜ°ÑÌsK\Ò:× Aú
+øÁN¾ç \UJ
+mñÔ§T §UAjuJ
+uÔ§T¥SmM
+uLU; RMºûµ%©Õ)TÛ¥AjuJ
+]Iju]fáü¿#Çø«$_PÍ_+æZϱ®{1¼-Ú»Z9wð±oZ¤ý¯QTÈà¡SXÐåÖòû¿iíûÙç²ë+Ç0<2{aya.hxli-.kp%®¨+7Û1¹ÄØ^Ý[5å¥ðÁ, Òæ5À84ZÐÐBäR|;ñ #553444CrÒÒÂ÷aÝGoäd_»E«&,¤uYS4Ó( 5жæÀ¾¹ÎÏ9ògµÆËËg=ïy
+kÖÈKçÐ $Wn}»í`}ÍÎ+%´l.{Ým3ZÖ´UÎs kZ$ ¤®:ú+n-Zà)J¦ÚÕUJ
+utTéìLÉUµî¦ÖÛ+É͵>
¡%$´<}Ö¼46ÛùvégL§Nرn¤I#èS*RDJ Xæe1rd_æe£Hø362@tUÖI 8ÒH¡]ÇX_²É¹'Á3qÏyce,pÏK%4 - u-Û§Mw¨
+ê×µ0)Ü%©Õ()·ZÔêªmÓÜ©-*ªëÚ(¯bb©·Çߥ@SªPSª¤µURu©Õ)TÛ§Oz¤´§UºEGÊMÈ3
/- ¹0hâBAó9nÍTÕråsøBÃà
+ë]\ÛY[¾îöHáµµsÞàÖ4ç8 í$Ío÷S6ÞÕáækAsOPhô »>êÁY²ÅûCxâ|mA µ´g#ã<pÈ0QA8J¹1¨ kx½ñ²óÝø|®>æûª8çÏu:t´:®KAë;Ú{£m÷Ì>òN·¾µ£ÿ -£~ê~%ÕeSn´~©ANºÔêªmêÒR]U)Të÷jhT ¦Ý)ªªPS® µ:¤*z§JuíJ
+wJu[¤T|äxXçÓòncÑÃù)®T*MÙ±bÑ5];táSHe1Îa ®½ÕÍ»ï/dd64¹ï{ÆRç9Ä5$Jæ·{©ÙmjÇÉs#ZÖç9Ç
+h©$ R¾h©{zMì$üTÌjæk#0ÅÔd$Ó}»ÖRAÓUɨjES½êK«L
³/l%{9©Fæ½ok\ÒZáôB»{9Ýkyâ¹a£ö=§±Íp ¯¹Ý¹rÇBCܲüÛrâ;äíûäKö°ªE¸3I4áåVnFgtQIpAC* ú%uâÈãn/fÆÛÜ@ü¸i&È×IxÔÃ$`3[|fêPâ*$7ÐZÅ}42²Êbácr;CÈÒí'´CÀñ[@)·Jí®µRÁJ
0{M½CKZuJ祧±:¤íî÷jSª@?pT§T }ºÔ§U¿ÅÛ×Ó Hx ¹XËq²O. ȧÏØA4\çMS/ «x¶Ë(E2e0@Dº79,}ðÚÞ\AÍËbcÞÖ>WRØÚâÈ ·oc}u·°Ë%¼
+ÍcØÚzÈ0P´uÜ ]Tp¤Zª¿Z at 8óÔ¢£ÀUU yõ¨-EUÀáÑKi@ý~Z\ð¤
Sª¸jHE{Rùêtªª¸jHíERÇÃËS§±5p8søèâRÆpW
*'Ç©\
+ÍHëÚ½Já-ë}°éßI!ñ¦Aäñ×æüýøÌþÖ»ýbE÷ÏýÒÅþζýsv=ÚÖ©ÿ n
±)Ø÷kGýº¿<SKÄ÷À>óÃo&A¸k÷£þUmø{ú+òß5ø÷9û^óõD¢½
jWxjH Õ\ÏKJÀÜÃRBu*àq¥DøxÂø¬ýáfÖ°²L;«{#½fÙxf,.ÎÈPP¥e1©*Ø®ÖE·¤c
+¢NÓ7¾µáüÁÍn-»vën *ÙÚ5jh5{Ú%ºÀà[N{Ô³Çå,!mì¢'QÒ´é-5 vÇ¡f]ÊâÚ;´Åêç|Gtì)»b´D
&ºróù~,dïeNí"MÀPº¼ZâOk4Yè ¶y*<4¨V:8Àº=ò-U6ôö9Îc&át\{³X"tÛ S º ºÖóo$Ìt:¨Ö+ÒOWÒ°RÖè[S(øÅc§"&£[º¸Ìñ)ÖÆ (MÙòÙN]ôÑ
+@£¼÷À 4ï"/s$µqmË ÓJñ ð÷öp+²¸¾ÁXÃ/·¼^Jäzví£!Ú,uaH¡Ô¥
+èê&w*¶ä1S\Ûÿ -g¡Ý»ä(àcdMzOgi§«é\BÂÑÕsÜü:ðùkaùçuqêdÍ87ÎÜg¨Ûªº§dºª»L¦*Å0<5ªîLÕæWL
+tN:À¯:EOObîE¬éÇU>ïÛBL£gì{ènÌ".ÄIôzåY£Ä¨6] ÝÐu.µ©1·1=¤º =Gª«²£Ä-åÀ¢n7e ç÷¤Pºo ÎrÍ®¿äë]i-ËYZPt ó®Q3öÐËEWQ¾èÜ@ê tÂ:{ãFµl½5¯Â¨=äTNÅMÅ `0È¡ô(¨0H»1D
0Qðìä«é#Å"ê<kÄô®V xÕµ]6r·4ªmÊ·ôS¹zÑgtHªÜPÄ¢Sî¥vqùSassb
Á¯ Ð é¯I¥kZøx.GÛ ¡&SÑÒÅw¸å·:ºdºî!IËè¬téR):*$ÆDzPQ´-½ªN¢ÎÍ¡Ä
+JoD~á·Ë5¶Ø1µ
+}Í4ÀGjßµ#Ï«?Jê²ÄÚ-Ùl-û1ZuÖNÀ;:{V'Ü¢Î:qrÍJJ<RnàP ÑûÖÛªiÔàOF@ Dº&R t×mÂ"íc"dM½.$¸ñ«mOWuL_AÜ^ç¸×«êx.4
+t
+m´Kª@>Ý)§T ë
+Ôê®ÛÝîT§T §=M
+uJU6õRð§UÏUgå#áÓÈlI/aã«^éË7\"tg#¬v$vÖ)Ëeqã'.ZæËr#éÄCÆ9õº2Û[³;!9¹Æ ¡÷.-sÁZá~
+8µÀÔé¦ÁcóÛÂ1hg·R³¤=°¶¡¤u´¼·Sx6"®øÄâ,߯¯Ù*ñ¶
+{[^سîy»rÛ²#¥¶#"1lÁ(ÆÉ&Nܤ¢§2&¬Þ×å&ÄÚØ6a!ÇZ\iáY®^~Ü=íqqy$é'KAÒÐ X¼÷0·f{*ì··xß_p´}FÖ
+©ÄUÄ+(3$ÂNðAmñ+y&ßrÂXZø¼Á²
+¤r)ͯ)q(Ü¥!7åêWtV2ETêÊ!æ»FѼ¶çEÇ.±ÍÙy|YÈ[[ÔZܲCÌKc5Ò×Hq`m(Ví¸®½¹gòÈíÍ¿sM@q¤¥ÂàÀzHÔOH_~Vàç
®®è[S3q?v%!u[öôÜTUBfJÙe8ܦ4ýò²³ ŤYR¢ÍºYûa) ä)¸6·79¿±Se6~Úµ0ZÏ,o}ÅïvÉÿ elZý:K¤DMqÑWHäÏrïcmv7p%(ÞÖÃmѵãý¤Ä¿HmjªBѪ ·Wõ§{y[[VÊ[-Îfw/öEAoÍNUU at 2jvhÙL^ß±)ÄÎz`ååí¾öÎáù;«Ác<ß» \[÷]D 8]æödÈaʬ¬{Æm¯-Ä-±ØÝ>ðÝ05wúA' éÑ«íÔjÒÖû ÂÇÙ±Ùnð½oÓ-Zì
ÊÆÊÈ8äLUI¤Ìí%ª·`ùHXÂUé^s?~lÙmrËÂZYí[»Bë[¾ýÖoÒ?½1Ñ´9ø¯7im âKîÕ¶ÅÚ{;M¸¹ÏÛÂéöýйk_Ü8=Ä:ZÇG£pÙ1_
+¸Âãá¥&2p[Û-rÃüy)
+
É1,[sãm,ä[I¶4¥Õ*ñBp
+Ú6dj, f~îçæ~åÇóܸÛ8QÉ;Û¦HgÆÂé{·:à1 MÔ÷Èèâk*ýC«ØKÍ7¦s&l¬~ëw0Bd{XáªW
+;KZÀùïIã÷kÈÅ×=á7bl3;i.Ëubîµ.û|uâeÙ³bñ)ÍÖYP0OAÞæÈì^`fó[#±w
6;«sþbS4Á-(øÜæµÍ,%s\*I¨¥×´1ÌêÛrÝà/$|_G,RÇÒÇç4 \< ë¨+§]zÉjóêîÞuÚvÄóe^Á¡-´Ë$dÖyÄO"Õé¸fS¢(º~ºwñÝÉc4vN½tO¸ô5å¤1ÄPÔPv-.¢}ÓKíD/¤°¨$Tt¯o¸µ8¶Î× ån
+òãËó·¶Ã´pÎUoe<Æì"¡#))`nØrÎi6Êt©.ôtÓ1S*eI?9yåNÈÃ|/ÍìS,wæï3ä,ÃnÜùDºîæk£, TÇPçââç}5¼¬9º2_ßܺÈ:ëkãî"³ºvµ¸Èxp&sè@ 0+kû0gÃãÜå®!m¸¶XÞfb]È»»+/+*ÍâZìTaRzÊ*N£ß¡9LRB½Ë8-¥²±|þÚËEs°.%uÜqÆæ¾ Æ9×5ï«H
+.a
+1è
+ JòéÜ;#Äg1òC»¡`·{Þeº.pl%ì-m5À¸?UA³¤øPá˾Ú`ÅÌfnYÄ|,Ä7ø×Ú7¢hú=¯1p¸c.÷°tá4W|)7ncÿ njÕ·4¹Á¿|`vÌ2l°×É%»Ñ}=» ¬ÑÄ"tm«Asc.s^ÒsSì-Ê·jåó3sÖ=Ì·×iÎ¥"|
í{¨Hx¯¦¯`ø8BWbý=µtð¿b¿¼gl.Ã7)ÇwN\Ç.Ê&n-D·\Q2å&¨~÷¶/µÚÙ<xÆn[æÀçètàú´>71íÔ¦8+m˦O±ÊÊ`¾ÁÚºRÝM[BKHcÛG5Ô®¯°F i¬Î n·+0.y2B1'éÜ6Qr[
zÔc?cþêR¬!¯ù5°o}ñ6ÑÌ`qqÛ6værm´./-1 kµ?døV#kmX÷7-~ùÌGbn
+ï¯MFÈ{{\
°¦vÍ\D«m«w({n>Ëyp]®& §RbÊ×i»Ó=I¨,æIûM½ !Îè¦&æÆô»Þ9³vø¿ÉbäwϸlPåÈçLçéyvCL¼y-vû>^í}µÝ;0lì¯Ù/æÛ Rö<1¢ Òu0
+ºG¸ Ï´%à'Ãf$³±¥¸Ë%Öq¬kÍFæ¾®;V)âmò<¤LU»àU!ÐI]ãºI@:gÔ@ÊÞóuå÷%ÖÕåö*ÚòïØÅíÍÍÁÚ)Òï»Ç¡>Wç6®Xë]·ñØ[}Á¼/涷¾/6°Ay"i§|ýNc#i¨-¨=!n¡ÁQ.¼aÁbLµmÞX²ý²&²Y²t% ÏaÙÖ¨%y+~Û>íäL¥¼«¶é1P©»UÊZ"Å>©ç!ÅíËëí׸³Üö7±ÙýÍ}æâpM¸µKZöJçBXÖ;hw8å ¿ÍZZíü8+»WÜýåÍ,0Cc<u%T7A:w[.s+Û,ótÝvRbݾñá-(¤H6§w(ÎÊJeãÈ©f =¢
+
+¸Bª²}[þeoݾa`í6Ó29%¶»ïå²ï¥¸a{5×:'PÖ;Ócí-Æùq{;+=Æá7=ÏoÝGu UÂ5ÔÍl¤tÐ9¸
+aQ%¥:j¤s&¢JH¢jD§!È`ä0h < 5îà49´-" ±Ú¼ÒZàC°)ÕÑÞ¢^¹pçhfÛëÙåwC`4î
oqd³ÕKhÜE¶%~!CYéÈ ¤+hC}.×ßtwGwPùCYmçý¥Þû6Ãv¨hïâïÞÛßD5¨í<8ñâ¾ÙØíÍåŶӧÄǺºvk¯[8T¶¢¼xpàº/ á_h=¥dÜ÷E.ekbÇD;i|©ñ_ÄIèoNó|g̤àSQ.É@PÖïÞ\Êæ¬6÷÷;³rLÞàGe¡ýàñXónÝ.T;P¡«UËínãñÝæ¼dg½.ºÔÝß@B(j
+(ºêÒáĹ7;Ê8®~JîÈ6ÛnäLL"E¹±uÛÎI9s9 ùD[(QlÑXVþÍõ6¯0ÎÚß,Û;í0vÒøÈ{·¾ê ZXocC·7E<gén³oj;9÷{{Çqi kcd:b2KØçQ§Å]M©æwok²Î8ç»ôB÷˳(³´±äúѤ$Û7Òn&Sµãp³åÁÇt!+è§Åsil¬1³¶n²ÚpHï¹EÓÝÄݲCÁåºEÎîÉd9vè÷EËÄÜÃ+÷¤ä-Öökqx¡ÅîÒ:håqü9p½w\r«ñ;*÷)´Fe»ªÂonb;¶v»·+ÃÇÜcp;}ÝѨ¾pU[«¹ª]¨¨
+ÌÄããÝíµ6ÃÝ|p]oàBÐ$t=Ó[!n ]^ÚÑÚt¸ô[3cdoÄç$~u¡á¤¯`$±²w
ÌKÝVxºªÐ{ΰfýxÐk ÛVÏ7»ÇÂ-s]S ÅË1Jܵá]«E¤UTæ:®8I«dS1Ì&ÒP½Ë笹ù;RÀdr78`Ýr`
ñ¸Í49ÁP±{ÜC@HÙ-qØQY
+Áy÷+2óiaY¥íÄÀ@.'sÖMxY[jصðîLÄWÛ«Óæ[~õßÖѶnxY4¢_Å\äÎcÑn.¡Êè§*%MuO³UOJÚÁÉd²y}·»,[e¹0ѲYÝ<sC#|>(y4 , ¸4}Mn¹6m;7·®sɽѱҴBøåcÙF¢Ð+S¨PÑGÉ?ü%AÞq¸k®bþ~þ*ÕÓbc¸ù¼Y;4
+HÝ%¹BNu'.®>º$%9K®·~óZ÷&ê°Û°àcò6·Gzø£©.Ð!ÑHcÍGki9´y}kfß¼ÍÏ&Yïk°[µö{éA«½Ôö´Àÿ £BÑ85}ugÙo;ê2ÌÃÖ%Ýw¸ºÐîm÷¿g¤-¦ì\?QuZ9¹ñW*Ýÿ ¹k¹¹9Ã/cawÆÆKË|½ôui½ë&.
+ 8>V¾YP×8ý [ Ëio÷^Ojä®Ùm>6ÒY´¬nîÝiq$ÆæÈ]BZÙ%}Iðá
o¬æpng¹okÏZ®/¢6ä°¾ÊÀ]V¤P'æmw&ÍÔ+7ÉÊJA!DÂbñbo<&g½°öÖXlÍж
ðÝwòÁ;ÿ ÙGp45/>)1 Ôê4¡±²öÆWsµ²SÜäñæy[$ÔrÄÏöë.£5µ¥q¤(µrçy"ã±còS©1¥fZhÜ×LädÊÝRC!'Â.«&cv®`Q3h ÞËoÍɺ®¶ÀÇ[ß\c[¼âs¾P\È¡sä-¸FZá^¦?há-0ûx^Ík
+ë-¢!,¯lfÚÆµÄ :\
+A¢Þr ¬`pÜç_ëå¥8u±¶¥²µ¤sAËÛ}!ܵ9xÞ
+è3¶PJ¢©(==³ÍY¯çÜqîËâ·#ÓRa9=äs=Ô-kCæu§í«Zïv3¼¾Î,+öíáÈÓålUÄÆÖÔ8ö=x0´Ð¹¼W+ÿ «
+
+/a'üJM/¨ZÎ&Zc£+_\}Vei¤fIzä{"6¨b H¿â72eÂéÜá.뾺î榮øF#1cüàQ}<PO²le>7/Ä]çt^-ëhÙ맺// d mx:ä"ãÆ7µÏîæ
eqÚRîá¥EAU¹lxéÆ"b»ÍÌESt½¢*ÚºW¯à3íË
¶Ïb_»²0CCÒ8ÑÍ5k
Mê^mÅ^àòâ2
+Ó{o!cÀâ*:Áëk
ÓN ¸TÛ¯k-¤,}V{ð)w[2Ù·»²Åç×·0õýu,(h[ñ3øñ]'
+¡ßÌÑÁ ¢MåTðxâr7öÃgqÚ¶y6BÖ ]$ø®Ð263¯S¡Ô¨Ð\ßYåNBÊÒç%l.a²Ü6F;;Hk!>3uCÿ Kê T×vÌ+~>¸l¸~_0/cµIÝòô[(X÷eºù´ºô)H¶Å"¿¦8jSTNrU½üÆÇ{NákÙÜHÛqessK[¦@xiîÚ÷_h#aµg76MáËe"¼Èá]ß1Ó¨%Í!Åú])hã«[Å$Wĸb'-þ¥d«ámp¦?pÅ6£'CƸ$VNÛ²í;'óNJ(c¦Tº¢"rþ£º÷ÞÓþíÛxûwe÷ûK"9°µÝÓâgB(ÇP\jÖÃ@ÛÛbßpýû7{3qÛbÌHúK{Çîâx6¤
+8ôyeÃqµÏï£ÃÞH½ZãQdã YW¥®µvÄÀH,£v÷LZò2QÓ1I¬ÅÁ ¸vÉNqïqXýý¸ñÏls-BÖâÞc4ÃØÇÆòÐMCÜCZ:HÈ^m%þç=³¯fºÇI¸xr²7¬Òç5ì¨:¡hÐ=_
Ì-ecÜ]2Î{ql²ÉØý¥ÑjÅZ¥îNÛÁÙ¢F*?I¼Äª¦S?p{UOÙ%¬|ÏÞyÁÛSÛ±îIßpØá´Ð8ê.Ô$DÂt´j$²¯Ø[c°Íî» úÌJÈ |¥äVIp¶ w¤ÐEÓÏ^V¡4òú·òhÞVÙ£Ss6ÚìA»2MãÔP~òöb«¼P`.ðVå±÷ÈÜø{ûܼ,±Èbï'·ºYxÁÄ»QkIioé¥C³ºöÀäí-qÒ:îÎþÚäÒ^%à§QÁÜ)^°M*»b_èç[«Edfd·±uÖñÌ*b!Da¬´o)4F,ݪ¬ÚÌÑ~h"URUuûB³%Õ-9¹#ö5®íºÇ<ä2®·°³@d¸%å9Í0â×8µÍkt«SAØ.9pÆî˹ozß¹ØZ¯.^Â
+x
+i:ËCÚçjNAgÃæÊ×|<åë¾ì×BöUóe¥m«xÀÄn»Û9û)7Àg¡L
·=èówíË7smk½°k0·J÷m¸kßÐHá´ë¨
+#Ù»o=mr6vB{µ¬.Ã<#4lûn
Ís¼aÒá¨×«_eÃ>0wì\í³_éí±rÎܯâR¶ÎN.æEÔ{ËV®âEg`Ðë9UDJ4ÀÛûÁ\YÎeîx·¥öÆÛ_ï´ÈÇQ#÷:g8 ÀÝA¬hqt¢+±°2m{MÙÊ}ÎÂydc"2<8µ¢ ÒK¡.% 0tÖ«'IÖreµ¾ùyHòÒ(BI9 at Z¹IâÉƾrÔÅ).íH¡Ó!! i^½bë¹laýýÑ0ÈÆAöuº °*¼Þí¶ÑÝÊË7¹öÁ"
̸¢[BGQà¶â©¶»««1øJl¢9SD3,d:qmzBbtdÛØ-¨¦>ñb »×8Q1>È`ñîlHü·÷_/mï³wPжÊÚ\º½Dµ££U\Ú úW.ØÜqÈo9À1bI£º±@>ç4é[¯¨"Ú8o¦"de;;#=ÍæùFÁH°Ï¼)4ìrC´MväL(·MâëÕå{ÎÝËf9i9!¸ÛqiZñ²º=ãZÞÞæG¼ôj}A\ûù5Æo¨
]} ç躷]ÙÞ°4témOH]0ÎÙá7«È;iÕßÓaY·H/é6!"Ìá©]˦ÀN R(&åÓA×,æÉÛs3}OägÐÇ?»i?uejú;MWH
j³1XO±6Y9®oµ9¬ÖGûéâÔV® <xOR߸À6Åÿ ÅÓüw¤BL½A¬ÿ µ´ÞÛ²1=g?Ji«èõE 6òQë*åÀ»}Ǫ!
+ tyi¿²xRG¸w\oÍs-d®oeêá¦75â¬,xkKXÁu nÚß[>Ã1ÌwávëÛÓÀuÃB(-cd¸<9¦i.uÚ<ñ.ªêÈ°VN°pÆoÉíXH9gvØå¶\ê)¢¯GÛrEvö%Â[(¢^Ê^þèåÚo÷þùÛ6±ç·}°ùÙ]Ï}=£^àÖ¾fwml8îìð'¶8M´³×Äm¬ÓgÇÄÐwQ\âج¹¬q§eHÛq_
+Ù¦³GÊdÆÖ®Pua\LßÛÎez3(S£W!!s;+b³wRI591³ºyÅov~ÝÅåÖ-·P¹²6®F~qÎYyU\âÖW.¾ßØøÜÚræòp¶·¿6ò5Ñ:ñ :)sôR<4
¼[|9bKÇÉU,ØîX¹ ¬Ê^^ÐtêJ~xÈÇ©¸c¯¸^:ìh)¦EU!
+aK»³Æíga[q¹/±îÑÇpÖ²)ÞÒ!hf§IRxµ¥Ä.ÍÉÛø«íÀÜ£¡ÁÚ^÷ÂK¤ak\Xwxâí-e á©Î Ãòn±£±D>nÄW¬åÛc¹¼W°'Ý0-àn+zåN3ãà©>zÉã'qâSï³
+L'0'Û;×9qº¦Ù;ºÊLÛlÅÔNS,RÂ_Ý5®kú; bó»[Þum»©nq.¹6ò6XÄrG(n±].s\ÒÞ<:*:jiÉßáþ,3D@äí;!xHÅÇÈË0µ#n«JÒ^A P#ßOt§]NTY¤ ]À6ã ÞÆÏ ¯öÞ
+ðñÊæG÷Ùßókl]Õ"èox領]ù¶ÎÈÄ3i|msþëeáö]'yùÂÞ }ªî°%±xÎar«+ ÌIÊYml£)n_ÑòÖ<ì%É,ªP¦9LGEÍ»2ÁºµiÀß¹=ÇÉ7>Þö¢IËßMjøîba d×%PX{§ê ±m7gØa9ÌjF\1ÏwAñÜ5ðHà^HfUÝüãtx9ut>>}
+ÅKìa®¤,»*ÙcñÄI^àöBD fcPØC?IR íBöéuÒ¶{ÍÁsæÕsâ]½¹w{Þm,e%æ1WÈÒCÂ¥köØX%¶Üà27
+ÅÚÁÞï»ês«Û¯Xàt½4©³!mãñ]ÅoÎ9¹í|«b²ºbd+ÛLqo=m»Á,²:!¾et»fÎÝÒî;®;!mr«çA#õ+Õ!´âPoO®îm´Ì8ûÛ)]qÈZ6V8·I$Éh'¬
Û$¹mc1[KѲàñ.9ÿ FÆ-Å$fÙ¨VîÖVWâÆ dͼoé$׳)T9u+^mG&ÕuKdçE>Möxøc~©/N¸U 3[6h;Ç.ÍÃÞé¢H¬s{#ÛFZ:ÓBKôÒ8·V¡ö@$R/â
Á
+rµÇsd+väÛ[^ï³n7¾EªI
¤õ¼Å[¾"Z¨GIöÊéJ¢»ý»¶Ä÷ïmm·®&lnÞã¾6®wí,h-¯HÃ¥½<IkJ·Ùûk<ÉvFyóPDéSAݳíw.$:ZÇGèÎ~¯` +Ìê®ðR-N¿ZP?]Aj*®ÕUJ(ª¸(úRâRÆUÀà4§R<õ¨¨ð$óÒ-T®æ;QUp?8xªiØ@?0ÿ M.=iÕzÇÁÚzÛLÇAånó÷ÑLkó?~~üæ¿k]þ±"ûÓgþébÿ g[~
:»Ûÿ ZبìGoþM _*Í»ÅAÍ3rlÈwWîW)?éNØÿ ±ß©Â¿-y?óörø¼ýfEÐÀ`ô¨Tp6á ê
+¸*t§ÅXá¤AER¦¦:«ÃÃÉRZɾn¬~Ë"»<K[¹Ví;îÞ>
+ìméG¥"ªBG-ËEé9; y5QòdZg`æp >xuwS,tñA#ÓÒà
+<`¦ìK}Äc2dT»û$õø*(OUGUVkHÆÈÛî¶%ç+$@nv©¼rF6¤w"äâç
+á14A@[]wÒ æy»+æÎåÑV ð¨ixÍ¡áÄ}kn½ÅÏm!'°tPôÐGQ¯Ð¶ÇÆU±»LæHçHH¢ªÞNØ:öb òVjôt/þ©ÄJÃôÆjìälOHjSHs&ºº@JÂs v
Ð4ï½]à×@Ò÷isº¼+¦8t
Ä%!¤Ñjç}Gj IûS.rh`íìNÉ!¯'³6VÒHÑP$ T8£é¯RêÈÉ#ããiðsì9-!+f ¤³BF¹m3(Ù
ÒlsS¦1äj¥ìn]Ð.ÊÔw,&ã
+]£iÄH$Áô®í±kâñxËÔ)OÆx.ÞMÙLCé¡Ä¿Û)¸c §ìÓÜÔ
+*xµÇBC
xu
+ý&¾Ùèéÿ x(I^ÇtÀ "øE1 öA|D`Ôû¾ÀÔhuº5Úð¯i?ç)h>Áü?÷-íàS¡¡Ûn½²¤M$å8
+j¨ªÇM4ÌTÇP.£ËÊ5Ò{~JÑ-iARiÖ '_à]¸m¯&«âèë&£ë4[ÜkB¬à)0YP "mdÑzä `)^>7f͸j"'8ìïWNæg2>ùwQþÒâ¬oþ«\~ ²Ö±Èá5Òö £à/û#ðÜ6ý¨ñöPÿèìËâ îjþºî¢u÷Õ¦ä2ÐÈx<££PÓOQlc¤ý.'À¶;k e>ï飵Jÿ ¿ú£ÿ
+>µÄstlsotÄôm%w4û(È[6ºzêX¾ S!t©ö§75ËìÉnï³öóÞ=ò[Z;µgM ð.¦P[ÇlYnƳXé$Æh¼QÈÂ\jÆ»$[QZA!Éô¿¤.öqÂ"_xfävª(¼A
+}gµÛ$ØßïXû§OKYÁ±ØK at q®+Å7<ÍvKîÌ5l
+¨ëwK¿§Á@ûkb-Zõ~´ q¥DêÏ¥/
+uJë¥AÔ¤óPÔ§T~%Ij`¬»à;Û¼?ñn]×»uãÉø©Ün«.y1çÏÝí§ð»U"ê*"eåçÙ
+÷°î1Xgçà;«RH ÏnímmO ^ÝL$ ç㤿òÓtZm=ÙC&ÒìD±¾Têfés¨8'KÈHi T
Ú7³´¢|)m¡ñdûµÇÙBømy)ècTòíKnË ÝbâN$\§Ü9Ó.ýkxæ`ÿ wiÞWÂnhÕÌS2X¥ÇíÝë Ææjqn´8Ñfò<Ýß|®Úe0rº°\Á$ncØO^uíÀ@ZW&âRÔáã
«S¨+ÂÞ½²tþIW2g¹K>E »jÖB8s¶lc5} 8~Tµ+gÄ Â
+éXÝ
mßÜͺæåõ¥ÅÛ,19¦aË-ÙøÌkÉsb'ãxáV®îíÃhìx9ykq
+Îj[Ͻß:'Ç4Gn89Í 9ôû/oO²Î¸
ÎA[×V'±>Û@Icle æF*~ÜL¶ä³H2Í®´K3un¦-WMÉr¨Ý@10Ê_5äW6vËØw½Ó}÷;øò7>)zÇIÀÀZÇ6S¨°Gwnkr÷wnmÙö×ï6³¶asdóoâ%p1ð!ÁÎ¥¦ w?XÕ·×¼ñë·L¸2µ8a´òÖtÆ/¸3
+2sMØNKz.BÚ]Ç\
+Î)ÅDÌmFïûNYZoK»;öDýá>b{Xã¼ÂëDeÑèñÙ3ehmKY&²F°Ûîü37ÍÆÙ·¹´sÛ·"ÆÅq(kí¤»SÃ_«ÅtnsÜÂMs4j ãv;®6ñÌÏåKmu9"ï-¾Âø´8~V.µ·,tí©R÷$µÒÔA²[qrS9Ô"JdsQògpÛÛ`¶ÅöãÜùlѱ¶-È^Ð7P.äÍ! 9ÆFÕ¤P5®{zxÇó/4ùl害î7FÎÚ¥ÚHÃݽ®òµ¡*I
+8mq¼Qç²¢Üz©S*®øé~áR¢B¤T_]
+L¾õ4ÀÆ÷¥@JõÜ|Bæ~âWKvK@¯A}âzÏÒ¼êòC'"¡Ôvèqú8ÚJ~ ù?ÿ åÆ
+þ¨/pÿ åú¼ ÿ þÍWü5oúhåüÆ~Ûôr/9N௡hBñÐW(³][MîÛYÅèÑô
ǵٿ¢Ê>¶RjyæqÎGÿ f~æ,ª?Ø(`c2ñddÅ]G{#˺ÞA51³:Ú¤¸uBîãdÌÉ5ÏÇ ekMèðÓÔâÚzôG%ð3ßÇ¿¸3BO*ákt$±Å÷¯çSè¹n® .¥+=/
+èÆIEI 1 »âEATùÿ ns¯jÍ.oº<^ñ¥v×p=±ÈA KXè¤FÑÀ4Ðis½{5ËüYcåÈ}þÛ[Ïo3KØcÈsdcØj p)R©£½óVaý![hÜýq±¿øÁ÷ó»1ÈGÊ°».[FÄ5Ýú"ѹ®Ç.ºÑD«#¬ªÄQ®ùÌ à«8Ò6vÒøêãb[¾Ã`æ¬{3Ü÷lÃÃLp ipkZCè îË#Ú7&âø}ÛR×3n÷v2ìËvæ¹²Éë\Ȥ¤Ê$[R|pçõîcàw4e%îÌ
`%qàü¹~Jå¬àÂç·Æ˳.é
îYI)%¤Z9kQk¤fê&[fCï]hó«gín\Zà3¦K}é±eñÎ_¼Iqb1¬!ârÖ»P:F³¨b7,w&z\eñ!m
Óî[zÙcîY¯29Îqp-1á¤GO jG5ÊM{A-\i1!)0ö'äY±igl(ØHBI8X]+0ý58Ã"Ú2ÅóÉ6ÆW·ØYMDZÛb³¢êúskĦF¨Ú@
[!ÑBâÐwgqûËzîÛ,¾{üIÖ® NøXÖǤ¸9W SÃùO `N7$²´C+.VàáÒy´E'1¥ê¼{A~w«ynã ='Fé.ë±kÙå)O0¹¶7úÙÛ^gÞZÁ¸"2\27pçi¤BWµòÓÆsY«Ki¨@X³ó»gjni³Ñ¶Úypï
Ïi´j¬6[|PçSQû Jé)O§Î±ïkÄGö³ktåkÎ>`ÿ ÷ø¯Õî±¾¿é¶Ïÿ 
v6VÆ·X#
ËÛ Æ
ý-q>ÉöTbwU£-gvqÊÁ<zÙÓØ»©r8n
+ÞÐÀ '¯m}Çå&øÜØm÷'Ü-rÙi26wOcÌÇ=\øik_£K_CZÒ ´»1Âäyµ°y=¦Ï½\cñ̲¹®o{á kË ¶QW6¼)ZiÏxc³á¸>Ìã\1û,¸~½-IX)æñS®!¾&^Fº²m&rvôÂWcÖ+ÖÒ()TIÁ69{Îmm&î=¹¿~ÜÁççd±Ç=ý´mx¸Ñ,f-m1È*ãã¸ite£+²qÖܼÜ'¼´nk+'Fð×Åi3ËL1Ü;S£xKµ°Ð}Mx'´¬bq£eÜ÷VJ°øjá¦Ì°LIÉæ§øú+C"ÁÒlÚÙç·¥JÜoî-þÁ2T;DÕ1u2"*ë9·rs1·/·ãÌ_Imýæ§UÍ.uÇzÇ2&ÅödCÜæ-¼ÉÆÞÉ´Âáq¶{xëKj
+4ÐCݸ:GIöZxGC]áì̺ósÓ.E39&àQ@SߺUÒ¢T΢mÓ#¥}©ihË;H¬ã¯wm`©ÔhÖ¸ÐAÓA^ó
+Åînd¹}5È÷8ÐPUÄ맣©|%SnÞ*ç-\U^¬áLI³_³ví´1}®êî¹RâôÓ'fî5Åeí$;í¥^°l$EW©@'þ@×O7ëÛÛ3ù´Ën[ÚcÓîÃÜ׸kuìä6k×uSJ÷µ·ó;7츽^ZÚÄ «GG]x¬tàxçòÒXNq´t['R/ÜrÎ9[²d].b¥qS1
+Q0r z¿=ùKwq¾f\Jö± Gp*ç8ÅN$Ä´é¹OÌ;x_q62VÃKuÃÀ4TW!8L|Õ^1/äd¿<øÝâÖ½áM«Þð*{À0Q,X;tÌ1@j¡´jÂîon1Ê,[Ø7ïW÷eâÚMmµ»+ÿ Å{ºHpSA:ehÛ¶£8SÌ\°yìýÞÎÜ8´ÎÍM3ÌêQm#Ô(_BGÉì*Ñá#.HÝO%8zâJï±2Ô¥Yy
+=c¸Båzs¬åµ? 2|ÜÄîfï-ÌNÞíK{VE¿öìÐ2æÅ 8Ú¸ ac@9¢cX(\Ó*4fq¶ØýÌ]Á5äڨ¦tn$î!ñÈæ¶G8Ô5ÚÝC¨vözfö·t³\hls-öÒòÓ9ÊRNFÄ%ºÁ³
㦢ým'sÉ9'n© ¸pA¹çö˸6CtÜ:6Gc$eÏzâã~¨Ëcî¼bçéñI¨Zt< Üñä$fcº²ÀB×½÷ÎsvÐK^Ú>¯×À5£Æ¼`(Vó~ û7ðù[.w
+ĽîFº;~ÑnÀÊ ÂMóîé¨étðZÝüÄeÌ6C¶íª¨½¢´§Eh+Ó@»m#8á.g÷Üô4¥GvúTÒ½ú×0zÒÖàÃèÛåúvT7£ÂM%cgw{÷ôÖQJ¨ÐwDºéXfÊ[szÜá#æcÛöî·a¶àÄÒ:ä
+}+#,vò×kÃyüÄÍÕ¡lFb$p=D2¦«-硸²²ók[{Øx§ðËq@üQxÄÛXì¶?+¶B[fõ¹ÍÍHÏK4Pæ1QP(áOxC{CyMç*³;-Ù
+ã}Ës*Ky{ËwÍßÇu¥ßÞG"Ô ¸wAÆ x£Ðní¹Üí³ÛVíÉ¢fÇiÝ>
+·ó@÷ºGYqà ñÈ¿íÓí
+nrXÿ òî'®ãüØÿ ö?Òß.«OüÓÞ°.Gh°ïëmq¥Ë®åÁñ0J½wÂ-ÿ جWr°ÿ ¹noønïýP»ýÆ7Ü:pµp`Ø¢_¸ºÏÅYÏ}í,Ñò}ñÓc|ûVÊ.. w
+LDuîkø-Ëå0·=öÙZäîÙ{i<yv9§¼c^Ö'Ý$S W1Áä·æÍÀÝíhÅÕÅ
»n!c$áÃCÜÒG ÚºGÓNóºåãøfeìÅ}|ICH1±$sk+¾JÞBv&(f&-8¹ã"ú4ÎP= ¼Ê¤sè¨fj!?½×IÅÚÏ̹9£ú<s d¬1=ýÜs¾*µúKÀ¥éFÈÒêq[MýÄ;"-.Qñ¾+GÞ¶gFàö7[âlsjÜí5«CkÁoópZHeWcqo
+RتVáw9oç"ã\TúÒ%¼®Ð»ä§ÁÑU3Èèßí\¦.Nºfì÷õ)ÍѲ¿åM¾×g÷ÆSrEºb·lrã~ùzÙþò`dZi¥ïñX~Ài©BjæÏ3gÝýÛa$Åñß}ÚÕÑwÄ%kV·Ú.¨'Ë.%/7×ÖsÈ·,ß~¼q0Þ5[ÎÚ,ÆìT}¸¤DY¿"lWB(½¥YB¹ ítR¾åÆÈÇãmí'°
°y¤ïe½{å,ú[WóVéb*ð}ë+ºo/g¸îC i6wqÉݱ±1µuC
+N¯µÖºHëеjõY_Ãn5Ź#(XWók_0;
ÂR©Ã[³L,¤Í«$w;ÆBq·bA9ÀC}CÉMåÅÜ£h]ã3¸øu´Y3Ùdq&dnhÎÊxÚ#:%SA q#ÙX<ä·¾ÄÞJØ7¢k¬ù4D÷´ø^(SÖH©9EÃ&âïeráº>9Ãx®Ôk'&.{Æ>Àqh´rU®. Åâ'dÑlt¸¤¹È¹LMÎоgÌïÊmñµn1øÎç1º. s,£ÞGÝ ÜÚDà{±$a!Ï-ÔÐXAÕ¤ï;ksjno/ûÜnÞPë§Ë3na²4e.h!¥¡ÔqR£a<¯{Eñaðn<ºéÌ.²³r,zø^PÌÞ@DÄܽC)ƱMHåS ¸& j<ôÚ·Ø[«¸÷¤î\Cl²J%¶3SeHk#¢sÜY#ÅAÑ©ÕsÚùûLµÙgýãq7VpÜ19ã.¡kà s¨(Ö¸¾éâRÇÂYn{-ÂaLq[/lHÛq®/²â¯¤7KFÉÂÁ¡oI7dÞ5»pwDÑ íHCf1{».\f÷®&ÇiÍÏ\Ûܶåó:öáöÖ]ÑdXXâò4ÚAwØ$j ðßÜïl^×ÈÝî(±x&Ð66ÚÂÉî»ÀZæ0Fàæ¨¼Ú é$tWÓðT<ü<Æþo£ù£yÿ Äþ-SÇÿ mØíþ²
);#a«.øÈ/ü]Mê«UE1u9`LAIÝV»ÖPQgì²,"dhA4QÉï(óNÛ7·w
î ÃÜoX-Ã
tÇu¬g8ºÒBd< s·
+>/5¶r¹ûjO,Ô4«íߥ õ¹·ºGÖ\fÌ_<DEÜr¶Lí¹)+^FýjÅå'JÈÍ3¶¦[ËoÇúòÊ _û0JBï()Û77ökm0{zëÛð82vZ¹Í¸e¡c#tÑèýQÁ:xøÅÆpÁrÛs®fÙ-ËÀçDéÃL.¸sÛÃü]25pñ@qh=õmIq_Q»ï¬h`~û.
+Y_¶OqF?$ì¯bdZv«h)6²3/.ï¦A@âÃÞêa1J:.JÛ{ö=¹wÜ9ÙãwmõÖZç2±Ì±p'PÔ:x HÛ,fæ·9lݶ'
+ikÏ|ëK}R:Ä#psÝ'4'£ \ÉGÿ °G
+#ÿ IÙLé):ôý¶?ç¾äÿ ²ÿ QCÎùGÿ ùë¯õ°dî
+öâÕå ¦:ýÚT)ÕzK3á[¬7Q²qÝßuåÖO3]ÿ f×|c(ÉeÇN%â¨Àæ7jQ2P(js|ãgo4¹ÜR^ä-1X·k%æÝî|`¾ì
+[Þ8§ZO@^ÛuvÀÙ¸Ì+ml®rºöá1 Ö¾·ñEÇì¸:%rMÅ~3Ì\;½°ñ}:ðå,TÇÙlæOo{PÉQ²±ìÜ.ÙÔÌôAfEB*V°NP(¡ºöãyU¹püÂÿ '{c÷¹_:òá×m´õÐCÜlqIªBÒKL)BM{{{6yÉlÉm,-nû½Z6Ú]<_h´_#(ÀàÕZSd)³àû.OØ¢ÚîÌË89ßÙ¦KpuLb ýáJ" #ÉYý¹¥æöö1WºÓÒM§áX|ÛÛ-¶«ßÁ¹½'èäÕfÒá|[Ç=ñÞA¸ÇÇØúþ^&NÑV\,|w¸æY·¤¬2ÖùZ©é$#uStS »#áã8¸Ùº9cÃ÷Óî½wv±p#ûÍÝDgHüçw)xÐKÚX@ÀÓïÞü5îó>ê,.fËîö÷,t%ýÅ·\z C®Jàö>,-û¡ÌµçdðûíMrYÞ4Ç
+Ý&ËyÜKæÏæU84JÔåSE½öé½àæòÓr«!m¦÷pf²×e¬f=·}ãÉpÔÙ[#Kcx¼*<aÇGÌ+;÷\äípؼu¸szmô4 tËòþº
+xñ¡àqÚFi{
p9Y5ÜÍñúYÂé4+^JÃzª©1"j(¸$0&»¨éz%½,9é°ÅÎl`j 2êF]A¨>Õzh´©î_yÊ[Û¹såÜÎy iºÝ$6§HãÑSN
³Úÿ °Wú|µþ"®æ\ÏÌHáô².®7þäkÅú6/ªP7³æl¨t&ep¢eßQ4@§L:åLD@<#\Wáãù» Éð¨A?{=\&åï
+ñ©4û´u§ÓE9ÞÏ6TôTO Ön<·pOÙÛ}ÜUk
+¥Z)¢Ów
+ùz^M¤Î¤Á`PÊ5tÄ¥0|³Ø« nù¯y¸ß_x²ØºKÖáV¶öåÍ4 ÷E ^²ÝØ«¸íùwmeÒî#,»µx¥É%Äóô:µ¨PõpÉ6aí6ÅN$äY³²ÛɤÕãù\cvÇ1âM=dä&%(ñÕ)@9 at +§¶å+´o¨¼s´ñ.kY{Ý^â1¤¸ +³y<póÛùÞÚPÝ] ¹ö³5´è3
+dº*ð.üibñÕlÞÐêAͶ¤¢Y»í?¸nX¼Mf.¢d$Å÷ÛÚwÀ+zÏgñ;±²xYö_shæÅsHp<
+v©b0Ù,#vØåb1]}Î'i«Oé$- ´B8µ¹ð¡±W I Ír
+y¡ªîE
+¾8YùK²©
+¬p\qH¸w¨Pr^Qå
+êóeù}£¹dÊíøÜù76<ãÂÍd×û}ËÜÈú~Á\ü¹n7r`̼5ß¾xÖصÏ:g½c\þ´ÇÃfvFçÍYáõÍ!nÃOçkfçmi¼¼ÒjúÕgsç¦ZÖÌêOÊ,;=è°N&2]þdìWã6^dwX`®¡3¶Ü¹³º:g"ÏK«ÇñxNw Òº{v¶ÿ tåæ¿|]åàBfÑ6]Z¢@ïÇO¤7!w¬ã-ìíßZxC[dd£Ç
+Ö2°ÁeªÈ·
µ &ÖBjBy3$ÙMÕJa r&};)+óPAÀ]æóùÙXÑhÛÛªêÉ?xÇ26Dhç´ê ³ãß¿±rÍÌ[â°öV±½ÆäÚÛÔvàçºN i4#CO+º3¹Stª8YEÎ SC_zBÈà
+úÅãlm©k@¼OOjùÑï/y{©Wxtqúqé¢jÛ§MêJô'T}½ÞåIjuíH©-N½ üÃ¥IjuH-M;ª@>ß.=iÕ B at 8R-N§Â<õ%©Ô+ÃÃS¥:¯^ø4OzÖ;í¢<íӯ̽ûûóýyúÄï]û£ýmú,ðìvkS[Àñ_
+Än%C½¦ÌâÈ·Wîg)þíø{ú+òÓ_¿ÙÊ{âóõAë^E¨T
`0
¨=*à~à¤;ÀÀ4"§X!Þ(¥p?=NÄÒ:@å$×H¶rTÕ.ò`»7);jsA&G(N_öiï¼a¬fZÉ×Ö/¼%¥Z~þ~#ëY<>Cûºýÿ eZ<v´ôþô
è:pÕ{-û{ÙµñøÛjiBã¶)V#èy(ÇEY¦B·U ºP
+>v½¸{²¶¹´uµÄdøÂdá¨8PMAÀÚ½§¹³A3dà°á^#FÂg3Gâá2psr°ÉâÆ
Û÷
+2©öb %ñ4¬t°ÎíE¿m%ÿ Úiñ#ûTw>°j"JJP¢vë@Y%)SQW$ Ü
+J&ûhù
+ª5¤(&¾é0£wrÃZ!k¥Í¯¥qºâÕü%¶ôjßè4üKO½HƼÇì^·tA"Åe~ÜN@0
+ñ#nGT'(rdíáÊ襵è«Oõ¡ßåë\ýx_à#ü
r¸'%dÕîA»tÎo"¡H EJnª :ð ®¼µÕ¹ÿ YuÎF>ôP[Wü»û Í[ߦCÇësF®]ÃØXP §¡Dª->õa0C¦}¼
ÝÔ@L(ÇûLÁ=&Û_誦]BÑHì¢I{Þûp³¤hþÛD¥TÂ8dÞ &/)^¼2¢U
+chµÒ¸ØçÌË«pûRÔÿ ám8.ÔwwãFGú,ñí½°ÑáÁ[z^qN]QUë¶ÔâQMGM±SÓMºe¦hÅÛÁnÎÐÖêáÚóWWëRèß3ëu#äãÖISzÔ»ÒbÙªiÇ1'Úvi)L¢A(ï)ºDÌaè<£ ~´¬ÅÍIJ\ÉWR¦§ x8µ²aÃc5kG`<;?Ëô.Ûe¶âeL_ìôÝ( sDuæN[¦j$+`û¼4
+VBâ:z>z8u¬Eâû Ââë=7ʼE{¶u³ÈË&8§Ij¤Á;ër452mª%ÿ vqÉïLcÔù_½Ü9?¹BÇ7Ç\?¨éã5ë5¬h?Õmx«ºnáÂØÙÈ3DMí'¡×N zÅHà¼7:çYE9Ê*s(sqG^QÔF¾Ïclc@ }|èù#Ìq{$ý'ÔÏËOOb«ù¨i§T~z)Õ jKSªPS
+uH
+mÒ
4~१±:ɬ´4¶g"õ«g¤Þ7nítvénRMBr
+jº40ºòÚÛÌöÉ4lt5i-´ôÔ8xv.V\M\ÈÞæ±Ã|4à~µóùêËTUe÷|GÃñG"Ù,n[b%l{gÙnãæjÝó£Ûñ~ÿ ·,Kçmv~RÇ1Ê(w«ÉùKËÛ½´þ̾Þæè_Ïp×FZÞõúMmihé p=oüÂÞû»pÿ {ã[<Ha-yÇ»nWC-=@X
+WªñZ
+~µ¸-&ýÚ-[º|íÓv$2lpåefb5MCÈ`H P Ðæ
+áe½¼Ot1¬æ® \{IIéí\¯YÖHç´PIÁÙÑÔê÷+µER}ªªÛPZRô¨zªÜËHÇ
+zÄ˳XYº]°¬³PQ:b¡5ð¡]yî ±àM¡í9æ¦'9hH¨ì4_8)ÕÑ\ºj¢«ïNIé*ÀêeÙÂ¥j²¤ÝÜUVÅ8"¢
Ü
+%
+¸m Næ7¿h u ;éjäÈbpSB{HèFÆLå:g2jÅ9S LCu)`¢÷ÀjÀàZáV5#ð¯©Ã×/;váQUÃT]uD
+QULc@¥ åðWp²áhlc 8*|Åò8¹ç¤R~µR©·ÇUNÔª¾öR/#Ö:bà
+bìÜ*Ù`!CDäP
+ok ×ÖðÜ3»|} Àx.HækÎkûA þ$}©"cxÆ1#©GDDyDDj´ (85©©é_zo Ý«®ÖlÐ
+[,áelÓx¢s4@Ú» é\
+¶7ºXØÑ#þÑ ï OÖ¹]4¯cc{æ7 h<«êB
+Ué§B¥6øûµ©§juL
+t)Rªªëè©-@)J¦ÚÕUJ
+TЧU÷Iêb£ÇJ1ns(ÝÜ*f¨(q9t[âG90@DL<ã\"[)1¢w
+ 5Ã=' uõÊfÆ"sÝI ð´ESn5zAQT §pT¦
+ûÍ ñVÈ2QÛ¶1ÌÝ¡×TíCêaI#(cJ¨ë\Þ&ÈéÆ]ÒàM:*zM>Êe̹ÎîÛÐ+P+ÓAÐ>¤ESnT*jëè©N«1±þLáW[vNb±²E¥uZN'K%àp´¾ ç¦ìÑ>é^9 ÅveIªä\û©¡¸*
+¾GÛ|˵Ü9¡}»Åݶ2lòx1[IK{ËWBXRç´´UÄý>Ílk$8½Çk{on^Ír;$5ÑpÙKC´Òpq൫q-ü®\oeãëfJÑÄønØqkXQS¯Ñ¹übáÆáI¼ã¨T §¨ÛÚ¿Ë͵G3¹ïuf.D×O¥·@-¼sAÎ
+s¨ã^N==纬óâËöûHàé¨ù$#Åy¡¼:Mxc$¢ñÉXª ,«2¸TX74UFà~Äê &_|%×Þ0W¡:Þ(±½ø Ô`=4âxWi¢if ç©4'¶ATÛã«¡QT §WE*&
+b©Ð>íIju_z² W®Ù° 6l»A¸w@Hç2i 4÷ ×m¬½ÒÆÆ6Gt 'ÂGõ®gO3Ø#{æ7 h< }HJ²Õ_sÕ<rõ`(&
+»]W
+îD@¢Æ9÷J&]Zá nXÖ2µ£@ðÉ$ÒJíS9Îu:I'ñeS«Êtª¥:ú*KSªR©¶ µ:¯¹iÝ7NܸMª`R,áUHÙ @À`R n@иoNs¢cZç¸'´Ó¤ñé+ÓI
+{Ñ@ &°W£êF
+tj袩¦Ý6
+*UJ
+wIjuJ
+m©-N©NªÔêè%M
+u_aß9]4YÊë$Ø¢FÉ,ª&ÜÂTa Ô
+q¶ç=k^ãÄ'é#§ë\G´5î%èôx;AÚ¨"ÕgNTjÜL-Û(º§nDL(¢c
+i G]Ð
+u¨ðµæV5¢GtOô̲979Æ1Ð 4Ôªmª-ST §UIjuJ
+t
+MN«ì+÷^è^àö½·¢
+Êz7m¦ïmØov]®ï&öé\]Ì]ç|XÞúÕAZvW¦BäïdîûGºiSJöÓ¢«Bª%Ð@C¾TZ§R@Ó¡}K<píc¸tág+©»Ú,áS¬±÷
+.úÇ6é
+ ÄÈc8è _@áÒò>GÈKzI5?ªÖËRªPSnµ¢*¾Åºp¸tådHÙ%UTÛ b CJL. P äjâd1Fç=h{\@ oIéí\®G´5î%è³êT:êèU 9é§T ¥AjuHÛ§w¤µURþJ¥*ÃÕKÂRè¥zª@?0÷tT§^Ô~zÔÁìHæîÔêÏä©¥:HSó
+êJô"«Ù.ÓÞ´£1Ôv¶K½_ÛûúÍ~Ö¼ýbE÷ÆÎýÑÅ~ͶýzöA³ÅZVÇÅNÈ6x¨ª8¯Áç§<L7Y?þƹ+÷;ô§lÃØïÔá_|ÂýþÎ~ؼýfEÚW¡-BªÀ~zZQÁ\á©¡G[ZTN¥X?×I
+¸»¿B|zÀÀ4"½«txú2u´ÄtØ9Ñlà2ÙÁP0'8gÊýîâ7½ ´}ÏnßÃ¨Ï x´8¾°EzÍ7·kÜmË´¸³qÿ Pÿ öbΫNñ{¢wwÏ{$ÌdhÄ¥3Æöo¢"LÂ;ºk¥y¶ñHÓ5+ áN£ØGQú?ßxÝÌ;z×y8qA,£)Bz0 fÝ`íUfE@5³éÅ10xy£lë¹Ümݸõé<!Ç(ýGþßJê[¯3A¦«¦¬W
+Æê¥:Z81H#é$eYEÔO©4ÞxhÆàîÝR1ºúè¯WPükq<zªËñIº¢E(S¸p«RÏË(8? ¬*ªb¡DÊ JnN`ÖºYlMÄ2nhè¡êìê(í{tµw{ °
+©©º@PL)ÊîtJR% ä×{ÁZÅÅ«
+h[SN~Ûh}Rç1ªéÂ[âe Éö`ê
+Âh`éáku¢(Í(
+kø+^=~ÜdLw+³¢£ÚfT
+äÈS(QT¥Ox@y3A ð V±u9Óã:"¼G?Zï².>(]ßn4ì! &Fè'|¢á}Ó9ÒoÈ#Èÿ eh¹)5´;ñÿ BØñO0Èñâøúzѳ
ì÷âèv¬á Z¨CK\Ój[A9D¦.§ûtµ9Ä mm®çʳi×À¾BZj?I?e¿iÇ£
HÌÞäm,ß!¶ÂºYZ8ì©Àt4_Ì·®ÌÍ{J^÷k;ÇÆ*,c[¨¡£`â1ý"13èlÑ5SîPÆPÚ ·K÷ÏÚvG2É´-s¿¬ç´ç·8ñ>
óVéÜsî,®Op?îê phêI+@áÑ[QjÖkØ54N½©Nz\Sð$)ùªU <T´¦Ì5%½©Õ ¤µ:®]bÙ>I¼mÊøêí¼&[ÖäO¦ÇÇ|c1&¹1iéÒÎØF´í×PÚ.²I]L`ZÄæòøÝ»¹Îæ$îqvºY_¥ïÑ\í,kêÐÖ¸ W½Ìä!ÅcÞ_ÜHØãmZÝOq£F§´Tõ¸:ÊܲF:¾1
+ïpcn¼µo[YÙXÎA½Q¢ê´YVè»nt°pî=û7lÜ&²¬³uÑPª&sÀ#Á··uá Ü;záX{jF à i«\æ¹®®kÚ×5ÀµÀBæÌaò{'.1 É@í/c¨H$(ZK\ µÍ%®H âàÄYÔÆØó/O[Þò«¥
püoëãçlª°"³s9ñl¢&KWm7CWVÃvmì¦á¿Ú7óø¶Âë´HÞè\0I Öæß;óo~i<=ÞßËØa3÷pèÄ_kaÖaqd q{t¸SÇkkÒÚ+® ýÁ[ªû¶xý^ÁW/Ü:Tp°&j¢$9÷¢:h\I
+×;ÆVq Tô
+W$qÉ+´ÆÒçtÐM>¥Ø¶î#È·V7ÈYvÞôì{Ü[-/Ûãx&¿¸¼eS¶Óø©äiÉOdÖ*Z²là¨ë¼¨µìêÛø½Ãaµ/®4gòmÖÑwrô[°É)ÖÖÙ¡Î=
Ý
+Ôx,½1}»ÏÚůbcÉ©AÚ#ñKÝ©Ä®§K¨8®¹6ÖÃ¥aêê¥áN©NºTª@Sn5%ªªÜ%©ÕvÎ"Âyc;Ü*ÚØȽf7c¢¤y9;*å5Q)UxåÌpÝäWuï-²,Ou^ÃghçinN|þÌq°:I\ØØâ(³Ø
+µÝ7fÇk%ÍÀv°v½î-cÒ÷4ÁwBà<mjÉß2ö39ûBÆ%Á?`]¶Ain2}½¡5/#ݺA¾¢ë¢FéCy@KÎ~^n,¤x[K×Á~j+¨'µtµà;£<q²BO Ö¸¸°å¹i¼°Ö/ÉÜZ¶\|_í±N#íÖ!{ÜÀç44u ¦ÝzkÔhT §HyBmSªûÙâ-¼U«Ù»A«³ ©9N)¬
+×1A%
é·DwGkIät,sL̦¦ÔUµâ*:Ez«Ò¹$k
®º´444é¡è4ë]
1>BÃs1þHû9/;kÃ^qLþ5ô«jà*æíàd¥¡é
lìT9'»ïÈ]C\ÛÝ8
+ßg-þÞï\Én÷h=3ENñqÓQã ZkÁÅeóx¾Ý¹Ó3sq,£[Xä®Up¡àHpëuè)ÏYú°õJU6ëÓJ©Õ()ÒP©ÓTê»/*boYwíÿ ³7KxçRá+ 3èèJ±BE[òRÑJöìús uÐÀ ×6ÆèÀï<4{mO÷D®{[&#©c4ÊÆ<QÀ-éVg;Ëíðù¸»a¥ÌÔÇÐ9¡Íñ£sj<i×ÅuñTÛã¬ñjÄÕ()SBR½t©Ú¥*téïRÓUUL
+wAj`¥*jSªR©ÕJ
0Ru4N©J¦ß"Ú§T §UAjª¥*u©Õ}É ìíxghÈîldUp(¤Ô÷ ">
+ât¶AÞõ¡µ t:M d
@Òc$Âzj
+e[¸²ìcþoæ©ÙkHÕ½ÿ 9fâ§l¿eè-é°ÝáÁÒA6¨]òS÷õ¬é¶FC)7?ïøh5ã{¹3âïí]Þ+HÜ:à³£lgM@AþçÑÛ;\{$îÚkÔÊ?ŬôGÆo2èÆ×tõzÆ|Mu[/9é±ò"ÉéMS£éÑ.ßG9ÐwYBr÷ûõÂæ1s
+'}¹f¸ß¥ìÔÒH®µ¯oÐæô.S}
ÈKÉÇÝ_Àý/n¦»Kºi©
Í?Q!oVV1¾òEó;gÁümµnëÑ×ÆpÑÿ ÛÈåVC°dâGtSìuÇNBWK3¹px»+¼ýÕÖFàAnÝ;¼Ò«àδòÖý+³Áås÷WXè»È,¡2Ìu1º#.£Òïô-è['ÝÅ×`[:Ûù¢vBÛÆ[Áöj*t¶Ëö^ñ·¦Ãöf;GéµHßå¾®Þ[hd2x¯¼ÿ ¿á d×îåüÌo¾kµhÓ%cñ©{AÜdmá³°¿î?Ý2rº;gkódÛMzGøµ4Hⶺ¼¬;ºâ±.7.»MÂÍ®(g.1·"J.*½
s!ª)ro*ÇH7ßWÄg16ùÌdítÐbyX51à ðè]<#%ÈM¿Ì¿·q0ý$RµsAQÄ>ÄNò
e¨>©AN¾E¨)TÛã¨-UT ¥Fêè Ò¡N©J¦Ý:{Ô¨ªPS¸*KS)TÛAjuJU:ªtªªR©×Ñß©N©®ß*êê©-N©J§]AjuHU6éîT§TÀ§?*S±)TÛã¥@RU%©Õ()×RZRMº{ªªçåè¥BRzÜ¥@R:UU )¶¤µ:¤:º*SªPS jiDêtéîÒ
:¥)P"© üÃRZª© üõ%©§æ¡¨-N©NR¡M u¥ÃJ¥§±:¤ó
+IjuíHç©ÒRù¨jKSªö§kgD<sèÕ¢=êüÃßß¿y¯Ú׬H¾úÙ¿º¯Ù¶ß¡bÏ®Ïoüu©-NÏoüt!~8¶ä⯠æâ3ÿ ¬{¿sùGÿ JvÇü=ýNùeÌ/ßìçíÏÖdXù^´õ(B!j!á¢:«ùêt£°¼4G[ZTN½ªàqå
+¼!§<4¨¡èLS¤p+¶|«-ÞM³yød90t«c²¾+(c@ûÛ
9LÛtæ(¡Ê>c¸v$où<%bæ¯c@ ²À:½`ïìð^ÝÕ¶l¤vOíqÚkwO;×h¤¹
+¨ÙTõU3h ÉåSAÐÉt~M5
+Ö!Æ_-ï¼Axx´ÉG6±qñ`ÐGá[#Û¾×J¹\¤IdÊ£èõ?¢©Ê%MRoê8ßÝy`0w´×?n'ªH¨¯ÀV:HK N?Ê8JÞ-X%'n,xÃ*e® HDÔí&lALtÜ´ÿ wDj/¯73áû:ÊÞJ´ñÍ¥< õ.{hqÅÚîe{hGÙþú}k'¡x¤ÆNx[^'$M'Ô}t©»ù26.f`ÈÐÚ9
+¤ÓQ8V¥6ÖÎÆ6AöMYtµ ¸×
+p4ú|Íe+¤6½èdm©ïMOÑ¥eÊVÖBq7Òe1E¸k,À[8,(r²¾»WmÄDå0è;£È:âÁßcå6·ZËkPêÚñý¾.Í´Í{u
+R½B~µñ×)IÙ© 8d0©¼'Ý ÔJ]©ÌpOÃÈ=þýh÷jâê0q<?Êh)Ud§ë+äþ$;£©ÌÜ*ödÄ8KÓTTûÆ+ËÑd #
+m4"ÆË»©#˼¬Å¿Ü×ÚÊ72ÔS\îi اxÿ ô¸DÓÅÏ4Ò{<-±»È=¿è°'³W`ÿ DUç¨ÅxÍ3ã.÷eß*«õÎS4fBú<d$IT1Ñ)Ú
+¦2®
+õ:¤ú«ilÜVÒ°m¥a®I®¢\Eâ*çÓ@ÐOnM×}êqÝC¢ t
+
+hêhðJêð70ÖßÀR½© üü´SWt©!HÔê®ÔÁ) ãJÔ$óÒO
m*¬®àdúñÃ@Ó5ÿ .´¯/çPÿ öEÏèÜ·®YÔ,7í?×Ñî1"Xq¦3Vûq)ÁQÊöíÅB$ë(p×.VpS gSؽ"v.7=ñÚsW-Q'Ï|¥ºÎÛ¶wïyåÞïÆYK5yy-at±¹ßÕðL¯ ú ØåyöaA1ÆbæÕÇn_]G#ÀÜãq cÀë}·C©ÒÚKÆyÏ &ëÙËìèl³¤¤êëâUº]v¾Í5²Ügtç°Me½¹M¾}Âû : %oÛ!ÎùækæÚâki©ÄX´é Tô
++ÒBÔ·CCùA´\×O5 Ó¸h:M+ÂâqÆXV&!âë
+sq `9q¤,3!jY¨XÏpê2n
+°!© ª©¼Ýæn>Læo-µöåõ$|8» $±¥ÝÛg¸7-ñä
+âèZ[BkMZÞõ¾ñ¬^?=µ«%ü±·Eø¬'¢GPA.qÈ®0ÍÃ?´=àÛ×U×pÚ64áì+è¸Ö²¦,bÝ(\ñ¢ÕÁÞO¿·®´ªÝDQAÊÉNB@æþðÎóØ=éc÷[[»Øþó÷»ïÜ÷_¨ÄÙb¸<9ÎcªÒNÝ˹ÙØÊí³<÷vöÏî$k[ܾõâFÐÕîHÃKHÁäAâ</}pÕÆq°É6ô^&ÁqͱpÝQïÊ£Öî·çÉ{2%iç UÕftE·a¼A0uöÍ×»ðÅÙû/8qÓÜå`ɹ¢
Í£à|±}ß[Übµê¡èªó;lÜÉìÝǹ±bö,%²ñÉ+]âÍ+#¾ÒÐzKÓ§MÉÄ¿
+ݱ8~K|{1aq7`Ø6%Ã"ÚRYªç~¿1gÈÈ0`Éd¡§W@«ê¹*c©jîrçÙ<íõÜCÛw×Q]÷L,acsC$8´xÚ¸[yìË;,¶%»S½µKq#%ÝÛâsÖæ<¶´5S¤rü`ÅxÎöÜeÓ~6áûÛöe¹¢Íp^÷eúéM{BÇDY%'/;éè¤#eã)÷÷ÊpÐ9Ž[°0y[oÍÓ{+qð¿\VÐ[4ðäê/{#L®Ðæ¶VJ¶Ë[mnì¥Ý7iàm빦I¥1B4µÏ~¨Û¨×FàkPVÅ8qâZØÉÑÄÍxg.ã2fÿ ¶ar<ãK®ÔÊ6íµÙ©3/ÂÍ»zªÝb²$QV¢:ê& éw¯·×0yuÆÜïì6_jd/#µKHÝörÍQô÷ mÁ=Äôtî®ÔÙûÎÊö
+kÇgìí<l¸x+ãûmÕ¡9#H·Â*[æ(5ôÕ )·J<)¯P3Lìà
Ìib¹VHþÊyV8þòî,L´\e©n>tÊÐñ40öY± ï_öu¾õçæÜy¶Þ6¶VØ5±ïV´ð9í:^<`׸p£W¶nK¶Ï*ðx\[C3ßÜݹ¼ºÖÅâXÖVôÐxÔ¬`á0ÝXg<cqÛrc'wÛöÍßUL1·UpÊ6bsú.#Þ¨d;r¨:*k éCÒ¹±´±¿ad±ùÚfÒY <ÄÂø¥c¾ÓHs at v\ÃÁÅi<¾Ü7ûsvÙ^Y½Â7ÜG¬¯,R81ìxèp-'N tº@YøFÅ̯¿i ÑÈðîÎîÆQ[³`KÙËrCÈ5Yê»dé&è&E1
+)Í߯!ÛÜÖÜÓa9x\bûòÁxù]#¸÷pp
+|î$8ôè)¼@ïÜCcÙ¬ 1½ñ/ÐàZIkC@R%c/BËÊ8W;þäZl¸NÀ¶.k8µ`¬¼¬³7en³'*½l²&áSQ×ߺ¤oíçÛ;Çk`±Âe¿öàÈØÇ7»!À4ÕƤupZVÑÛ8ÜÞÛÏå¯Lëiip
+.{°AÔ( !fOÒ¸(þÎ>þ+µ²:=S1#îåY8;
®D_¯.ò¥¦bå_ÑãRl-ÔjS(%0röÛ{æv}æëæ0XÍ0È:×ýÙ°Uç»{ Lçê!Å¡ z.ñkOmþâÀç±mYtH.?>eñ¶¹ÚaºKAÄЮkÄf#¸¿Ã6;éáµ-n±Í÷î·j[v=¯4¼¼
+Þªåg.µKP1H£Å1J%?/·Øåï)³¨ ûÖZmÛwmkt®ftb6Ô yè$0´MFGxmOy
ÆK/qo[Ïq-+ÝÃ^^à:É%4.CcYÁo÷T¦ÂÑyäçQ¼Kx_·U¿r at d)kz)äÇÄפ(v#k++ª(És!)ÂsÖÞ7çç-qqo=ã.%¶Û,M¾ÚaÕ½±÷ò:GwÁsA4T@LÕpø.[ï{÷í·JË6èä6²Ï,rGpøÚ_¢f7º.kIj at c¸0ÀÈÁRÜHq8
òú!ÎA{1Æ*²_Ç@L]·4+wÜR7Âý¤ÃÛq*´]±
»I@Á¨ï&U3Û|îÖ÷¶u.Û`Û˻۾XàBL&¹äÏkƧiÐáØâÜNjàq^Mã½EÓÍÙ¶·µ
Ícå$ÑsN«SOh²Ö÷/Íx áÈoX{j÷Kå<i}ÈGNÉÙ3}1 q0i2ÖÄ8I 2évþ±yCuB¶®òݸíøîZsîsd¥²7VWÌ|L¸®-9"s¢fQΣ]§KOkK§?¶víæÓn÷Ùÿ yÊ;¡oum;÷B÷ æ=47\n¨o5j?A=øÝáÚáâ2ñdfì¾ì¨{¼:)Ûnå,xp°qÚNÒU²\8.ߪQjÌ
0êUNòc7þYáöÈÎ`ÞKtðÉ î,à2jº»- þÎ&r(8´?Õ9³í¯7ÎGvîÉm³í£·is ïneîY¦pA'í¼,¯C|D}önQÕ·êw«)þP&ßGG´lÙì¸1$²&Ú,VÈçÔJBÙö^CeY[5ûX5Û^î²Øõ?CIèi{.'ùîKi.^û8Ý©qÐÇ;[Þ _¥º:Nzµté®ÑjàªÍ°f7Åy#õ%u·ÄxêjζìCÇ6ºò@+gI at 2EËبçH¸|¡íLÂ)¦&ñÝý½w¦çÇrócGjí×KÍs¬ÁkkZesC¤{Þ×21]!ÍñáéGká®0WËu>àmû9cHâwÐÃXÖ´<ÒºOAw[Åá0Y²|=îÇy}[öÖ²RÂýÑu'yµ¼$P
²nñQoEãGiät©Æ&@:Ö¾cí,ÄÛøZd6±àäma|ÜÀÃ#㸽íÒæ5ÝÛj\ 5¯ÏwÙ[ÉöÞ,÷ »g<L&pc_5kÖפtqíkãð+ò)°CG5^W,2ñðy3Û7-«r<A²¯ÍkÙNa$+oÐ&ëÒÕ:ûÉ* ¢Õð»ÛÓoüwvÏ3_%¦>heI¡i!½õÀ$6¬ÐÐÚê-©¦{)ånÙÌ|'+ØËYqy±H at .î¡,v¦GZ;Q.àêp[õÀÝ 8£ÅY¦ë¸[XSÜ9NÞ¾ífèW0h!)t9<tÛA¾1ÜG"ºfQÒ'Dé¡Ç£çfn÷emѳmÝÌæ"²Úbh$%ìËâ÷dÈÐ+@cË:gÊü]¶çÎ`w-ÄͲÆcdºxâÀæJYÇ]â]p«ZÖ¾kCðmñRɶ³^*áæJÒ{|«7#oßsõu-&Ê58¦-cá£-ëÒZFD9ãXBnÙ3 åËooìýÛÛyOîl¥ÆàvÛÙ-´v·9åîs¤|¶ñ²@ãÀM 3C
ý·ËÉ·¯³vÞváߧ/ts¾xe.kt´5g¹
£ÕÚjÞ¼É8Ýü1/Äv¿,ulì¢Ó^vmïqÇÝhÈ5FN2çg¢.̳´RY¸³ãJ at H¦_?·wVøÄó)¼¼ÞÒØÞ¶óëË{had
HÜ÷Ú5ůx6¤ê!|ÖßÚÙwÖêÔÛ_i¡FÊÀæÊÇ´RJq4H.í,µx3áѦq{Cfl
rdì/`dö5Ñ oD@áM÷Æ®aVzùY¨¤R VJwíë;Wus2æÇcs7VHdI{¢ÝwB@Ö´K1$¸ÈÑcC«Ïíþ[ìèñ¯ÉǼ¼¾ÆÁ;¢d¬÷Ú¤ï %ÄÇn¼êm8%ÿ Ã.°³¶2e=%βÖ?ËÝû#é·r¤NS´×kåÝæ|Ý6Ý¿¢ú: ¹"ª&cèsÌåØù)¬qQ\s~ûXý0Øæ8sÞÜi%úuëqc× CÖ+-²6Ö+uXÅu$;'!hÛ¸çsuJ"sIÖÞ꺴éhpqÕÜØËÄ\°w¸±ûû~qþ?Ë÷MZRê?Fïdkb2=¬â)w½íNR¦p?rs}òúÞ<î7·2Gqn¬-ÙÝÎÆHà×ß>Gº2øýK
+- ³6ñøF/5a+á{ »ÚâsÒæÝ5úé ¾¼)
öwgC]¶Ö@E¥ýe¥âb¤´ûòÎumÜ[b£2?I~ÙG
+&¨¦bãßvÛÍÿ Ìbnl#{ì.
+¯yEþðÙ´¼k{Ü$1é
+¡ÀÐ×i϶YÉì¡ÈAvö¶î>Ýr?2b«Nµ¥áÕ.!Ô"¡u}©»ZÂö|å¨÷÷
+×RÍ-n/å
+æßfBÆ`5LÑÊ8jÀªvªêo{Þ)º²9<îþÚ··ìf7D沸ÜX:G÷¯ÔuãFpG+a·ì¬q;G?æ7·ù7çV1ÜÞ5ÐÚx¤ãq5<x.óâ%§x¶¿¬\Ë/ËÝW½úÞ>èÈÓpVõ¹eçSbÙ0¶ãÉ'7oIHd];T»Æ"&)JÒ9}/8!åMso¿2ÊĺI#Y®ã¸¸É0{.K»¦1§hàFѼcå¼¼Á»Åfþêì6[=Çn÷é
+µÆF²£¼sÈ⡤^á>:ÖãjȽ&gáóH\¶ÓÈ'åe<'D$àN²;gFrÂFÓuØ]Ã(%Öå{ÍKÌÍaáZgòLfÊÝnDÀ¶d{Cèj :GBÖmv6{Sq²t;Cdá©
í¡«\ÂÒ[QJÒ«OÂ3ºxSök[*»A
Ë2´å,
+$Î_4s¥Y¸(
+ÝϺmæ±¾Í.cdíÃöØ«Z*ÒèñÚÚ8U¤"¢£Ê]ÚÇ°vUŲQ¸´ÑÀ>óI-<hhxp+½¸u´1&+â',v£öeKKå&Å^âYWxѪvqî¥Z0ª©w½|º&jô@¤S¤aÑù
Ý{£Û'pµö¶ï3dto ¸î }
+hp|mÄ(¶ÛØãº0År:ßt5I¶ÏxÓVÔÌçéÙ ZVIâ|]xðá3^+ovÇKã\ÂÊà·®f2âË^+2eáØƳ)f >`b±Ê Ý èíöÛ§sâ9Ù¡ÖZd±)bc£Õ{nA¸¡Ïwæû¯Î4µ¥y\ûÙÛ\YdZÉ#áôµR-oÞxýBhÏñømÂwÔ³³ÍÏp¶3Öá`<L{
cHÐF~ID\¶\ÎC¶íÙïRööþìËîbæ°Â
pðÃ~ÞIy(Öðª"`sÐÐCôT<zÙ»Ãì¼fRs'Ä)e4¸he´~#Im+ªG渺
µ¨á ¦Ýz{õéZ5RMºt÷©P'T §pT§T¥SmAjuJU:º*têèvuJU6øêh
+uJ
+uT§T §]Ajª¥*t÷*KSªPS¸?¢±1TÛãïÔª@Sª¤µ:¥:êKSªR©Ì:t÷ªJuJ
+wôRLÄÅSn¾í*êê©-N©ANºÕUJU6é°{Õ%©Õ()Ü)تm×Ý¥@RTSªPS® µ:¤*t÷*KSªPS¯¢¦
:¥*z
:¥9éiìN© üÃRZRùêSª@SuéîÖ¤µ:¥:¼´¸§T¦ÝipB@=-)Õ{}Á!5²¡G¿¬dxøÙ 5ù}¿ÿ 3µï?X}û³t1_³m¿@ÅÝÿ µ%j_ZÙìÇý¨y(úп<\rq[Äàõ?ÖEË_¹Ü£ÿ ¥;cþÇ~§
+ü²æïösöÅçë2,z¯BZz!J¥R)B a
+(ª¸§J8+iQBû¼QLw%!NB&íÜ
P ö¥1k¨îj<µÈáqù1[R_í´éwá>P²ØìÞCÝù¯ì»èð»6b»u bÜ;(n&àÆ@4IÊÉ7\®Ì:iª©ºhQÓZÔîöAþã¼û/¯ýãýU¸Zo (/!1¿¬¶~êñøÑk¢Û îÁ©é
+h3Ëöʱ3gÓQ1!ûBHMÒ7@§(ã~á¹-ÜDðЯGhý}=«/W0;4v;SúW-`AI¤ñõ¶>ógL1ÈöÔm_ÊÀ¢# d÷b¢q
+áFìi}¬Vôè §ej¹¼qLq,»ÓãµwÄWµÚ߶;+u..AFd]Ã¥ªª9QÊ¥XÇL M0&á@ F±_ç2âñÙ=¤pvqð©qàí¡ÆµÇükÎqS~ÉÊqÀ88}º®
+¢i]ädTCBCwÁ ¹ûN\Ø Ó~í`t4è©p=¼Þï.:-'ûN<~¦´ÿ ø:ÈJ¿r£·îr²ªSÚ{EGyC!L¡¹L yGQòÖÆÖÆ.æÕú:Oôi·W×WÒw·O/ÓÐ< }Kãó»WU\
+¯xjHN¥ B¨WÐ
+ at 70Ò (¨Wóù)iM jHíEUÀãá©Ò@8søêKUT¬àÒàµø®áê⹦¢Ûz-YRS3³²,â!¢cM6UÓù9I²`ɲE(ª§!PÔD¼ã¶¹.Wçñøèe¸¿pÈâG½ÑÖ±Îq<Z ' -Ëwv¶[ëyy#!´þ=ïpcÐðKçÖ8HveÉÄ\Æãç.g¼W78Ù9rmñHÈ[Ý;.%Güz˲·.¨_Ù.&&áo3»Øǹá·ìcp{f¶¸Ö ×éxd°ÈÞ- â
Àæ¯7uÎÛæþéÁÈÉXܽÓÁk£Ï!-ÔÒC£CÚjYÁÇVGácð?'mùÌQ2ùxc+)ÍÝd[Yí¾î{FfÝ;UTKȱf D ¨r>3É=½Í[MѼçÝÏèkmä<Aq5¬[C<r½º&G8Tâ^ÐIÒ¹Ø7=µßpQÝÏ<¶Ì¦Xc¸ÉãkµEBùÆ H]n<tf7Æ8öáìOÂSÛ+ØðØ÷78±Ü[6DT{-gY%¹e.
¢äô58ùJ¡Û¢æËÇí¼nÓ~pì<¶Sî.±ÂäMp÷8þÿ q®Bu4÷pè%çæw5æj÷p7'Ýû
+Ó
÷-kkÝ!Ó#¤pÐAé ZÐgpêØl©y)ØA/ +B$7º`ßX*K¾ÀvLbeRíhýX"$YhµÙ ÅÆè=( "
+írK³÷k¼f c/¿¿ì¯òZdmȹ;@æ+¡íkÝg÷Þ?ÌöDßZÿ tÝZp%c .u-ÿ jYMm,®¯¶4ôðX±o±¶pw¾Ð¬seLG;~¼¸xe5´ÞËÈ0ì¯5½ .i
,SÝ$¶ãîÉVæôXªîöb5éód·§6võÆã2°`ÙoïŬ:غÞXc<ØL¯oæu¼wsk¨£ÚEg¶y}»vÅíõ¹GMîÄ3±âjLÉÜñ»iüæ8:+µø"ÏxE§ìd³eÇo5¿x!»ï¯íÙé¦ïoæwõ>tìqÇh<xÛ'³o&§¢l&§¾zÕùͱ÷»íöû6ÞáØ=çime(ÜæÚºÚâ*ÝJæ´µ6n|#]yB]¤,ï-wNÚj6mË4MÊí«®¬£{ÚÓ8ÒÚH."ä6C¦¤ ©]CÀod´§8³¯L°¾$¹øk! ÜÞÕËP·Ì+ût\X@Ü.n§¤|ë³¥©@Û
8¨ÙÎþZ;+e·rØ|[r¸Ý¹;&4tÏc+"F ¥C«¸Ò¤»_ånöY~FüØ^æbeéèéìt¥^êpáZ\2öEâÙêâÚ% &ÑRa4±°NT³ò=ßn÷I ÌåVûä!,D§
+Ä) *;aîÖ?°vÑLn£uÝÎJÊ{H- ó.¦K¦h¥Í$t¸T·m/ºðøËËíÛ»£|bxl®b¸âR<J <u=Ô £@|Cô
}Z¾iªP?_EAju^cÛÃq?Ã=Ã^IÈÖÎËx.jæÂ7þ@t¤f9º-KÍÙ$ní¸AÁmwåRIVï( ` p7ÎùìNæå·1¯y·q÷9}«dmmZwöíÑÌ;æ×FÓ«SãÂöLNC½¶]¶ÍÌÞAÏâäÖsÎtÛËÇTK ºpp¯pÓ¥«zÄ\=ão,׾rÃÐØâQ¥Ûkâ¬A}Ådû÷#Ý0.·#ÌÒ´·í£K Ü:|©ST2) ªNëß»¸Yöo.p¹x®ò: ¯oígki ²WjnìÆFÒF ð\Z{
+¥Ù8·&óÊc¤¶³x;[IÛs=Ĭ!ѶñcXÎy¡¡i Cpé`³÷îI½mLgzqih8{eLÞéÄØìnXÉé9(«%õÂè%Üì¥hÕÂàØ´6 u
4ÇódÞìËÛ¶wY>Õ»
+¸Þ2ûBøØÇÜ6!Ró©{Øßë<}js{?sÛnkÑi¹Ë#·.
ó?L"F½Îl.ÓH£Zçu4ôº<Y¼3q«jÞ\A`éÌ¥±¥´Â"À²oÈåB2bQTQm>Eи.7ª;8.4]8feQq/lB;sf³¼Àæ>ÎÉáð9¨vÍJgIuqlø¸¾6LT/&M6ÈâZÊè%w0xÌVÐÙ{Ç#ÆK»²¬Ù'½Ä !²Hêǧ1 SPÞMmìÞáå{'c(ûI¬Òâü°îK½5îñ+Òüw3ż°(úmGL $Ý)©bæ2J¹D¹-¯üÃgÝÉIÜãŵÌ0:Kv{fÇ'}(£c
+s]^ Òqì³¼Ä6Òöɸy/ðI+Y1N^Îê3Åä)Ð
+H2ZèâgZÜ^ÙNf¯X9¬U¸!¶øx¿ï6Z>èFÉVçláG» å#ó}AËd2C @ó¬g.7O÷ÙÙÏçÆï9²¶¶÷t&àB at hoxâÈǼÆï°÷46 á¹ßoM·cÌgÜÜÅ&
+÷lÇa<°½²LÔÜXæ´=¿i$ÐCÓÜ<aûì´ùWL
+wÙØÆ>é°`1^G¼ï±pH[Ò°"-ؤÏzPtáÞâMì°öQbmÿ vg9³µ]ËݱÎZeòRBË©omoocedºI^CdwF5tÔYã°ëÛGob¹{Ç9Å\c¬+ Öá³Mu#£s#k#h.`ñªç:ÒâáÆm[²ÒâÓ
ÀÁ²¹ÂÅ«æ;»(ÙÄÈ·6[¹i)ø7+Òü_s±8 U"$RAEß'ÅåyWÌÏml/²{;!Êãîî-eµdRºøÏ
Ñ0js>É.$U¬t¬o±ûûcü1=Ý¥ä³ÈËsÞ$C<s9ì;Ål¡î:Cº@h6Ì!dpßÁÜç
+Íò5òþbÉøLip%uÚxþÓ´´RÕÌÍ/ä.sÊ*¢ÜÃÙêÄ
+'qÙÛ°fyÍÈ9&>û´ñÙ-í¾ù{©ç.H!qÖØ[<xÄ4.x¯³¹y.ÍeåöáÈÞ²iþí ("Æ ÒéKÇÞ]^¥ù¸ÂÇ÷W ä<¸@ËÖMÝÉÛ÷$í±çk)-Ù¨·bÈÛ·«ÓAȨ ¦ ÇöG)3ØÎRc÷=6q7·Md±I×Qk,o
+{-»@<[ß=ÇÑ÷O0±7üüÛY{È®ù{¶èäcãåÍ7´G3Õ4]^í'dë5s.«)¥Õkßmùw£¯.r2â¶n8ÍAhÙx¹HwÙY*ÔH*&E@*1Cìµ~áÀÚæeµ¹²â çÁqâ'ô>7²FµÞ+Ô£ÛG¶p+æ¬Þ5¸|´øØî ºl°½²G#zZö¹
ÃÆiÕ¦wW*u¬ÑjÅÕz!ÃÑae.2×]÷kbÛ²O%BælWvßF
±¥®&ñÖÌíqO*§¢ð±Ä35U)QUM®L¥SÀyÎíec9¯±ºÉââÇI½ÙåË"/|ÑMUP$yàÖâ[ëÛ>÷ÙÜ¿¿ºÆý÷¬¼µwh
ò67Å#ètU àI= ~$ñ
Âu.ì³d_âÙË6ÑbãIzA^m m
Å1)'#ؼo¤#-Ð\ªo,
+µ"\îÜÙÞi\^mlV*öÇcÜ⮡¹¼¾·ÞGK<N6ZFç4¼4¿TsiF¹£IÒ]Â0x
+¶{!µºÝ0_Á,Ö³2fE#d{®ÖÝZhƵÕâ5öîcáûñ §sÅĦ·ðÎNF÷¹Ö¾/øËo!ãÕ%JÝÍÕ -b?Þs:YpXäP¤èçLp Õ6üÜ[fÁ±ó[s7q¼1°hEµ«æ´º¨Hî[â´i2¹Ôs qÒMZ6
+Ç´°Û»r˺q\;rúA4iÛŹu¬|ñõjîÀ¨q-§Û?õÅy72ñív°¹ «6_{ób.foU¡mæ-áÎ,Åü½Êõ%dÄæABÉb«ü6Ýohl\TöÓÜåâÝö×·¢Ý+mĺGsY--lWº!ÚH+?ñ¶7¸÷^B)â&ÜÖ×½xÌYcË\çÈAsMzHºª±CËÎÒá#nné·!î+¾¥i at JÍÆGÍ]
+Ä]÷ctíاnQ6¤[g)¨à&¨ E
+cèRæ.+{Ím²µ¸i6HÏ+#{ãI3+Úc k-ÔA¤¡lÌ>×ûªÊêxb¼¸ÄDÇ=|¥Ê_Ý´çéiiTeçi5öwåû)ÍÓn6¼äø
´f£mæã¹ä!@B¢æ]K*î1ºÉpFH(_øÌv×ÃÅ7Î#y
²d"7J¼ipqÇdqìåCùá'åâ{b/hÌ°¶2u. GJÊî.x{qpÁ)
+°¥¡(Ǭ-)mdëù¥*Ös:ow´<«ak1eÝ8Ar´:®Û®¦DJªb>]ÊýÐrÛ^b³7vÏÝy²k;W\±Ò~e¦h:£k^Çðx-rß9´_¸äÁÏmÆ[ÎÍ¿f×Gs8Á"Q¨QñÔ¹§I.ioÑÁ}ötáÝ)ð-öíµæ,N°)1=îÀµ¾hk
+¡~ª¢×i&_Gjá]ävR¹M at Hr7û'åw5
+Ì9¼þwï×1\{Cjx÷Îgö¶s Í/.rZn Í÷ÆKq¼F+î°ÝÈ+¼
+¨ÿ ;ÅkZÁÓG®Ôáªêɸÿ Hû»<qµ¶ª*ìö|@§pÛ#×2@ÒQÌ+WQ¶E£Ð
+eÚ¨ù6ÉQA{Cæ±Ìl^ÛÏl1\´ØÙ(²!Ð\;b¶Fj`Í}Ìò;^#/
ï{ô9Ý}Änæd7Æê±È _÷ÈâÇQŶ>ÓKà vµµ<0ë
¶ÖÞKá#L#XWåÁyc[¶2ìcgCIÄ¿Ay3¶z
+vÊ3F5NÐMNÌÊ%¿ºU ÁëÍ#·9·7·÷vFûogyÎ\HÇÈÒV6/©új[Eç;;,×/ó[[ïvY®m¥gÞel,sà]G;¦¦´¶´«xG Ø¡ýÐãzÚA/bæ{îRø$¬Ø· V7[yéVëQe)¬ì¨¦váÚDµÔ~9ñß1¯>åw÷Kì=³-ÜÉ¢áíÇ9;N\×ø
±ïð]å±_ ì»o¼Ûýâ×%;§oxÍP´ÞJÚÖ6øÀ¼ [Æ´â¹ÆcÁ66OâïÌíxáÌ0ãëýÑrÍ'"qÃÅÇ(ÀeâÛ[)G³2ÎÌÉT£NÈ˵|c¦b*]á)pÛC|f¶×,-6t»spü^ËCfÍýÌxwvó1£ccuL$
+|tp-4ä÷ÕÅç7ÝÆä7øq÷bY÷÷ktëhq{Î#,.kêÒÇ2â6ÃÊW¯´s!¹¸a-¦y79Ç.9hØI[¡ÖöÄX¸÷ë5púnJ&Ìͪ²fWtw7&åæwla¹y·ã·æ\n\Kvèc|Êó4®{Ú#$qkHmxt
+xâ³¹=å|ÑAö4ÇnÙÖ>QDQµÄ=Ìc]¡µp&zWG X¥À¾Í¸q½-0±³5õ){Å
+ÇVtc¼Ô«I©¦zM¼ÁÔXÖvTS;pí
+"NZÌ¿;ç·sºû¥îÙÏî¤ÑpöãȦ¹¯ñc.!Þ)à±ËbþÙvÿ y·ûÅ®JwLÞñ¡i¼µ¬m-ñ}oÃíë ãN:øÄILcFÀæO¬"örÅÉ;q
´f·:NUôEqº¡?htÁ21J:w¸y!´\ÜuìØÕͳaÞ[?xüÉú{jS¨ÐHØ19|4üÔÜm7¶¬µÈãîáÒ7¹tw%¿¶5Ô AR@]!ÁäCxlé¸P».;~^7Ø·n*y?iJ䶼#cOÚwDDr¤©¡´ps @ á}
+ ÖëÍËÉ/6F+x»yá¾ÂßA|اacÞ"jYÞ5Í/®ðêZ¿.mºoö
+üÑIk´ÔÉ»ÈÍi)XáÁÚpoV§q]OÆÞC½3Üä¦ }ÄQPøfÂA3&£tmüzÜÑ.¨¹AåÀ/WIRC¢¡4 ¯ø¼6Å÷*?úöZY2DÔ-ÑÖ*
+H-»ii<×U¯ó;/oÝÚãÿ þÑpBvãA¡2k ±,î
+õbÕçÕJU6ÔªªR©ÕÑS¤§TÀ§@ù¦Õ()·ÇJ§T ¥IjuJU6ëPZRMº{:JuL
+XTª)TÛãïÒÒT §UIjª¥:êSªR©·ÇSBRN¡R)J¦Ý}ÚE¡:¥6éRZR©Õ()·ÇS¥UR]êIÕ)Tëè© ERMºTªªPS¤µ:¥6õ
+F'T§VФSu¥@Rt©-N©ANºÔêÛ§w µ:¥9ü¨SªR©·]¸u§T¥-=Õ(mAjuHêÚ%©Õ (<úÔé¢u^ép>]lx!çÿ ÜGݯ˾`~þfÿ kÞ~±"ûÿ fþèb¿fÚþÐ-ÀÛäþÔVȦàmòE_^.ï]Äïþ!sOúȹk÷?ô§lÃØïÔá_\ÂýþÎ~ؼýfEUèKOR)B¡
+P
(B!J¥VR NªÀpðÒÒ
+à<ÃSDø
`6QíWÒN©\B*B°0éEPUÀãáå©Ò¸e"
+uWxjhª¸jÀÜÃRBªµp8Òâp¡>) ÜÃJ¢¡\Î*)«ù«üTíN© üþJÔÕÀüÃRZRƦ¨H<)ñJT¡0UÀáÏ¥IjuHÔêúT§Tq©¢*< @è¥áUT §]*U n4SªP?? µ0RüÃRZRõ4)Õ)TÛÕKZuJ
+w-=Õ )·_v¤µ:¥:ªSªPR§JuHU6éîE/
+iANà¥@=AMºôÔ§T §UAjª¥:êt§T¥SnçôTÚRÁJ0RuéïÔ¢«!¸Ïîóô0ym7¶
+0ÕÐI´²
mf¸pê§U!f»ñ3p
+fÚòhaű-²Vðܺädr÷äwfàFBv Þï¸_²(¶ýÝ»$ÝXÍ$-îXØm .Ö!/:Í@¡v¿³Æé+ ÁNºÞV§T¥Wm*´êî
+ÁJU6ëîÔ§T ¦Ý;¼U%©Õ()Q¦
+ªªíñÒ§juJ
+uyBN«)pP2Ù{jb¦3£¶ÓvÎk}vJ¨{*"}QÎÍbDÆÝ©¼¤DʸS17ʧï>^ßïlå27d1Ѿls``ûÄ8½½åήóº.Ò]BÝëlïMe,¶
+;¥Í{c½t¯=Ë$hiÑàdÔÕJPqW21Îsç0ç9Ç9:Æ1DÆ0¢=ñ¯HîÃF(Ò5jx®
+wNÔ¥zÈ4¨Sté¥@UU()ܨ)TÛIjª¥*tîæ¨ÒSª`S¯¢uJU6øéi Õ()ÕPZRu©Õ)TÛãïTUU()ýaý¯bb©·_vhN©J¦Ý*SªPR µ:¥*z
+uíJ
+t*hRN¾E¡0RMµ©Õ()RZª©J¦Ýz{õ4!:¥:CʨR{B§H= Õ()¶¤µ:¥; µ0RMºìQ:¤:CËKÂS}¨ )¶¤µ:¥óÔ¦
+B©Ì=CRZRÁKuJU6ëÝã¥@RU%©Õ{¿Àçÿ ÀÄñþAµ~[s÷÷9û^óõèÌýÏÄþ͵ý ¨-J¿\\ÿ Þ»ßüBæõr×î(ÿ éNØÿ ±ß©Â¿,¹
ûýý±yúÌ«Ð¥R)B¡
+P
(B!J¥R)BÃÓJ:«vR¡B¾µ4N¤-@Â" ô«ûú)'NÅp0
+©*àna¢Ôp?8xªt¦¬ï
+*U CmMuVENü ÜÃSDWµ\4qOR¸(OZ at 8óøéPÀááä©Ò@0øZª¸ÉS¥:¤ó
+I ×µ
++ØúQáOÂ×KObuH};¼U%©Õ |5Sª@>ßðT§_ (>TN©MºRð¦×J©Hæ¡©-N© üþJÔêÌ5©Õ )J
:¥6øûµ¥@R]Sª@S¯¢ µ:¥6éRZª©JS¡:¥*ixQT §pTÐêÛ¯»RZRU%ªª¨§buJU6øéSµ:¥:º)PêÛ¯»RZRtîñT§T¥Nt'TÅSo¦©Õ()Ò¨
+uJ
+uôT§T¥SmAjª¥;§IêN©¦Ýi'T¥SnåMN©ANà©-L¥SmAjuJU:ªhUU)Tëò
+$Wð¦*z§H)Õ()ÕRZª©ANºÔêªmþ
+uJ
+w*&bb©·_ Ô§T §UIjuJ
+sÔªªPSo»Zêªt)Q:¦:ú*KSªR©¶¤µ:¥?¬*SªPSn½=úRMºyB:¥<[*KUU)TÛRZR]©Õ()Ð>í*RMºtÔR´ö'T¥SmAjuH
+wIjuL
+t»SBªB©·Nõ/
+uJ
+RÒ:ªR©·» µ:¤*KSªPSn½=ÚÔé¢u^õp5ËaÛÃÏÿ 'µ¯Ë.a~ÿ g?l^~³"ýÙ¹øÙ¶¿ bôµ²©BàKû×q;ÿ \Óþ².ZýÏåý)Ûðö;õ8Wå0¿³¶/?YcÕzÓÔ¡
+P
(B!J¥R)B¡
+P
(B!JµÔBUX>ZZSV ÔУÀ¯*'RÂPUÀô'CÔ®¡íVw ðêWó
-)ñWs
+I¨ª¸zii «Ã¢¤µ?¸jh{RèâW
$ëÚ=4i¯b¸:*tê<úÔ§Up?UIjuìHæ¯j at SëØÌ:QÀô¢½© üþJ)¤óPÔ§T~%IjuWó
+IjuíJ
+sÒ¡N©
+~aÓgø©pëN©@üþJZ{ uØ5%©Õ )ÕPZR{½ÚÔê¥Å:¥6ëÝÏJH
+m÷*KUU()×ÑRZ¤*jUU()ÏJ
:¥6øûµ©§juJ
+utRÓTêèÔêÛÝîT§T¥MèN©¦ßv´©ÚR!ÑJN©AN¾ÔÁHU6Ô§T ¥MRuL
+íצ¦©Õ)TÛ§)iURÁRZ)J¦ÚÔêªuTЦ
+PS¯ÉSDêªmêZjRÁRZRMºÔªªR©·Or¤RÖ4ESM¾>ý"ÕUJ
+uT§T §]IjuJUvøêhSªPS«¢ª¦:¤µJU6ÔªªPR§JuJU6ëÓß©¡N©J¦Ñ(R N©Nà©-L¥SmAjuH
+utTª1Tëò
+M
+*ªmñÒ UT ¥IjuJU6ëPZR]%©Õ()׶¦
:¥6øéP'T §=-=Õ()·ZÔêêè¨-UT §_»J
J
+mñ÷iJÕ()ÏS§±0W¾Üð
+»ÿ Dÿ ÉÍkò·_¿ùÏÛ¿¬È¿Aö_îv'öe¯è½=lªP
øâçþõÜNÿ â4ÿ ¬¿sùGÿ JvÇü=ýNùeÌ/ßìçíÏÖdXõ^´õ(B!J¥R)B¡
+P
(B!J¥R)B¡
+P
¨xh¢uVóÒÒ
+à`
+M
+<
+ÚÒ¢u*ÀqþºÀ«û»ôãÔ®¡íW=*ü
+àpðòRÒ¸jHíEUÀãáå©Ò¸9üt)zÀÃSDTu«èL} Áà\¯j at 8ôÒ-MXJ*=5BuWE"ÔÁJz'^Õp?=.)øùU ÉHµ:¤ó»¤µ:¤óÔéN© üÃRZRô¸§^Ä¥So»Z\ª@?õ
-)Õ(nµ©Õ )ÕRZRǦÔxT¸õ¦è%*U )·NÕUJçòT¦
+B©¶¤µ:¥*hSªPSn½4¨ªPSnå"Ôêþ°¨-L
SmIjuJ
+TЧTÀ¦ÝziSµ:¥6éîTéªuH
+wIj`¥*jUU()Ü4)ë¥DU()·N5U^Ô §pT§T¥Snµ©Õ)Tê¥BR}4LÅSojuH
+uTªª`S® µ:¥*»|t¨SªPS¸*hªb©·_vjuJ
+mÒ µ:¥*SªR©·]Jªé(TÐ'TÀ§_EIjuJU6øêKSªR©ÕÑPZ)ANò
+*'T¥SoPÔ¯jPS¸)§T¥Snµ©Õ)TÛ§¹PZª©N¾TN©J¦Þ¡© 'T §U"Ôêë¨-N©J¦Ý=Ïè©-N©ANà©LÄ¥So¿J:¥:ªKSªPS® µUWÖÑ%]¹nÕ¹¢îVMS/(¨¢§ ßt®FòÛa6JõáDéãÐÖ°| .Õ¥ÅýäV6/¹F± t8Ьú#àêXk>1±;XµnSi [·M ^PܯÉÖEÙÍÞ]⺺b;¯sÈÿ Þ_¢Ø«&ã1ØÖ¶Þãè¿äYÃXÅßR/À?÷®âwÿ ¹§ýd\µûÊ?úS¶?áìwêp¯Ë.a~ÿ g?l^~³"Ǫô%§©B¡
+P
(B!J¥R)B¡
+P
(B!J¥R)B¡
+P
¨ê®ç©Ò
+À`ð
+*#VÖ¯j¸øp8P!\Tu«6Ò 'àVEN¸iÚUÀüáS¥ÀÀ>I Ô«Ä)Q:zÇ©\
+Ì4¸ëÚÏËHµ5p8xJTqðòÔéM\útÔ§R54N£ëH
+ ñHÛ¯M*¤E-)Õ yõ¨-N© üüåIjª¤=MT¥.)¥6ëÓJ:¤õR-N©@ýu%©Õ\Û¥AjuJ
+
+MªPSnÞ*<)¥óòûµ4I×± )·¨jKSª@S¤µ:¥*u¨-N©ANª\SªPS iP'T ¦Ý:i§T §=Aj`¤*ÃAjuJ
+uR¡N©NºêÛ§M"ÔëÚ¨-UT¥Snµ%©Õ)Tê©¡LÀ§]*êªmñÔ§T §UIjuJ
+uÔ§T¥SnåI:¥;uìJU6ëîÔ§T §UIjª¦*SªR«·ÇSDêêò
*êëè©-N©
+¦ßAjuL
+wNÅUJ
+ôjh¥6éÓJURÁRZSMµ©Õ!Tê©ÒSª`S¯¢¦ªíñÒ N©ANªÕUJ
+uÔ§T¥SnçôTé)Õ()ܱ1TÛ¯»S¤'T §UIjuJ
+uÔ§T
So§Jª§!s¥)s¥ Æ0è
+DDDkI#7K+bh$@ $x :ÉàÆÇÈñ@¹î4
+O@ t¼:`éàa-$ÅRn*C3l¢c¼ðzBÅ÷ªGÞyKßJøæ´ÎBý´åï1¥Ãï3´ø²i5î£=l¨«Ü8:EZM~©å,.12·sî(ô_Só¸qeGûG§ÓZx·í:ýâëE;RÞhÐ8"@0né˺óxkåô:ìê¥_Î"ýØâïÉwæE¸r¡¥²
+åsß-1ici[²qôôxÄ~ÄúRè»~r¢EVYR¦(qÔÃõvÝþp¹¶výÛ°±Á>Çg
+´n£#£6ÄÂòÛÖ4¼µ¸µÖð,Ïòç²s{¬ÕÝÖU·W2ÎðÉmÃå{¤ph6Î! ¸ç)ROÿ ´%·óÎJúVØü£Yîk{¿oyÏoXß
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;ÜÖ÷~ÞòÞ
+é+mì~ÐßÏ9+é[cò;¼Ö÷~ÞòÞ
+é+mìÁì·ûç%})l~Q£çwÞïÛÞBóÛÓù`Ø>ò¶Þȵý¡íÏ2OÒÇå*_;Ö÷~ÞòÞËÁôÌǶöE?h{sçô¥±ùJÎk{¿oyÏoOå`ÿ yò¶Þȵý¢-ÐþùÉ?J[©|íó[Ýû{È^{z,;ÒòþVßÙU¿h«{çô¥±ùJÎç5½ß·¼
ç·¥òÁ°}31åm½kûEÛß<d¥-ÊT|íó[Ýû{È^{z,;Ó3VÛÙTý£-àþøÉJ[?©|íóWÝû{È^{z>Xv¥åü¿²«~ÑÖÿ Ï#éKgò/®jû¿oyÏnGËÂôÌǶöU¯íoüïþ¶)ÑóµÍ_wíï!yíÈùbØ^ò¶þʵd |d¥-Êt¾vy©îý½ä/=¹?-
éy+oì«_ÚFç|ôµùRÎÇ5=ß·ü
ç·%òÅ°½//åmýkûI@üᄊ¿*Qó¯ÍOwíÿ !yíÉü±ì/KËù[eVd¤{äo¤í¯Ê|ëóSÝûÈ^{r>Xö¥åü¿²iX/ò/Òv×åJ>uù©îý¿ä/=¹?=
éy+oì«PöKÁz_"ý'm~U¥ó¯ÍOwíÿ !yíÈùcØ^ò¶þÊûLAüí>¶ÿ *ÑóÍ?wíÿ !yíÈùdØ~ò¶þÊ {&¡½->¶ÿ *ÒùÕæ»öÿ ¼öäþY6¥åü¿²«~Óp;d?¤¿ÊÔ¾u9§èÈ]ûr>Y6¥åü¿²iØ_²ÒVßåj_:|Òô
+¿ä.ý¹,ÛÒòþVßÙUÙ?ÞÙé+sòµ:|Óô»öä|²ì?KËù[eZþÔß:ä/¤ÏÊô|éóKÐ6ÿ »öäþY¶¥åü¿²«²?½rôÉ[é|ésKÐ6ÿ »öä|³l?KËù[eZþÔpÿ :ä¤ßÊô|ésKÐ0BïÛòϱ=//åmý[ö¥ù× þñ·+ÒùÐæ `<
ß·#åaú^_ÊÛû*×ö§ùÓ }#nþX¥ó¡Í@Ày¿nOåbz^_ÊÛû*°{*bûÓ }#nþX£ç?>ò~Ü}éy+oìªßµTWÎÿ Ò6÷å>sù£è!wíÉü´lOKËù[eVý«bþt¿ÿ xÛßi|çsCÐ0BïÛòѱ=//åmýjÊèÀïIßßHÛßi|æóCÐ0BïÛòÓ±}//åmý[ö°ùÎýúBßüµKç3ò~ÜËNÅô¼··öU¨{,£CûÎýúBßüµKç/þò~Üéyo+oìªßµ¤wÎWçÒÿ åª>rùè!wí¨ùjؾò¶þʬËhðïI_H[ÿ èùËæyÿ ö!wí©üµl_KËy[eZþÖñÿ 9_H@~[¥óÌÿ @Àù¿mGË^Åô¼··öU`ö]0ï+ìz_À~[¥óÌï@Àù¿mOå¯bú^[ÊÛû*·ívÄ?¼o¯ãà?.RùÈæw `|
߶£å³cz^[ÊÛû*°{/÷óü|åÊ_8üÎô»öÔ|¶loKËy[eVf0ïHß?ÇÀþ]£çÞò~ÚËnÆô¼··öU¯íÏçãøøË´¾q¹è8#wí¨ùmØÞò¶þʬÌFýá|u¿ü»GÎ/3}änýµ?Ýéyo+oìªß¶3_/ã ¿/RùÄæg à¼ß¶£å»cú^[ÊÛû*°{2÷
ïütåê_8|Ìô»öÔ|·lKËy[eVfSpïH^ßÇAþ_£çò7^ÚË~Çô¬··öUoÛ1¿ú}ëütåú_8\ÌôºöÔ|·ìKËy[eVfrþzõ½ü¿Kç~ò7^ÚËÇô¬¯·öU¯í úuéül'Ô¾p9è8/#uí¨ùpÙò¶þʬÍ$üúóþ6ê
+_7üÊôºöÔ|¸ìJÊù[fVf¢aÞ}yÿ õ
+7üÊôºöÔþ\vG¥e|¿³+~ÚÉÿ ¦Þ_ÆÂýCKæû^ò7^ÚéY_+oìÊÁìÙ Þ?ÆBýEKæ÷>ò7^ÚËÈô¬¯·öe`öm?Ïoã!~¢¥óyÌAÁù¯lGËÈô¬¯·öeoÛt?Ó/ã!¾¢¥ówÌAÁù¯lOåÏdúVWÊÛû2°{7ôÿ <¼:ÞC}GGÍß2}än½±.{'Ò²¾VßÙ¿nóË¿øȨèùºæG àü׶#åÓdúVWÊÛû2·íÈoôË»ø¸©*~nyè8?#uíüºlJÊùX=jÎSùåÝü\?Ô|ÜsÐp~FëÛòë²}++å öeoÛ ÿ éwoñqRÒù·æ?¡a<׶'òí²}++å öepöu(çw`ô»ú~cúÈÝ{b>]¶O¥e|¤Ìµgb¡Þwvõ-/ncúÈÝ{b.Û+Ò²RfVý»ÿ Jºÿ úͯ1½ än½±.û+Ò²RfVgáþuuõ5/>czÈÝ{b>]öW¥e<¤Ì¬Ï5üêêþ*'êz_6|Æô,'ºöÄþ^6W¥e<¤Ìûz¸ÿ Iºú>czÈÝ{b>^6W¥e<¤Ì¬Ïw!þstõE/búÈÝ{b/;/Ò²RfVý¾]¤]ÄÅ}QKæþ
ò7^ØéYO)³+~ßnÿ Ò.âbþ¨¥ó_ÌOBÂùlGËÖËô¬§ÙÙúð;Î.âbþ©¥ó_ÌOBÂùlOåëeúVSÊAìÊßõ yÿ ¹¿úªîbzÈÜûb>^ö_¥e<¤Ì¬=÷ûøϪ©|Öóа¾FçÛù{Ùò{2°pø?ßîOâ#>ª¥óYÌ?BÂùkGËæÌô¬§Ù¿êÿ ÿ =rõ]/¾aúÈÜûZ/3Ò²RfV$ýþãëqõ]5|Ãô<7¹ö´|¾lÏIÉùH=[þ¡R!ÞZãþ"7êÊ>j¹
èX_#síhù}Ùò{2dxß.òÃ^Rv;¢ÃÙÇÚu
qKüÓsF6×Çë6«§Â
+äùÙlxs§É8£,4>0ø]÷øB9Ê0©¨Q.ów<ÂU[Þ&è5yVëæùÞ0g²¾È÷,
+/¢¬4>FMdv¯AÛÛiíw qq²è
+w®¬}4{ËkÖ¤}Ѽk!,è§Û¥ÔÛ
×PþºsÖ·Þ
)HP)C@ Ð+P
(Bø|]¯ü'Ñ÷¿ûÍ5¡æùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüڧȧæÐ
>Dõ?6)ò'©ù´!O=OÍ¡
+|ê~mSäOSóhB"zBùÔüÚ¾ô=Oì;
+?û¿à¡é¡
+P
(B!ÿÙ
\ No newline at end of file
Added: trunk/openchange/doc/doxygen/pictures/middle_bg.jpg
===================================================================
--- trunk/openchange/doc/doxygen/pictures/middle_bg.jpg (rev 0)
+++ trunk/openchange/doc/doxygen/pictures/middle_bg.jpg 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,2 @@
+ÿØÿà JFIF d d ÿì Ducky d ÿî Adobe dÀ ÿÛ ÿÀ d ÿÄ U
+ Q¡Ña ÿÚ ? ßÀ#¿ªÚ0 ïæ¶ 3Yû ñݲ ?ÿÙ
\ No newline at end of file
Added: trunk/openchange/doc/doxygen/pictures/nav_tab.gif
===================================================================
--- trunk/openchange/doc/doxygen/pictures/nav_tab.gif (rev 0)
+++ trunk/openchange/doc/doxygen/pictures/nav_tab.gif 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,7 @@
+GIF89aP æ ïïïþþþýþýûüúõ÷óñôïøú÷ýýüúûù÷ùöôöòöøõïóíðôîóöñùúøüýûòõðïòìîòëíñëòõïõõõÿÿÿúúúîòìðóîêëéðððôôôñññýýýñôðÆÉÅìîëÇÊÆÈÊÆÏÏÎÇÊÅËÍÊêìéïóîçèæÎÏÍÐÐÐõ÷ôÊÍÉïñíÆÈÄÊÌÊêêéïóìüýüÊËÉÏÏÏèêçÕ×ÓüüûÍÎÌëíêÌÍËíñêÏÐÏùûøêëêòöðóõñÉÊÇñôîîñì !ù , P ÿ @;/ ¡¢£¤¥¦§¨E( )·¸¹º»¼½¾¿À¸723ËÌÍÎÏÐÑÒÓÔÐ=*"DÝÞßàáâãäåæä8îïðñòóôõö÷õ. A
+þÿ
+H° ÁM R ¡Ã#JH±¢Å0)À±£Ç CI²$É8Xɲ¥Ë0cÊIsæD-èÜɳ§Ï@
+*¢*]Ê´©Ó§P£J:QX³jÝʵ«×¯`ÃÈ@³hÓª]˶۷pßÆ@ôÃÝ»xóêÝË·¯ß¿~O Bð °áÃ+^̸±ãÆ<
+@@¹²åË3kÞ̹3grMº´éÓ¨S«^Ízõ
+D4 ÈM»¶íÛ¸sëÞ»¢ÀN¼¸ñãÈ'·HóçУKN½ºõë×}
+À½»÷ïàÃO¾|y ;
\ No newline at end of file
Added: trunk/openchange/doc/doxygen/pictures/pixel_grey.gif
===================================================================
--- trunk/openchange/doc/doxygen/pictures/pixel_grey.gif (rev 0)
+++ trunk/openchange/doc/doxygen/pictures/pixel_grey.gif 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1 @@
+GIF89a îîî !ù , D ;
\ No newline at end of file
Added: trunk/openchange/doc/examples/Makefile
===================================================================
--- trunk/openchange/doc/examples/Makefile (rev 0)
+++ trunk/openchange/doc/examples/Makefile 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,15 @@
+all: fetchappointment \
+ fetchmail \
+ mapi_sample1
+
+clean:
+ rm -f fetchappointment fetchmail mapi_sample1
+
+fetchappointment:
+ gcc fetchappointment.c -o fetchappointment `pkg-config libmapi --cflags --libs`
+
+fetchmail:
+ gcc fetchmail.c -o fetchmail `pkg-config libmapi --cflags --libs`
+
+mapi_sample1:
+ gcc mapi_sample1.c -o mapi_sample1 `pkg-config libmapi --cflags --libs`
\ No newline at end of file
Added: trunk/openchange/doc/examples/fetchappointment.c
===================================================================
--- trunk/openchange/doc/examples/fetchappointment.c (rev 0)
+++ trunk/openchange/doc/examples/fetchappointment.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,97 @@
+#include <libmapi/libmapi.h>
+
+#define DEFAULT_PROFDB "%s/.openchange/profiles.ldb"
+
+int main(int argc, char *argv[])
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_session *session = NULL;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_table;
+ mapi_object_t obj_message;
+ struct mapi_SPropValue_array props_all;
+ struct SRowSet rowset;
+ struct SPropTagArray *SPropTagArray;
+ mapi_id_t id_inbox;
+ mapi_id_t *fid, *mid;
+ char *profname;
+ char *profdb;
+ uint32_t Numerator;
+ uint32_t Denominator;
+ uint32_t i;
+
+ mem_ctx = talloc_named(NULL, 0, "fetchappointment");
+
+ /* Initialize MAPI */
+ profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, getenv("HOME"));
+ retval = MAPIInitialize(profdb);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ /* Find Default Profile */
+ retval = GetDefaultProfile(&profname);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ /* Log on EMSMDB and NSPI */
+ retval = MapiLogonEx(&session, profname, NULL);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ /* Open Message Store */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ /* Find Inbox default folder */
+ retval = GetDefaultFolder(&obj_store, &id_inbox, olFolderCalendar);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ /* Open Inbox folder */
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_inbox, &obj_folder);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ /* Retrieve Inbox content table */
+ mapi_object_init(&obj_table);
+ retval = GetContentsTable(&obj_folder, &obj_table, 0x0, NULL);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ /* Create the MAPI table view */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x2, PR_FID, PR_MID);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Get current cursor position */
+ retval = QueryPosition(&obj_table, &Numerator, &Denominator);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ /* Iterate through rows */
+ while ((retval = QueryRows(&obj_table, Denominator, TBL_ADVANCE, &rowset)) != -1 && rowset.cRows) {
+ for (i = 0; i < rowset.cRows; i++) {
+ fid = (mapi_id_t *)find_SPropValue_data(&(rowset.aRow[i]), PR_FID);
+ mid = (mapi_id_t *)find_SPropValue_data(&(rowset.aRow[i]), PR_MID);
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(&obj_store, *fid, *mid, &obj_message, 0x0);
+ if (retval != MAPI_E_NOT_FOUND) {
+ retval = GetPropsAll(&obj_message, &props_all);
+ mapidump_appointment(&props_all, NULL);
+ mapi_object_release(&obj_message);
+ }
+ }
+
+ }
+
+ /* Release MAPI objects */
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_folder);
+
+ Logoff(&obj_store);
+
+ /* Uninitialize MAPI */
+ MAPIUninitialize();
+
+ talloc_free(mem_ctx);
+
+ return (0);
+}
Added: trunk/openchange/doc/examples/fetchmail.c
===================================================================
--- trunk/openchange/doc/examples/fetchmail.c (rev 0)
+++ trunk/openchange/doc/examples/fetchmail.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,96 @@
+#include <libmapi/libmapi.h>
+
+#define DEFAULT_PROFDB "%s/.openchange/profiles.ldb"
+
+int main(int argc, char *argv[])
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_session *session = NULL;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_table;
+ mapi_object_t obj_message;
+ struct mapi_SPropValue_array props_all;
+ struct SRowSet rowset;
+ struct SPropTagArray *SPropTagArray;
+ mapi_id_t id_inbox;
+ mapi_id_t *fid, *mid;
+ char *profname;
+ char *profdb;
+ uint32_t Numerator;
+ uint32_t Denominator;
+ uint32_t i;
+
+ mem_ctx = talloc_named(NULL, 0, "fetchmail");
+
+ /* Initialize MAPI */
+ profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, getenv("HOME"));
+ retval = MAPIInitialize(profdb);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Find Default Profile */
+ retval = GetDefaultProfile(&profname);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Log on EMSMDB and NSPI */
+ retval = MapiLogonEx(&session, profname, NULL);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Open Message Store */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Find Inbox default folder */
+ retval = GetDefaultFolder(&obj_store, &id_inbox, olFolderInbox);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Open Inbox folder */
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_inbox, &obj_folder);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve Inbox content table */
+ mapi_object_init(&obj_table);
+ retval = GetContentsTable(&obj_folder, &obj_table, 0x0, NULL);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Create the MAPI table view */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x2, PR_FID, PR_MID);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+ talloc_free(mem_ctx);
+
+ /* Get current cursor position */
+ retval = QueryPosition(&obj_table, &Numerator, &Denominator);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Iterate through rows */
+ while ((retval = QueryRows(&obj_table, Denominator, TBL_ADVANCE, &rowset))
+ != -1 && rowset.cRows) {
+ for (i = 0; i < rowset.cRows; i++) {
+ fid = (mapi_id_t *)find_SPropValue_data(&(rowset.aRow[i]), PR_FID);
+ mid = (mapi_id_t *)find_SPropValue_data(&(rowset.aRow[i]), PR_MID);
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(&obj_store, *fid, *mid, &obj_message, 0x0);
+ if (retval != MAPI_E_NOT_FOUND) {
+ retval = GetPropsAll(&obj_message, &props_all);
+ mapidump_message(&props_all, NULL);
+ mapi_object_release(&obj_message);
+ }
+ }
+
+ }
+
+ /* Release MAPI objects */
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_folder);
+
+ Logoff(&obj_store);
+
+ /* Uninitialize MAPI */
+ MAPIUninitialize();
+ return (0);
+}
Added: trunk/openchange/doc/examples/mapi_sample1.c
===================================================================
--- trunk/openchange/doc/examples/mapi_sample1.c (rev 0)
+++ trunk/openchange/doc/examples/mapi_sample1.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,33 @@
+#include <libmapi/libmapi.h>
+
+#define DEFAULT_PROFDB_PATH "%s/.openchange/profiles.ldb"
+
+int main(int argc, char *argv[])
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct mapi_session *session = NULL;
+ char *profdb;
+ char *profname;
+
+ mem_ctx = talloc_named(NULL, 0, "mapi_sample1");
+
+ profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB_PATH, getenv("HOME"));
+
+ retval = MAPIInitialize(profdb);
+ mapi_errstr("MAPIInitialize", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return -1;
+
+ retval = GetDefaultProfile(&profname);
+ mapi_errstr("GetDefaultProfile", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return -1;
+
+ retval = MapiLogonEx(&session, profname, NULL);
+ mapi_errstr("MapiLogonEx", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return -1;
+
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return 0;
+}
Added: trunk/openchange/doc/howto.txt
===================================================================
--- trunk/openchange/doc/howto.txt (rev 0)
+++ trunk/openchange/doc/howto.txt 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,434 @@
+Copyright 2005-2008 OpenChange Project
+under the terms at http://creativecommons.org/licenses/by-sa/3.0/
+
+
+OpenChange developer howto
+--------------------------
+
+== Updated on January 2009 ==
+
+
+###############
+[0x0] CONTENTS
+###############
+
++------------------------------------+
+[0x1] INTRODUCTION
+ [0x1a] What is OpenChange?
+ [0x1b] What is libmapi?
+[0x2] INSTALLATION
+ [0x2a] Samba4 installation
+ [0x2b] Requirements
+ [0x2c] OpenChange installation
+[0x3] POST INSTALLATION
+ [0x3a] Create a profile store
+ [0x3b] Create a profile
+ [0x3c] Test the profile
+[0x4] USING LIBMAPI
+ [0x4a] Doxygen
+ [0x4b] Sample applications
+ [0x4c] External resources
+[0x5] OPENCHANGE SERVER
+ [0x5a] Provision
+ [0x5b] Extending users Samba AD schema
+ [0x5c] Setting smb.conf
+ [0x5d] Running the Address Book Provider (EMSABP)
+[0x6] SWIG BINDINGS
+ [0x6a] Installation
+ [0x6b] Sample applications
++------------------------------------+
+
+
+####################
+[0x1] INTRODUCTION
+####################
+
+
+[0x1a] What is OpenChange?
+==========================
+
+OpenChange both provides an Open Source implementation of Microsoft
+Exchange protocols under unix/linux platforms and a server able to
+replace transparently Exchange in a company environment.
+
+
+[0x1b] What is libmapi?
+=======================
+
+libmapi is the OpenChange MAPI implementation. It is a programming
+interface designed to offer Exchange support to third party
+applications.
+
+
+[0x1c] Why do I have to do all this compilation?
+================================================
+
+Several distributions (Debian, Ubuntu, SuSE and Fedora) contain
+packages for OpenChange. These packages are not maintained by the
+OpenChange team but by the distributions, and may be out of date.
+
+Furthermore the OpenChange project is moving along quickly and you may
+want to evaluate or benefit from latest features, changes and bug
+fixes we may supply in the future.
+
+
+####################
+[0x2] INSTALLATION
+####################
+
+
+[0x2a] Samba4 Installation
+==========================
+
+[*] First of all, you need to install a Samba 4 version and pidl
+ version compliant with OpenChange. Furthermore talloc became an
+ external dependency and needs to be installed apart from
+ Samba4. This task can automatically be done using the
+ installsamba4.sh script located in the script directory.
+
+ Note that the script relies on sudo for "make install" operations
+ and requires your account to be in the sudoers file.
+
+ Run the following command:
+
+
+$ make samba
+
+
+This should give you the libraries, headers and tools you need to
+compile OpenChange. It is rare that you will need to update Samba,
+when you have successfully done this once you should not need to do it
+again. As a hint, as well as your base compiler (apt-get install
+build-essential on Debian and Ubuntu) you will need pkg-config.
+
+If you want to control every detail of the Samba build, follow the
+instructions for checking out the git tree. You will require
+tools such as autoconf (apt-get install automake on Debian and
+Ubuntu), it will take more time and disk space, and there is more to
+go wrong.
+
+Since the libraries will be installed in /usr/local/samba/lib,
+ldconfig needs to know about it. On Linux, make sure this directory is
+listed in /etc/ld.so.conf and run 'ldconfig -v'. On FreeBSD, add this
+directory to the line 'ldconfig_paths' in /etc/rc.conf and then run
+'ldconfig -rv'.
+
+Similarly, you need to have /usr/local/samba/bin in your PATH for the
+pidl binary. This is also where OpenChange installs its binaries. Eg,
+if your shell is bash:
+
+$ export PATH=$PATH:/usr/local/samba/bin
+
+If you did a standard Samba install to the normal Samba4 location you
+should not need to change PKG_CONFIG_PATH, however it does need to be
+set. Use
+
+$ echo $PKG_CONFIG_PATH
+
+to see if it has a current value. So if PKG_CONFIG_PATH points to a valid place
+and OpenChange configure still complains, you may have a problem with the Samba
+installation.)
+
+If you have installed Samba4 somewhere else, you need to change Samba references
+in ld.so.conf, and in the PATH and PKG_CONFIG_PATH environment variables.
+For example, if you installed to /opt/otherplace/samba
+run:
+
+$ export PATH=$PATH:/opt/otherplace/samba
+$ export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/opt/otherplace/samba/lib/pkgconfig
+
+pkg-config >= 0.20 is required.
+
+
+[0x2b] Requirements
+===================
+
+OpenChange has only these dependencies in addition to Samba4's
+requirements:
+
+* automake (autogen will fail with 'autogen.sh: aclocal not found')
+* flex
+* libpopt
+
+Samba4 can *use* some of the above, and will tell you in the
+'configure' summary that some of them have not been found, however it
+does not *require* them.
+
+OpenChange also includes a new build system which will gathers
+dependencies on your system and only build what can be compiled with
+your current system. If your system doesn't meet the requirements for
+a particular tool or library, you will need to install missing
+dependencies check below for the list of dependencies you need to
+install:
+
+ * libmagic (with development headers): exchange2mbox. For
+ example:
+ # apt-get install libmagic-dev (Debian, Ubuntu)
+ # pkg_add libmagic (BSD)
+
+ * bison: libocpf, openchangeclient
+
+ * dcerpc_samr (samba4 installation): libmapiadmin and
+ openchangepfadmin
+
+ * doxygen: build the documentation
+
+ * boost-thread: thread support for libmapi++
+
+Similarly for the others:
+
+# apt-get install automake flex bison libpopt or
+# pkg_add automake flex bison libpopt
+
+If you have boost development libraries installed, but they aren't being
+found by the configure script (see below), you may need to set the
+BOOST_LIB_SUFFIX environmental variable:
+$ export BOOST_LIB_SUFFIX=-mt
+
+
+[0x2c] OpenChange libmapi installation
+======================================
+
+If you retrieved the soure code from Subversion, run autogen.sh now:
+
+$ ./autogen.sh
+
+Now, run configure:
+
+$ ./configure --prefix=path_where_samba_is_installed
+
+The default is not /usr/local/samba as you might expect, but /usr/local . So you normally
+do need to specify --prefix.
+
+You should already have made sure that the output of 'ldconfig -v' mentions
+the samba library directory in the Samba installation step. If you didn't, OpenChange
+will not find the libraries it needs.
+
+You should now be able to build and install openchange MAPI library:
+
+$ make && make install
+
+You can test like this:
+
+$ openchangeclient --help
+
+
+
+#########################
+[0x3] POST-INSTALLATION
+#########################
+
+The MAPI library requires a profile database and a profile in that database
+before it can be used.
+
+
+[0x3a] Create a profile store
+=============================
+
+$ mapiprofile --database=/tmp/profiles.ldb \
+ --ldif=/usr/local/samba/share/setup -n
+
+
+[0x3b] Create a profile
+=======================
+
+$ mapiprofile --database=/tmp/profiles.ldb \
+ --profile=testuser-2000 \
+ --username=testuser \
+ --password=openchange \
+ --domain=OPENCHANGE \
+ -I 192.168.194.22 \
+ --create
+Profile testuser-2000 completed and added to database /tmp/profiles.ldb
+
+You need to specify:
+ - the full path to the profile store database
+ - the profile name you want to create
+ - the username/password couple mapiprofile will use to connect to
+ the Exchange server (you might want to use Administrator, on a test server)
+ - the Windows domain your Exchange server belongs to
+ - the IP address of the Exchange server (this must be real. Change the example!)
+ - the create operation
+
+
+[0x3c] Test the profile
+=======================
+
+You can next ensure your profile was correctly created by running the
+commands below:
+
+$ mapiprofile --database=/tmp/profiles.ldb --list
+We have 1 profiles in the database:
+ Profile = testuser-2000
+
+$ mapiprofile --database=/tmp/profiles.ldb --profile=testuser-2000 --dump
+Profile: testuser-2000
+ username == testuser
+ password == openchange
+ mailbox == /o=First Organization/ou=First Administrative Group/cn=Recipients/cn=testuser
+ workstation == LOCALHOST
+ domain == OPENCHANGE
+ server == 192.168.194.22
+
+
+####################
+[0x4] USING LIBMAPI
+####################
+
+[0x4a] Doxygen
+==============
+
+HTML documentation and Man pages are supplied with the MAPI library so
+developers can have an overview on how to use each function properly.
+
+Run the following commands to generate and install man pages:
+$ make doxygen
+# make installman
+
+If you have troubles accessing man pages, be sure your MANPATH
+environment variable is set properly and point on openchange prefix
+installation path.
+
+$ export MANPATH=$MANPATH:/usr/local/samba/share/man
+
+The HTML documentation is available in the apidocs/html/ directory or
+can directly be browsed online at http://www.openchange.org/apidocs/.
+
+[0x4b] Sample applications
+==========================
+
+A sample openchangeclient application is supplied so you can test the
+library and have an overview on how to use it into your
+applications. Please refer to the openchangeclient man page for
+further information on its command line option.
+
+$ openchangeclient --database=/tmp/profiles.ldb --profile=testuser-2000 --fetchmail
+
+
+
+For further examples see:
+
+$ man openchangeclient
+
+openchangeclient is also useful in its own right as a scriptable client.
+
+[0x4c] Web resources
+====================
+
+For up to date material on how to use libmapi + discussions, you
+are strongly encouraged to visit the OpenChange wiki:
+ * http://apidocs.openchange.org
+ * http://wiki.openchange.org
+ * http://wiki.openchange.org/index.php/ClientSideProgramming
+
+
+
+########################
+[0x5] OPENCHANGE SERVER
+########################
+
+If you download one of the libmapi releases, please note that the
+server code is not supplied. Consider using subversion to retrieve the
+latest openchange revision:
+
+svn co https://svn.openchange.org/openchange/trunk
+
+
+[0x5a] Provision
+================
+
+In order to run the openchange server, you need to setup Samba4
+correctly. If you have not already installed Samba4, please refer to
+section 2 for further information.
+
+Under your root account, provision the server:
+
+# ./setup/provision --domain=OPENCHANGE --realm=OPENCHANGE.LOCAL \
+ --adminpass=secret --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:
+
+# ./setup/newuser <username> <password>
+
+
+[0x5b] Extending Samba AD schema
+================================
+
+In the OpenChange source directory, run the following command to extend
+Samba4 AD. This script will add necessary schema and attributes to run
+OpenChange Server
+
+# ./setup/openchange_provision
+
+[0x5c] Extending Samba AD users
+===============================
+
+Finally running OpenChange server for a given user implies it belongs
+to the "Exchange Organization". The openchange_newuser script will
+extend existing user records and add attributes needed by OpenChange
+
+# ./setup/openchange_newuser --create <username>
+
+Users created with this script are enabled by default. You can
+enable/disable these users at any time by running:
+
+# ./setup/openchange_newuser --enable <username>
+# ./setup/openchange_newuser --disable <username>
+
+
+[0x5c] Setting smb.conf
+=======================
+
+In order to run OpenChange server, you need to set up additional
+parameters in the [global] section of smb.conf. OpenChange server
+being part of mapiproxy, detailed and up to date information can be
+found at the following address:
+
+http://mapiproxy.openchange.org
+
+
+[0x5d] Running the Address Book Provider (EMSABP)
+=================================================
+
+The simplest is to just run "smbd", but as a developer you may find
+the following more useful:
+
+ # smbd -d3 -i -M single
+
+that means "start smbd without messages in stdout, and running a
+single process". That mode of operation makes debugging smbd with gdb
+particularly easy.
+
+
+########################
+[0x5] SWIG BINDINGS
+########################
+
+OpenChange has introduced SWIG bindings support for its MAPI
+Library. This development provides MAPI library support for different
+languages.
+
+[0x6a] Installation
+===================
+
+o Perl bindings support:
+ [*] run configure with --enable-swig-perl=yes
+ [*] make && make install
+
+Note: The compilation process requires quite some time due to the code
+generation for mapitags and mapicodes constants. If you intend to
+develop on libmapi bindings, you should comment out the following
+directives in mapi.i:
+
+ %include "swig_mapitags.h"
+ %include "swig_mapicodes.h"
+
+
+[0x6b] Sample applications
+==========================
+
+Tests applications are located in the tests directory of the
+supported swig languages.
+
+Example: swig/perl/fetchmail.pl
Added: trunk/openchange/doc/man/man1/exchange2ical.1
===================================================================
--- trunk/openchange/doc/man/man1/exchange2ical.1 (rev 0)
+++ trunk/openchange/doc/man/man1/exchange2ical.1 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,93 @@
+.\" OpenChange Project Tools Man Pages
+.\"
+.\" This manpage is Copyright (C) 2008 Brad Hards
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the OpenChange and Samba4 libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.\" Process this file with
+.\" groff -man -Tascii exchange2ical.1
+.\"
+.TH EXCHANGE2ICAL 1 2008-11-21 "OpenChange libmapi 0.8" "OpenChange Users' Manual"
+
+.SH NAME
+exchange2ical \- Convert Exchange calendar to ical file
+
+.SH SYNOPSIS
+.nf
+exchange2ical [-?|--help] [--usage] [-f|--database=STRING] [-p|--profile=STRING]
+ [-P|--password=STRING] [-d|--debuglevel=STRING] [--dump-data]
+.fi
+
+.SH DESCRIPTION
+exchange2ical provides a way to extract appointments from an Exchange calendar
+into the ical format. The ical is provided on stdout.
+
+.SH OPTIONS
+
+.TP
+.B --database
+.TP
+.B -f
+Set the path to the profile database to use
+
+.TP
+.B --profile
+.TP
+.B -p
+Set the profile to use. If no profile is specified, exchange2ical tries
+to retrieve the default profile in the database. If no default profile
+has been set, exchange2ical returns
+.B MAPI_E_NOT_FOUND .
+
+.TP
+.B --password
+.TP
+.B -P
+Specify the password for the profile to use. This can be omitted if the
+password is stored in the profile.
+
+.TP
+.B --dump-data
+Dump the hex data. This is only required for debugging or educational purposes.
+
+.TP
+.B --debuglevel
+.TP
+.B -d
+Set the debug level.
+
+.SH EXAMPLES
+
+.B Extract appointments from the Exchange calendar:
+.nf
+exchange2ical > appointments.ical
+.fi
+
+.SH REMARKS
+If you are using the default profile database path and have set a
+default profile (using
+.B mapiprofile --profile=profile_name -S
+) you do not need to specify these parameters on the command line.
+
+.SH AUTHOR
+exchange2ical was written by Julien Kerihuel <j.kerihuel at openchange dot org>
+
+This man page was written by Brad Hards <bradh at openchange dot org>
Added: trunk/openchange/doc/man/man1/exchange2mbox.1
===================================================================
--- trunk/openchange/doc/man/man1/exchange2mbox.1 (rev 0)
+++ trunk/openchange/doc/man/man1/exchange2mbox.1 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,116 @@
+.\" OpenChange Project Tools Man Pages
+.\"
+.\" This manpage is Copyright (C) 2007 Julien Kerihuel;
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the OpenChange and Samba4 libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.\" Process this file with
+.\" groff -man -Tascii exchange2mbox.1
+.\"
+.TH EXCHANGE2MBOX 1 2008-11-14 "OpenChange libmapi 0.8" "OpenChange Users' Manual"
+
+.SH NAME
+exchange2mbox \- Convert Exchange mailbox to mbox file
+
+.SH SYNOPSIS
+.nf
+exchange2mbox [-?|--help] [--usage] [-f|--database PATH] [-p|--profile PROFILE]
+ [-P|--password PASSWORD] [-m|--mbox FILENAME] [-u|--update]
+ [-d|--debuglevel LEVEL] [--dump-data]
+.fi
+
+.SH DESCRIPTION
+exchange2mbox provides a way to synchronize an Exchange mailbox with a
+mbox file. The tool is developed so it only retrieves mails not already
+stored in the message ID index database and reflects changes back to
+the Exchange server if the local message copy are deleted.
+
+.SH OPTIONS
+
+.TP
+.B --database
+.TP
+.B -f
+Set the path to the profile database to use
+
+.TP
+.B --profile
+.TP
+.B -p
+Set the profile to use. If no profile is specified, exchange2mbox try
+to retrieve the default profile in the database. If no default profile
+has been set, exchange2mbox returns
+.B MAPI_E_NOT_FOUND .
+
+.TP
+.B --password
+.TP
+.B -P
+Set the password for the profile to use. This can be omitted if the
+password is stored in the profile.
+
+.TP
+.B --mbox
+.TP
+.B -m
+Set the mbox file full path
+
+.TP
+.B --update
+.TP
+.B -u
+Synchronize the local mbox file with the remote Exchange server mailbox.
+
+.TP
+.B --dump-data
+Dump the hex data. This is only required for debugging or educational purposes.
+
+.TP
+.B --debuglevel LEVEL
+.TP
+.B -d
+Set the debug level.
+
+.SH EXAMPLES
+
+.B Create/Update the mbox file and indexes within the profile database:
+.nf
+exchange2mbox
+.fi
+
+.B Update the Exchange mailbox and indexes according to the changes made to the mbox file.
+
+.nf
+exchange2mbox -u
+.fi
+
+.SH REMARKS
+If no mbox file is specified, one will be automatically created in
+.B $(HOME)/.openchange/mbox .
+If you are using the default profile database path and have set a
+default profile (using
+.B mapiprofile --profile=profile_name -S
+) you do not need to specify these parameters on the command line.
+
+.SH AUTHOR
+Julien Kerihuel <j.kerihuel at openchange dot org>
+
+Brad Hards <bradh at openchange dot org>
Added: trunk/openchange/doc/man/man1/mapiprofile.1
===================================================================
--- trunk/openchange/doc/man/man1/mapiprofile.1 (rev 0)
+++ trunk/openchange/doc/man/man1/mapiprofile.1 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,281 @@
+.\" OpenChange Project Tools Man Pages
+.\"
+.\" This manpage is Copyright (C) 2007-2008 Julien Kerihuel;
+.\" This manpage is Copyright (C) 2008 Brad Hards;
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the OpenChange and Samba4 libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.\" Process this file with
+.\" groff -man -Tascii mapiprofile.1
+.\"
+.TH MAPIPROFILE 1 2008-12-16 "OpenChange libmapi 0.8" "OpenChange Users' Manual"
+
+.SH NAME
+mapiprofile \- administer OpenChange MAPI Profiles databases
+
+.SH SYNOPSIS
+.nf
+mapiprofile [-?GSncrl] [-?|--help] [--usage] [-L|--ldif PATH] [-G|--getdefault] [-S|--default]
+ [-n|--newdb] [-f|--database PATH] [-P|--profile PROFILE] [-I|--address xxx.xxx.xxx.xxx]
+ [-M|--workstation WORKSTATION_NAME] [-D|--domain DOMAIN] [-R|--realm REALM]
+ [-u|--username USERNAME] [-C|--langcode LANGCODE] [-s|--pattern USERNAME]
+ [-p|--password PASSWORD] [--nopass] [-c|--create] [-r|--delete] [-R|--rename STRING]
+ [-l|--list] [--listlangs] [--dump] [-a|--attr VALUE] [--dump-data] [-d|--debuglevel LEVEL]
+ [--getfqdn]
+.fi
+
+.SH DESCRIPTION
+mapiprofile is a command line tool designed to provide administrative
+support for OpenChange MAPI profiles. A profile in this context represents a
+single user's connection to a server. It can be thought of as a user's account
+information stored on the client side. Most OpenChange utilities make use of
+the profile information stored in the local profile database, often by referring
+to the name of the profile. In addition, because most users only have a single
+account, it is possible to designate one profile as the default profile. If a
+profile is not specified, other utilities will use the default profile (if any)
+to establish a connection.
+
+mapiprofile is designed so it also provides sample code for developers interested in
+adding OpenChange MAPI profile support to their applications.
+
+.SH COMMANDS
+
+.TP
+.B --newdb
+.TP
+.B -n
+Create a new database.
+
+.TP
+.B --create
+.TP
+.B -c
+Create a new profile in the database.
+
+.TP
+.B --delete
+.TP
+.B -r
+Delete a profile from the database.
+
+.TP
+.B --rename PROFILE
+.TP
+.B -R
+Rename a profile in the database
+
+.TP
+.B --default
+.TP
+.B -S
+Set the default profile in the database.
+
+.TP
+.B --getdefault
+.TP
+.B -G
+Get the default profile name from the database.
+
+.TP
+.B --dump
+Display information about a specific profile from information stored in the database.
+
+.TP
+.B --list
+.TP
+.B -l
+List existing profiles in the database.
+
+.TP
+.B --listlangs
+.TP
+.B -l
+List the available languages. These can be used to specify the
+language name (--language) when creating a profile.
+
+
+
+.SH OPTIONS
+
+.TP
+.B --database DATABASE
+.TP
+.B -f
+Path to the profile database. If no path database is specified then the default one will be used
+.B $HOME/.openchange/profiles.ldb
+
+.TP
+.B --ldif LDIF
+.TP
+.B -L
+Path to the ldif files. If no ldif directory is specified then the default one set at compilation time will be used. This option is only used when creating a new profile database.
+
+.TP
+.B --profile PROFILE
+.TP
+.B -p
+Set the profile name to use (e.g. the profile to create or delete, or to dump information about).
+
+.TP
+.B --address IP_ADDR|FQDN
+.TP
+.B -I
+Set the Exchange server IP address or fully qualified domain name.
+
+.TP
+.B --workstation WORKSTATION
+.TP
+.B -M
+Sets the local computer name.
+
+.TP
+.B --domain DOMAIN
+.TP
+.B -D
+Set the Windows domain name.
+
+.TP
+.B --realm REALM
+.TP
+.B -R
+Set the Windows realm
+
+.TP
+.B --username
+.TP
+.B -u
+Set the username to use to log on the Exchange server.
+
+.TP
+.B --password
+.TP
+.B -p
+Set the password corresponding to the username described above.
+
+.TP
+.B --langcode
+.TP
+.B -C
+Specify the language to use with the account. This can be specified
+as a code (in hexadecimal) or as a name. When specifying the name,
+you use the name of the language, and the location (if any), separated
+by underscores (e.g. English_United_States). See the --listlangs option for
+how to obtain the full list of languages. The default language code is 0x0409,
+for US English.
+
+.TP
+.B --pattern
+.TP
+.B -s
+Set a username string pattern mapiprofile should use rather than the
+default username. This option is used during mapi profile creation.
+
+.TP
+.B --nopass
+Do not save password in the profile.
+
+.TP
+.B --attr VALUE
+.TP
+.B -a
+Print an attribute value.
+
+.TP
+.B --dump-data
+Dump the hex data.
+
+.TP
+.B --debuglevel LEVEL
+.TP
+.B -d
+Set the debug level.
+
+.TP
+.B --getfqdn
+Returns the DNS fully qualified domain name of the NSPI server matching the legacyDN.
+
+.SH EXAMPLES
+
+.B Create a blank MAPI profile database:
+.nf
+mapiprofile --database=/tmp/profiles2.ldb --ldif=/usr/local/samba/share/setup --newdb
+.fi
+
+.B Create a new profile using NTLMSSP authentication:
+.nf
+mapiprofile --database=/tmp/profiles.ldb --profile=jkerihuel
+ --username=jkerihuel --password=secret --language=0x040C
+ --address=192.168.194.22 --workstation=LOCALHOST --domain=OPENCHANGE
+ --create
+Profile jkerihuel completed and added to database /tmp/profiles.ldb. Note
+that this account will use French.
+.fi
+
+.B Create a new profile using Kerberos authentication:
+.nf
+mapiprofile --database=/tmp/profiles.ldb --profile=jkerihuel
+ --username=jkerihuel --password=secret --language=0x040C
+ --address=exchange.openchange.local --domain=OPENCHANGE
+ --realm=OPENCHANGE.LOCAL --create
+.fi
+
+
+.B Delete a profile:
+.nf
+mapiprofile --database=/tmp/profiles.ldb --profile=jkerihuel --delete
+Profile jkerihuel deleted from database /tmp/profiles.ldb
+.fi
+
+.B List profiles:
+.nf
+mapiprofile --database=/tmp/profiles.ldb --list
+We have 2 profiles in the database:
+ Profile = exchange-2000
+ Profile = jkerihuel
+.fi
+
+.B Dump a profile:
+.nf
+mapiprofile --database=/tmp/profiles.ldb --profile=jkerihuel --dump
+Profile: jkerihuel
+ username == jkerihuel
+ password == secret
+ mailbox == /o=First Organization/ou=First Administrative Group/cn=Recipients/cn=jkerihuel
+ workstation == LOCALHOST
+ domain == OPENCHANGE
+ server == exchange.openchange.local
+.fi
+
+.B Dump profile attribute:
+.nf
+mapiprofile --database=/tmp/profiles.ldb --profile=jkerihuel --attr=HomeMDB
+Profile jkerihuel: HomeMDB = /o=First Organization/ou=First Administrative Group/cn=Configuration/cn=Servers/cn=EXCHANGE2000
+.fi
+
+.SH AUTHOR
+Julien Kerihuel <j.kerihuel at openchange dot org>
+
+Brad Hards <bradh at openchange dot org>
+
+.SH "SEE ALSO"
+The codes for various languages can be found in many places, including
+the Windows Language Code Identifier (LCID) Reference.
+
Added: trunk/openchange/doc/man/man1/mapitest.1
===================================================================
--- trunk/openchange/doc/man/man1/mapitest.1 (rev 0)
+++ trunk/openchange/doc/man/man1/mapitest.1 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,146 @@
+.\" OpenChange Project Tools Man Pages
+.\"
+.\" This manpage is Copyright (C) 2008 Brad Hards
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the OpenChange and Samba4 libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.\" Process this file with
+.\" groff -man -Tascii mapitest.1
+.\"
+.TH MAPITEST 1 2008-11-21 "OpenChange libmapi 0.8" "OpenChange Users' Manual"
+
+.SH NAME
+mapitest \- OpenChange torture test utility
+
+.SH SYNOPSIS
+.nf
+mapitest [-?|--help] [--usage] [-f|--database=STRING] [-p|--profile=STRING]
+ [-u|--username=STRING] [-p|--password=STRING] [--confidential] [--color]
+ [-o|--outfile=STRING] [--mapi-calls=STRING] [--list-all] [--no-server]
+ [--dump-data] [-d|--debuglevel=STRING]
+.fi
+
+.SH DESCRIPTION
+mapitest is a test harness / utility used for verifying correct operation
+of various ExchangeRPC calls / MAPI functions provided by the OpenChange
+MAPI libraries.
+
+mapitest is not normally required by users, but you may be asked to provide
+the output of mapitest for some kinds of bug investigations.
+
+Note that mapitest performs a lot of transactions, including deleting folders
+and messages. Unless you're very familiar with mapitest, we recommend only
+using it with a test account.
+
+.SH OPTIONS
+
+.TP
+.B --database
+.TP
+.B -f
+Set the path to the profile database to use
+
+.TP
+.B --profile
+.TP
+.B -p
+Set the profile to use. If no profile is specified, mapitest tries
+to retrieve the default profile in the database. If no default profile
+has been set, mapitest returns
+.B MAPI_E_NOT_FOUND .
+
+.TP
+.B --username
+.TP
+.B -u
+Set the username of the account to use.
+
+.TP
+.B --password
+.TP
+.B -P
+Specify the password for the profile to use. This can be omitted if the
+password is stored in the profile.
+
+.TP
+.B --confidential
+Remove any sensitive data from the report.
+
+.TP
+.B --color
+Use colors to indicate the results of each operation.
+
+.TP
+.B --outfile
+.TP
+.B -o
+Redirect the output of the tests to a file. The filename must be specified
+as the argument to this option.
+
+.TP
+.B --mapi-calls
+Run a specific test. The name of the test must be specified as the argument
+to this option. See the --list-all option to obtain the name of the test.
+This can be specified more than once in order to run a subset of tests.
+
+.TP
+.B --list-all
+Provide a list of all test suites and test names, along with a description
+of the test. No tests will be run.
+
+.TP
+.B --no-server
+Only run tests that do not require a server connection. This is the default
+if a connection to the server cannot be established.
+
+.TP
+.B --dump-data
+Dump the hex data. This is only required for debugging or educational purposes.
+
+.TP
+.B --debuglevel
+.TP
+.B -d
+Set the debug level.
+
+.SH EXAMPLES
+
+.B Run all tests
+.nf
+mapitest
+.fi
+
+.B Only run two specific tests
+.nf
+mapitest --mapi-calls=NOSERVER-SROWSET --mapi-calls=OXCPRPT-GET-PROPS
+.fi
+
+.SH REMARKS
+If you are using the default profile database path and have set a
+default profile (using
+.B mapiprofile --profile=profile_name -S
+) you do not need to specify these parameters on the command line.
+
+.SH AUTHOR
+mapitest was written by Julien Kerihuel <j.kerihuel at openchange dot org>
+with contributions from other OpenChange developers.
+
+This man page was written by Brad Hards <bradh at openchange dot org>
Added: trunk/openchange/doc/man/man1/openchangeclient.1
===================================================================
--- trunk/openchange/doc/man/man1/openchangeclient.1 (rev 0)
+++ trunk/openchange/doc/man/man1/openchangeclient.1 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,562 @@
+.\" OpenChange Project Tools Man Pages
+.\"
+.\" This manpage is Copyright (C) 2007 Julien Kerihuel;
+.\" This manpage is Copyright (C) 2008 Brad Hards
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the OpenChange and Samba4 libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.\" Process this file with
+.\" groff -man -Tascii openchangeclient.1
+.\"
+.TH OPENCHANGECLIENT 1 2008-11-24 "OpenChange libmapi 0.8" "OpenChange Users' Manual"
+
+.SH NAME
+openchangeclient \- MAPI command line messaging tool
+
+.SH SYNOPSIS
+.nf
+openchangeclient [-?|--help] [--usage] [-f|--database=STRING] [--pf]
+ [-p|--profile=STRING] [-P|--password=STRING] [-S|--sendmail]
+ [--sendappointment] [--sendcontact] [--sendtask] [--sendnote]
+ [-F|--fetchmail] [-G|--storemail=STRING] [-i|--fetch-items=STRING]
+ [--freebusy=STRING] [--force] [--delete=STRING] [-u|--update=STRING]
+ [-m|--mailbox] [-D|--deletemail] [-A|--attachments=STRING]
+ [-I|--html-inline=STRING] [-W|--html-file=STRING] [-t|--to=STRING]
+ [-c|--cc=STRING] [-b|--bcc=STRING] [-s|--subject=STRING] [-B|--body=STRING]
+ [--location=STRING] [--label=STRING] [--dtstart=STRING] [--dtend=STRING]
+ [--busystatus=STRING] [--taskstatus=STRING]
+ [--importance=STRING] [--email=STRING] [--fullname=STRING] [--cardname=STRING]
+ [--color=STRING] [--notifications] [--folder=STRING] [--mkdir] [--rmdir]
+ [--userlist] [--folder-name=STRING] [--folder-comment=STRING]
+ [-d|--debuglevel=STRING] [--dump-data] [--private]
+ [--ocpf-file=STRING] [--ocpf-dump=STRING] [--ocpf-syntax] [--ocpf-sender]
+.fi
+
+
+.SH DESCRIPTION
+openchangeclient is a MAPI command line tool designed to facilitate
+mail send, receive and delete operations using the MAPI protocol. It
+also provides operations on tasks, contacts (address book) and calendar
+operations.
+
+.SH COMMANDS
+
+.TP
+.B --fetchmail
+.TP
+.B -F
+Fetch Exchange user mails from the inbox and display general information from
+the mails on the standard output.
+
+.TP
+.B --storemail=DIRECTORY
+.TP
+.B -G
+Store mail attachments to the local filesystem in the specified directory. This
+is the normal way to retrieve attachments.
+
+.TP
+.B --fetch-items=STRING
+.TP
+.B -i
+Retrieve specific items from Exchange default folders. Possible value
+for STRING are Mail, Appointment, Contact, Task, Note.
+
+.TP
+.B --mkdir
+Create a folder within the mailbox or public folders store
+hierarchy. This command requires that the --folder-name option
+be used to specify the name of the folder to create.
+
+.TP
+.B --rmdir
+Deletes a folder within the mailbox or public folders store
+hierarchy. This option requires that the --folder-name option
+be used to specify the name of the folder to delete.
+
+.TP
+.B --mailbox
+.TP
+.B -m
+Display the user mailbox folder hierarchy with folder names, folder
+comments, the folder type, number of unread items in the folder
+and total number of items in the folder.
+
+.TP
+.B --notifications
+Monitor NEWMAIL notifications in the Inbox folder and display summary
+on standard output.
+
+.TP
+.B --sendmail
+.TP
+.B -S
+Send a mail to a user belonging to the Exchange organization. This
+requires specifying one or more recipients (see the --to, --cc and
+--bcc options), a subject (see the --subject option) and a body
+(see the --body, --html-file and --html-inline options).
+
+.TP
+.B --sendappointment
+Create an appointment in the default calendar folder.
+
+.TP
+.B --sendcontact
+Create a contact in the default contact folder.
+
+.TP
+.B --sendtask
+Create a task in the default task folder.
+
+.TP
+.B --sendnote
+Create a note in the default notes folder.
+
+.TP
+.B --deletemail
+.TP
+.B -D
+Delete a mail from the exchange user mailbox. This requires
+use of the --subject option to specify the mail to be deleted.
+
+.TP
+.B --userlist
+Display the users listed in the address book.
+
+.TP
+.B --delete=STRING
+Delete a specified item from the store by ID number.
+
+.TP
+.B --ocpf-dump=STRING
+Download a message (specified by the argument, which must be
+the folder ID and unique message ID for the message) as OCPF format.
+The message will be saved to a file given by the message ID, followed
+by a suffix of .ocpf
+
+See the separate (HTML) documentation for libocpf for more information
+on the OCPF format.
+
+.TP
+.B --ocpf-sender
+Send a message given in OCPF format to the server. This requires
+use of the
+.B --ocpf-file
+option to specify the file to load from.
+
+See the separate (HTML) documentation for libocpf for more information
+on the OCPF format.
+
+.TP
+.B --ocpf-syntax
+Check the syntax of an OCPF file. This does not perform any network
+operations. This requires use of the
+.B --ocpf-file
+option to specify
+the file to load from.
+
+See the separate (HTML) documentation for libocpf for more information
+on the OCPF format.
+
+.SH OPTIONS
+
+.TP
+.B --database=DATABASE
+.TP
+.B -f
+Set the MAPI profile database. If no database is specified, then openchangeclient tries to load the default one:
+.B $HOME/.openchange/profiles.ldb
+
+.TP
+.B --profile=PROFILE
+.TP
+.B -p
+Set the profile to use. If a profile is not specified, and one of the
+profiles has been set as the default in the profile database
+(for example, using mapiprofile -S), then that default profile will be used.
+
+.TP
+.B --password
+.TP
+.B -P
+Specify the password for the profile to be used. This can be omitted if the
+password is stored in the profile.
+
+.TP
+.B --pf
+Perform operations against the Public Folders store, rather than the normal
+operations against a user's private folders.
+
+.TP
+.B --folder
+Specify the folder name we want to work with want to open. This option
+is mandatory for public folders, but can also be used to open specific
+folders in the mailbox store.
+
+.TP
+.B --attachments="ATTACHMENT1;ATTACHMENT2"
+.TP
+.B -A
+Set attachments to send when sending a mail. Attached filenames need
+to be separated with
+.B semi-colons
+as specified in the description above. This is only meaningful with
+.B --sendmail
+
+.TP
+.B --subject=STRING
+.TP
+.B -s
+Specify the mail subject. If no subject is specified, the mail subject will be empty.
+This is only meaningful with
+.B --sendmail
+
+.TP
+.B --body=STRING
+.TP
+.B -B
+Set the body of the mail to be the UTF8 text only content specified on the command
+line. This is only meaningful with
+.B --sendmail
+
+.TP
+.B --html-inline=STRING
+.TP
+.B -I
+Set the body of the mail to be the HTML content specified on command line. This is
+only meaningful with
+.B --sendmail
+
+.TP
+.B --html-file=FILENAME
+.TP
+.B -W
+Set the body of the mail to be the content of the specified file. This is only
+meaningful with
+.B --sendmail
+
+.TP
+.B --to="USERNAME1,USERNAME2"
+.TP
+.B -t
+Specify
+.B To
+recipients for the mail. Usernames need to be separated with commas
+as specified in the example above. This is only meaningful with
+.B --sendmail
+
+.TP
+.B --cc="USERNAME1,USERNAME2"
+.TP
+.B -c
+Specify
+.B Cc
+recipients for the mail. Usernames need to be separated with commas
+as specified in the example above. This is only meaningful with
+.B --sendmail
+
+.TP
+.B --bcc="USERNAME1,USERNAME2"
+.TP
+.B -b
+Specify
+.B Bcc
+recipients for the mail. Usernames need to be separated with commas
+as specified in the example above. This is only meaningful with
+.B --sendmail
+
+.TP
+.B --location=STRING
+Specify the appointment location. This is only meaningful with
+.B --sendappointment
+
+.TP
+.B --dtstart=STRING
+Specify the start date of an event. The following date format needs to be used:
+.B "%Y-%m-%d %H:%M:%S"
+e.g: 2007-06-01 14:59:00. This is only meaningful with
+.B --sendappointment
+and
+.B --sendtask
+
+.TP
+.B --dtend=STRING
+Specify either the end date or due date of an event. The following date
+format needs to be used:
+.B "%Y-%m-%d %H:%M:%S"
+e.g: 2007-06-01 14:59:00
+When no
+.B dtend
+parameter is specified, default value is set to
+.B dtstart
+This is only meaningful with
+.B --sendappointment
+and
+.B --sendtask
+
+.TP
+.B --force
+Add appointment to the calendar, even if it would overlap with
+an existing appointment. This is only meaningful with
+.B --sendappointment
+
+.TP
+.B --private
+Mark the appointment as private event. This is only meaningful with
+.B --sendappointment
+
+.TP
+.B --busystatus=STRING
+Set the busy status of an appointment. Possible values are FREE,
+TENTATIVE, BUSY or OUTOFOFFICE. This is only meaningful with
+.B --sendappointment
+
+.TP
+.B --label=STRING
+Set the type of appointment. Possible values are NONE, IMPORTANT,
+BUSINESS, PERSONAL, VACATION, MUST_ATTEND, TRAVEL_REQUIRED,
+NEEDS_PREPARATION, BIRTHDAY, ANNIVERSARY and PHONE_CALL.
+This is only meaningful with
+.B --sendappointment
+
+.TP
+.B --taskstatus=STRING
+Set the status of a task. Possible values are NOTSTARTED, PROGRESS,
+COMPLETED, WAITING, DEFERRED. This is only meaningful with
+.B --sendtask
+
+.TP
+.B --fullname=STRING
+Set the full name in a contact message. This is only meaningful with
+.B --sendcontact
+
+.TP
+.B --cardname=STRING
+Set the card name of a task or contact message. This is only meaningful with
+.B --sendcontact
+or
+.B --sendtask
+
+.TP
+.B --email=STRING
+Set the email address in a contact message. This is only meaningful with
+.B --sendcontact
+
+.TP
+.B --importance=STRING
+Set the relative importance of a task. Possible values are LOW, NORMAL
+and HIGH. This is only meaningful with
+.B --sendtask
+
+.TP
+.B --color=STRING
+Set the color of the note. The default color is Yellow. Other options
+are Blue, Green, Pink and White. This is only meaningful with
+.B --sendnote
+
+.TP
+.B --folder-name=STRING
+Set the folder name to create. This is only meaningful with
+.B --mkdir
+or
+.B --rmdir
+
+.TP
+.B --folder-comment=STRING
+Set the folder comment. This is only meaningful with
+.B --mkdir
+
+.TP
+.B --update=STRING
+.TP
+.B -u
+Change (update) an existing item, rather than creating a new one. This
+is only meaningful with
+.B --sendtask
+,
+.B --sendnote
+,
+.B --sendappointment
+and
+.B --sendcontact
+
+.TP
+.B --ocpf-file=STRING
+Specify the file to load OCPF data from. This is only meaningful with
+.B --ocpf-sender
+and
+.B --ocpf-syntax
+
+.TP
+.B --dump-data
+Display raw format data associated with the operation. You normally only
+need this when debugging.
+
+.TP
+.B --debug-level=LEVEL
+Display debugging information at the specified level (or higher). Level
+10 is a lot of debug information.
+
+
+.SH EXAMPLES
+
+.B Fetching emails:
+.nf
+openchangeclient --database=/tmp/profiles.ldb --profile=2000 --fetchmail
+.fi
+
+.B Fetch emails and store attachments:
+.nf
+openchangeclient --database=/tmp/profiles.ldb --profile=2000 --fetchmail --storemail=test
+.fi
+
+All attachments from any mails will be stored in the test
+directory. If the specified directory does not exist, it will
+automatically be created. Note that if the attachment name
+is not unique amongst all emails, some attachments may be
+overwritten.
+
+
+.B Send a basic email:
+.nf
+openchangeclient --database=/tmp/profiles.ldb --profile=2000
+ --to="Adm,jker" --cc=Paul --bcc=Bill
+ --subject="It is working"
+ --body="This is a sample body" --sendmail
+.fi
+
+A mail with UTF8 (text only) content will be sent with the following recipients:
+
+to = Administrator and jkerihuel
+
+cc = Paul
+
+bcc = Bill
+
+
+.B Send an inline HTML email:
+.nf
+openchangeclient --database=/tmp/profiles.ldb --profile=2000
+ --to=Adm --subject="Inline HTML sample email"
+ --html-inline="<body bgcolor=yellow><h1>My first HTML email</h1></body>"
+ --sendmail
+.fi
+
+Administrator will receive a mail with HTML body - yellow background and a title.
+
+
+.B Send a HTML mail using a file:
+.nf
+openchangeclient --database=/tmp/profiles.ldb --profile=2000
+ --to=Adm --subject="HTML file email"
+ --html-file=/tmp/myfile.html
+ --sendmail
+.fi
+
+The content of /tmp/myfile.html will be used to fill the HTML body. If
+the HTML file exceed a fixed size (0x4000 bytes), then PR_HTML content
+will be sent using MAPI streams.
+
+
+.B Send email with attachments:
+.nf
+openchangeclient --database=/tmp/profiles.ldb --profile=2000
+ --to=Adm --subject="Attachments"
+ --attachments="/tmp/file1.jpg;/tmp/file2.jpg;tmp/file2.jpg"
+ --body="These are sample attachments"
+ --sendmail
+.fi
+
+The example above will send a UTF8 body mail to Administrator and
+attach file1,jpg, file2.jpg and file3.jpg to the email.
+
+.B Display the users in the address book
+.nf
+openchangeclient --userlist
+.fi
+
+.B Fetch calendar items:
+.nf
+openchangeclient --fetch-items=Appointment
+.fi
+
+
+.B Fetch contact items:
+.nf
+openchangeclient --fetch-items=Contact
+.fi
+
+
+.B Fetch task items:
+.nf
+openchangeclient --fetch-items=Task
+.fi
+
+
+.B Create appointment:
+.nf
+openchangeclient --sendappointment --dtstart="2007-06-01 22:00:00" \\
+ --dtend="2007-06-01 22:35:00" \\
+ --busystatus=FREE \\
+ --location="Home" \\
+ --subject="Check the Junk folder"
+.fi
+
+
+.B Create Task:
+.nf
+openchangeclient --sendtask --dtstart="2008-11-01 18:00:00" \\
+ --cardname="openchangeclient" --importance=HIGH \\
+ --taskstatus=COMPLETED --body="my new task"
+.fi
+
+
+.B Create contact:
+.nf
+openchangeclient --sendcontact --cardname="openchangeclient" \\
+ --fullname="OpenChange Client 3rd" \\
+ --email="openchangeclient at nonexistentdomain.com"
+.fi
+
+.B Create folder:
+.nf
+openchangeclient --mkdir --folder-name="openchange" \\
+ --folder-comment="comment"
+.fi
+
+This example will create a generic folder named openchange under the
+Inbox folder.
+
+.B Delete folder:
+.nf
+openchangeclient --rmdir --folder-name="openchange"
+.fi
+
+This example will delete the generic folder named openchange under
+Inbox folder.
+
+.B List Mailbox hierarchy:
+.nf
+openchangeclient --mailbox
+.fi
+
+.SH AUTHOR
+Julien Kerihuel <j.kerihuel at openchange dot org>
Added: trunk/openchange/doc/man/man1/openchangepfadmin.1
===================================================================
--- trunk/openchange/doc/man/man1/openchangepfadmin.1 (rev 0)
+++ trunk/openchange/doc/man/man1/openchangepfadmin.1 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,267 @@
+.\" OpenChange Project Tools Man Pages
+.\"
+.\" This manpage is Copyright (C) 2007 Julien Kerihuel;
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the OpenChange and Samba4 libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.\" Process this file with
+.\" groff -man -Tascii openchangepfadmin.1
+.\"
+.TH OPENCHANGEPFADMIN 1 2007-11-14 "OpenChange libmapi 0.8" "OpenChange Users' Manual"
+
+.SH NAME
+openchangepfadmin \- Exchange users and Public Folder administration tool
+
+.SH SYNOPSIS
+.nf
+openchangepfadmin [-?] [-?|--help] [--usage] [-f|--database PATH] [-p|--profile PROFILE]
+ [-P|--password PASSWORD] [--apassword=PASSWORD] [--adesc=DESCRIPTION] [--acomment=COMMENT]
+ [--afullname=NAME] [--list] [--mkdir] [--rmdir] [--comment=COMMENT] [--dirclass=CLASS]
+ [--adduser=USERNAME] [--rmuser=USERNAME] [--addright=RIGHT] [--rmright] [--modright=RIGHT]
+ [--debuglevel=LEVEL] [--dump-data] [--folder=FOLDER] [--username=USERNAME]
+.fi
+
+.SH DESCRIPTION
+openchangepfadmin is a administrative command line tool designed to
+facilitate user management related operations (create, delete, modify)
+on a remote Exchange server and manage public folder store and
+permissions.
+
+.SH COMMANDS
+
+.TP
+.B --adduser=USERNAME
+Create a Exchange user with the username specified by USERNAME
+
+.TP
+.B --rmuser=USERNAME
+Delete the Exchange user account specified by USERNAME
+
+.TP
+.B --list
+List Public Folder hierarchy (IPM_SUBTREE)
+
+.TP
+.B --mkdir
+Create a folder in the Public Folder store
+
+.TP
+.B --rmdir
+Delete a folder in the Public Folder store
+
+.TP
+.B --addright=RIGHT
+Add permission and roles for a user on a Public Folder directory.
+
+.TP
+.B --modright=RIGHT
+Modify permissions and roles for a user on a Public Folder directory
+
+.TP
+.B --rmright
+Delete permissions and roles for a specific user
+
+
+.SH OPTIONS
+
+.TP
+.B --database=DATABASE
+.TP
+.B -f
+Set the MAPI profile database. If no database is specified, then
+openchangeclient tries to load the default one:
+.B $HOME/.openchange/profiles.ldb
+
+.TP
+.B --profile=PROFILE
+.TP
+.B -p
+Set the profile to use. If a profile is not specified, and one of the
+profiles has been set as the default in the profile database (for
+example, using mapiprofile -S), then that default profile will be
+used.
+
+.TP
+.B --password
+.TP
+.B -P
+Set the password for the profile to use. This can be omitted if the
+password is stored in the profile.
+
+.TP
+.B --apassword=PASSWORD
+Define the password to set for the user specified with --adduser. If
+no password is explicitely supplied, openchangepfadmin will arbitrary
+set a random one.
+
+.TP
+.B --adesc=DESCRIPTION
+This command can only be used with --adduser and specifies a
+description for this account
+
+.TP
+.B --acomment=COMMENT
+This command can only be used with --adduser and specifies a comment
+for this account.
+
+.TP
+.B --afullname=NAME
+This command can only be used with --adduser and specifies the user
+full name for this account.
+
+.TP
+.B --comment=COMMENT
+This command can only be used with --mkdir and specifies a comment for
+the folder.
+
+.TP
+.B --dirclass=CLASS
+This command can only be used with --mkdir and specifies the container
+class of the directory we want to create. Possible values are:
+IPF.Appointment, IPF.Contact, IPF.Journal, IPF.Note, IPF.StickyNote,
+IPF.Task, IPF.Post
+
+.TP
+.B --folder=FOLDER
+This command can only be used with --addright, --modright and
+--rmright. Specify the folder where permissions and roles have to be
+changed.
+
+.TP
+.B --username=USERNAME
+This command can only be used with --addright, --modright and
+--rmright. Specify the username we want to change permissions and
+roles for.
+
+.TP
+.B --dump-data
+Dump the hex data. This is only required for debugging or educational purposes.
+
+.TP
+.B --debuglevel LEVEL
+.TP
+.B -d
+Set the debug level.
+
+.SH EXAMPLES
+
+.B Creating user
+.nf
+openchangepfadmin --adduser=linuxowner --apassword=linuxowner \\
+ --adesc="Linux Owner Test account" \\
+ --afullname="Linux Owner"
+ mapiadmin_user_add : MAPI_E_SUCCESS (0x0)
+username: linuxowner
+password: linuxowner
+.fi
+
+Creates a user account with username and password set to linuxowner.
+
+.B Deleting user:
+.nf
+openchangepfadmin --rmuser=linuxowner
+ mapiadmin_user_del : MAPI_E_SUCCESS (0x0)
+.fi
+
+.B Create Public Folder:
+.nf
+openchangepfadmin --mkdir --folder=public_events --dirclass=IPF.Appointment
+.fi
+
+Creates a folder in the Public Folder store named public_events with a
+container class set to Appointment. This folder will display calendar
+items.
+
+.B Delete Public Folder:
+.nf
+openchangepfadmin --rmdir --folder=public_events
+.fi
+
+.B List Public Folder hierarchy:
+.nf
+openchangepfadmin --list
+.fi
+
+.B Add Permission:
+.nf
+openchangepfadmin --username=linuxowner --folder=public_events \\
+ --addright=RoleOwner
+Permission RoleOwner added for linuxowner on folder public_events
+.fi
+
+.B Modify Permission
+.nf
+openchangepfadmin --username=Anonymous --folder=public_events \\
+ --modright=RoleNone
+Permission changed to RoleNone for Anonymous on folder appointment
+.fi
+
+Note that you can only change permissions for a user already listed in
+the ACL table.
+
+.SH NOTE
+Permissions and Roles possible values are:
+.IP "\(bu" 2
+RightsNone
+.IP "\(bu" 2
+RightsReadItems
+.IP "\(bu" 2
+RightsCreateItems
+.IP "\(bu" 2
+RightsEditOwn
+.IP "\(bu" 2
+RightsDeleteOwn
+.IP "\(bu" 2
+RightsEditAll
+.IP "\(bu" 2
+RightsDeleteAll
+.IP "\(bu" 2
+RightsCreateSubfolders
+.IP "\(bu" 2
+RightsFolderOwner
+.IP "\(bu" 2
+RightsFolderContact
+.IP "\(bu" 2
+RoleNone
+.IP "\(bu" 2
+RoleReviewer
+.IP "\(bu" 2
+RoleContributor
+.IP "\(bu" 2
+RoleNoneditingAuthor
+.IP "\(bu" 2
+RoleAuthor
+.IP "\(bu" 2
+RoleEditor
+.IP "\(bu" 2
+RolePublishAuthor
+.IP "\(bu" 2
+RolePublishEditor
+.IP "\(bu" 2
+RightsAll
+.IP "\(bu" 2
+RoleOwner
+
+.SH SEE ALSO
+AddUserPermission, ModifyUserPermission, RemoveUserPermission
+
+.SH AUTHOR
+Julien Kerihuel <j.kerihuel at openchange dot org>
Added: trunk/openchange/doc/man/man3/mapidump.3
===================================================================
--- trunk/openchange/doc/man/man3/mapidump.3 (rev 0)
+++ trunk/openchange/doc/man/man3/mapidump.3 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,47 @@
+.\" OpenChange Project Libraries Man Pages
+.\"
+.\" This manpage is Copyright (C) 2007 Julien Kerihuel;
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the OpenChange and Samba4 libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.\" Process this file with
+.\" groff -man -Tascii mapidump.3
+.\"
+.TH MAPIDUMP 3 2007-04-23 "OpenChange libmapi 0.2" "OpenChange Programmer's Manual"
+.SH NAME
+mapidump API \- dump MAPI data and object on stdout
+.SH SYNOPSIS
+.nf
+.B #include <libmapi/libmapi.h>
+.sp
+.BI "void mapidump_SPropValue(struct SPropValue " lpProp ", const char *" sep ");"
+.BI "void mapidump_SPropTagArray(struct SPropTagArray *" proptags ");"
+.BI "void mapidump_SRow(struct SRow *" aRow ", const char *" sep ");"
+.BI "void mapidump_Recipients(const char **" usernames ", struct SRowSet *" rowset ", struct FlagList *" flaglist ");"
+.BI "void mapidump_message(struct mapi_SPropValue_array *" properties ");"
+.fi
+.SH DESCRIPTION
+These functions dumps MAPI data structures and high level objects on stdout. The
+.IR sep
+parameters describes a parameter used in output format.
+
+.SH AUTHOR
+Julien Kerihuel <j.kerihuel at openchange dot org>
Added: trunk/openchange/exchange.idl
===================================================================
--- trunk/openchange/exchange.idl (rev 0)
+++ trunk/openchange/exchange.idl 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,3699 @@
+#include "idl_types.h"
+
+cpp_quote("#include <gen_ndr/ndr_misc.h>")
+
+/*
+ http://support.microsoft.com/default.aspx?scid=KB;en-us;q159298
+ Any UUID starting with:
+ A4 - store
+ F5 - directory
+ */
+
+[
+ uuid("99e64010-b032-11d0-97a4-00c04fd6551d"),
+ pointer_default(unique),
+ version(3.0)
+] interface exchange_store_admin3
+{
+ void ec_store_admin3_dummy();
+}
+
+
+[
+ uuid("89742ace-a9ed-11cf-9c0c-08002be7ae86"),
+ pointer_default(unique),
+ version(2.0)
+] interface exchange_store_admin2
+{
+ void ec_store_admin2_dummy();
+}
+
+[
+ uuid("a4f1db00-ca47-1067-b31e-00dd010662da"),
+ pointer_default(unique),
+ version(1.0)
+] interface exchange_store_admin1
+{
+ void ec_store_admin1_dummy();
+}
+
+
+[
+ uuid("1544f5e0-613c-11d1-93df-00c04fd7bd09"),
+ endpoint("ncacn_np:[\\pipe\\lsass]","ncacn_np:[\\pipe\\protected_storage]","ncacn_ip_tcp:[]"),
+ pointer_default(unique),
+ version(1.0),
+ helpstring("Exchange 2003 Directory Request For Response")
+] interface exchange_ds_rfr
+{
+
+#include "mapitags_enum.h"
+#include "mapicodes_enum.h"
+
+ /*****************/
+ /* Function 0x00 */
+ MAPISTATUS RfrGetNewDSA(
+ [in] uint32 ulFlags,
+ [in,string,charset(DOS)] uint8 *pUserDN,
+ [in,out,unique,string,charset(DOS)] uint8 **ppszUnused,
+ [in,out,unique,string,charset(DOS)] uint8 **ppszServer
+ );
+
+ /*****************/
+ /* Function 0x01 */
+ MAPISTATUS RfrGetFQDNFromLegacyDN(
+ [in] uint32 ulFlags,
+ [in,range(10,1024)] uint32 cbMailboxServerDN,
+ [in,string,charset(DOS),size_is(cbMailboxServerDN)] uint8 *szMailboxServerDN,
+ [out,ref,string,charset(DOS)] uint8 **ppszServerFQDN
+ );
+}
+
+[
+ uuid("f930c514-1215-11d3-99a5-00a0c9b61b04"),
+ helpstring("System Attendant Cluster Interface"),
+ pointer_default(unique),
+ version(1.0)
+] interface exchange_sysatt_cluster
+{
+ void sysatt_cluster_dummy();
+}
+
+/*
+[83d72bf0-0d89-11ce-b13f-00aa003bac6c] MS Exchange
+System Attendant Private Interface
+*/
+
+[
+ uuid("469d6ec0-0d87-11ce-b13f-00aa003bac6c"),
+ pointer_default(unique),
+ helpstring("Exchange 5.5 System Attendant Request for Response")
+] interface exchange_system_attendant
+{
+ void sysatt_dummy();
+}
+
+[
+ uuid("9e8ee830-4559-11ce-979b-00aa005ffebe"),
+ pointer_default(unique),
+ version(2.0),
+ helpstring("Exchange 5.5 MTA")
+] interface exchange_mta
+{
+ /*****************/
+ /* Function 0x00 */
+ void MtaBind();
+
+ /*****************/
+ /* Function 0x01 */
+ void MtaBindAck();
+}
+
+[
+ uuid("f5cc59b4-4264-101a-8c59-08002b2f8426"),
+ pointer_default(unique),
+ version(21.0),
+ helpstring("Exchange 5.5 DRS")
+] interface exchange_drs
+{
+ /*****************/
+ /* Function 0x00 */
+ void ds_abandon();
+
+ /*****************/
+ /* Function 0x01 */
+ void ds_add_entry();
+
+ void ds_bind();
+ void ds_compare();
+ void ds_list();
+ void ds_modify_entry();
+ void ds_modify_rdn();
+ void ds_read();
+ void ds_receive_result();
+ void ds_remove_entry();
+ void ds_search();
+ void ds_unbind();
+ void ds_wait();
+ void dra_replica_add();
+ void dra_replica_delete();
+ void dra_replica_synchronize();
+ void dra_reference_update();
+ void dra_authorize_replica();
+ void dra_unauthorize_replica();
+ void dra_adopt();
+ void dra_set_status();
+ void dra_modify_entry();
+ void dra_delete_subref();
+}
+
+[
+ uuid("f5cc5a7c-4264-101a-8c59-08002b2f8426"),
+ version(21.0),
+ pointer_default(unique),
+ helpstring("Exchange 5.5 XDS")
+] interface exchange_xds
+{
+ void xds_dummy();
+}
+
+[
+ uuid("38a94e72-a9bc-11d2-8faf-00c04fa378ff"),
+ pointer_default(unique),
+ version(1.0)
+] interface exchange_mta_qadmin
+{
+ void exchange_mta_qadmin();
+}
+
+
+[
+ uuid("0e4a0156-dd5d-11d2-8c2f-00c04fb6bcde"),
+ pointer_default(unique),
+ version(1.0)
+] interface exchange_store_information
+{
+ void exchange_store_information_dummy();
+}
+
+[
+ uuid("f5cc5a18-4264-101a-8c59-08002b2f8426"),
+ endpoint("ncacn_np:[\\pipe\\lsass]","ncacn_np:[\\pipe\\protected_storage]","ncacn_ip_tcp:[]"),
+ pointer_default(unique),
+ version(56.0),
+ helpstring("Exchange 5.5 Name Service Provider")
+] interface exchange_nsp
+{
+
+#define PT_UNSPECIFIED 0x0000
+#define PT_NULL 0x0001
+#define PT_I2 0x0002
+#define PT_LONG 0x0003
+#define PT_R4 0x0004
+#define PT_DOUBLE 0x0005
+#define PT_CURRENCY 0x0006
+#define PT_APPTIME 0x0007
+#define PT_ERROR 0x000a /* means the given attr contains no value */
+#define PT_BOOLEAN 0x000b
+#define PT_OBJECT 0x000d
+#define PT_I8 0x0014
+#define PT_STRING8 0x001e
+#define PT_UNICODE 0x001f
+#define PT_SYSTIME 0x0040
+#define PT_CLSID 0x0048
+#define PT_SVREID 0x00fb
+#define PT_SRESTRICT 0x00fd
+#define PT_ACTIONS 0x00fe
+#define PT_BINARY 0x0102
+/* Multi-valued properties */
+#define PT_MV_I2 0x1002
+#define PT_MV_LONG 0x1003
+#define PT_MV_R4 0x1004
+#define PT_MV_DOUBLE 0x1005
+#define PT_MV_CURRENCY 0x1006
+#define PT_MV_APPTIME 0x1007
+#define PT_MV_I8 0x1014
+#define PT_MV_STRING8 0x101e
+#define PT_MV_TSTRING 0x101e
+#define PT_MV_UNICODE 0x101f
+#define PT_MV_SYSTIME 0x1040
+#define PT_MV_CLSID 0x1048
+#define PT_MV_BINARY 0x1102
+
+ typedef [v1_enum] enum {
+ SortTypeDisplayName = 0x00000000,
+ SortTypePhoneticDisplayName = 0x00000003,
+ SortTypeDisplayName_RO = 0x000003E8,
+ SortTypeDisplayName_W = 0x000003E9
+ } TableSortOrders;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ TableSortOrders SortType;
+ uint32 ContainerID;
+ uint32 CurrentRec;
+ uint32 Delta;
+ uint32 NumPos;
+ uint32 TotalRecs;
+ uint32 CodePage;
+ uint32 TemplateLocale;
+ uint32 SortLocale;
+ } STAT;
+
+ typedef struct {
+ uint8 ab[16];
+ } FlatUID_r;
+
+ typedef struct {
+ FlatUID_r *lpguid;
+ uint32 ulReserved;
+ uint32 lID;
+ } PropertyName_r;
+
+ typedef struct {
+ [range(0,100000)] uint32 cNames;
+ [size_is(cNames)] PropertyName_r aNames[];
+ } PropertyNameSet_r;
+
+ typedef struct {
+ [range(0,100000)] uint32 cValues;
+ [string,size_is(cValues),charset(DOS)] uint8 **lppszA;
+ } StringArray_r;
+
+ typedef struct {
+ [range(0,100000)] uint32 Count;
+ [string,size_is(Count),charset(DOS)] uint8 *Strings[];
+ } StringsArray_r;
+
+ typedef struct {
+ [range(0,100000)] uint32 cValues;
+ [string,size_is(cValues),charset(UTF16)] uint16 **lppszW;
+ } WStringArray_r;
+
+ typedef struct {
+ [range(0,100000)] uint32 Count;
+ [string,size_is(Count),charset(UTF16)] uint16 *Strings[];
+ } WStringsArray_r;
+
+ typedef struct {
+ [range(0,100001)] uint32 cValues;
+ [size_is(cValues+1),length_is(cValues)] MAPITAGS aulPropTag[];
+ } SPropTagArray;
+
+ typedef [public] struct {
+ [range(0,2097152)] uint32 cb;
+ [size_is(cb)] uint8 *lpb;
+ } Binary_r;
+
+ typedef [public] struct {
+ uint32 dwLowDateTime;
+ uint32 dwHighDateTime;
+ } FILETIME;
+
+ typedef struct {
+ [range(0,100000)] uint32 cValues;
+ [size_is(cValues)] uint16 *lpi;
+ } ShortArray_r;
+
+ typedef struct {
+ [range(0,100000)] uint32 cValues;
+ [size_is(cValues)] uint32 *lpl;
+ } LongArray_r;
+
+ typedef struct {
+ [range(0,100000)] uint32 cValues;
+ [size_is(cValues)] Binary_r *lpbin;
+ } BinaryArray_r;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ [range(0,100000)]uint32 cValues;
+ [size_is(cValues)] FlatUID_r **lpguid;
+ } FlatUIDArray_r;
+
+ typedef struct {
+ [range(0,100000)] uint32 cValues;
+ [size_is(cValues)] FILETIME *lpft;
+ } DateTimeArray_r;
+
+ typedef [switch_type(uint32)] union {
+ [case(PT_I2)] uint16 i;
+ [case(PT_LONG)] uint32 l;
+ [case(PT_DOUBLE)] dlong dbl;
+ [case(PT_BOOLEAN)] uint8 b;
+ [case(PT_I8)] dlong d;
+ [case(PT_STRING8)][unique][string,charset(DOS)] uint8 *lpszA;
+ [case(PT_BINARY)] Binary_r bin;
+ [case(PT_UNICODE)][string,charset(UTF16)] uint16 *lpszW;
+ [case(PT_CLSID)] FlatUID_r *lpguid;
+ [case(PT_SYSTIME)] FILETIME ft;
+ [case(PT_ERROR)] MAPISTATUS err;
+ [case(PT_MV_I2)] ShortArray_r MVi;
+ [case(PT_MV_LONG)] LongArray_r MVl;
+ [case(PT_MV_STRING8)] StringArray_r MVszA;
+ [case(PT_MV_BINARY)] BinaryArray_r MVbin;
+ [case(PT_MV_CLSID)] FlatUIDArray_r MVguid;
+ [case(PT_MV_UNICODE)] WStringArray_r MVszW;
+ [case(PT_MV_SYSTIME)] DateTimeArray_r MVft;
+ [case(PT_NULL)] uint32 null;
+ [case(PT_OBJECT)] uint32 object;
+ } SPropValue_CTR;
+
+ typedef [public]struct {
+ MAPITAGS ulPropTag;
+ uint32 dwAlignPad;
+ [switch_is(ulPropTag & 0xFFFF)] SPropValue_CTR value;
+ } SPropValue;
+
+ typedef struct {
+ uint32 ulAdrEntryPad;
+ [range(0,100000)] uint32 cValues;
+ [size_is(cValues)]SPropValue *lpProps;
+ } SRow;
+
+
+ typedef [public] struct {
+ [range(0,100000)] uint32 cRows;
+ [size_is(cRows)] SRow aRow[];
+ } SRowSet;
+
+ typedef struct {
+ [range(0,100000)] uint32 cRes;
+ [size_is(cRes)] Restriction_r *lpRes;
+ } AndRestriction_r;
+
+ typedef struct {
+ [range(0,100000)] uint32 cRes;
+ [size_is(cRes)] Restriction_r *lpRes;
+ } OrRestriction_r;
+
+ typedef struct {
+ Restriction_r *lpRes;
+ } NotRestriction_r;
+
+ typedef struct {
+ uint32 ulFuzzyLevel;
+ MAPITAGS ulPropTag;
+ SPropValue *lpProp;
+ } ContentRestriction_r;
+
+ typedef struct {
+ uint32 relop;
+ MAPITAGS ulPropTag;
+ SPropValue *lpProp;
+ } PropertyRestriction_r;
+
+ typedef struct {
+ uint32 relop;
+ MAPITAGS ulPropTag1;
+ MAPITAGS ulPropTag2;
+ } ComparePropsRestriction_r;
+
+ typedef struct {
+ uint32 relMBR;
+ MAPITAGS ulPropTag;
+ uint32 ulMask;
+ } BitMaskRestriction_r;
+
+ typedef struct {
+ uint32 relop;
+ MAPITAGS ulPropTag;
+ uint32 cb;
+ } SizeRestriction_r;
+
+ typedef struct {
+ uint32 ulReserved1;
+ MAPITAGS ulPropTag;
+ uint32 ulReserved2;
+ } ExistRestriction_r;
+
+ typedef struct {
+ uint32 ulSubObject;
+ Restriction_r *lpRes;
+ } SubRestriction_r;
+
+ typedef [v1_enum] enum {
+ RES_AND = 0x0,
+ RES_OR = 0x1,
+ RES_NOT = 0x2,
+ RES_CONTENT = 0x3,
+ RES_PROPERTY = 0x4,
+ RES_COMPAREPROPS = 0x5,
+ RES_BITMASK = 0x6,
+ RES_SIZE = 0x7,
+ RES_EXIST = 0x8,
+ RES_SUBRESTRICTION = 0x9,
+ RES_COMMENT = 0xA
+ } RestrictionType_r;
+
+ typedef [switch_type(uint32)] union {
+ [case(RES_AND)] AndRestriction_r resAnd;
+ [case(RES_OR)] OrRestriction_r resOr;
+ [case(RES_NOT)] NotRestriction_r resNot;
+ [case(RES_CONTENT)] ContentRestriction_r resContent;
+ [case(RES_PROPERTY)] PropertyRestriction_r resProperty;
+ [case(RES_COMPAREPROPS)] ComparePropsRestriction_r resCompareProps;
+ [case(RES_BITMASK)] BitMaskRestriction_r resBitMask;
+ [case(RES_SIZE)] SizeRestriction_r resSize;
+ [case(RES_EXIST)] ExistRestriction_r resExist;
+ [case(RES_SUBRESTRICTION)] SubRestriction_r resSub;
+ } RestrictionUnion_r;
+
+ typedef [public] struct _Restriction_r{
+ RestrictionType_r rt;
+ [switch_is(rt)] RestrictionUnion_r res;
+ } Restriction_r;
+
+ /*****************/
+ /* Function 0x00 */
+ typedef [bitmap32bit] bitmap {
+ fAnonymousLogin = 0x00000020
+ } NspiBind_dwFlags;
+
+ MAPISTATUS NspiBind(
+ [in] NspiBind_dwFlags dwFlags,
+ [in] STAT *pStat,
+ [in,out,unique] GUID *mapiuid,
+ [out] policy_handle *handle
+ );
+
+ /*****************/
+ /* Function 0x01 */
+ MAPISTATUS NspiUnbind(
+ [in, out] policy_handle *handle,
+ [in] uint32 Reserved
+ );
+
+ /*****************/
+ /* Function 0x02 */
+ MAPISTATUS NspiUpdateStat(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in,out] STAT *pStat,
+ [in,out,unique] uint32 *plDelta
+ );
+
+ /*****************/
+ /* Function 0x03 */
+ typedef [bitmap32bit] bitmap {
+ fSkipObjects = 0x00000001,
+ fEphID = 0x00000002
+ } NspiQueryRows_dwFlags;
+
+ MAPISTATUS NspiQueryRows(
+ [in] policy_handle *handle,
+ [in] NspiQueryRows_dwFlags dwFlags,
+ [in,out] STAT *pStat,
+ [in,range(0,100000)] uint32 dwETableCount,
+ [in,unique,size_is(dwETableCount)] uint32 *lpETable,
+ [in] uint32 Count,
+ [in,unique] SPropTagArray *pPropTags,
+ [out] SRowSet **ppRows
+ );
+
+ /*****************/
+ /* Function 0x04 */
+ MAPISTATUS NspiSeekEntries(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in,out] STAT *pStat,
+ [in] SPropValue *pTarget,
+ [in,unique] SPropTagArray *lpETable,
+ [in,unique] SPropTagArray *pPropTags,
+ [out] SRowSet **pRows
+ );
+
+ /*****************/
+ /* Function 0x05 */
+ MAPISTATUS NspiGetMatches(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in,out] STAT *pStat,
+ [in][unique] SPropTagArray *pReserved,
+ [in] uint32 Reserved2,
+ [in][unique] Restriction_r *Filter,
+ [in][unique] PropertyName_r *lpPropName,
+ [in] uint32 ulRequested,
+ [out] SPropTagArray **ppOutMIds,
+ [in][unique] SPropTagArray *pPropTags,
+ [out] SRowSet **ppRows
+ );
+
+ /*****************/
+ /* Function 0x06 */
+ MAPISTATUS NspiResortRestriction(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in,out] STAT *pStat,
+ [in] SPropTagArray *pInMIds,
+ [in,out] SPropTagArray **ppMIds
+ );
+
+ /*****************/
+ /* Function 0x07 */
+ MAPISTATUS NspiDNToMId(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in] StringsArray_r *pNames,
+ [out] SPropTagArray **ppMIds
+ );
+
+ /*****************/
+ /* Function 0x08 */
+ MAPISTATUS NspiGetPropList(
+ [in] policy_handle *handle,
+ [in] uint32 dwFlags,
+ [in] uint32 dwMId,
+ [in] uint32 CodePage,
+ [out] SPropTagArray **ppPropTags
+ );
+
+ /*****************/
+ /* Function 0x09 */
+ MAPISTATUS NspiGetProps(
+ [in] policy_handle *handle,
+ [in] uint32 dwFlags,
+ [in] STAT *pStat,
+ [in,unique] SPropTagArray *pPropTags,
+ [out] SRow **ppRows
+ );
+
+ /*****************/
+ /* Funcion 0xa */
+ MAPISTATUS NspiCompareMIds(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in] STAT *pStat,
+ [in] uint32 MId1,
+ [in] uint32 MId2,
+ [out] uint32 *plResult
+ );
+
+ /*****************/
+ /* Function 0xb */
+ MAPISTATUS NspiModProps(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in] STAT *pStat,
+ [in,unique] SPropTagArray *pPropTags,
+ [in] SRow *pRow
+ );
+
+ /*****************/
+ /* Function 0x0c */
+ typedef [bitmap32bit] bitmap {
+ NspiAddressCreationTemplates = 0x00000002,
+ NspiUnicodeStrings = 0x00000004
+ } NspiGetSpecialTable_dwFlags;
+
+ MAPISTATUS NspiGetSpecialTable(
+ [in] policy_handle *handle,
+ [in] NspiGetSpecialTable_dwFlags dwFlags,
+ [in] STAT *pStat,
+ [in,out] uint32 *lpVersion,
+ [out] SRowSet **ppRows
+ );
+
+ /*******************/
+ /* Function 0x0d */
+ typedef [bitmap32bit] bitmap {
+ TI_TEMPLATE = 0x00000001,
+ TI_SCRIPT = 0x00000004,
+ TI_EMT = 0x00000010,
+ TI_HELPFILE_NAME = 0x00000020,
+ TI_HELPFILE_CONTENTS = 0x00000040
+ } TI_dwFlags;
+
+ MAPISTATUS NspiGetTemplateInfo(
+ [in] policy_handle *handle,
+ [in] TI_dwFlags dwFlags,
+ [in] uint32 ulType,
+ [in,unique,string,charset(DOS)] uint8 *pDN,
+ [in] uint32 dwCodePage,
+ [in] uint32 dwLocaleID,
+ [out] SRow **ppData
+ );
+
+ /*******************/
+ /* Function 0x0e */
+ MAPISTATUS NspiModLinkAtt(
+ [in] policy_handle *handle,
+ [in] uint32 dwFlags,
+ [in] uint32 ulPropTag,
+ [in] uint32 MId,
+ [in] BinaryArray_r *lpEntryIds
+ );
+
+ /*************************************/
+ /* Function 0x0f: Not used on wire */
+ MAPISTATUS NspiDeleteEntries(
+ [in] policy_handle *Reserved1,
+ [in] uint32 Reserved2,
+ [in] uint32 Reserved3,
+ [in] BinaryArray_r *Reserved4
+ );
+
+ /*******************/
+ /* Function 0x10 */
+ typedef [bitmap32bit] bitmap {
+ NspiUnicodeProptypes = 0x80000000
+ } NspiQueryColumns_dwFlags;
+
+ MAPISTATUS NspiQueryColumns(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in] NspiQueryColumns_dwFlags dwFlags,
+ [out] SPropTagArray **ppColumns
+ );
+
+ /*******************/
+ /* Function 0x11 */
+ MAPISTATUS NspiGetNamesFromIDs(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in,unique] FlatUID_r *lpGuid,
+ [in,unique] SPropTagArray *pPropTags,
+ [out] SPropTagArray **ppReturnedPropTags,
+ [out] PropertyNameSet_r **ppNames
+ );
+
+ /*******************/
+ /* Function 0x12 */
+ MAPISTATUS NspiGetIDsFromNames(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in] uint32 dwFlags,
+ [in,range(0,100000)] uint32 cPropNames,
+ [in,size_is(cPropNames)] PropertyName_r **ppNames,
+ [out] SPropTagArray **ppPropTags
+ );
+
+ /*****************/
+ /* Function 0x13 */
+ MAPISTATUS NspiResolveNames(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in] STAT *pStat,
+ [in,unique] SPropTagArray *pPropTags,
+ [in] StringsArray_r *paStr,
+ [out] SPropTagArray **ppMIds,
+ [out] SRowSet **ppRows
+ );
+
+ /*****************/
+ /* Function 0x14 */
+ MAPISTATUS NspiResolveNamesW(
+ [in] policy_handle *handle,
+ [in] uint32 Reserved,
+ [in] STAT *pStat,
+ [in,unique] SPropTagArray *pPropTags,
+ [in] WStringsArray_r *paWStr,
+ [out] SPropTagArray **ppMIds,
+ [out] SRowSet **ppRows
+ );
+}
+
+[
+ uuid("a4f1db00-ca47-1067-b31f-00dd010662da"),
+ pointer_default(unique),
+ endpoint("ncacn_np:[\\pipe\\lsass]","ncacn_np:[\\pipe\\protected_storage]","ncacn_ip_tcp:"),
+ //version(0.81),
+ version(5308416),
+ helpstring("Exchange 5.5 EMSMDB")
+] interface exchange_emsmdb
+{
+ /*****************/
+ /* Function 0x00 */
+
+ MAPISTATUS EcDoConnect(
+ [out] policy_handle *handle,
+ [in,string,charset(DOS)] uint8 szUserDN[],
+ [in] uint32 ulFlags,
+ [in] uint32 ulConMod,
+ [in] uint32 cbLimit,
+ [in] uint32 ulCpid,
+ [in] uint32 ulLcidString,
+ [in] uint32 ulLcidSort,
+ [in] uint32 ulIcxrLink,
+ [in] uint16 usFCanConvertCodePages,
+ [out] uint32 *pcmsPollsMax,
+ [out] uint32 *pcRetry,
+ [out] uint32 *pcmsRetryDelay,
+ [out] uint32 *picxr,
+ [out,unique,string,charset(DOS)]uint8 *szDNPrefix,
+ [out,unique,string,charset(DOS)]uint8 *szDisplayName,
+ [out] uint16 rgwServerVersion[3],
+ [in,out] uint16 rgwClientVersion[3],
+ [in,out] uint32 *pullTimeStamp
+ );
+
+ /*****************/
+ /* Function 0x01 */
+ MAPISTATUS EcDoDisconnect(
+ [in,out] policy_handle *handle
+ );
+
+ /*****************/
+ /* Function 0x02 */
+
+ /*
+ EcDoRpc opnums
+ */
+
+ typedef [public, enum8bit, flag(NDR_PAHEX)] enum
+ {
+ MAPI_STORE = 0x1,
+ MAPI_ADDRBOOK = 0x2,
+ MAPI_FOLDER = 0x3,
+ MAPI_ABCONT = 0x4,
+ MAPI_MESSAGE = 0x5,
+ MAPI_MAILUSER = 0x6, /* Individual Recipient */
+ MAPI_ATTACH = 0x7,
+ MAPI_DISTLIST = 0x8,
+ MAPI_PROFSECT = 0x9,
+ MAPI_STATUS = 0xA,
+ MAPI_SESSION = 0xB,
+ MAPI_FORMINFO = 0xC
+ } MAPI_OBJTYPE;
+
+ typedef [public, v1_enum, flag(NDR_PAHEX)] enum
+ {
+ RightsNone = 0x00000000,
+ RightsReadItems = 0x00000001,
+ RightsCreateItems = 0x00000002,
+ RightsEditOwn = 0x00000008,
+ RightsDeleteOwn = 0x00000010,
+ RightsEditAll = 0x00000020,
+ RightsDeleteAll = 0x00000040,
+ RightsCreateSubfolders = 0x00000080,
+ RightsFolderOwner = 0x00000100,
+ RightsFolderContact = 0x00000200,
+ RoleNone = 0x00000400,
+ RoleReviewer = 0x00000401,
+ RoleContributor = 0x00000402,
+ RoleNoneditingAuthor = 0x00000413,
+ RoleAuthor = 0x0000041B,
+ RoleEditor = 0x0000047B,
+ RolePublishAuthor = 0x0000049B,
+ RolePublishEditor = 0x000004FB,
+ RightsAll = 0x000005FB,
+ RoleOwner = 0x000007FB
+ } ACLRIGHTS;
+
+ typedef [public, enum8bit, flag(NDR_PAHEX)] enum
+ {
+ op_MAPI_Release = 0x1,
+ op_MAPI_OpenFolder = 0x2,
+ op_MAPI_OpenMessage = 0x3,
+ op_MAPI_GetHierarchyTable = 0x4,
+ op_MAPI_GetContentsTable = 0x5,
+ op_MAPI_CreateMessage = 0x6,
+ op_MAPI_GetProps = 0x7,
+ op_MAPI_GetPropsAll = 0x8,
+ op_MAPI_GetPropList = 0x9,
+ op_MAPI_SetProps = 0xa,
+ op_MAPI_DeleteProps = 0xb,
+ op_MAPI_SaveChangesMessage = 0xc,
+ op_MAPI_RemoveAllRecipients = 0xd,
+ op_MAPI_ModifyRecipients = 0xe,
+ op_MAPI_ReadRecipients = 0xf,
+ op_MAPI_ReloadCachedInformation = 0x10,
+ op_MAPI_SetMessageReadFlag = 0x11,
+ op_MAPI_SetColumns = 0x12,
+ op_MAPI_SortTable = 0x13,
+ op_MAPI_Restrict = 0x14,
+ op_MAPI_QueryRows = 0x15,
+ op_MAPI_GetStatus = 0x16,
+ op_MAPI_QueryPosition = 0x17,
+ op_MAPI_SeekRow = 0x18,
+ op_MAPI_SeekRowBookmark = 0x19,
+ op_MAPI_SeekRowApprox = 0x1a,
+ op_MAPI_CreateBookmark = 0x1b,
+ op_MAPI_CreateFolder = 0x1c,
+ op_MAPI_DeleteFolder = 0x1d,
+ op_MAPI_DeleteMessages = 0x1e,
+ op_MAPI_GetMessageStatus = 0x1f,
+ op_MAPI_SetMessageStatus = 0x20,
+ op_MAPI_GetAttachmentTable = 0x21,
+ op_MAPI_OpenAttach = 0x22,
+ op_MAPI_CreateAttach = 0x23,
+ op_MAPI_DeleteAttach = 0x24,
+ op_MAPI_SaveChangesAttachment = 0x25,
+ op_MAPI_SetReceiveFolder = 0x26,
+ op_MAPI_GetReceiveFolder = 0x27,
+ op_MAPI_RegisterNotification = 0x29,
+ op_MAPI_Notify = 0x2a,
+ op_MAPI_OpenStream = 0x2b,
+ op_MAPI_ReadStream = 0x2c,
+ op_MAPI_WriteStream = 0x2d,
+ op_MAPI_SeekStream = 0x2e,
+ op_MAPI_SetStreamSize = 0x2f,
+ op_MAPI_SetSearchCriteria = 0x30,
+ op_MAPI_GetSearchCriteria = 0x31,
+ op_MAPI_SubmitMessage = 0x32,
+ op_MAPI_MoveCopyMessages = 0x33,
+ op_MAPI_AbortSubmit = 0x34,
+ op_MAPI_MoveFolder = 0x35,
+ op_MAPI_CopyFolder = 0x36,
+ op_MAPI_QueryColumnsAll = 0x37,
+ op_MAPI_Abort = 0x38,
+ op_MAPI_CopyTo = 0x39,
+ op_MAPI_CopyToStream = 0x3a,
+ op_MAPI_GetTable = 0x3e,
+ op_MAPI_GetRulesTable = 0x3f,
+ op_MAPI_ModifyTable = 0x40,
+ op_MAPI_ModifyRules = 0x41,
+ op_MAPI_GetOwningServers = 0x42,
+ op_MAPI_LongTermIdFromId = 0x43,
+ op_MAPI_IdFromLongTermId = 0x44,
+ op_MAPI_PublicFolderIsGhosted = 0x45,
+ op_MAPI_OpenEmbeddedMessage = 0x46,
+ op_MAPI_SetSpooler = 0x47,
+ op_MAPI_SpoolerLockMessage = 0x48,
+ op_MAPI_AddressTypes = 0x49,
+ op_MAPI_TransportSend = 0x4a,
+ op_MAPI_FastTransferSourceGetBuffer = 0x4e,
+ op_MAPI_FindRow = 0x4f,
+ op_MAPI_Progress = 0x50,
+ op_MAPI_GetNamesFromIDs = 0x55,
+ op_MAPI_GetIDsFromNames = 0x56,
+ op_MAPI_EmptyFolder = 0x58,
+ op_MAPI_ExpandRow = 0x59,
+ op_MAPI_CollapseRow = 0x5a,
+ op_MAPI_CommitStream = 0x5d,
+ op_MAPI_GetStreamSize = 0x5e,
+ op_MAPI_QueryNamedProperties = 0x5f,
+ op_MAPI_GetPerUserLongTermIds = 0x60,
+ op_MAPI_GetPerUserGuid = 0x61,
+ op_MAPI_ReadPerUserInformation = 0x63,
+ op_MAPI_SetReadFlags = 0x66,
+ op_MAPI_CopyProperties = 0x67,
+ op_MAPI_GetReceiveFolderTable = 0x68,
+ op_MAPI_GetCollapseState = 0x6b,
+ op_MAPI_SetCollapseState = 0x6c,
+ op_MAPI_GetTransportFolder = 0x6d,
+ op_MAPI_Pending = 0x6e,
+ op_MAPI_RegisterOptions = 0x6f,
+ op_MAPI_SyncConfigure = 0x70,
+ op_MAPI_SyncImportMessageChange = 0x72,
+ op_MAPI_SyncImportHierarchyChange = 0x73,
+ op_MAPI_SyncImportDeletes = 0x74,
+ op_MAPI_SyncUploadStateStreamBegin = 0x75,
+ op_MAPI_SyncUploadStateStreamContinue = 0x76,
+ op_MAPI_SyncUploadStateStreamEnd = 0x77,
+ op_MAPI_SyncImportMessageMove = 0x78,
+ op_MAPI_SetPropertiesNoReplicate = 0x79,
+ op_MAPI_DeletePropertiesNoReplicate = 0x7a,
+ op_MAPI_GetStoreState = 0x7b,
+ op_MAPI_SyncOpenCollector = 0x7e,
+ op_MAPI_GetLocalReplicaIds = 0x7f,
+ op_MAPI_SyncImportReadStateChanges = 0x80,
+ op_MAPI_ResetTable = 0x81,
+ op_MAPI_SyncGetTransferState = 0x82,
+ op_MAPI_OpenPublicFolderByName = 0x87,
+ op_MAPI_SetSyncNotificationGuid = 0x88,
+ op_MAPI_FreeBookmark = 0x89,
+ op_MAPI_Logon = 0xfe,
+ /****** custom MAPI opnum for mapiproxy ******/
+ op_MAPI_proxypack = 0xa5
+ } MAPI_OPNUM;
+
+
+ typedef [public,noprint,flag(NDR_NOALIGN)] struct {
+ uint16 cb;
+ [flag(NDR_BUFFERS)]uint8 lpb[cb];
+ } SBinary_short;
+
+ typedef [public] struct {
+ uint32 cValues;
+ uint32 lpl[cValues];
+ } mapi_MV_LONG_STRUCT;
+
+ typedef [public] struct {
+ astring lppszA;
+ } mapi_LPSTR;
+
+ typedef [public] struct {
+ uint32 cValues;
+ mapi_LPSTR strings[cValues];
+ } mapi_SLPSTRArray;
+
+ typedef struct {
+ [flag(STR_NULLTERM)] string lppszW;
+ } mapi_LPWSTR;
+
+ typedef struct {
+ uint32 cValues;
+ mapi_LPWSTR strings[cValues];
+ } mapi_SPLSTRArrayW;
+
+ typedef [public] struct {
+ uint32 cValues;
+ SBinary_short bin[cValues];
+ } mapi_SBinaryArray;
+
+ typedef struct {
+ uint32 cValues;
+ GUID lpguid[cValues];
+ } mapi_SGuidArray;
+
+ /******* part of the no-pointer deep recursion hack *******/
+ typedef [nopull,nopush,noprint,flag(NDR_NOALIGN)] struct {
+ uint8 wrap[0x8000];
+ } mapi_SRestriction_wrap;
+
+ typedef [nopush,nopull,noprint,flag(NDR_NOALIGN)] struct {
+ uint8 wrap[0x8000];
+ } mapi_SPropValue_wrap;
+
+ typedef [nopush,nopull,noprint,flag(NDR_NOALIGN)] struct {
+ uint8 wrap[0x8000];
+ } mapi_SPropValue_array_wrap;
+ /**********************************************************/
+
+ typedef [enum8bit] enum {
+ ActionType_OP_MOVE = 0x1,
+ ActionType_OP_COPY = 0x2,
+ ActionType_OP_REPLY = 0x3,
+ ActionType_OP_OOF_REPLY = 0x4,
+ ActionType_OP_DEFER_ACTION = 0x5,
+ ActionType_OP_BOUNCE = 0x6,
+ ActionType_OP_FORWARD = 0x7,
+ ActionType_OP_DELEGATE = 0x8,
+ ActionType_OP_TAG = 0x9,
+ ActionType_OP_DELETE = 0xA,
+ ActionType_OP_MARK_AS_READ = 0xB
+ } ActionType;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 FolderInThisStore;
+ SBinary_short StoreEID;
+ SBinary_short FolderEID;
+ } MoveCopy_Action;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper ReplyTemplateFID;
+ hyper ReplyTemplateMID;
+ GUID ReplyTemplateGUID;
+ } ReplyOOF_Action;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 Reserved;
+ mapi_SPropValue_array_wrap PropertyValue;
+ } RecipientBlock;
+
+ typedef [flag(NDR_NOALIGN)] enum {
+ BOUNCE_MESSAGE_TOO_LARGE = 0x0000000d,
+ BOUNCE_MESSAGE_NOT_DISPLAYED = 0x0000001f,
+ BOUNCE_MESSAGE_DENIED = 0x00000026
+ } BounceCode;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 RecipientCount;
+ RecipientBlock RecipientBlock[RecipientCount];
+ } ForwardDelegate_Action;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(ActionType_OP_MOVE)] MoveCopy_Action MoveAction;
+ [case(ActionType_OP_COPY)] MoveCopy_Action CopyAction;
+ [case(ActionType_OP_REPLY)] ReplyOOF_Action ReplyAction;
+ [case(ActionType_OP_OOF_REPLY)] ReplyOOF_Action ReplyOOFAction;
+ [case(ActionType_OP_DEFER_ACTION)][flag(NDR_REMAINING)] DATA_BLOB DeferAction;
+ [case(ActionType_OP_BOUNCE)] BounceCode BounceCode;
+ [case(ActionType_OP_TAG)] mapi_SPropValue_wrap PropValue;
+ [case(ActionType_OP_FORWARD)] ForwardDelegate_Action ForwardAction;
+ [case(ActionType_OP_DELEGATE)] ForwardDelegate_Action DelegateAction;
+ [case(ActionType_OP_DELETE)];
+ [case(ActionType_OP_MARK_AS_READ)];
+ } ActionData;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ ActionType ActionType;
+ uint32 ActionFlavor;
+ uint32 ActionFlags;
+ [switch_is(ActionType)] ActionData ActionDataBuffer;
+ } ActionBlockData;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 ActionLength;
+ [subcontext(0),subcontext_size(ActionLength),flag(NDR_REMAINING)] ActionBlockData ActionBlockData;
+ } ActionBlock;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 count;
+ ActionBlock ActionBlock[count];
+ } RuleAction;
+
+ typedef [public,nodiscriminant,flag(NDR_NOALIGN)] union {
+ [case(PT_I2)] uint16 i;
+ [case(PT_LONG)] uint32 l;
+ [case(PT_DOUBLE)] dlong dbl;
+ [case(PT_ERROR)] uint32 err;
+ [case(PT_BOOLEAN)] uint8 b;
+ [case(PT_I8)] dlong d;
+ [case(PT_STRING8)] astring lpszA;
+ [case(PT_UNICODE)][flag(STR_NULLTERM)] string lpszW;
+ [case(PT_SYSTIME)] FILETIME ft;
+ [case(PT_CLSID)] GUID lpguid;
+ [case(PT_SRESTRICT)] mapi_SRestriction_wrap Restrictions;
+ [case(PT_ACTIONS)] RuleAction RuleAction;
+ [case(PT_BINARY)] SBinary_short bin;
+ [case(PT_SVREID)] SBinary_short bin;
+ [case(PT_MV_LONG)] mapi_MV_LONG_STRUCT MVl;
+ [case(PT_MV_STRING8)] mapi_SLPSTRArray MVszA;
+ [case(PT_MV_UNICODE)] mapi_SPLSTRArrayW MVszW;
+ [case(PT_MV_CLSID)] mapi_SGuidArray MVguid;
+ [case(PT_MV_BINARY)] mapi_SBinaryArray MVbin;
+ } mapi_SPropValue_CTR;
+
+ typedef [public,flag(NDR_NOALIGN)] struct {
+ MAPITAGS ulPropTag;
+ [switch_is(ulPropTag & 0xFFFF)] mapi_SPropValue_CTR value;
+ } mapi_SPropValue;
+
+ typedef [public,flag(NDR_NOALIGN)] struct {
+ uint16 cValues;
+ [flag(NDR_REMAINING)]mapi_SPropValue lpProps[cValues];
+ } mapi_SPropValue_array;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 cValues;
+ MAPITAGS aulPropTag[cValues];
+ } mapi_SPropTagArray;
+
+ typedef [enum8bit, flag(NDR_PAHEX)] enum {
+ ROW_ADD = 0x1,
+ ROW_MODIFY = 0x2,
+ ROW_REMOVE = 0x4
+ } ulRowFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ ulRowFlags ulRowFlags;
+ mapi_SPropValue_array lpProps;
+ } mapi_SRow;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 padding;
+ uint16 cEntries;
+ mapi_SRow aEntries[cEntries];
+ } mapi_SRowList;
+
+ /**************************/
+ /* EcDoRpc Function 0x1 */
+ typedef [nopush,nopull,flag(NDR_NOALIGN)] struct {
+ } Release_req;
+
+ typedef [nopush,nopull,flag(NDR_NOALIGN)] struct {
+ } Release_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x2 */
+ typedef [enum8bit] enum {
+ OpenModeFlags_Folder = 0x0,
+ OpenModeFlags_SoftDeleted = 0x4
+ } OpenFolder_OpenModeFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ hyper folder_id;
+ OpenFolder_OpenModeFlags OpenModeFlags;
+ } OpenFolder_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 ServerCount;
+ uint16 CheapServerCount;
+ astring Servers[ServerCount];
+ } OpenFolder_Replicas;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)];
+ [case(0x1)] OpenFolder_Replicas Replicas;
+ } IsGhosted;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 HasRules;
+ boolean8 IsGhosted;
+ [switch_is(IsGhosted)] IsGhosted Ghost;
+ } OpenFolder_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x3 */
+ typedef [enum8bit] enum {
+ StringType_NONE = 0x0,
+ StringType_EMPTY = 0x1,
+ StringType_STRING8 = 0x2,
+ StringType_UNICODE_REDUCED = 0x3,
+ StringType_UNICODE = 0x4
+ } StringType;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)];
+ [case(0x1)];
+ [case(0x2)] astring lpszA;
+ [case(0x3)] astring lpszW_reduced;
+ [case(0x4)] [flag(STR_NULLTERM)] string lpszW;
+ } String;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ StringType StringType;
+ [switch_is(StringType)] String String;
+ } TypedString;
+
+ typedef [bitmap8bit] bitmap {
+ /* 0x0 means Read Only */
+ ReadWrite = 0x1,
+ Create = 0x3
+ } OpenMessage_OpenModeFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ uint16 CodePageId;
+ hyper FolderId;
+ OpenMessage_OpenModeFlags OpenModeFlags;
+ hyper MessageId;
+ } OpenMessage_req;
+
+ typedef [v1_enum, flag(NDR_PAHEX)] enum {
+ CP_USASCII = 0x04E4,
+ CP_UNICODE = 0x04B0,
+ CP_JAUTODETECT = 0xC6F4,
+ CP_KAUTODETECT = 0xC705,
+ CP_ISO2022JPESC = 0xC42D,
+ CP_ISO2022JPSIO = 0xC42E
+ } CODEPAGEID;
+
+ typedef [enum8bit, flag(NDR_PAHEX)] enum {
+ MAPI_ORIG = 0x0,
+ MAPI_TO = 0x1,
+ MAPI_CC = 0x2,
+ MAPI_BCC = 0x3
+ } ulRecipClass;
+
+ typedef [enum8bit, flag(NDR_PAHEX)] enum {
+ SINGLE_RECIPIENT = 0x0,
+ DISTRIBUTION_LIST = 0x1
+ } addr_type;
+
+ typedef [flag(NDR_NOALIGN)]struct {
+ uint8 organization_length;
+ addr_type addr_type;
+ astring username;
+ } RecipExchange;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } RecipSMTP;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)] RecipExchange EXCHANGE;
+ [case(0xA)] RecipSMTP SMTP;
+ [default];
+ } recipient_type;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)];
+ [case(0x400)] astring lpszA;
+ [case(0x600)][flag(STR_NULLTERM)] string lpszW;
+ [default];
+ } recipient_SimpleDisplayName;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)];
+ [case(0x20)] astring lpszA;
+ [case(0x220)][flag(STR_NULLTERM)] string lpszW;
+ [default];
+ } recipient_TransmittableDisplayName;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)];
+ [case(0x10)] astring lpszA;
+ [case(0x210)][flag(STR_NULLTERM)] string lpszW;
+ [default];
+ } recipient_DisplayName;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)];
+ [case(0x8)] astring lpszA;
+ [case(0x208)][flag(STR_NULLTERM)] string lpszW;
+ [default];
+ } recipient_EmailAddress;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 RecipientFlags;
+ [switch_is(RecipientFlags & 0xA)] recipient_type type;
+ [switch_is(RecipientFlags & 0x208)] recipient_EmailAddress EmailAddress;
+ [switch_is(RecipientFlags & 0x210)] recipient_DisplayName DisplayName;
+ [switch_is(RecipientFlags & 0x600)] recipient_SimpleDisplayName SimpleDisplayName;
+ [switch_is(RecipientFlags & 0x220)] recipient_TransmittableDisplayName TransmittableDisplayName;
+ uint16 prop_count;
+ uint8 layout;
+ [flag(NDR_REMAINING)] DATA_BLOB prop_values;
+ } RecipientRow;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ ulRecipClass RecipClass;
+ CODEPAGEID codepage;
+ [subcontext(2)] RecipientRow RecipientRow;
+ } OpenMessage_recipients;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 HasNamedProperties;
+ TypedString SubjectPrefix;
+ TypedString NormalizedSubject;
+ uint16 RecipientCount;
+ mapi_SPropTagArray RecipientColumns;
+ uint8 RowCount;
+ OpenMessage_recipients recipients[RowCount];
+ } OpenMessage_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x4 */
+ typedef [bitmap8bit] bitmap {
+ TableFlags_Depth = 0x4,
+ TableFlags_DeferredErrors = 0x8,
+ TableFlags_NoNotifications = 0x10,
+ TableFlags_SoftDeletes = 0x20,
+ TableFlags_UseUnicode = 0x40,
+ TableFlags_SuppressNotifications = 0x80
+ } TableFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ TableFlags TableFlags;
+ } GetHierarchyTable_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 RowCount;
+ } GetHierarchyTable_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x5 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ TableFlags TableFlags;
+ } GetContentsTable_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 RowCount;
+ } GetContentsTable_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x6 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ uint16 CodePageId;
+ hyper FolderId;
+ boolean8 AssociatedFlag;
+ } CreateMessage_req;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)];
+ [case(0x1)] hyper MessageId;
+ } CreateMessage_MessageId;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 HasMessageId;
+ [switch_is(HasMessageId)] CreateMessage_MessageId MessageId;
+ } CreateMessage_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x7 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 PropertySizeLimit;
+ uint16 WantUnicode;
+ uint16 prop_count;
+ MAPITAGS properties[prop_count];
+ } GetProps_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 layout;
+ [flag(NDR_REMAINING)] DATA_BLOB prop_data;
+ } GetProps_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x8 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 PropertySizeLimit;
+ uint16 WantUnicode;
+ } GetPropsAll_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ mapi_SPropValue_array properties;
+ } GetPropsAll_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x9 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } GetPropList_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 count;
+ MAPITAGS tags[count];
+ } GetPropList_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0xa */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 index; /* index into array of property tags */
+ MAPITAGS property_tag; /* property for which there was an error */
+ MAPISTATUS error_code; /* the error that occurred for this property */
+ } PropertyProblem;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ [subcontext(2)] mapi_SPropValue_array values;
+ } SetProps_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 PropertyProblemCount;
+ PropertyProblem PropertyProblem[PropertyProblemCount];
+ } SetProps_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0xb */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 count;
+ MAPITAGS tags[count];
+ } DeleteProps_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 PropertyProblemCount;
+ PropertyProblem PropertyProblem[PropertyProblemCount];
+ } DeleteProps_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0xc */
+ typedef [enum8bit] enum {
+ KeepOpenReadOnly = 0x9,
+ KeepOpenReadWrite = 0xA,
+ ForceSave = 0xC
+ } SaveFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ uint8 SaveFlags;
+ } SaveChangesMessage_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ hyper MessageId;
+ } SaveChangesMessage_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0xd */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 ulReserved;
+ } RemoveAllRecipients_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+
+ } RemoveAllRecipients_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0xe */
+
+ /*
+ * MODRECIP_NULL and INVALID are not part of the msdn flags
+ * but are added for printing support
+ */
+ typedef [enum8bit,flag(NDR_PAHEX)] enum {
+ MODRECIP_NULL = 0x0,
+ MODRECIP_INVALID = 0x1,
+ MODRECIP_ADD = 0x2,
+ MODRECIP_MODIFY = 0x4,
+ MODRECIP_REMOVE = 0x8
+ } modrecip;
+
+ typedef [flag(NDR_NOALIGN)]struct {
+ uint32 idx;
+ ulRecipClass RecipClass;
+ [subcontext(2),flag(NDR_REMAINING)] RecipientRow RecipientRow;
+ } ModifyRecipientRow;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 prop_count;
+ MAPITAGS properties[prop_count];
+ uint16 cValues;
+ ModifyRecipientRow RecipientRow[cValues];
+ } ModifyRecipients_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+
+ } ModifyRecipients_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0xf */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 RowId;
+ uint16 ulReserved;
+ } ReadRecipients_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 RowId;
+ ulRecipClass RecipientType;
+ uint16 CodePageId;
+ uint16 ulReserved;
+ [subcontext(2)] RecipientRow RecipientRow;
+ } ReadRecipientRow;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 RowCount;
+ ReadRecipientRow RecipientRows[RowCount];
+ } ReadRecipients_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x10 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ ulRecipClass RecipientType;
+ uint16 CodePageId;
+ uint16 Reserved;
+ uint16 RecipientRowSize;
+ [subcontext(0),subcontext_size(RecipientRowSize),flag(NDR_REMAINING)]RecipientRow RecipientRow;
+ } OpenRecipientRow;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 Reserved;
+ } ReloadCachedInformation_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 HasNamedProperties;
+ TypedString SubjectPrefix;
+ TypedString NormalizedSubject;
+ uint16 RecipientCount;
+ uint16 ColumnCount;
+ MAPITAGS RecipientColumns[ColumnCount];
+ uint8 RowCount;
+ OpenRecipientRow RecipientRows[RowCount];
+ } ReloadCachedInformation_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x11 */
+
+ 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
+ } MSGFLAG_READ;
+
+ /* TODO: there is a variation that can provide "client data" here */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ MSGFLAG_READ flags;
+ [flag(NDR_REMAINING)] DATA_BLOB clientdata;
+ } SetMessageReadFlag_req;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)];
+ [case(0x1)] uint8 LogonId;
+ } SetMessageReadFlag_LogonId;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)];
+ [case(0x1)] uint8 ClientData[24];
+ } SetMessageReadFlag_ClientData;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 ReadStatusChanged;
+ [switch_is(ReadStatusChanged)] SetMessageReadFlag_LogonId LogonId;
+ [switch_is(ReadStatusChanged)] SetMessageReadFlag_ClientData ClientData;
+ } SetMessageReadFlag_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x12 */
+ typedef [enum8bit] enum {
+ SetColumns_TBL_SYNC = 0x0,
+ SetColumns_TBL_ASYNC = 0x1
+ } SetColumnsFlags;
+
+ typedef [enum8bit] enum {
+ TBLSTAT_COMPLETE = 0x0,
+ TBLSTAT_SORTING = 0x9,
+ TBLSTAT_SORT_ERROR = 0xA,
+ TBLSTAT_SETTING_COLS = 0xB,
+ TBLSTAT_SETCOL_ERROR = 0xD,
+ TBLSTAT_RESTRICTING = 0xE,
+ TBLSTAT_RESTRICT_ERROR = 0xF
+ } TableStatus;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ SetColumnsFlags SetColumnsFlags;
+ uint16 prop_count;
+ MAPITAGS properties[prop_count];
+ } SetColumns_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ TableStatus TableStatus;
+ } SetColumns_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x13 */
+ typedef [enum8bit, flag(NDR_PAHEX)] enum {
+ TBL_ASYNC = 0x1,
+ TBL_BATCH = 0x2
+ } TBL_FLAGS;
+
+ typedef [enum8bit, flag(NDR_PAHEX)] enum {
+ TABLE_SORT_ASCEND = 0x0,
+ TABLE_SORT_COMBINE = 0x1,
+ TABLE_SORT_DESCEND = 0x2
+ } TABLE_SORT;
+
+ typedef [public, flag(NDR_NOALIGN)] struct _SSortOrder{
+ MAPITAGS ulPropTag;
+ TABLE_SORT ulOrder;
+ } SSortOrder;
+
+ typedef [public, flag(NDR_NOALIGN)] struct _SSortOrderSet {
+ uint16 cSorts;
+ uint16 cCategories;
+ uint16 cExpanded;
+ SSortOrder aSort[cSorts];
+ } SSortOrderSet;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 SortTableFlags;
+ SSortOrderSet lpSortCriteria;
+ } SortTable_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ TableStatus TableStatus;
+ } SortTable_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x14 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 cRes;
+ mapi_SRestriction_and res[cRes];
+ } mapi_SAndRestriction;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 cRes;
+ mapi_SRestriction_or res[cRes];
+ } mapi_SOrRestriction;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ mapi_SRestriction_wrap res;
+ } mapi_SNotRestriction;
+
+ typedef [noprint, bitmap32bit] bitmap {
+ FL_FULLSTRING = 0x00000,
+ FL_SUBSTRING = 0x00001,
+ FL_PREFIX = 0x00002,
+ FL_IGNORECASE = 0x10000,
+ FL_IGNORENONSPACE = 0x20000,
+ FL_LOOSE = 0x40000
+ } fuzzyLevel;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ fuzzyLevel fuzzy;
+ MAPITAGS ulPropTag;
+ mapi_SPropValue lpProp;
+ } mapi_SContentRestriction;
+
+ typedef [enum8bit, flag(NDR_PAHEX)] enum {
+ BMR_EQZ = 0x0,
+ BMR_NEZ = 0x1
+ } relMBR;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ relMBR relMBR;
+ MAPITAGS ulPropTag;
+ uint32 ulMask;
+ } mapi_SBitmaskRestriction;
+
+ typedef [enum8bit, flag(NDR_PAHEX)] enum {
+ RELOP_LT = 0x0, /* < */
+ RELOP_LE = 0x1, /* <= */
+ RELOP_GT = 0x2, /* > */
+ RELOP_GE = 0x3, /* >= */
+ RELOP_EQ = 0x4, /* == */
+ RELOP_NE = 0x5, /* != */
+ RELOP_RE = 0x6 /* LIKE (Regular expression) */
+ } CompareRelop;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ CompareRelop relop;
+ MAPITAGS ulPropTag;
+ uint32 size;
+ } mapi_SSizeRestriction;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 relop;
+ MAPITAGS ulPropTag;
+ mapi_SPropValue lpProp;
+ } mapi_SPropertyRestriction;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ CompareRelop relop;
+ MAPITAGS ulPropTag1;
+ MAPITAGS ulPropTag2;
+ } mapi_SCompareProps;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ MAPITAGS ulPropTag;
+ } mapi_SExistRestriction;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ MAPITAGS ulSubObject;
+ mapi_SRestriction_sub res[ulSubObject - ulSubObject + 1]; /* nasty hack - generates fake pointer */
+ } mapi_SSubRestriction;
+
+ typedef [nopush,nopull,noprint,nodiscriminant] union {
+ [case(0x0)];
+ [case(0x1)] mapi_SRestriction_comment *res;
+ } RestrictionVariable;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 TaggedValuesCount;
+ mapi_SPropValue TaggedValues[TaggedValuesCount];
+ boolean8 RestrictionPresent;
+ [switch_is(RestrictionPresent)] RestrictionVariable Restriction;
+ } mapi_SCommentRestriction;
+
+ typedef [public,nodiscriminant] union {
+ [case(RES_AND)] mapi_SAndRestriction resAnd;
+ [case(RES_OR)] mapi_SOrRestriction resOr;
+ [case(RES_NOT)] mapi_SNotRestriction resNot;
+ [case(RES_CONTENT)] mapi_SContentRestriction resContent;
+ [case(RES_PROPERTY)] mapi_SPropertyRestriction resProperty;
+ [case(RES_COMPAREPROPS)] mapi_SCompareProps resCompareProps;
+ [case(RES_BITMASK)] mapi_SBitmaskRestriction resBitmask;
+ [case(RES_SIZE)] mapi_SSizeRestriction resSize;
+ [case(RES_EXIST)] mapi_SExistRestriction resExist;
+ [case(RES_SUBRESTRICTION)] mapi_SSubRestriction resSub;
+ [case(RES_COMMENT)] mapi_SCommentRestriction resComment;
+ [default];
+ } mapi_SRestriction_CTR;
+
+ typedef [public,flag(NDR_NOALIGN)] struct {
+ uint8 rt;
+ [switch_is(rt)] mapi_SRestriction_CTR res;
+ } mapi_SRestriction;
+
+ typedef [public,flag(NDR_NOALIGN)] struct _mapi_SRestriction {
+ uint8 rt;
+ [switch_is(rt)] mapi_SRestriction_CTR res;
+ } mapi_SRestriction_and;
+
+ typedef [public,flag(NDR_NOALIGN)] struct _mapi_SRestriction {
+ uint8 rt;
+ [switch_is(rt)] mapi_SRestriction_CTR res;
+ } mapi_SRestriction_or;
+
+ typedef [public,flag(NDR_NOALIGN)] struct _mapi_SRestriction {
+ uint8 rt;
+ [switch_is(rt)] mapi_SRestriction_CTR res;
+ } mapi_SRestriction_sub;
+
+ typedef [public,flag(NDR_NOALIGN)] struct _mapi_SRestriction {
+ uint8 rt;
+ [switch_is(rt)] mapi_SRestriction_CTR res;
+ } mapi_SRestriction_comment;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ [subcontext(2)] mapi_SRestriction restrictions;
+ } Restrict_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ TableStatus TableStatus;
+ } Restrict_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x15 */
+ typedef [enum8bit] enum {
+ TBL_ADVANCE = 0x0,
+ TBL_NOADVANCE = 0x1,
+ TBL_ENABLEPACKEDBUFFERS = 0x2
+ } QueryRowsFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ QueryRowsFlags QueryRowsFlags;
+ uint8 ForwardRead;
+ uint16 RowCount;
+ } QueryRows_req;
+
+ typedef [nopush,nopull,flag(NDR_NOALIGN)] struct {
+ uint8 Origin;
+ uint16 RowCount;
+ [flag(NDR_REMAINING)]DATA_BLOB RowData;
+ } QueryRows_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x16 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } GetStatus_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ TableStatus TableStatus;
+ } GetStatus_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x17 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } QueryPosition_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 Numerator;
+ uint32 Denominator;
+ } QueryPosition_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x18 */
+ typedef [enum8bit] enum {
+ BOOKMARK_BEGINNING = 0x0,
+ BOOKMARK_CURRENT = 0x1,
+ BOOKMARK_END = 0x2,
+ BOOKMARK_USER = 0x3
+ } BOOKMARK;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ BOOKMARK origin;
+ int32 offset;
+ boolean8 WantRowMovedCount;
+ } SeekRow_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 HasSoughtLess;
+ uint32 RowsSought;
+ } SeekRow_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x19 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ SBinary_short Bookmark;
+ uint32 RowCount;
+ boolean8 WantRowMovedCount;
+ } SeekRowBookmark_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 RowNoLongerVisible;
+ boolean8 HasSoughtLess;
+ uint32 RowsSought;
+ } SeekRowBookmark_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x1a */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 ulNumerator;
+ uint32 ulDenominator;
+ } SeekRowApprox_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SeekRowApprox_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x1b */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } CreateBookmark_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ SBinary_short bookmark;
+ } CreateBookmark_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x1c */
+ typedef [enum8bit] enum {
+ FOLDER_GENERIC = 0x1,
+ FOLDER_SEARCH = 0x2
+ } FOLDER_TYPE;
+
+ typedef [enum8bit] enum {
+ MAPI_FOLDER_ANSI = 0x0,
+ MAPI_FOLDER_UNICODE = 0x1
+ } FOLDER_STRING;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(MAPI_FOLDER_ANSI)] astring lpszA;
+ [case(MAPI_FOLDER_UNICODE)][flag(STR_NULLTERM)] string lpszW;
+ } LPTSTR;
+
+ typedef [enum16bit] enum {
+ NONE = 0x0000,
+ OPEN_IF_EXISTS = 0x0001
+ } FOLDER_FLAGS;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ FOLDER_TYPE ulFolderType;
+ FOLDER_STRING ulType;
+ FOLDER_FLAGS ulFlags;
+ [switch_is(ulType)] LPTSTR FolderName;
+ [switch_is(ulType)] LPTSTR FolderComment;
+ } CreateFolder_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 HasRules;
+ boolean8 IsGhosted;
+ [switch_is(IsGhosted)] IsGhosted Ghost;
+ } CreateFolder_GhostInfo;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)];
+ [case(0x1)] CreateFolder_GhostInfo GhostInfo;
+ } CreateFolder_GhostUnion;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper folder_id;
+ boolean8 IsExistingFolder;
+ [switch_is(IsExistingFolder)] CreateFolder_GhostUnion GhostUnion;
+ } CreateFolder_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x1d */
+ typedef [bitmap8bit] bitmap {
+ DEL_MESSAGES = 0x1,
+ DEL_FOLDERS = 0x4,
+ DELETE_HARD_DELETE = 0x10
+ } DeleteFolderFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ DeleteFolderFlags DeleteFolderFlags;
+ hyper FolderId;
+ } DeleteFolder_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 PartialCompletion;
+ } DeleteFolder_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x1e */
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 WantAsynchronous;
+ boolean8 NotifyNonRead;
+ uint16 cn_ids;
+ hyper message_ids[cn_ids];
+ } DeleteMessages_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 PartialCompletion;
+ } DeleteMessages_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x1f */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper msgid;
+ } GetMessageStatus_req;
+
+ /**************************/
+ /* EcDoRpc Function 0x20 */
+ typedef [bitmap32bit] bitmap {
+ MSGSTATUS_HIGHLIGHTED = 0x1,
+ MSGSTATUS_TAGGED = 0x2,
+ MSGSTATUS_HIDDEN = 0x4,
+ MSGSTATUS_DELMARKED = 0x8,
+ MSGSTATUS_REMOTE_DOWNLOAD = 0x1000,
+ MSGSTATUS_REMOTE_DELETE = 0x2000
+ } ulMessageStatus;
+
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper msgid;
+ uint32 ulNewStatus;
+ ulMessageStatus ulNewStatusMask;
+ } SetMessageStatus_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ ulMessageStatus ulOldStatus;
+ } SetMessageStatus_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x21 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ TableFlags TableFlags;
+ } GetAttachmentTable_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } GetAttachmentTable_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x22 */
+ typedef [enum8bit] enum {
+ OpenAttachmentFlags_ReadOnly = 0x0,
+ OpenAttachmentFlags_ReadWrite = 0x1,
+ OpenAttachmentFlags_BestAccess = 0x3
+ } OpenAttachmentFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ OpenAttachmentFlags OpenAttachmentFlags;
+ uint32 AttachmentID;
+ } OpenAttach_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } OpenAttach_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x23 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ } CreateAttach_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 AttachmentID;
+ } CreateAttach_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x24 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 AttachmentID;
+ } DeleteAttach_req;
+
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } DeleteAttach_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x25 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ SaveFlags SaveFlags;
+ } SaveChangesAttachment_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SaveChangesAttachment_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x26 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper fid;
+ astring lpszMessageClass;
+ } SetReceiveFolder_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SetReceiveFolder_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x27 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ astring MessageClass;
+ } GetReceiveFolder_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper folder_id;
+ astring MessageClass;
+ } GetReceiveFolder_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x29 */
+ typedef [bitmap16bit] bitmap {
+ fnevCriticalError = 0x0001,
+ fnevNewMail = 0x0002,
+ fnevObjectCreated = 0x0004,
+ fnevObjectDeleted = 0x0008,
+ fnevObjectModified = 0x0010,
+ fnevObjectMoved = 0x0020,
+ fnevObjectCopied = 0x0040,
+ fnevSearchComplete = 0x0080,
+ fnevTableModified = 0x0100,
+ fnevStatusObjectModified = 0x0200,
+ fnevReserved = 0x0400,
+ fnevTbit = 0x1000,
+ fnevUbit = 0x2000,
+ fnevSbit = 0x4000,
+ fnevMbit = 0x8000
+ } NotificationFlags;
+
+ typedef [nodiscriminant,flag(NDR_NOALIGN)] union {
+ [case(0x0)] hyper ID;
+ [case(0x1)];
+ } hyperbool;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ NotificationFlags NotificationFlags;
+ boolean8 WantWholeStore;
+ [switch_is(WantWholeStore)] hyperbool FolderId;
+ [switch_is(WantWholeStore)] hyperbool MessageId;
+ } RegisterNotification_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } RegisterNotification_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x2a */
+ typedef [bitmap32bit] bitmap {
+ MSGFLAG_READ = 0x1,
+ MSGFLAG_UNMODIFIED = 0x2,
+ MSGFLAG_SUBMIT = 0x4,
+ MSGFLAG_UNSENT = 0x8,
+ MSGFLAG_HASATTACH = 0x10,
+ MSGFLAG_FROMME = 0x20,
+ MSGFLAG_ASSOCIATED = 0x40,
+ MSGFLAG_RESEND = 0x80,
+ MSGFLAG_RN_PENDING = 0x100,
+ MSGFLAG_NRN_PENDING = 0x200
+ } MsgFlags;
+
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)] astring lpszA;
+ [case(0x1)][flag(STR_NULLTERM)] string lpszW;
+ } MessageClass;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ GUID DatabaseGUID;
+ uint8 GlobalCounter[6];
+ } GID;
+
+ typedef [enum16bit] enum {
+ TABLE_CHANGED = 0x1,
+ TABLE_ROW_ADDED = 0x3,
+ TABLE_ROW_DELETED = 0x4,
+ TABLE_ROW_MODIFIED = 0x5,
+ TABLE_RESTRICT_DONE = 0x7
+ } RichTableNotificationType;
+
+ /* NewMailNotification: case 0x2 and 0x8002 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper MID;
+ MsgFlags MessageFlags;
+ boolean8 UnicodeFlag;
+ [switch_is(UnicodeFlag)] MessageClass MessageClass;
+ } NewMailNotification;
+
+ /* FolderCreatedNotification: case 0x4 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper ParentFID;
+ uint16 TagCount;
+ MAPITAGS Tags[TagCount];
+ } FolderCreatedNotification;
+
+ /* FolderDeletedNotification: case 0x8 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper ParentFID;
+ } FolderDeletedNotification;
+
+ /* FolderModifiedNotification: case 0x10 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ uint16 TagCount;
+ MAPITAGS Tags[TagCount];
+ } FolderModifiedNotification_10;
+
+ /* FolderMoveCopyNotification: case 0x20 and 0x40 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper ParentFID;
+ hyper OldFID;
+ hyper OldParentFID;
+ } FolderMoveCopyNotification;
+
+ /* SearchCompleteNotification: case 0x80 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ } SearchCompleteNotification;
+
+ /* HierarchyTable: case 0x100 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper InsertAfterFID;
+ [subcontext(2)] DATA_BLOB Columns;
+ } HierarchyRowAddedNotification;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ } HierarchyRowDeletedNotification;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper InsertAfterFID;
+ [subcontext(2)] DATA_BLOB Columns;
+ } HierarchyRowModifiedNotification;
+
+ typedef [nodiscriminant] union {
+ [case(TABLE_ROW_ADDED)] HierarchyRowAddedNotification HierarchyRowAddedNotification;
+ [case(TABLE_ROW_DELETED)] HierarchyRowDeletedNotification HierarchyRowDeletedNotification;
+ [case(TABLE_ROW_MODIFIED)] HierarchyRowModifiedNotification HierarchyRowModifiedNotification;
+ [default];
+ } HierarchyTableChangeUnion;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ RichTableNotificationType TableEvent;
+ [switch_is(TableEvent)] HierarchyTableChangeUnion HierarchyTableChangeUnion;
+ } HierarchyTableChange;
+
+ /* IcsNotification: case 0x200 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 HierChanged;
+ uint32 GIDCount;
+ GID GID[GIDCount];
+ } IcsNotification;
+
+ /* FolderModifiedNotification: case 0x1010 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ uint16 TagCount;
+ MAPITAGS Tags[TagCount];
+ uint32 TotalMessageCount;
+ } FolderModifiedNotification_1010;
+
+ /* FolderModifiedNotification: case 0x2010 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ uint16 TagCount;
+ MAPITAGS Tags[TagCount];
+ uint32 UnreadMessageCount;
+ } FolderModifiedNotification_2010;
+
+ /* FolderModifiedNotification: case 0x3010 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ uint16 TagCount;
+ MAPITAGS Tags[TagCount];
+ uint32 TotalMessageCount;
+ uint32 UnreadMessageCount;
+ } FolderModifiedNotification_3010;
+
+ /* MessageCreatedNotification: case 0x8004 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper MID;
+ uint16 TagCount;
+ MAPITAGS Tags[TagCount];
+ } MessageCreatedNotification;
+
+ /* MessageDeletedNotification: case 0x8008 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper MID;
+ } MessageDeletedNotification;
+
+ /* MessageModifiedNotification: case 0x8010 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper MID;
+ uint16 TagCount;
+ MAPITAGS Tags[TagCount];
+ } MessageModifiedNotification;
+
+ /* MessageMoveCopyNotification: case 0x8020 and 0x8040 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper MID;
+ hyper OldFID;
+ hyper OldMID;
+ } MessageMoveCopyNotification;
+
+ /* ContentsTableChange: case 0x8100 and 0xc100 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper MID;
+ uint32 Instance;
+ hyper InsertAfterFID;
+ hyper InsertAfterMID;
+ uint32 InsertAfterInstance;
+ [subcontext(2)] DATA_BLOB Columns;
+ } ContentsRowAddedNotification;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper MID;
+ uint32 Instance;
+ } ContentsRowDeletedNotification;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper MID;
+ uint32 Instance;
+ hyper InsertAfterFID;
+ hyper InsertAfterMID;
+ uint32 InsertAfterInstance;
+ [subcontext(2)] DATA_BLOB Columns;
+ } ContentsRowModifiedNotification;
+
+ typedef [nodiscriminant] union {
+ [case(TABLE_ROW_ADDED)] ContentsRowAddedNotification ContentsRowAddedNotification;
+ [case(TABLE_ROW_DELETED)] ContentsRowDeletedNotification ContentsRowDeletedNotification;
+ [case(TABLE_ROW_MODIFIED)] ContentsRowModifiedNotification ContentsRowModifiedNotification;
+ [default];
+ } ContentsTableChangeUnion;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ RichTableNotificationType TableEvent;
+ [switch_is(TableEvent)] ContentsTableChangeUnion ContentsTableChangeUnion;
+ } ContentsTableChange;
+
+ /* SearchMessageRemovedNotification: case 0xc008 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper MID;
+ hyper SearchFID;
+ } SearchMessageRemovedNotification;
+
+ /* SearchMessageModifiedNotification: 0xc010 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FID;
+ hyper MID;
+ hyper SearchFID;
+ uint16 TagCount;
+ MAPITAGS Tags[TagCount];
+ } SearchMessageModifiedNotification;
+
+ typedef [nodiscriminant] union {
+ [case(0x0002)] NewMailNotification NewMailNotification;
+ [case(0x0004)] FolderCreatedNotification FolderCreatedNotification;
+ [case(0x0008)] FolderDeletedNotification FolderDeletedNotification;
+ [case(0x0010)] FolderModifiedNotification_10 FolderModifiedNotification_10;
+ [case(0x0020)] FolderMoveCopyNotification FolderMoveNotification;
+ [case(0x0040)] FolderMoveCopyNotification FolderCopyNotification;
+ [case(0x0080)] SearchCompleteNotification SearchCompleteNotification;
+ [case(0x0100)] HierarchyTableChange HierarchyTableChange;
+ [case(0x0200)] IcsNotification IcsNotification;
+ [case(0x1010)] FolderModifiedNotification_1010 FolderModifiedNotification_1010;
+ [case(0x2010)] FolderModifiedNotification_2010 FolderModifiedNotification_2010;
+ [case(0x3010)] FolderModifiedNotification_3010 FolderModifiedNotification_3010;
+ [case(0x8002)] NewMailNotification NewMessageNotification;
+ [case(0x8004)] MessageCreatedNotification MessageCreatedNotification;
+ [case(0x8008)] MessageDeletedNotification MessageDeletedNotification;
+ [case(0x8010)] MessageModifiedNotification MessageModifiedNotification;
+ [case(0x8020)] MessageMoveCopyNotification MessageMoveNotification;
+ [case(0x8040)] MessageMoveCopyNotification MessageCopyNotification;
+ [case(0x8100)] ContentsTableChange ContentsTableChange;
+ [case(0xc008)] SearchMessageRemovedNotification SearchMessageRemovedNotification;
+ [case(0xc010)] SearchMessageModifiedNotification SearchMessageModifiedNotification;
+ [case(0xc100)] ContentsTableChange SearchTableChange;
+ } NotificationData;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 NotificationHandle;
+ uint8 LogonId;
+ NotificationFlags NotificationType;
+ [switch_is(NotificationType)] NotificationData NotificationData;
+ } Notify_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x2b */
+ typedef [enum8bit] enum {
+ OpenStream_ReadOnly = 0x0,
+ OpenStream_ReadWrite = 0x1,
+ OpenStream_Create = 0x2,
+ OpenStream_BestAccess = 0x3
+ } OpenStream_OpenModeFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ MAPITAGS PropertyTag;
+ OpenStream_OpenModeFlags OpenModeFlags;
+ } OpenStream_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 StreamSize;
+ } OpenStream_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x2c */
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0xBABE)] uint32 value;
+ [default];
+ } MaximumByteCount;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 ByteCount;
+ [switch_is(ByteCount)] MaximumByteCount MaximumByteCount;
+ } ReadStream_req;
+
+ typedef [flag(NDR_ALIGN2)] struct {
+ [subcontext(2), flag(NDR_REMAINING)] DATA_BLOB data;
+ } ReadStream_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x2d */
+ typedef [flag(NDR_NOALIGN)] struct {
+ [subcontext(2), flag(NDR_REMAINING)] DATA_BLOB data;
+ } WriteStream_req;
+
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 WrittenSize;
+ } WriteStream_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x2e */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 Origin;
+ hyper Offset;
+ } SeekStream_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper NewPosition;
+ } SeekStream_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x2f */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper SizeStream;
+ } SetStreamSize_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SetStreamSize_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x30 */
+ typedef [bitmap32bit, flag(NDR_PAHEX)] bitmap {
+ STOP_SEARCH = 0x00000001,
+ RESTART_SEARCH = 0x00000002,
+ RECURSIVE_SEARCH = 0x00000004,
+ SHALLOW_SEARCH = 0x00000008,
+ FOREGROUND_SEARCH = 0x00000010,
+ BACKGROUND_SEARCH = 0x00000020,
+ CONTENT_INDEXED_SEARCH = 0x00010000,
+ NON_CONTENT_INDEXED_SEARCH = 0x00020000,
+ STATIC_SEARCH = 0x00040000
+ } SearchFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ [subcontext(2)] mapi_SRestriction res;
+ uint16 FolderIdCount;
+ hyper FolderIds[FolderIdCount];
+ SearchFlags SearchFlags;
+ } SetSearchCriteria_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SetSearchCriteria_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x31 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 UseUnicode;
+ boolean8 IncludeRestriction;
+ boolean8 IncludeFolders;
+ } GetSearchCriteria_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ [subcontext(2)] mapi_SRestriction res;
+ uint8 unknown;
+ uint16 FolderIdCount;
+ hyper FolderIds[FolderIdCount];
+ SearchFlags SearchFlags;
+ } GetSearchCriteria_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x32 */
+ typedef [enum8bit] enum {
+ None = 0x0, /* None */
+ PreProcess = 0x1, /* Needs to be preprocessed by the server */
+ NeedsSpooler = 0x2 /* Is to be processed by a client spooler */
+ } SubmitFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ SubmitFlags SubmitFlags;
+ } SubmitMessage_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SubmitMessage_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x33 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ uint16 count;
+ hyper message_id[count];
+ boolean8 WantAsynchronous;
+ boolean8 WantCopy;
+ } MoveCopyMessages_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 PartialCompletion;
+ } MoveCopyMessages_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x34 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FolderId;
+ hyper MessageId;
+ } AbortSubmit_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } AbortSubmit_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x35 */
+ typedef [nodiscriminant, flag(NDR_NOALIGN)] union {
+ [case(0x0)] astring lpszA;
+ [case(0x1)][flag(STR_NULLTERM)] string lpszW;
+ } Folder_name;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ boolean8 WantAsynchronous;
+ boolean8 UseUnicode;
+ hyper FolderId;
+ [switch_is(UseUnicode)] Folder_name NewFolderName;
+ } MoveFolder_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 PartialCompletion;
+ } MoveFolder_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x36 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ boolean8 WantAsynchronous;
+ boolean8 WantRecursive;
+ boolean8 UseUnicode;
+ hyper FolderId;
+ [switch_is(UseUnicode)] Folder_name NewFolderName;
+ } CopyFolder_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 PartialCompletion;
+ } CopyFolder_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x37 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } QueryColumnsAll_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 PropertyTagCount;
+ MAPITAGS PropertyTags[PropertyTagCount];
+ } QueryColumnsAll_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x38 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } Abort_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ TableStatus TableStatus;
+ } Abort_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x39 */
+ typedef [bitmap8bit] bitmap {
+ CopyFlagsMove = 0x1, /* Move properties */
+ CopyFlagsNoOverwrite = 0x2 /* Do not overwrite existing properties */
+ } CopyFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ boolean8 WantAsynchronous;
+ boolean8 WantSubObjects;
+ CopyFlags CopyFlags;
+ mapi_SPropTagArray ExcludedTags;
+ } CopyTo_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 PropertyProblemCount;
+ PropertyProblem PropertyProblem[PropertyProblemCount];
+ } CopyTo_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x3a */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ hyper ByteCount;
+ } CopyToStream_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper ReadByteCount;
+ hyper WrittenByteCount;
+ } CopyToStream_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x3e */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ uint8 padding;
+ } GetTable_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } GetTable_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x3f */
+ typedef [bitmap8bit] bitmap {
+ RulesTableFlags_Unicode = 0x40
+ } RulesTableFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ RulesTableFlags TableFlags;
+ } GetRulesTable_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } GetRulesTable_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x40 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ mapi_SRowList rowList;
+ } ModifyTable_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ [flag(NDR_REMAINING)] DATA_BLOB remaining;
+ } ModifyTable_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x41 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ ulRowFlags RulesDataFlags;
+ mapi_SPropValue_array PropertyValues;
+ } RulesData;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 ModifyRulesFlags;
+ uint16 RulesCount;
+ RulesData RulesData[RulesCount];
+ } ModifyRules_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } ModifyRules_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x42 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FolderId;
+ } GetOwningServers_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 OwningServersCount;
+ uint16 CheapServersCount;
+ astring OwningServers[OwningServersCount];
+ } GetOwningServers_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x43 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper Id;
+ } LongTermIdFromId_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ GUID DatabaseGuid;
+ uint8 GlobalCounter[6];
+ uint16 padding;
+ } LongTermId;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ LongTermId LongTermId;
+ } LongTermIdFromId_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x44 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ LongTermId LongTermId;
+ } IdFromLongTermId_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper Id;
+ } IdFromLongTermId_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x45 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FolderId;
+ } PublicFolderIsGhosted_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 IsGhosted;
+ [switch_is(IsGhosted)] IsGhosted Ghost;
+ } PublicFolderIsGhosted_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x46 */
+ typedef [enum8bit, flag(NDR_PAHEX)] enum {
+ MAPI_READONLY = 0x0,
+ MAPI_READWRITE = 0x1,
+ MAPI_CREATE = 0x2
+ } OpenEmbeddedMessage_OpenModeFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ uint16 CodePageId;
+ OpenEmbeddedMessage_OpenModeFlags OpenModeFlags;
+ } OpenEmbeddedMessage_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 Reserved;
+ hyper MessageId;
+ boolean8 HasNamedProperties;
+ TypedString SubjectPrefix;
+ TypedString NormalizedSubject;
+ uint16 RecipientCount;
+ uint16 ColumnCount;
+ MAPITAGS RecipientColumns[ColumnCount];
+ uint8 RowCount;
+ OpenRecipientRow RecipientRows[RowCount];
+ } OpenEmbeddedMessage_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x47 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SetSpooler_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SetSpooler_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x48 */
+ typedef [enum8bit] enum {
+ LockState_1stLock = 0x0,
+ LockState_1stUnlock = 0x1,
+ LockState_1stFinished = 0x2
+ } LockState;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper MessageId;
+ LockState LockState;
+ } SpoolerLockMessage_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SpoolerLockMessage_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x49 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } AddressTypes_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 cValues;
+ uint16 size;
+ mapi_LPSTR transport[cValues];
+ } AddressTypes_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x4a */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } TransportSend_req;
+
+ typedef [nodiscriminant] union {
+ [case(0x0)] mapi_SPropValue_array lpProps;
+ [case(0x1)];
+ } TransportSend_lpProps;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 NoPropertiesReturned;
+ [switch_is(NoPropertiesReturned)] TransportSend_lpProps properties;
+ } TransportSend_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x4e */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 BufferSize;
+ } FastTransferSourceGetBuffer_req;
+
+ typedef [enum16bit] enum {
+ TransferStatus_Error = 0x0,
+ TransferStatus_Partial = 0x1,
+ TransferStatus_NoRoom = 0x2,
+ TransferStatus_Done = 0x3
+ } TransferStatus;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ TransferStatus TransferStatus;
+ uint16 InProgressCount;
+ uint16 TotalStepCount;
+ uint8 Reserved;
+ uint16 TransferBufferSize;
+ [subcontext(0),subcontext_size(TransferBufferSize),flag(NDR_REMAINING)] DATA_BLOB TransferBuffer;
+ } FastTransferSourceGetBuffer_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x4f */
+ typedef [enum8bit] enum {
+ DIR_FORWARD = 0x0,
+ DIR_BACKWARD = 0x1
+ } FindRow_ulFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ FindRow_ulFlags ulFlags;
+ [subcontext(2)] mapi_SRestriction res;
+ BOOKMARK origin;
+ SBinary_short bookmark;
+ } FindRow_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 RowNoLongerVisible;
+ uint8 HasRowData;
+ [flag(NDR_NOALIGN)] DATA_BLOB row;
+ } FindRow_repl;
+
+ /**************************/
+ /* EcDoRpc Function 0x50 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 WantCancel;
+ } Progress_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 CompletedTaskCount;
+ uint32 TotalTaskCount;
+ } Progress_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x55 */
+ typedef [enum8bit] enum {
+ MNID_ID = 0,
+ MNID_STRING = 1
+ } ulKind;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 NameSize;
+ [flag(STR_NULLTERM)] string Name;
+ } mapi_name;
+
+ typedef [nodiscriminant] union {
+ [case(MNID_ID)] uint32 lid;
+ [case(MNID_STRING)] mapi_name lpwstr;
+ } Kind;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ ulKind ulKind;
+ GUID lpguid;
+ [switch_is(ulKind)] Kind kind;
+ } MAPINAMEID;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ MAPITAGS ulPropTag;
+ } GetNamesFromIDs_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 count;
+ MAPINAMEID nameid[count];
+ } GetNamesFromIDs_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x56 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 ulFlags;
+ uint16 count;
+ MAPINAMEID nameid[count];
+ } GetIDsFromNames_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 count;
+ uint16 propID[count];
+ } GetIDsFromNames_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x58 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 WantAsynchronous;
+ boolean8 WantDeleteAssociated;
+ } EmptyFolder_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 PartialCompletion;
+ } EmptyFolder_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x59 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 MaxRowCount;
+ hyper CategoryId;
+ } ExpandRow_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 ExpandedRowCount;
+ uint16 RowCount;
+ [flag(NDR_REMAINING)]DATA_BLOB RowData;
+ } ExpandRow_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x5a */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper CategoryId;
+ } CollapseRow_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 CollapsedRowCount;
+ } CollapseRow_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x5d */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } CommitStream_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } CommitStream_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x5e */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } GetStreamSize_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 StreamSize;
+ } GetStreamSize_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x5f */
+ typedef [bitmap8bit] bitmap {
+ NoStrings = 0x01,
+ NoIds = 0x02
+ } QueryFlags;
+
+ typedef [nodiscriminant] union {
+ [case(0x0)];
+ [case(0x1)] GUID guid;
+ } QueryNamedProperties_guid;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ QueryFlags QueryFlags;
+ boolean8 HasGuid;
+ [switch_is(HasGuid)] QueryNamedProperties_guid PropertyGuid;
+ } QueryNamedProperties_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 IdCount;
+ uint16 PropertyIds[IdCount];
+ MAPINAMEID PropertyNames[IdCount];
+ } QueryNamedProperties_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x60 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ GUID DatabaseGuid;
+ } GetPerUserLongTermIds_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 LongTermIdCount;
+ LongTermId LongTermIds[LongTermIdCount];
+ } GetPerUserLongTermIds_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x61 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ LongTermId LongTermId;
+ } GetPerUserGuid_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ GUID DatabaseGuid;
+ } GetPerUserGuid_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x63 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 FolderId[24];
+ boolean8 WhatIfChanged;
+ uint32 DataOffset;
+ uint16 MaxDataSize;
+ } ReadPerUserInformation_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 HasFinished;
+ uint16 DataSize;
+ [subcontext(0), subcontext_size(DataSize), flag(NDR_REMAINING)] DATA_BLOB Data;
+ } ReadPerUserInformation_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x66 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 WantAsynchronous;
+ MSGFLAG_READ ReadFlags;
+ uint16 MessageIdCount;
+ hyper MessageIds[MessageIdCount];
+ } SetReadFlags_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 PartialCompletion;
+ } SetReadFlags_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x67 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ boolean8 WantAsynchronous;
+ CopyFlags CopyFlags;
+ mapi_SPropTagArray PropertyTags;
+ } CopyProperties_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 PropertyProblemCount;
+ PropertyProblem PropertyProblem[PropertyProblemCount];
+ } CopyProperties_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x68 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 unknown;
+ hyper fid;
+ astring lpszMessageClass;
+ FILETIME modiftime;
+ } ReceiveFolder;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } GetReceiveFolderTable_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 cValues;
+ ReceiveFolder entries[cValues];
+ } GetReceiveFolderTable_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x6b */
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper RowId;
+ uint32 RowInstanceNumber;
+ } GetCollapseState_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ SBinary_short CollapseState;
+ } GetCollapseState_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x6c */
+ typedef [flag(NDR_NOALIGN)] struct {
+ SBinary_short CollapseState;
+ } SetCollapseState_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ SBinary_short bookmark;
+ } SetCollapseState_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x6d */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } GetTransportFolder_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FolderId;
+ } GetTransportFolder_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x6e */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 SessionIndex;
+ } Pending_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x6f */
+ typedef [enum8bit,flag(NDR_NOALIGN)] enum {
+ OPTION_TYPE_RECIPIENT = 0x1,
+ OPTION_TYPE_MESSAGE = 0x2
+ } OPTIONDATA_ulFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ astring transport;
+ OPTIONDATA_ulFlags type;
+ } RegisterOptions_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ OPTIONDATA_ulFlags ulFlags;
+ DATA_BLOB data;
+ } RegisterOptions_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x70 */
+ typedef [enum8bit] enum {
+ Contents = 0x1,
+ Hierarchy = 0x2
+ } SynchronizationType;
+
+ typedef [bitmap8bit] bitmap {
+ SendOptions_Unicode = 0x1,
+ SendOptions_ForUpload = 0x3,
+ SendOptions_RecoverMode = 0x4,
+ SendOptions_ForceUnicode = 0x8,
+ SendOptions_Partial = 0x10
+ } SendOptions;
+
+ typedef [bitmap16bit] bitmap {
+ SynchronizationFlag_Unicode = 0x1,
+ SynchronizationFlag_NoDeletions = 0x2,
+ SynchronizationFlag_NoSoftDeletions = 0x4,
+ SynchronizationFlag_ReadState = 0x8,
+ SynchronizationFlag_FAI = 0x10,
+ SynchronizationFlag_Normal = 0x20,
+ SynchronizationFlag_OnlySpecifiedProperties = 0x80,
+ SynchronizationFlag_NoForeignIdentifiers = 0x100,
+ SynchronizationFlag_Reserved = 0x1000,
+ SynchronizationFlag_BestBody = 0x2000,
+ SynchronizationFlag_IgnoreSpecifiedOnFAI = 0x4000,
+ SynchronizationFlag_Progress = 0x8000
+ } SynchronizationFlag;
+
+ typedef [bitmap32bit] bitmap {
+ Eid = 0x00000001,
+ MessageSize = 0x00000002,
+ Cn = 0x00000004,
+ OrderByDeliveryTime = 0x00000008
+ } SynchronizationExtraFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ SynchronizationType SynchronizationType;
+ SendOptions SendOptions;
+ SynchronizationFlag SynchronizationFlag;
+ uint16 RestrictionSize;
+ [subcontext(0),subcontext_size(RestrictionSize),flag(NDR_REMAINING)] DATA_BLOB RestrictionData;
+ SynchronizationExtraFlags SynchronizationExtraFlags;
+ mapi_SPropTagArray PropertyTags;
+ } SyncConfigure_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SyncConfigure_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x72 */
+ typedef [bitmap8bit] bitmap {
+ ImportFlag_Associated = 0x10,
+ ImportFlag_FailOnConflict = 0x40
+ } ImportFlag;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ ImportFlag ImportFlag;
+ mapi_SPropValue_array PropertyValues;
+ } SyncImportMessageChange_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper MessageId;
+ } SyncImportMessageChange_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x73 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ mapi_SPropValue_array HierarchyValues;
+ mapi_SPropValue_array PropertyValues;
+ } SyncImportHierarchyChange_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FolderId;
+ } SyncImportHierarchyChange_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x74 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 IsHierarchy;
+ mapi_SPropValue_array PropertyValues;
+ } SyncImportDeletes_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SyncImportDeletes_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x75 */
+ typedef [v1_enum,flag(NDR_PAHEX)] enum {
+ PidTagIdsetGiven = 0x40170003,
+ PidTagCnsetSeen = 0x67960102,
+ PidTagCnsetSeenFAI = 0x67da0102,
+ PidTagCnsetRead = 0x67d20102
+ } StateProperty;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ StateProperty StateProperty;
+ uint32 TransferBufferSize;
+ } SyncUploadStateStreamBegin_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SyncUploadStateStreamBegin_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x76 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 StreamDataSize;
+ uint8 StreamData[StreamDataSize];
+ } SyncUploadStateStreamContinue_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SyncUploadStateStreamContinue_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x77 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SyncUploadStateStreamEnd_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SyncUploadStateStreamEnd_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x78 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 SourceFolderIdSize;
+ uint8 SourceFolderId[SourceFolderIdSize];
+ uint32 SourceMessageIdSize;
+ uint8 SourceMessageId[SourceMessageIdSize];
+ uint32 PredecessorChangeListSize;
+ uint8 PredecessorChangeList[PredecessorChangeListSize];
+ uint32 DestinationMessageIdSize;
+ uint8 DestinationMessageId[DestinationMessageIdSize];
+ uint32 ChangeNumberSize;
+ uint8 ChangeNumber[ChangeNumberSize];
+ } SyncImportMessageMove_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper MessageId;
+ } SyncImportMessageMove_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x79 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ [subcontext(2)] mapi_SPropValue_array values;
+ } SetPropertiesNoReplicate_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 PropertyProblemCount;
+ PropertyProblem PropertyProblem[PropertyProblemCount];
+ } SetPropertiesNoReplicate_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x7a */
+ typedef [flag(NDR_NOALIGN)] struct {
+ mapi_SPropTagArray PropertyTags;
+ } DeletePropertiesNoReplicate_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 PropertyProblemCount;
+ PropertyProblem PropertyProblem[PropertyProblemCount];
+ } DeletePropertiesNoReplicate_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x7b */
+ typedef [public,bitmap32bit] bitmap {
+ STORE_HAS_SEARCHES = 0x010000000
+ } StoreState;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } GetStoreState_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ StoreState StoreState;
+ } GetStoreState_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x7e */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ boolean8 IsContentsCollector;
+ } SyncOpenCollector_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SyncOpenCollector_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x7f */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint32 IdCount;
+ } GetLocalReplicaIds_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ GUID ReplGuid;
+ uint8 GlobalCount[6];
+ } GetLocalReplicaIds_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x80 */
+// typedef [flag(NDR_NOALIGN)] struct {
+// uint16 MessageSize;
+// uint8 MessageId[MessageSize];
+// boolean8 MarkAsRead;
+// } MessageReadStates;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint16 MessageReadStateSize;
+ [subcontext(0),subcontext_size(MessageReadStateSize),flag(NDR_REMAINING)] DATA_BLOB MessageStates;
+ } SyncImportReadStateChanges_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SyncImportReadStateChanges_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x81 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ } ResetTable_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } ResetTable_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x82 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ } SyncGetTransferState_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SyncGetTransferState_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x87 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 handle_idx;
+ asclstr name;
+ } OpenPublicFolderByName_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ boolean8 HasRules;
+ boolean8 IsGhosted;
+ [switch_is(IsGhosted)] IsGhosted Ghost;
+ } OpenPublicFolderByName_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x88 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ GUID NotificationGuid;
+ } SetSyncNotificationGuid_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } SetSyncNotificationGuid_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0x89 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ SBinary_short bookmark;
+ } FreeBookmark_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ } FreeBookmark_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0xFE */
+ typedef [public,bitmap8bit] bitmap {
+ LogonPrivate = 0x1,
+ UnderCover = 0x2,
+ Ghosted = 0x4,
+ SpIProcess = 0x8
+ } LogonFlags;
+
+ typedef [public,bitmap32bit] bitmap {
+ PUBLIC = 0x2,
+ HOME_LOGON = 0x4,
+ TAKE_OWNERSHIP = 0x8,
+ ALTERNATE_SERVER = 0x100,
+ IGNORE_HOME_MDB = 0x200,
+ NO_MAIL = 0x400,
+ USE_PER_MDB_REPLID_MAPPING = 0x010000000
+ } OpenFlags;
+
+ typedef [enum8bit] enum {
+ DayOfWeek_Sunday = 0x0,
+ DayOfWeek_Monday = 0x1,
+ DayOfWeek_Tuesday = 0x2,
+ DayOfWeek_Wednesday = 0x3,
+ DayOfWeek_Thursday = 0x4,
+ DayOfWeek_Friday = 0x5,
+ DayOfWeek_Saturday = 0x6
+ } DayOfWeek;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ uint8 Seconds;
+ uint8 Minutes;
+ uint8 Hour;
+ DayOfWeek DayOfWeek;
+ uint8 Day;
+ uint8 Month;
+ uint16 Year;
+ } LogonTime;
+
+ typedef [bitmap8bit] bitmap {
+ ResponseFlags_Reserved = 0x1,
+ ResponseFlags_OwnerRight = 0x2,
+ ResponseFlags_SendAsRight = 0x4,
+ ResponseFlags_OOF = 0x10
+ } ResponseFlags;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FolderIds[13];
+ uint16 ReplId;
+ GUID Guid;
+ GUID PerUserGuid;
+ } store_pf;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ hyper FolderIds[13];
+ ResponseFlags ResponseFlags;
+ GUID MailboxGuid;
+ uint16 ReplId;
+ GUID ReplGUID;
+ LogonTime LogonTime;
+ hyper GwartTime;
+ StoreState StoreState;
+ } store_mailbox;
+
+ typedef [nodiscriminant] union {
+ [case(0x0)] store_pf store_pf;
+ [case(LogonPrivate)] store_mailbox store_mailbox;
+ } LogonType;
+
+ typedef [nopush,flag(NDR_NOALIGN)] struct {
+ LogonFlags LogonFlags;
+ OpenFlags OpenFlags;
+ StoreState StoreState;
+ ascstr3 EssDN;
+ } Logon_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ LogonFlags LogonFlags;
+ [switch_is(LogonFlags)] LogonType LogonType;
+ } Logon_repl;
+
+ /*************************/
+ /* EcDoRpc Function 0xA5 */
+ typedef [flag(NDR_NOALIGN)] struct {
+ SBinary_short bin;
+ } proxypack_req;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ SBinary_short bin;
+ } proxypack_repl;
+
+ typedef [public, nodiscriminant] union {
+ [case(op_MAPI_Release)] Release_req mapi_Release;
+ [case(op_MAPI_OpenFolder)] OpenFolder_req mapi_OpenFolder;
+ [case(op_MAPI_OpenMessage)] OpenMessage_req mapi_OpenMessage;
+ [case(op_MAPI_GetHierarchyTable)] GetHierarchyTable_req mapi_GetHierarchyTable;
+ [case(op_MAPI_GetContentsTable)] GetContentsTable_req mapi_GetContentsTable;
+ [case(op_MAPI_CreateMessage)] CreateMessage_req mapi_CreateMessage;
+ [case(op_MAPI_GetProps)] GetProps_req mapi_GetProps;
+ [case(op_MAPI_GetPropsAll)] GetPropsAll_req mapi_GetPropsAll;
+ [case(op_MAPI_GetPropList)] GetPropList_req mapi_GetPropList;
+ [case(op_MAPI_SetProps)] SetProps_req mapi_SetProps;
+ [case(op_MAPI_DeleteProps)] DeleteProps_req mapi_DeleteProps;
+ [case(op_MAPI_SaveChangesMessage)] SaveChangesMessage_req mapi_SaveChangesMessage;
+ [case(op_MAPI_SetMessageReadFlag)] SetMessageReadFlag_req mapi_SetMessageReadFlag;
+ [case(op_MAPI_ReloadCachedInformation)] ReloadCachedInformation_req mapi_ReloadCachedInformation;
+ [case(op_MAPI_SetColumns)] SetColumns_req mapi_SetColumns;
+ [case(op_MAPI_SortTable)] SortTable_req mapi_SortTable;
+ [case(op_MAPI_Restrict)] Restrict_req mapi_Restrict;
+ [case(op_MAPI_RemoveAllRecipients)] RemoveAllRecipients_req mapi_RemoveAllRecipients;
+ [case(op_MAPI_ModifyRecipients)] ModifyRecipients_req mapi_ModifyRecipients;
+ [case(op_MAPI_ReadRecipients)] ReadRecipients_req mapi_ReadRecipients;
+ [case(op_MAPI_QueryRows)] QueryRows_req mapi_QueryRows;
+ [case(op_MAPI_GetStatus)] GetStatus_req mapi_GetStatus;
+ [case(op_MAPI_QueryPosition)] QueryPosition_req mapi_QueryPosition;
+ [case(op_MAPI_SeekRow)] SeekRow_req mapi_SeekRow;
+ [case(op_MAPI_SeekRowBookmark)] SeekRowBookmark_req mapi_SeekRowBookmark;
+ [case(op_MAPI_SeekRowApprox)] SeekRowApprox_req mapi_SeekRowApprox;
+ [case(op_MAPI_CreateBookmark)] CreateBookmark_req mapi_CreateBookmark;
+ [case(op_MAPI_CreateFolder)] CreateFolder_req mapi_CreateFolder;
+ [case(op_MAPI_DeleteFolder)] DeleteFolder_req mapi_DeleteFolder;
+ [case(op_MAPI_DeleteMessages)] DeleteMessages_req mapi_DeleteMessages;
+ [case(op_MAPI_GetMessageStatus)] GetMessageStatus_req mapi_GetMessageStatus;
+ [case(op_MAPI_SetMessageStatus)] SetMessageStatus_req mapi_SetMessageStatus;
+ [case(op_MAPI_GetAttachmentTable)] GetAttachmentTable_req mapi_GetAttachmentTable;
+ [case(op_MAPI_OpenAttach)] OpenAttach_req mapi_OpenAttach;
+ [case(op_MAPI_CreateAttach)] CreateAttach_req mapi_CreateAttach;
+ [case(op_MAPI_DeleteAttach)] DeleteAttach_req mapi_DeleteAttach;
+ [case(op_MAPI_SaveChangesAttachment)] SaveChangesAttachment_req mapi_SaveChangesAttachment;
+ [case(op_MAPI_SetReceiveFolder)] SetReceiveFolder_req mapi_SetReceiveFolder;
+ [case(op_MAPI_GetReceiveFolder)] GetReceiveFolder_req mapi_GetReceiveFolder;
+ [case(op_MAPI_RegisterNotification)] RegisterNotification_req mapi_RegisterNotification;
+ [case(op_MAPI_OpenStream)] OpenStream_req mapi_OpenStream;
+ [case(op_MAPI_ReadStream)] ReadStream_req mapi_ReadStream;
+ [case(op_MAPI_WriteStream)] WriteStream_req mapi_WriteStream;
+ [case(op_MAPI_SeekStream)] SeekStream_req mapi_SeekStream;
+ [case(op_MAPI_SetStreamSize)] SetStreamSize_req mapi_SetStreamSize;
+ [case(op_MAPI_SetSearchCriteria)] SetSearchCriteria_req mapi_SetSearchCriteria;
+ [case(op_MAPI_GetSearchCriteria)] GetSearchCriteria_req mapi_GetSearchCriteria;
+ [case(op_MAPI_SubmitMessage)] SubmitMessage_req mapi_SubmitMessage;
+ [case(op_MAPI_MoveCopyMessages)] MoveCopyMessages_req mapi_MoveCopyMessages;
+ [case(op_MAPI_AbortSubmit)] AbortSubmit_req mapi_AbortSubmit;
+ [case(op_MAPI_MoveFolder)] MoveFolder_req mapi_MoveFolder;
+ [case(op_MAPI_CopyFolder)] CopyFolder_req mapi_CopyFolder;
+ [case(op_MAPI_QueryColumnsAll)] QueryColumnsAll_req mapi_QueryColumnsAll;
+ [case(op_MAPI_Abort)] Abort_req mapi_Abort;
+ [case(op_MAPI_CopyTo)] CopyTo_req mapi_CopyTo;
+ [case(op_MAPI_CopyToStream)] CopyToStream_req mapi_CopyToStream;
+ [case(op_MAPI_GetTable)] GetTable_req mapi_GetTable;
+ [case(op_MAPI_GetRulesTable)] GetRulesTable_req mapi_GetRulesTable;
+ [case(op_MAPI_ModifyTable)] ModifyTable_req mapi_ModifyTable;
+ [case(op_MAPI_ModifyRules)] ModifyRules_req mapi_ModifyRules;
+ [case(op_MAPI_GetOwningServers)] GetOwningServers_req mapi_GetOwningServers;
+ [case(op_MAPI_LongTermIdFromId)] LongTermIdFromId_req mapi_LongTermIdFromId;
+ [case(op_MAPI_IdFromLongTermId)] IdFromLongTermId_req mapi_IdFromLongTermId;
+ [case(op_MAPI_PublicFolderIsGhosted)] PublicFolderIsGhosted_req mapi_PublicFolderIsGhosted;
+ [case(op_MAPI_OpenEmbeddedMessage)] OpenEmbeddedMessage_req mapi_OpenEmbeddedMessage;
+ [case(op_MAPI_SetSpooler)] SetSpooler_req mapi_SetSpooler;
+ [case(op_MAPI_SpoolerLockMessage)] SpoolerLockMessage_req mapi_SpoolerLockMessage;
+ [case(op_MAPI_AddressTypes)] AddressTypes_req mapi_AddressTypes;
+ [case(op_MAPI_TransportSend)] TransportSend_req mapi_TransportSend;
+ [case(op_MAPI_FastTransferSourceGetBuffer)] FastTransferSourceGetBuffer_req mapi_FastTransferSourceGetBuffer;
+ [case(op_MAPI_FindRow)] FindRow_req mapi_FindRow;
+ [case(op_MAPI_Progress)] Progress_req mapi_Progress;
+ [case(op_MAPI_GetNamesFromIDs)] GetNamesFromIDs_req mapi_GetNamesFromIDs;
+ [case(op_MAPI_GetIDsFromNames)] GetIDsFromNames_req mapi_GetIDsFromNames;
+ [case(op_MAPI_EmptyFolder)] EmptyFolder_req mapi_EmptyFolder;
+ [case(op_MAPI_ExpandRow)] ExpandRow_req mapi_ExpandRow;
+ [case(op_MAPI_CollapseRow)] CollapseRow_req mapi_CollapseRow;
+ [case(op_MAPI_CommitStream)] CommitStream_req mapi_CommitStream;
+ [case(op_MAPI_GetStreamSize)] GetStreamSize_req mapi_GetStreamSize;
+ [case(op_MAPI_QueryNamedProperties)] QueryNamedProperties_req mapi_QueryNamedProperties;
+ [case(op_MAPI_GetPerUserLongTermIds)] GetPerUserLongTermIds_req mapi_GetPerUserLongTermIds;
+ [case(op_MAPI_GetPerUserGuid)] GetPerUserGuid_req mapi_GetPerUserGuid;
+ [case(op_MAPI_ReadPerUserInformation)] ReadPerUserInformation_req mapi_ReadPerUserInformation;
+ [case(op_MAPI_SetReadFlags)] SetReadFlags_req mapi_SetReadFlags;
+ [case(op_MAPI_CopyProperties)] CopyProperties_req mapi_CopyProperties;
+ [case(op_MAPI_GetReceiveFolderTable)] GetReceiveFolderTable_req mapi_GetReceiveFolderTable;
+ [case(op_MAPI_GetCollapseState)] GetCollapseState_req mapi_GetCollapseState;
+ [case(op_MAPI_SetCollapseState)] SetCollapseState_req mapi_SetCollapseState;
+ [case(op_MAPI_GetTransportFolder)] GetTransportFolder_req mapi_GetTransportFolder;
+ [case(op_MAPI_RegisterOptions)] RegisterOptions_req mapi_RegisterOptions;
+ [case(op_MAPI_SyncConfigure)] SyncConfigure_req mapi_SyncConfigure;
+ [case(op_MAPI_SyncImportMessageChange)] SyncImportMessageChange_req mapi_SyncImportMessageChange;
+ [case(op_MAPI_SyncImportHierarchyChange)] SyncImportHierarchyChange_req mapi_SyncImportHierarchyChange;
+ [case(op_MAPI_SyncImportDeletes)] SyncImportDeletes_req mapi_SyncImportDeletes;
+ [case(op_MAPI_SyncUploadStateStreamBegin)] SyncUploadStateStreamBegin_req mapi_SyncUploadStateStreamBegin;
+ [case(op_MAPI_SyncUploadStateStreamContinue)] SyncUploadStateStreamContinue_req mapi_SyncUploadStateStreamContinue;
+ [case(op_MAPI_SyncUploadStateStreamEnd)] SyncUploadStateStreamEnd_req mapi_SyncUploadStateStreamEnd;
+ [case(op_MAPI_SyncImportMessageMove)] SyncImportMessageMove_req mapi_SyncImportMessageMove;
+ [case(op_MAPI_SetPropertiesNoReplicate)] SetPropertiesNoReplicate_req mapi_SetPropertiesNoReplicate;
+ [case(op_MAPI_DeletePropertiesNoReplicate)] DeletePropertiesNoReplicate_req mapi_DeletePropertiesNoReplicate;
+ [case(op_MAPI_GetStoreState)] GetStoreState_req mapi_GetStoreState;
+ [case(op_MAPI_SyncOpenCollector)] SyncOpenCollector_req mapi_SyncOpenCollector;
+ [case(op_MAPI_GetLocalReplicaIds)] GetLocalReplicaIds_req mapi_GetLocalReplicaIds;
+ [case(op_MAPI_SyncImportReadStateChanges)] SyncImportReadStateChanges_req mapi_SyncImportReadStateChanges;
+ [case(op_MAPI_ResetTable)] ResetTable_req mapi_ResetTable;
+ [case(op_MAPI_SyncGetTransferState)] SyncGetTransferState_req mapi_SyncGetTransferState;
+ [case(op_MAPI_OpenPublicFolderByName)] OpenPublicFolderByName_req mapi_OpenPublicFolderByName;
+ [case(op_MAPI_SetSyncNotificationGuid)] SetSyncNotificationGuid_req mapi_SetSyncNotificationGuid;
+ [case(op_MAPI_FreeBookmark)] FreeBookmark_req mapi_FreeBookmark;
+ [case(op_MAPI_Logon)] Logon_req mapi_Logon;
+ [case(op_MAPI_proxypack)] proxypack_req mapi_proxypack;
+ } EcDoRpc_MAPI_REQ_UNION;
+
+ typedef [public, nodiscriminant] union {
+ [case(op_MAPI_Release)] Release_repl mapi_Release;
+ [case(op_MAPI_OpenFolder)] OpenFolder_repl mapi_OpenFolder;
+ [case(op_MAPI_OpenMessage)] OpenMessage_repl mapi_OpenMessage;
+ [case(op_MAPI_GetHierarchyTable)] GetHierarchyTable_repl mapi_GetHierarchyTable;
+ [case(op_MAPI_GetContentsTable)] GetContentsTable_repl mapi_GetContentsTable;
+ [case(op_MAPI_CreateMessage)] CreateMessage_repl mapi_CreateMessage;
+ [case(op_MAPI_GetProps)] GetProps_repl mapi_GetProps;
+ [case(op_MAPI_GetPropsAll)] GetPropsAll_repl mapi_GetPropsAll;
+ [case(op_MAPI_GetPropList)] GetPropList_repl mapi_GetPropList;
+ [case(op_MAPI_SetProps)] SetProps_repl mapi_SetProps;
+ [case(op_MAPI_DeleteProps)] DeleteProps_repl mapi_DeleteProps;
+ [case(op_MAPI_SaveChangesMessage)] SaveChangesMessage_repl mapi_SaveChangesMessage;
+ [case(op_MAPI_RemoveAllRecipients)] RemoveAllRecipients_repl mapi_RemoveAllRecipients;
+ [case(op_MAPI_ModifyRecipients)] ModifyRecipients_repl mapi_ModifyRecipients;
+ [case(op_MAPI_ReadRecipients)] ReadRecipients_repl mapi_ReadRecipients;
+ [case(op_MAPI_SetMessageReadFlag)] SetMessageReadFlag_repl mapi_SetMessageReadFlag;
+ [case(op_MAPI_ReloadCachedInformation)] ReloadCachedInformation_repl mapi_ReloadCachedInformation;
+ [case(op_MAPI_SetColumns)] SetColumns_repl mapi_SetColumns;
+ [case(op_MAPI_SortTable)] SortTable_repl mapi_SortTable;
+ [case(op_MAPI_Restrict)] Restrict_repl mapi_Restrict;
+ [case(op_MAPI_QueryRows)] QueryRows_repl mapi_QueryRows;
+ [case(op_MAPI_GetStatus)] GetStatus_repl mapi_GetStatus;
+ [case(op_MAPI_QueryPosition)] QueryPosition_repl mapi_QueryPosition;
+ [case(op_MAPI_SeekRow)] SeekRow_repl mapi_SeekRow;
+ [case(op_MAPI_SeekRowBookmark)] SeekRowBookmark_repl mapi_SeekRowBookmark;
+ [case(op_MAPI_SeekRowApprox)] SeekRowApprox_repl mapi_SeekRowApprox;
+ [case(op_MAPI_CreateBookmark)] CreateBookmark_repl mapi_CreateBookmark;
+ [case(op_MAPI_CreateFolder)] CreateFolder_repl mapi_CreateFolder;
+ [case(op_MAPI_DeleteFolder)] DeleteFolder_repl mapi_DeleteFolder;
+ [case(op_MAPI_DeleteMessages)] DeleteMessages_repl mapi_DeleteMessages;
+ [case(op_MAPI_SetMessageStatus)] SetMessageStatus_repl mapi_SetMessageStatus;
+ [case(op_MAPI_GetAttachmentTable)] GetAttachmentTable_repl mapi_GetAttachmentTable;
+ [case(op_MAPI_OpenAttach)] OpenAttach_repl mapi_OpenAttach;
+ [case(op_MAPI_CreateAttach)] CreateAttach_repl mapi_CreateAttach;
+ [case(op_MAPI_DeleteAttach)] DeleteAttach_repl mapi_DeleteAttach;
+ [case(op_MAPI_SaveChangesAttachment)] SaveChangesAttachment_repl mapi_SaveChangesAttachment;
+ [case(op_MAPI_SetReceiveFolder)] SetReceiveFolder_repl mapi_SetReceiveFolder;
+ [case(op_MAPI_GetReceiveFolder)] GetReceiveFolder_repl mapi_GetReceiveFolder;
+ [case(op_MAPI_RegisterNotification)] RegisterNotification_repl mapi_RegisterNotification;
+ [case(op_MAPI_Notify)] Notify_repl mapi_Notify;
+ [case(op_MAPI_OpenStream)] OpenStream_repl mapi_OpenStream;
+ [case(op_MAPI_ReadStream)] ReadStream_repl mapi_ReadStream;
+ [case(op_MAPI_WriteStream)] WriteStream_repl mapi_WriteStream;
+ [case(op_MAPI_SeekStream)] SeekStream_repl mapi_SeekStream;
+ [case(op_MAPI_SetStreamSize)] SetStreamSize_repl mapi_SetStreamSize;
+ [case(op_MAPI_SetSearchCriteria)] SetSearchCriteria_repl mapi_SetSearchCriteria;
+ [case(op_MAPI_GetSearchCriteria)] GetSearchCriteria_repl mapi_GetSearchCriteria;
+ [case(op_MAPI_SubmitMessage)] SubmitMessage_repl mapi_SubmitMessage;
+ [case(op_MAPI_MoveCopyMessages)] MoveCopyMessages_repl mapi_MoveCopyMessages;
+ [case(op_MAPI_AbortSubmit)] AbortSubmit_repl mapi_AbortSubmit;
+ [case(op_MAPI_MoveFolder)] MoveFolder_repl mapi_MoveFolder;
+ [case(op_MAPI_CopyFolder)] CopyFolder_repl mapi_CopyFolder;
+ [case(op_MAPI_QueryColumnsAll)] QueryColumnsAll_repl mapi_QueryColumnsAll;
+ [case(op_MAPI_Abort)] Abort_repl mapi_Abort;
+ [case(op_MAPI_CopyTo)] CopyTo_repl mapi_CopyTo;
+ [case(op_MAPI_CopyToStream)] CopyToStream_repl mapi_CopyToStream;
+ [case(op_MAPI_GetTable)] GetTable_repl mapi_GetTable;
+ [case(op_MAPI_GetRulesTable)] GetRulesTable_repl mapi_GetRulesTable;
+ [case(op_MAPI_ModifyTable)] ModifyTable_repl mapi_ModifyTable;
+ [case(op_MAPI_ModifyRules)] ModifyRules_repl mapi_ModifyRules;
+ [case(op_MAPI_GetOwningServers)] GetOwningServers_repl mapi_GetOwningServers;
+ [case(op_MAPI_LongTermIdFromId)] LongTermIdFromId_repl mapi_LongTermIdFromId;
+ [case(op_MAPI_IdFromLongTermId)] IdFromLongTermId_repl mapi_IdFromLongTermId;
+ [case(op_MAPI_PublicFolderIsGhosted)] PublicFolderIsGhosted_repl mapi_PublicFolderIsGhosted;
+ [case(op_MAPI_OpenEmbeddedMessage)] OpenEmbeddedMessage_repl mapi_OpenEmbeddedMessage;
+ [case(op_MAPI_SetSpooler)] SetSpooler_repl mapi_SetSpooler;
+ [case(op_MAPI_SpoolerLockMessage)] SpoolerLockMessage_repl mapi_SpoolerLockMessage;
+ [case(op_MAPI_AddressTypes)] AddressTypes_repl mapi_AddressTypes;
+ [case(op_MAPI_TransportSend)] TransportSend_repl mapi_TransportSend;
+ [case(op_MAPI_FastTransferSourceGetBuffer)] FastTransferSourceGetBuffer_repl mapi_FastTransferSourceGetBuffer;
+ [case(op_MAPI_FindRow)] FindRow_repl mapi_FindRow;
+ [case(op_MAPI_Progress)] Progress_repl mapi_Progress;
+ [case(op_MAPI_GetNamesFromIDs)] GetNamesFromIDs_repl mapi_GetNamesFromIDs;
+ [case(op_MAPI_GetIDsFromNames)] GetIDsFromNames_repl mapi_GetIDsFromNames;
+ [case(op_MAPI_EmptyFolder)] EmptyFolder_repl mapi_EmptyFolder;
+ [case(op_MAPI_ExpandRow)] ExpandRow_repl mapi_ExpandRow;
+ [case(op_MAPI_CollapseRow)] CollapseRow_repl mapi_CollapseRow;
+ [case(op_MAPI_CommitStream)] CommitStream_repl mapi_CommitStream;
+ [case(op_MAPI_GetStreamSize)] GetStreamSize_repl mapi_GetStreamSize;
+ [case(op_MAPI_QueryNamedProperties)] QueryNamedProperties_repl mapi_QueryNamedProperties;
+ [case(op_MAPI_GetPerUserLongTermIds)] GetPerUserLongTermIds_repl mapi_GetPerUserLongTermIds;
+ [case(op_MAPI_GetPerUserGuid)] GetPerUserGuid_repl mapi_GetPerUserGuid;
+ [case(op_MAPI_ReadPerUserInformation)] ReadPerUserInformation_repl mapi_ReadPerUserInformation;
+ [case(op_MAPI_SetReadFlags)] SetReadFlags_repl mapi_SetReadFlags;
+ [case(op_MAPI_CopyProperties)] CopyProperties_repl mapi_CopyProperties;
+ [case(op_MAPI_GetReceiveFolderTable)] GetReceiveFolderTable_repl mapi_GetReceiveFolderTable;
+ [case(op_MAPI_Pending)] Pending_repl mapi_Pending;
+ [case(op_MAPI_GetCollapseState)] GetCollapseState_repl mapi_GetCollapseState;
+ [case(op_MAPI_SetCollapseState)] SetCollapseState_repl mapi_SetCollapseState;
+ [case(op_MAPI_GetTransportFolder)] GetTransportFolder_repl mapi_GetTransportFolder;
+ [case(op_MAPI_RegisterOptions)] RegisterOptions_repl mapi_RegisterOptions;
+ [case(op_MAPI_SyncConfigure)] SyncConfigure_repl mapi_SyncConfigure;
+ [case(op_MAPI_SyncImportMessageChange)] SyncImportMessageChange_repl mapi_SyncImportMessageChange;
+ [case(op_MAPI_SyncImportHierarchyChange)] SyncImportHierarchyChange_repl mapi_SyncImportHierarchyChange;
+ [case(op_MAPI_SyncImportDeletes)] SyncImportDeletes_repl mapi_SyncImportDeletes;
+ [case(op_MAPI_SyncUploadStateStreamBegin)] SyncUploadStateStreamBegin_repl mapi_SyncUploadStateStreamBegin;
+ [case(op_MAPI_SyncUploadStateStreamContinue)] SyncUploadStateStreamContinue_repl mapi_SyncUploadStateStreamContinue;
+ [case(op_MAPI_SyncUploadStateStreamEnd)] SyncUploadStateStreamEnd_repl mapi_SyncUploadStateStreamEnd;
+ [case(op_MAPI_SyncImportMessageMove)] SyncImportMessageMove_repl mapi_SyncImportMessageMove;
+ [case(op_MAPI_SetPropertiesNoReplicate)] SetPropertiesNoReplicate_repl mapi_SetPropertiesNoReplicate;
+ [case(op_MAPI_DeletePropertiesNoReplicate)] DeletePropertiesNoReplicate_repl mapi_DeletePropertiesNoReplicate;
+ [case(op_MAPI_GetStoreState)] GetStoreState_repl mapi_GetStoreState;
+ [case(op_MAPI_SyncOpenCollector)] SyncOpenCollector_repl mapi_SyncOpenCollector;
+ [case(op_MAPI_GetLocalReplicaIds)] GetLocalReplicaIds_repl mapi_GetLocalReplicaIds;
+ [case(op_MAPI_SyncImportReadStateChanges)] SyncImportReadStateChanges_repl mapi_SyncImportReadStateChanges;
+ [case(op_MAPI_ResetTable)] ResetTable_repl mapi_ResetTable;
+ [case(op_MAPI_SyncGetTransferState)] SyncGetTransferState_repl mapi_SyncGetTransferState;
+ [case(op_MAPI_OpenPublicFolderByName)] OpenPublicFolderByName_repl mapi_OpenPublicFolderByName;
+ [case(op_MAPI_SetSyncNotificationGuid)] SetSyncNotificationGuid_repl mapi_SetSyncNotificationGuid;
+ [case(op_MAPI_FreeBookmark)] FreeBookmark_repl mapi_FreeBookmark;
+ [case(op_MAPI_Logon)] Logon_repl mapi_Logon;
+ [case(op_MAPI_proxypack)] proxypack_repl mapi_proxypack;
+
+ } EcDoRpc_MAPI_REPL_UNION;
+
+ typedef [public,flag(NDR_NOALIGN)] struct {
+ uint8 opnum;
+ uint8 logon_id;
+ uint8 handle_idx;
+ [switch_is(opnum)] EcDoRpc_MAPI_REQ_UNION u;
+ } EcDoRpc_MAPI_REQ;
+
+ typedef [public,nopush,nopull,noprint,flag(NDR_NOALIGN)] struct {
+ uint8 opnum;
+ uint8 handle_idx;
+ MAPISTATUS error_code;
+ [switch_is(opnum)] EcDoRpc_MAPI_REPL_UNION u;
+ } EcDoRpc_MAPI_REPL;
+
+
+ /*
+ Abstract way to represent MAPI content
+ */
+
+ typedef [public,nopull,nopush,noprint] struct {
+ uint32 mapi_len; /* whole mapi_data length */
+ uint16 length; /* content length */
+ EcDoRpc_MAPI_REQ *mapi_req;
+ uint32 *handles; /* handles id array */
+ } mapi_request;
+
+ typedef [public,nopull,nopush,noprint] struct {
+ uint32 mapi_len;
+ uint16 length;
+ EcDoRpc_MAPI_REPL *mapi_repl;
+ uint32 *handles;
+ } mapi_response;
+
+
+ [public] MAPISTATUS EcDoRpc(
+ [in,out] policy_handle *handle,
+ [in,out] uint32 size,
+ [in,out] uint32 offset,
+ [in] [subcontext(4),flag(NDR_REMAINING|NDR_NOALIGN)] mapi_request *mapi_request,
+ [out][subcontext(4),flag(NDR_REMAINING|NDR_NOALIGN)] mapi_response *mapi_response,
+ [in,out] uint16 *length,
+ [in] uint16 max_data
+ );
+
+ /*****************/
+ /* Function 0x03 */
+ void EcGetMoreRpc();
+
+ /*****************/
+ /* Function 0x04 */
+
+ /*
+ we could directly use a NOTIFKEY structure rather than
+ a uint8 array, but this makes the IDL more robust
+
+ sockaddr array is made of:
+ - family (unsigned short in) sa_family_t
+ - address data sa_data[14];
+ */
+
+ typedef struct {
+ uint16 cb;
+ uint8 ab[cb];
+ } NOTIFKEY;
+
+ MAPISTATUS EcRRegisterPushNotification(
+ [in,out] policy_handle *handle,
+ [in] NotificationFlags ulEventMask,
+ [in,size_is(cbContext)] uint8 rgbContext[*],
+ [in] uint16 cbContext,
+ [in] uint32 grbitAdviseBits,
+ [in,size_is(cbCallbackAddress)] uint8 rgCallbackAddress[*],
+ [in] uint16 cbCallbackAddress,
+ [out,ref] uint32 *hNotification
+ );
+
+ /*****************/
+ /* Function 0x05 */
+ MAPISTATUS EcRUnregisterPushNotification(
+ [in,out] policy_handle *handle,
+ [in] uint32 unknown[2]
+ );
+
+ /*****************/
+ /* Function 0x06 */
+ void EcDummyRpc();
+
+ /*****************/
+ /* Function 0x07 */
+ void EcRGetDCName();
+
+ /*****************/
+ /* Function 0x08 */
+ void EcRNetGetDCName();
+
+ /*****************/
+ /* Function 0x09 */
+ void EcDoRpcExt();
+
+ /*****************/
+ /* Function 0xa */
+ MAPISTATUS EcDoConnectEx(
+ [out] policy_handle *handle,
+ [in,string,charset(DOS)] uint8 szUserDN[],
+ [in] uint32 ulFlags,
+ [in] uint32 ulConMod,
+ [in] uint32 cbLimit,
+ [in] uint32 ulCpid,
+ [in] uint32 ulLcidString,
+ [in] uint32 ulLcidSort,
+ [in] uint32 ulIcxrLink,
+ [in] uint16 usFCanConvertCodePages,
+ [out] uint32 *pcmsPollsMax,
+ [out] uint32 *pcRetry,
+ [out] uint32 *pcmsRetryDelay,
+ [out] uint32 *picxr,
+ [out,unique,string,charset(DOS)]uint8 *szDNPrefix,
+ [out,unique,string,charset(DOS)]uint8 *szDisplayName,
+ [in] uint16 rgwClientVersion[3],
+ [out] uint16 rgwServerVersion[3],
+ [out] uint16 rgwBestVersion[3],
+ [in,out] uint32 *pulTimeStamp,
+ [in][subcontext(4),flag(NDR_REMAINING|NDR_NOALIGN)] DATA_BLOB rgbAuxIn,
+ [in,out][range(0x0,0x1008)] uint32 *pcbAuxOut,
+ [in][flag(NDR_REMAINING)] DATA_BLOB data
+ );
+}
+
+[
+ uuid("c840a7dc-42c0-1a10-b4b9-08002b2fe182"),
+ pointer_default(unique),
+ helpstring("Unknown")
+] interface exchange_unknown
+{
+ void unknown_dummy();
+}
+
Added: trunk/openchange/idl_types.h
===================================================================
--- trunk/openchange/idl_types.h (rev 0)
+++ trunk/openchange/idl_types.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,97 @@
+#define STR_ASCII LIBNDR_FLAG_STR_ASCII
+#define STR_LEN4 LIBNDR_FLAG_STR_LEN4
+#define STR_SIZE4 LIBNDR_FLAG_STR_SIZE4
+#define STR_SIZE2 LIBNDR_FLAG_STR_SIZE2
+#define STR_NOTERM LIBNDR_FLAG_STR_NOTERM
+#define STR_NULLTERM LIBNDR_FLAG_STR_NULLTERM
+#define STR_BYTESIZE LIBNDR_FLAG_STR_BYTESIZE
+#define STR_FIXLEN32 LIBNDR_FLAG_STR_FIXLEN32
+#define STR_FIXLEN15 LIBNDR_FLAG_STR_FIXLEN15
+#define STR_CONFORMANT LIBNDR_FLAG_STR_CONFORMANT
+#define STR_CHARLEN LIBNDR_FLAG_STR_CHARLEN
+#define STR_UTF8 LIBNDR_FLAG_STR_UTF8
+#define STR_LARGE_SIZE LIBNDR_FLAG_STR_LARGE_SIZE
+
+/*
+ a UCS2 string prefixed with [size], 32 bits
+*/
+#define lstring [flag(STR_SIZE4)] string
+
+/*
+ a null terminated UCS2 string
+*/
+#define nstring [flag(STR_NULLTERM)] string
+
+/*
+ fixed length 32 character UCS-2 string
+*/
+#define string32 [flag(STR_FIXLEN32)] string
+
+/*
+ fixed length 16 character ascii string
+*/
+#define astring15 [flag(STR_ASCII|STR_FIXLEN15)] string
+
+/*
+ an ascii string prefixed with [offset] [length], both 32 bits
+ null terminated
+*/
+#define ascstr2 [flag(STR_ASCII|STR_LEN4)] string
+
+/*
+ an ascii string prefixed with [size], 32 bits
+*/
+#define asclstr [flag(STR_ASCII|STR_SIZE4)] string
+
+/*
+ an ascii string prefixed with [size], 16 bits
+ null terminated
+*/
+#define ascstr3 [flag(STR_ASCII|STR_SIZE2)] string
+
+/*
+ an ascii string prefixed with [size] [offset] [length], all 32 bits
+ not null terminated
+*/
+#define ascstr_noterm [flag(STR_NOTERM|STR_ASCII|STR_SIZE4|STR_LEN4)] string
+
+/*
+ a null terminated ascii string
+*/
+#define astring [flag(STR_ASCII|STR_NULLTERM)] string
+
+/*
+ a null terminated UTF8 string
+*/
+#define utf8string [flag(STR_UTF8|STR_NULLTERM)] string
+
+/*
+ a null terminated UCS2 string
+*/
+#define nstring_array [flag(STR_NULLTERM)] string_array
+
+#define NDR_NOALIGN LIBNDR_FLAG_NOALIGN
+#define NDR_REMAINING LIBNDR_FLAG_REMAINING
+#define NDR_ALIGN2 LIBNDR_FLAG_ALIGN2
+#define NDR_ALIGN4 LIBNDR_FLAG_ALIGN4
+#define NDR_ALIGN8 LIBNDR_FLAG_ALIGN8
+
+/* this flag is used to force a section of IDL as little endian. It is
+ needed for the epmapper IDL, which is defined as always being LE */
+#define NDR_LITTLE_ENDIAN LIBNDR_FLAG_LITTLE_ENDIAN
+#define NDR_BIG_ENDIAN LIBNDR_FLAG_BIGENDIAN
+
+
+/*
+ these are used by the epmapper and mgmt interfaces
+*/
+#define error_status_t uint32
+#define boolean32 uint32
+#define unsigned32 uint32
+
+/*
+ this is used to control formatting of uint8 arrays
+*/
+#define NDR_PAHEX LIBNDR_PRINT_ARRAY_HEX
+
+#define bool8 uint8
Added: trunk/openchange/install-sh
===================================================================
--- trunk/openchange/install-sh (rev 0)
+++ trunk/openchange/install-sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
Added: trunk/openchange/libmapi/Doxyfile.in
===================================================================
--- trunk/openchange/libmapi/Doxyfile.in (rev 0)
+++ trunk/openchange/libmapi/Doxyfile.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1278 @@
+# Doxyfile 1.5.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = MAPI Client Libraries
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = apidocs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = libmapi doc/doxygen
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.h *.c *.doxy
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = *_private.h
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = *.yy.c *_private.h
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = doc/examples
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = doc/doxygen/pictures/
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER = "sed \
+ -e '20,40s/.*\<libmapi\/proto_private.h\>//' \
+ -e '20,40s/.*\<gen_ndr\/ndr_exchange.h\>//' \
+ -e '20,40s/.*\<gen_ndr\/ndr_exchange_c.h\>//' \
+ -e '20,40s/.*\<gen_ndr\/ndr_misc.h\>//' \
+ -e '20,40s/.*\<gen_ndr\/ndr_property.h\>//' \
+ -e '20,40s/.*\<param.h\>//' \
+ -e '20,40s/.*\<core\/error.h\>//' \
+ -e '20,40s/.*\<credentials.h\>//' \
+ -e '20,40s/.*\<ldb.h\>//' \
+ -e '20,40s/.*\<ldb_errors.h\>//' \
+ -e '20,40s/.*\<libmapi\/dlinklist.h\>//' \
+ -e '20,40s/.*\<libmapi\/mapi_nameid.h\>//' \
+ -e '20,40s/.*\<libmapi\/mapicode.h\>//' \
+ -e '20,40s/.*\<libmapi\/mapidump.h\>//' \
+ -e '20,40s/.*\<libmapi\/mapitags.h\>//' \
+ -e '20,40s/.*\<libmapi\/mapi_nameid_private.h\>//' \
+ -e '20,40s/.*\<libmapi\/defs_private.h\>//' \
+ -e '20,40s/.*\<libgen.h\>//' \
+ -e '20,40s/.*\<time.h\>//' \
+ -e '20,40s/.*\<sys\/*\>//' \
+ -e '20,40s/_PUBLIC_//'"
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html/libmapi
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER = doc/doxygen/header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = doc/doxygen/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET = doc/doxygen/apidocs.css
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = _PUBLIC_
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen will always
+# show the root nodes and its direct children regardless of this setting.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
Added: trunk/openchange/libmapi/FXICS.c
===================================================================
--- trunk/openchange/libmapi/FXICS.c (rev 0)
+++ trunk/openchange/libmapi/FXICS.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,114 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+
+/**
+ \file FXICS.c
+
+ \brief Incremental Change Synchronization operations
+ */
+
+
+/**
+ \details Reserves a range of IDs to be used by a local replica
+
+ \param obj_store pointer on the store MAPI object
+ \param IdCount ID range length to reserve
+ \param ReplGuid pointer to the GUID structure returned by the
+ server
+ \param GlobalCount byte array that specifies the first allocated
+ field
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: one of the function parameter is
+ invalid
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+ */
+_PUBLIC_ enum MAPISTATUS GetLocalReplicaIds(mapi_object_t *obj_store,
+ uint32_t IdCount,
+ struct GUID *ReplGuid,
+ uint8_t GlobalCount[6])
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetLocalReplicaIds_req request;
+ struct GetLocalReplicaIds_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ReplGuid, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetLocalReplicaIds");
+ size = 0;
+
+ /* Fill the GetLocalReplicaIds operation */
+ request.IdCount = IdCount;
+ size += sizeof (uint32_t);
+
+ /* Fill the MAPI_REQ structure */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetLocalReplicaIds;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetLocalReplicaIds = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ mapi_request->length = (uint16_t)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_store);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve output parameters */
+ reply = &mapi_response->mapi_repl->u.mapi_GetLocalReplicaIds;
+ *ReplGuid = reply->ReplGuid;
+ memcpy(GlobalCount, reply->GlobalCount, 6);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IABContainer.c
===================================================================
--- trunk/openchange/libmapi/IABContainer.c (rev 0)
+++ trunk/openchange/libmapi/IABContainer.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,280 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+
+
+/**
+ \file IABContainer.c
+
+ \brief Provides access to address book containers -- Used to
+ perform name resolution
+*/
+
+
+/**
+ \details Resolve user names against the Windows Address Book Provider
+
+ \param session pointer to the MAPI session context
+ \param usernames list of user names to resolve
+ \param rowset resulting list of user details
+ \param props resulting list of resolved names
+ \param flaglist resulting list of resolution status (see below)
+ \param flags if set to MAPI_UNICODE then UNICODE MAPITAGS can be
+ used, otherwise only UTF8 encoded fields may be returned.
+
+ Possible flaglist values are:
+ -# MAPI_UNRESOLVED: could not be resolved
+ -# MAPI_AMBIGUOUS: resolution match more than one entry
+ -# MAPI_RESOLVED: resolution matched a single entry
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ -# MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ -# MAPI_E_SESSION_LIMIT: No session has been opened on the provider
+ -# MAPI_E_NOT_ENOUGH_RESOURCES: MAPI subsystem failed to allocate
+ the necessary resources to operate properly
+ -# MAPI_E_NOT_FOUND: No suitable profile database was found in the
+ path pointed by profiledb
+ -# MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MAPILogonProvider, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS ResolveNames(struct mapi_session *session,
+ const char **usernames,
+ struct SPropTagArray *props,
+ struct SRowSet **rowset,
+ struct SPropTagArray **flaglist,
+ uint32_t flags)
+{
+ struct nspi_context *nspi;
+ enum MAPISTATUS retval;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_SESSION_LIMIT, NULL);
+ OPENCHANGE_RETVAL_IF(!session->nspi, MAPI_E_SESSION_LIMIT, NULL);
+ OPENCHANGE_RETVAL_IF(!session->nspi->ctx, MAPI_E_SESSION_LIMIT, NULL);
+ OPENCHANGE_RETVAL_IF(!rowset, MAPI_E_INVALID_PARAMETER, NULL);
+
+ nspi = (struct nspi_context *)session->nspi->ctx;
+
+ switch (flags) {
+ case MAPI_UNICODE:
+ retval = nspi_ResolveNamesW(nspi, usernames, props, &rowset, &flaglist);
+ break;
+ default:
+ retval = nspi_ResolveNames(nspi, usernames, props, &rowset, &flaglist);
+ break;
+ }
+
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve the global address list
+
+ \param session pointer to the MAPI session context
+ \param SPropTagArray pointer on an array of MAPI properties we want
+ to fetch
+ \param SRowSet pointer on the rows returned
+ \param count the number of rows we want to fetch
+ \param ulFlags specify the table cursor location
+
+ Possible value for ulFlags:
+ -# TABLE_START: Fetch rows from the beginning of the table
+ -# TABLE_CUR: Fetch rows from current table location
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ -# MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ -# MAPI_E_SESSION_LIMIT: No session has been opened on the provider
+ -# MAPI_E_INVALID_PARAMETER: if a function parameter is invalid
+ -# MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MapiLogonEx, MapiLogonProvider
+ */
+_PUBLIC_ enum MAPISTATUS GetGALTable(struct mapi_session *session,
+ struct SPropTagArray *SPropTagArray,
+ struct SRowSet **SRowSet,
+ uint32_t count,
+ uint8_t ulFlags)
+{
+ struct nspi_context *nspi;
+ struct SRowSet *srowset;
+ enum MAPISTATUS retval;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_SESSION_LIMIT, NULL);
+ OPENCHANGE_RETVAL_IF(!session->nspi, MAPI_E_SESSION_LIMIT, NULL);
+ OPENCHANGE_RETVAL_IF(!session->nspi->ctx, MAPI_E_SESSION_LIMIT, NULL);
+ OPENCHANGE_RETVAL_IF(!SRowSet, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
+
+ nspi = (struct nspi_context *)session->nspi->ctx;
+
+ if (ulFlags == TABLE_START) {
+ nspi->pStat->CurrentRec = 0;
+ nspi->pStat->Delta = 0;
+ nspi->pStat->NumPos = 0;
+ nspi->pStat->TotalRecs = 0xffffffff;
+ }
+
+ srowset = talloc_zero(session, struct SRowSet);
+ retval = nspi_QueryRows(nspi, SPropTagArray, NULL, count, &srowset);
+ *SRowSet = srowset;
+
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve Address Book information for a given recipient
+
+ \param session pointer to the MAPI session context
+ \param username pointer to the username to retrieve information from
+ \param pPropTags pointer to the property tags array to lookup
+ \param ppRowSet pointer on pointer to the results
+
+ Note that if pPropTags is NULL, then GetABNameInfo will fetch
+ the following default property tags:
+ -# PR_ADDRTYPE_UNICODE
+ -# PR_EMAIL_ADDRESS_UNICODE
+ -# PR_DISPLAY_NAME_UNICODE
+ -# PR_OBJECT_TYPE
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ -# MAPI_E_NOT_INITIALIZED if MAPI subsystem is not initialized
+ -# MAPI_E_SESSION_LIMIT if the NSPI session is unavailable
+ -# MAPI_E_INVALID_PARAMETER if a function parameter is invalid
+ -# MAPI_E_NOT_FOUND if the username to lookup doesn't match any
+ records
+
+ \sa nspi_DNToMId, nspi_GetProps
+ */
+_PUBLIC_ enum MAPISTATUS GetABRecipientInfo(struct mapi_session *session,
+ const char *username,
+ struct SPropTagArray *pPropTags,
+ struct SRowSet **ppRowSet)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct nspi_context *nspi_ctx;
+ struct SRowSet *SRowSet;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SPropTagArray *pMId = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ struct StringsArray_r pNames;
+ const char *usernames[2];
+ char *email = NULL;
+ bool allocated = false;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_SESSION_LIMIT, NULL);
+ OPENCHANGE_RETVAL_IF(!session->profile, MAPI_E_SESSION_LIMIT, NULL);
+ OPENCHANGE_RETVAL_IF(!session->nspi, MAPI_E_SESSION_LIMIT, NULL);
+ OPENCHANGE_RETVAL_IF(!session->nspi->ctx, MAPI_E_SESSION_LIMIT, NULL);
+ OPENCHANGE_RETVAL_IF(!ppRowSet, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!username, MAPI_E_INVALID_PARAMETER, NULL);
+
+ nspi_ctx = (struct nspi_context *)session->nspi->ctx;
+ mem_ctx = nspi_ctx->mem_ctx;
+
+ /* Step 1. Resolve the username */
+ usernames[0] = username;
+ usernames[1] = NULL;
+
+ SRowSet = talloc_zero(mem_ctx, struct SRowSet);
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0xc,
+ PR_ENTRYID,
+ PR_DISPLAY_NAME_UNICODE,
+ PR_ADDRTYPE_UNICODE,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_EMAIL_ADDRESS_UNICODE,
+ PR_SEND_INTERNET_ENCODING,
+ PR_SEND_RICH_INFO,
+ PR_SEARCH_KEY,
+ PR_TRANSMITTABLE_DISPLAY_NAME_UNICODE,
+ PR_7BIT_DISPLAY_NAME_UNICODE,
+ PR_SMTP_ADDRESS_UNICODE);
+ retval = ResolveNames(session, usernames, SPropTagArray, &SRowSet, &flaglist, MAPI_UNICODE);
+ MAPIFreeBuffer(SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, SRowSet);
+
+ if (flaglist->aulPropTag[0] != MAPI_RESOLVED) {
+ MAPIFreeBuffer(SRowSet);
+ return MAPI_E_NOT_FOUND;
+ }
+
+ username = (const char *) get_SPropValue_SRowSet_data(SRowSet, PR_7BIT_DISPLAY_NAME_UNICODE);
+ email = talloc_strdup(mem_ctx, (const char *) get_SPropValue_SRowSet_data(SRowSet, PR_EMAIL_ADDRESS_UNICODE));
+ MAPIFreeBuffer(SRowSet);
+
+ /* Step 2. Map recipient DN to MId */
+ pNames.Count = 0x1;
+ pNames.Strings = (const char **) talloc_array(mem_ctx, char **, 1);
+ pNames.Strings[0] = email;
+ pMId = talloc_zero(mem_ctx, struct SPropTagArray);
+ retval = nspi_DNToMId(nspi_ctx, &pNames, &pMId);
+ MAPIFreeBuffer((char *)pNames.Strings[0]);
+ MAPIFreeBuffer((char **)pNames.Strings);
+ OPENCHANGE_RETVAL_IF(retval, retval, pMId);
+
+ /* Step 3. Get recipient's properties */
+ if (!pPropTags) {
+ allocated = true;
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x4,
+ PR_ADDRTYPE_UNICODE,
+ PR_EMAIL_ADDRESS_UNICODE,
+ PR_DISPLAY_NAME_UNICODE,
+ PR_OBJECT_TYPE);
+ } else {
+ SPropTagArray = pPropTags;
+ }
+
+ SRowSet = talloc_zero(mem_ctx, struct SRowSet);
+ retval = nspi_GetProps(nspi_ctx, SPropTagArray, pMId, &SRowSet);
+ if (allocated == true) {
+ MAPIFreeBuffer(SPropTagArray);
+ }
+ MAPIFreeBuffer(pMId);
+ OPENCHANGE_RETVAL_IF(retval, retval, SRowSet);
+
+ *ppRowSet = SRowSet;
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IMAPIContainer.c
===================================================================
--- trunk/openchange/libmapi/IMAPIContainer.c (rev 0)
+++ trunk/openchange/libmapi/IMAPIContainer.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,745 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+
+
+/**
+ \file IMAPIContainer.c
+
+ \brief Containers and tables related operations
+*/
+
+
+/**
+ \details Returns a pointer to a container's table object
+
+ This function takes a pointer to a container object and returns a
+ pointer to its associated contents
+
+ \param obj_container the object to get the contents of
+ \param obj_table the resulting table containing the container's
+ contents.
+ \param TableFlags flags controlling the type of table
+ \param RowCount the number of rows in the hierarchy table
+
+ TableFlags possible values:
+
+ - TableFlags_Depth (0x4): Fills the hierarchy table with containers
+ from all levels. If this flag is not set, the hierarchy table
+ contains only the container's immediate child containers.
+
+ - TableFlags_DeferredErrors (0x8): The call response can return immediately,
+ possibly before the call execution is complete and in this case the
+ ReturnValue as well the RowCount fields in the return buffer might
+ not be accurate. Only retval reporting failure can be considered
+ valid in this case.
+
+ - TableFlags_NoNotifications (0x10): Disables all notifications on .this Table
+ object.
+
+ - TableFlags_SoftDeletes (0x20): Enables the client to get a list of the soft
+ deleted folders.
+
+ - TableFlags_UseUnicode (0x40): Requests that the columns that contain string
+ data be returned in Unicode format.
+
+ - TableFlags_SuppressNotifications (0x80): Suppresses notifications generated
+ by this clientâs actions on this Table object.
+
+ Developers can either set RowCount to a valid pointer on uint32_t
+ or set it to NULL. In this last case, GetHierarchyTable won't
+ return any value to the calling function.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenFolder, GetHierarchyTable, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS GetContentsTable(mapi_object_t *obj_container, mapi_object_t *obj_table,
+ uint8_t TableFlags, uint32_t *RowCount)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetContentsTable_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_container, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_container);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetContentsTable");
+ size = 0;
+
+ /* Fill the GetContentsTable operation */
+ request.handle_idx = 0x1;
+ request.TableFlags = TableFlags;
+ size += 2;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetContentsTable;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetContentsTable = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_container);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* set object session and handle */
+ mapi_object_set_session(obj_table, session);
+ mapi_object_set_handle(obj_table, mapi_response->handles[1]);
+
+ /* Retrieve RowCount if a valid pointer was set */
+ if (RowCount) {
+ *RowCount = mapi_response->mapi_repl->u.mapi_GetContentsTable.RowCount;
+ }
+
+ /* new table */
+ mapi_object_table_init((TALLOC_CTX *)session, obj_table);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns a pointer to a container's table object
+
+ This function takes a pointer to a container object and returns a
+ pointer to its associated hierarchy table
+
+ \param obj_container the object to get the contents of
+ \param obj_table the resulting table containing the container's
+ hierarchy
+ \param TableFlags flags controlling the type of table
+ \param RowCount the number of rows in the hierarchy table
+
+ TableFlags possible values:
+
+ - TableFlags_Depth (0x4): Fills the hierarchy table with containers
+ from all levels. If this flag is not set, the hierarchy table
+ contains only the container's immediate child containers.
+
+ - TableFlags_DeferredErrors (0x8): The call response can return immediately,
+ possibly before the call execution is complete and in this case the
+ ReturnValue as well the RowCount fields in the return buffer might
+ not be accurate. Only retval reporting failure can be considered
+ valid in this case.
+
+ - TableFlags_NoNotifications (0x10): Disables all notifications on .this Table
+ object.
+
+ - TableFlags_SoftDeletes (0x20): Enables the client to get a list of the soft
+ deleted folders.
+
+ - TableFlags_UseUnicode (0x40): Requests that the columns that contain string
+ data be returned in Unicode format.
+
+ - TableFlags_SuppressNotifications (0x80): Suppresses notifications generated
+ by this clientâs actions on this Table object.
+
+ Developers can either set RowCount to a valid pointer on uint32_t
+ or set it to NULL. In this last case, GetHierarchyTable won't
+ return any value to the calling function.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenFolder, GetContentsTable, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS GetHierarchyTable(mapi_object_t *obj_container, mapi_object_t *obj_table,
+ uint8_t TableFlags, uint32_t *RowCount)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetHierarchyTable_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_container, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_container);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetHierarchyTable");
+ size = 0;
+
+ /* Fill the GetHierarchyTable operation */
+ request.handle_idx = 0x1;
+ request.TableFlags = TableFlags;
+ size += 2;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetHierarchyTable;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetHierarchyTable = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_container);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* set object session and handle */
+ mapi_object_set_session(obj_table, session);
+ mapi_object_set_handle(obj_table, mapi_response->handles[1]);
+
+ /* Retrieve RowCount if a valid pointer was set */
+ if (RowCount) {
+ *RowCount = mapi_response->mapi_repl->u.mapi_GetHierarchyTable.RowCount;
+ }
+
+ /* new table */
+ mapi_object_table_init((TALLOC_CTX *)session, obj_table);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns a pointer to the permission's table object.
+
+ This function takes a pointer to a container object and returns a
+ pointer to its associated permission table
+
+ \param obj_container the object to get the contents of
+ \param obj_table the resulting table containing the container's
+ permissions
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa ModifyTable
+ */
+_PUBLIC_ enum MAPISTATUS GetTable(mapi_object_t *obj_container, mapi_object_t *obj_table)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetTable_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_container, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_container);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetTable");
+ size = 0;
+
+ /* Fill the GetTable operation */
+ request.handle_idx = 0x1;
+ request.padding = 0x0;
+ size += 2;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetTable;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx= 0;
+ mapi_req->u.mapi_GetTable = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_container);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* set object session and handle */
+ mapi_object_set_session(obj_table, session);
+ mapi_object_set_handle(obj_table, mapi_response->handles[1]);
+
+ /* new table */
+ mapi_object_table_init((TALLOC_CTX *)session, obj_table);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Gets the rules table of a folder
+
+ \param obj_folder the folder we want to retrieve the rules table
+ from
+ \param obj_table the rules table
+ \param TableFlags bitmask associated to the rules table
+
+ Possible values for TableFlags:
+
+ - RulesTableFlags_Unicode (0x40): Set if the client is requesting
+ that string values in the table to be returned as Unicode
+ strings.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+ */
+_PUBLIC_ enum MAPISTATUS GetRulesTable(mapi_object_t *obj_folder,
+ mapi_object_t *obj_table,
+ uint8_t TableFlags)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetRulesTable_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity check */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_folder);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetRulesTable");
+ size = 0;
+
+ /* Fill the GetRulesTable operation */
+ request.handle_idx = 0x1;
+ size += sizeof (uint8_t);
+
+ request.TableFlags = TableFlags;
+ size += sizeof (uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetRulesTable;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetRulesTable = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* set object session and handle */
+ mapi_object_set_session(obj_table, session);
+ mapi_object_set_handle(obj_table, mapi_response->handles[1]);
+
+ /* new table */
+ mapi_object_table_init((TALLOC_CTX *)session, obj_table);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+
+/**
+ \details Modify the entries of a permission table
+
+ This function takes a pointer to a table object, a list of entries
+ to modify and alter the permission table of its associated
+ container. This function can be used to add, modify or remove
+ permissions.
+
+ \param obj_table the table containing the container's permissions
+ \param rowList the list of table entries to modify
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetTable, AddUserPermission, ModifyUserPermission,
+ RemoveUserPermission
+ */
+_PUBLIC_ enum MAPISTATUS ModifyTable(mapi_object_t *obj_table, struct mapi_SRowList *rowList)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct ModifyTable_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+ uint32_t i, j;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!rowList, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "ModifyTable");
+ size = 0;
+
+ /* Fill the GetTable operation */
+ request.rowList = *rowList;
+ request.rowList.padding = 0;
+ size += sizeof (uint8_t) + sizeof (uint16_t);
+
+ for (i = 0; i < rowList->cEntries; i++) {
+ size += sizeof (uint8_t);
+ for (j = 0; j < rowList->aEntries[i].lpProps.cValues; j++) {
+ size += get_mapi_property_size(&(rowList->aEntries[i].lpProps.lpProps[j]));
+ size += sizeof (uint32_t);
+ }
+ size += sizeof (uint16_t);
+ }
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_ModifyTable;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx= 0;
+ mapi_req->u.mapi_ModifyTable = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Etablishes search criteria for the container
+
+ \param obj_container the object we apply search criteria on
+ \param res pointer to a mapi_SRestriction structure defining the
+ search criteria
+ \param SearchFlags bitmask of flags that controls how the search
+ is performed
+ \param lpContainerList pointer to a list of identifiers
+ representing containers to be included in the search
+
+ SearchFlags can take the following values:
+
+ - BACKGROUND_SEARCH: Search run at normal priority relative to
+ other searches. This flag is mutually exclusive with the
+ FOREGROUND_SEARCH one.
+ - FOREGROUND_SEARCH: Search run at high priority relative to other
+ searches. This flag is mutually exclusive with the
+ BACKGROUND_SEARCH one.
+ - RECURSIVE_SEARCH: The search should include the containers
+ specified in the lpContainerList parameter and all of their child
+ container. This flag is mutually exclusive with the
+ SHALLOW_SEARCH one.
+ - RESTART_SEARCH: The search should be initiated, if this is the
+ first call to SetSearchCriteria, or restarted, if the search is
+ inactive. This flag is mutually exclusive with the STOP_SEARCH
+ flag.
+ - SHALLOW_SEARCH: The search should only look in the containers
+ specified in the lpContainerList parameter for matching
+ entries. This flag is mutually exclusive with the
+ RECURSIVE_SEARCH one.
+ - STOP_SEARCH: The search should be aborted. This flag is mutually
+ exclusive with the RESTART_SEARCH one.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetSearchCriteria
+ */
+_PUBLIC_ enum MAPISTATUS SetSearchCriteria(mapi_object_t *obj_container,
+ struct mapi_SRestriction *res,
+ uint32_t SearchFlags,
+ mapi_id_array_t *lpContainerList)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SetSearchCriteria_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_container, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!res, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_container);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SetSearchCriteria");
+ size = 0;
+
+ /* Fill the SetSearchCriteria operation */
+ request.res = *res;
+ size += get_mapi_SRestriction_size(res);
+ if (lpContainerList != NULL) {
+ request.FolderIdCount = lpContainerList->count;
+ size += sizeof (uint16_t);
+
+ mapi_id_array_get(mem_ctx, lpContainerList, &request.FolderIds);
+ size += lpContainerList->count * sizeof (uint64_t);
+ } else {
+ request.FolderIdCount = 0;
+ size += sizeof (uint16_t);
+ request.FolderIds = NULL;
+ }
+ request.SearchFlags = SearchFlags;
+ size += sizeof (uint32_t);
+
+ /* add subcontext size */
+ size += sizeof (uint16_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SetSearchCriteria;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SetSearchCriteria = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_container);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Obtains the search criteria for a container
+
+ \param obj_container the object we retrieve search criteria from
+ \param res pointer to a mapi_SRestriction structure defining the
+ search criteria
+ \param SearchFlags bitmask of flags that controls how the search
+ is performed
+ \param FolderIdCount number of FolderIds entries
+ \param FolderIds pointer to a list of identifiers
+ representing containers included in the search
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetSearchCriteria
+ */
+_PUBLIC_ enum MAPISTATUS GetSearchCriteria(mapi_object_t *obj_container,
+ struct mapi_SRestriction *res,
+ uint32_t *SearchFlags,
+ uint16_t *FolderIdCount,
+ uint64_t **FolderIds)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetSearchCriteria_req request;
+ struct GetSearchCriteria_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_container, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SearchFlags, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!FolderIdCount, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!FolderIds, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_container);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetSearchCriteria");
+ size = 0;
+
+ /* Fill the GetSearchCriteria operation */
+ request.UseUnicode = 0x1;
+ request.IncludeRestriction = 0x1;
+ request.IncludeFolders = 0x1;
+ size += 3 * sizeof (uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetSearchCriteria;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetSearchCriteria = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_container);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ reply = &mapi_response->mapi_repl->u.mapi_GetSearchCriteria;
+
+ res = &reply->res;
+ *FolderIdCount = reply->FolderIdCount;
+ *FolderIds = talloc_steal((TALLOC_CTX *)session, reply->FolderIds);
+ *SearchFlags = reply->SearchFlags;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IMAPIFolder.c
===================================================================
--- trunk/openchange/libmapi/IMAPIFolder.c (rev 0)
+++ trunk/openchange/libmapi/IMAPIFolder.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1091 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+
+/**
+ \file IMAPIFolder.c
+
+ \brief Folder related functions
+ */
+
+
+/**
+ \details The function creates a message in the specified folder,
+ and returns a pointer on this message.
+
+ \param obj_folder the folder to create the message in.
+ \param obj_message pointer to the newly created message.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenFolder, DeleteMessage, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS CreateMessage(mapi_object_t *obj_folder, mapi_object_t *obj_message)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct CreateMessage_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_folder);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CreateMessage");
+ size = 0;
+
+ /* Fill the OpenFolder operation */
+ request.handle_idx = 0x1;
+ size += sizeof (uint8_t);
+ request.CodePageId = 0xfff;
+ size += sizeof (uint16_t);
+ request.FolderId = mapi_object_get_id(obj_folder);
+ size += sizeof (uint64_t);
+ request.AssociatedFlag = 0;
+ size += sizeof (uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_CreateMessage;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_CreateMessage = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof(mapi_handle_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, mapi_handle_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* set object session and handle */
+ mapi_object_set_session(obj_message, session);
+ mapi_object_set_handle(obj_message, mapi_response->handles[1]);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Delete one or more messages
+
+ This function deletes one or more messages based on their ids from
+ a specified folder.
+
+ \param obj_folder the folder to delete messages from
+ \param id_messages the list of ids
+ \param cn_messages the number of messages in the id list.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenFolder, CreateMessage, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS DeleteMessage(mapi_object_t *obj_folder, mapi_id_t *id_messages,
+ uint32_t cn_messages)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct DeleteMessages_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_folder);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "DeleteMessages");
+ size = 0;
+
+ /* Fill the DeleteMessages operation */
+ request.WantAsynchronous = 0x0;
+ size += sizeof (uint8_t);
+ request.NotifyNonRead = 0x1;
+ size += sizeof(uint8_t);
+ request.cn_ids = (uint16_t)cn_messages;
+ size += sizeof(uint16_t);
+ request.message_ids = id_messages;
+ size += request.cn_ids * sizeof(mapi_id_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_DeleteMessages;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_DeleteMessages = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Obtain the status associated with a message
+
+ This function obtains the status associated with a message in the
+ given folder.
+
+ \param obj_folder the folder where the message is located
+ \param msgid the message ID
+ \param ulStatus the message status
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+ */
+_PUBLIC_ enum MAPISTATUS GetMessageStatus(mapi_object_t *obj_folder,
+ mapi_id_t msgid,
+ uint32_t *ulStatus)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetMessageStatus_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!msgid, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_folder);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetMessageStatus");
+ size = 0;
+
+ /* Fill the GetMessageStatus operation */
+ request.msgid = msgid;
+ size += sizeof (uint64_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetMessageStatus;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetMessageStatus = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ *ulStatus = mapi_response->mapi_repl->u.mapi_SetMessageStatus.ulOldStatus;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Set the status associated with a message
+
+ This function sets the status associated with a message in the
+ given folder.
+
+ \param obj_folder the folder where the message is located
+ \param msgid the message ID
+ \param ulNewStatus the new status to be assigned
+ \param ulNewStatusMask bitmask of flags hat is applied to the new
+ status indicating the flags to be set
+ \param ulOldStatus pointer on the previous status of the message
+
+ ulNewStatusMask possible values:
+ - MSGSTATUS_DELMARKED: the message is marked for deletion
+ - MSGSTATUS_HIDDEN: the message is not to be displayed
+ - MSGSTATUS_HIGHLIGHTED: the message is to be displayed highlighted
+ - MSGSTATUS_REMOTE_DELETE: the message has been marked for deletion
+ on the remote message store without downloading to the local
+ client.
+ - MSGSTATUS_REMOTE_DOWNLOAD: the message has been marked for
+ downloading from the remote message store to the local client.
+ - MSGSTATUS_TAGGED: The message has been tagged for a
+ client-defined purpose.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+ */
+_PUBLIC_ enum MAPISTATUS SetMessageStatus(mapi_object_t *obj_folder,
+ mapi_id_t msgid,
+ uint32_t ulNewStatus,
+ uint32_t ulNewStatusMask,
+ uint32_t *ulOldStatus)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SetMessageStatus_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!msgid, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_folder);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SetMessageStatus");
+ size = 0;
+
+ /* Fill the SetMessageStatus operation */
+ request.msgid = msgid;
+ size += sizeof (uint64_t);
+
+ request.ulNewStatus = ulNewStatus;
+ size += sizeof (uint32_t);
+
+ request.ulNewStatusMask = ulNewStatusMask;
+ size += sizeof (uint32_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SetMessageStatus;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SetMessageStatus = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ *ulOldStatus = mapi_response->mapi_repl->u.mapi_SetMessageStatus.ulOldStatus;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Copy or Move a message from a folder to another
+
+ \param obj_src The source folder
+ \param obj_dst The destination folder
+ \param message_id pointer to container object for message ids.
+ \param WantCopy boolean value, defines whether the operation is a
+ copy or a move
+
+ Possible values for WantCopy:
+ -# 0: Move
+ -# 1: Copy
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenFolder, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS MoveCopyMessages(mapi_object_t *obj_src,
+ mapi_object_t *obj_dst,
+ mapi_id_array_t *message_id,
+ bool WantCopy)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct MoveCopyMessages_req request;
+ struct mapi_session *session[2];
+ uint32_t size;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_src, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_dst, MAPI_E_INVALID_PARAMETER, NULL);
+ session[0] = mapi_object_get_session(obj_src);
+ session[1] = mapi_object_get_session(obj_dst);
+ OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "MoveCopyMessages");
+ size = 0;
+
+ /* Fill the CopyMessage operation */
+ request.handle_idx = 0x1;
+ size += sizeof (uint8_t);
+
+ request.count = message_id->count;
+ size += sizeof (uint16_t);
+
+ retval = mapi_id_array_get(mem_ctx, message_id, &(request.message_id));
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+ size += request.count * sizeof (mapi_id_t);
+
+ request.WantAsynchronous = 0;
+ size += sizeof (uint8_t);
+
+ request.WantCopy = WantCopy;
+ size += sizeof (uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_MoveCopyMessages;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_MoveCopyMessages = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_src);
+ mapi_request->handles[1] = mapi_object_get_handle(obj_dst);
+
+ status = emsmdb_transaction(session[0]->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Create a folder
+
+ The function creates a folder (defined with its name, comment and type)
+ within a specified folder.
+
+ \param obj_parent the folder to create the new folder in
+ \param ulFolderType the type of the folder
+ \param name the name of the new folder
+ \param comment the comment associated with the new folder
+ \param ulFlags flags associated with folder creation
+ \param obj_child pointer to the newly created folder
+
+ ulFlags possible values:
+ - MAPI_UNICODE: use UNICODE folder name and comment
+ - OPEN_IF_EXISTS: open the folder if it already exists
+
+ ulFolderType possible values:
+ - FOLDER_GENERIC
+ - FOLDER_SEARCH
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenFolder, DeleteFolder, EmptyFolder, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS CreateFolder(mapi_object_t *obj_parent,
+ uint8_t ulFolderType,
+ const char *name,
+ const char *comment,
+ uint32_t ulFlags,
+ mapi_object_t *obj_child)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct CreateFolder_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_parent, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!name, MAPI_E_NOT_INITIALIZED, NULL);
+ session = mapi_object_get_session(obj_parent);
+ OPENCHANGE_RETVAL_IF(!obj_parent, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Sanitify check on the folder type */
+ OPENCHANGE_RETVAL_IF((ulFolderType != FOLDER_GENERIC &&
+ ulFolderType != FOLDER_SEARCH),
+ MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CreateFolder");
+ size = 0;
+
+ /* Fill the CreateFolder operation */
+ request.handle_idx = 0x1;
+ size+= sizeof(uint8_t);
+ switch (ulFlags & 0xFFFF0000) {
+ case MAPI_UNICODE:
+ request.ulType = MAPI_FOLDER_UNICODE;
+ break;
+ default:
+ request.ulType = MAPI_FOLDER_ANSI;
+ break;
+ }
+ request.ulFolderType = ulFolderType;
+ size += sizeof(uint16_t);
+ request.ulFlags = ulFlags & 0xFFFF;
+ size += sizeof(uint16_t);
+
+ switch (request.ulType) {
+ case MAPI_FOLDER_ANSI:
+ request.FolderName.lpszA = name;
+ size += strlen(name) + 1;
+ break;
+ case MAPI_FOLDER_UNICODE:
+ request.FolderName.lpszW = name;
+ size += strlen(name) * 2 + 2;
+ break;
+ }
+
+ if (comment) {
+ switch(request.ulType) {
+ case MAPI_FOLDER_ANSI:
+ request.FolderComment.lpszA = comment;
+ size += strlen(comment) + 1;
+ break;
+ case MAPI_FOLDER_UNICODE:
+ request.FolderComment.lpszW = comment;
+ size += strlen(comment) * 2 + 2;
+ break;
+ }
+ } else {
+ switch(request.ulType) {
+ case MAPI_FOLDER_ANSI:
+ request.FolderComment.lpszA = "";
+ size += 1;
+ break;
+ case MAPI_FOLDER_UNICODE:
+ request.FolderComment.lpszW = "";
+ size += 2;
+ break;
+ }
+ }
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_CreateFolder;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_CreateFolder = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + (2 * sizeof(uint32_t));
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_parent);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Set object session, handle and id */
+ mapi_object_init(obj_child);
+ mapi_object_set_session(obj_child, session);
+ mapi_object_set_handle(obj_child, mapi_response->handles[1]);
+ mapi_object_set_id(obj_child, mapi_response->mapi_repl->u.mapi_CreateFolder.folder_id);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Empty the contents of a folder
+
+ This function empties (clears) the contents of a specified folder.
+
+ \param obj_folder the folder to empty
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenFolder, CreateFolder, DeleteFolder, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS EmptyFolder(mapi_object_t *obj_folder)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct EmptyFolder_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_folder);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "EmptyFolder");
+ size = 0;
+
+ /* Fill the EmptyFolder operation */
+ request.WantAsynchronous = 0x0;
+ size += sizeof (uint8_t);
+
+ request.WantDeleteAssociated = 0x0;
+ size += sizeof (uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_EmptyFolder;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_EmptyFolder = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof(uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Delete a folder
+
+ The function deletes a specified folder.
+
+ \param obj_parent the folder containing the folder to be deleted
+ \param FolderId the ID of the folder to delete
+ \param DeleteFolderFlags control DeleteFolder operation behavior
+ \param PartialCompletion pointer on a boolean value which specify
+ whether the operation was partially completed or not
+
+ Possible values for DeleteFolderFlags are:
+ -# DEL_MESSAGES Delete all the messages in the folder
+ -# DEL_FOLDERS Delete the subfolder and all of its subfolders
+ -# DELETE_HARD_DELETE Hard delete the folder
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenFolder, CreateFolder, EmptyFolder, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS DeleteFolder(mapi_object_t *obj_parent,
+ mapi_id_t FolderId,
+ uint8_t DeleteFolderFlags,
+ bool *PartialCompletion)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct DeleteFolder_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_parent, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_parent);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF((!(DeleteFolderFlags & 0x1)) &&
+ (!(DeleteFolderFlags & 0x4)) &&
+ (!(DeleteFolderFlags & 0x10)),
+ MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "DeleteFolder");
+ size = 0;
+
+ /* Fill the DeleteFolder operation */
+ request.DeleteFolderFlags = DeleteFolderFlags;
+ size += sizeof (uint8_t);
+ request.FolderId = FolderId;
+ size += sizeof (uint64_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_DeleteFolder;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_DeleteFolder = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof(uint32_t);
+ 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_parent);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ if (PartialCompletion) {
+ *PartialCompletion = mapi_response->mapi_repl->u.mapi_DeleteFolder.PartialCompletion;
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Moves a folder
+
+ \param obj_folder the folder to move
+ \param obj_src source object where the folder to move is stored
+ \param obj_dst destination object where the folder will be moved
+ \param NewFolderName the new folder name in the destination folder
+ \param UseUnicode whether the folder name is unicode encoded or not
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenFolder, CopyFolder
+ */
+_PUBLIC_ enum MAPISTATUS MoveFolder(mapi_object_t *obj_folder,
+ mapi_object_t *obj_src,
+ mapi_object_t *obj_dst,
+ char *NewFolderName,
+ bool UseUnicode)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct MoveFolder_req request;
+ struct mapi_session *session[3];
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_src, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_dst, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!NewFolderName, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session[0] = mapi_object_get_session(obj_folder);
+ session[1] = mapi_object_get_session(obj_src);
+ session[2] = mapi_object_get_session(obj_dst);
+ OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[2], MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "MoveFolder");
+ size = 0;
+
+ /* Fill the MoveFolder operation */
+ request.handle_idx = 0x1;
+ size += sizeof (uint8_t);
+
+ request.WantAsynchronous = 0;
+ size += sizeof (uint8_t);
+
+ request.UseUnicode = UseUnicode;
+ size += sizeof (uint8_t);
+
+ request.FolderId = mapi_object_get_id(obj_folder);
+ size += sizeof (uint64_t);
+
+ if (!request.UseUnicode) {
+ request.NewFolderName.lpszA = NewFolderName;
+ size += strlen(NewFolderName) + 1;
+ } else {
+ request.NewFolderName.lpszW = NewFolderName;
+ size += strlen(NewFolderName) * 2 + 2;
+ }
+
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_MoveFolder;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_MoveFolder = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_src);
+ mapi_request->handles[1] = mapi_object_get_handle(obj_dst);
+
+ status = emsmdb_transaction(session[0]->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Copy a folder
+
+ \param obj_folder the folder to copy
+ \param obj_src source object where the folder to copy is stored
+ \param obj_dst destination object where the folder will be copied
+ \param NewFolderName the new folder name in the destination folder
+ \param UseUnicode whether the folder name is unicode encoded or not
+ \param WantRecursive whether we should copy folder's subdirectories
+ or not
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developer may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenFolder, MoveFolder
+ */
+_PUBLIC_ enum MAPISTATUS CopyFolder(mapi_object_t *obj_folder,
+ mapi_object_t *obj_src,
+ mapi_object_t *obj_dst,
+ char *NewFolderName,
+ bool UseUnicode,
+ bool WantRecursive)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct CopyFolder_req request;
+ struct mapi_session *session[3];
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_src, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_dst, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!NewFolderName, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session[0] = mapi_object_get_session(obj_folder);
+ session[1] = mapi_object_get_session(obj_src);
+ session[2] = mapi_object_get_session(obj_dst);
+ OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[2], MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CopyFolder");
+
+ size = 0;
+
+ /* Fill the CopyFolder operation */
+ request.handle_idx = 0x1;
+ size += sizeof (uint8_t);
+
+ request.WantAsynchronous = 0x0;
+ size += sizeof (uint8_t);
+
+ request.WantRecursive = WantRecursive;
+ size += sizeof (uint8_t);
+
+ request.UseUnicode = UseUnicode;
+ size += sizeof (uint8_t);
+
+ request.FolderId = mapi_object_get_id(obj_folder);
+ size += sizeof (uint64_t);
+
+ if (!request.UseUnicode) {
+ request.NewFolderName.lpszA = NewFolderName;
+ size += strlen(NewFolderName) + 1;
+ } else {
+ request.NewFolderName.lpszW = NewFolderName;
+ size += strlen(NewFolderName) * 2 + 2;
+ }
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_CopyFolder;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_CopyFolder = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_src);
+ mapi_request->handles[1] = mapi_object_get_handle(obj_dst);
+
+ status = emsmdb_transaction(session[0]->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Set the Read Flags on one or more messages
+
+ \param obj_folder the folder containing the messages to change
+ \param ReadFlags a bitmap of flags controlling the changes to
+ PR_PROPERTY_FLAGS
+ \param MessageIdCount the number of messages in the MessageIds array
+ \param MessageIds an array of message ids to set Read flags for
+
+ Note that the obj_folder argument is the object corresponding to the
+ folder containing the messages (e.g. the result of CreateFolder() or
+ OpenFolder(). It is \em not the content table of that folder (unlike
+ SetMessageReadFlag().)
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetMessageReadFlags for a slightly different version, working on
+ a single message
+*/
+_PUBLIC_ enum MAPISTATUS SetReadFlags(mapi_object_t *obj_folder,
+ uint8_t ReadFlags,
+ uint16_t MessageIdCount,
+ uint64_t *MessageIds)
+{
+ TALLOC_CTX *mem_ctx;
+ uint32_t size;
+ struct SetReadFlags_req request;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct mapi_request *mapi_request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ struct mapi_response *mapi_response;
+ enum MAPISTATUS retval;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_folder);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SetReadFlags");
+
+ size = 0;
+
+ /* Fill the SetReadFlags operation */
+ request.WantAsynchronous = 0;
+ size += sizeof(uint8_t);
+ request.ReadFlags = ReadFlags;
+ size += sizeof(uint8_t);
+ request.MessageIdCount = MessageIdCount;
+ size += sizeof(uint16_t);
+ request.MessageIds = MessageIds;
+ size += sizeof(uint64_t) * MessageIdCount;
+
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SetReadFlags;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SetReadFlags = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof(uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* TODO: parse response */
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
Added: trunk/openchange/libmapi/IMAPIProp.c
===================================================================
--- trunk/openchange/libmapi/IMAPIProp.c (rev 0)
+++ trunk/openchange/libmapi/IMAPIProp.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1209 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+ Copyright (C) Brad Hards 2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+
+/**
+ \file IMAPIProp.c
+
+ \brief Properties and named properties operations.
+ */
+
+
+/**
+ \details Returns values of one or more properties for an object
+
+ The function takes a pointer on the object obj, a MAPITAGS array
+ specified in mapitags, and the count of properties. The function
+ returns associated values within the SPropValue values pointer.
+
+ The array of MAPI property tags can be filled with both known and
+ named properties.
+
+ \param obj the object to get properties on
+ \param SPropTagArray an array of MAPI property tags
+ \param lpProps the result of the query
+ \param PropCount the count of property tags
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj or SPropTagArray are null, or the
+ session context could not be obtained
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetProps, GetPropList, GetPropsAll, DeleteProps, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS GetProps(mapi_object_t *obj,
+ struct SPropTagArray *SPropTagArray,
+ struct SPropValue **lpProps, uint32_t *PropCount)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetProps_req request;
+ struct mapi_session *session;
+ struct mapi_nameid *nameid;
+ struct SPropTagArray *SPropTagArray2 = NULL;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ enum MAPISTATUS mapistatus;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+ bool named = false;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetProps");
+
+ /* Named property mapping */
+ nameid = mapi_nameid_new(mem_ctx);
+ retval = mapi_nameid_lookup_SPropTagArray(nameid, SPropTagArray);
+ if (retval == MAPI_E_SUCCESS) {
+ named = true;
+ SPropTagArray2 = talloc_zero(mem_ctx, struct SPropTagArray);
+ retval = GetIDsFromNames(obj, nameid->count, nameid->nameid, 0, &SPropTagArray2);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+ mapi_nameid_map_SPropTagArray(nameid, SPropTagArray, SPropTagArray2);
+ MAPIFreeBuffer(SPropTagArray2);
+
+ }
+ errno = 0;
+
+ /* Reset */
+ *PropCount = 0;
+ *lpProps = 0;
+ size = 0;
+
+ /* Fill the GetProps operation */
+ request.PropertySizeLimit = 0x0;
+ size += sizeof (uint16_t);
+ request.WantUnicode = 0x0;
+ size += sizeof (uint16_t);
+ request.prop_count = (uint16_t) SPropTagArray->cValues;
+ size += sizeof (uint16_t);
+ request.properties = SPropTagArray->aulPropTag;
+ size += request.prop_count * sizeof(uint32_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetProps;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetProps = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF((retval && retval != MAPI_W_ERRORS_RETURNED), retval, mem_ctx);
+
+ /* Read the SPropValue array from data blob.
+ fixme: replace the memory context by the object one.
+ */
+ if (named == true) {
+ mapi_nameid_unmap_SPropTagArray(nameid, SPropTagArray);
+ }
+ talloc_free(nameid);
+
+ mapistatus = emsmdb_get_SPropValue((TALLOC_CTX *)session,
+ global_mapi_ctx->lp_ctx,
+ &mapi_response->mapi_repl->u.mapi_GetProps.prop_data,
+ SPropTagArray, lpProps, PropCount,
+ mapi_response->mapi_repl->u.mapi_GetProps.layout);
+ OPENCHANGE_RETVAL_IF(!mapistatus && (retval == MAPI_W_ERRORS_RETURNED), retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Set one or more properties on a given object
+
+ This function sets one or more properties on a specified object.
+
+ \param obj the object to set properties on
+ \param lpProps the list of properties to set
+ \param PropCount the number of properties
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetProps, GetPropList, GetPropsAll, DeleteProps, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS SetProps(mapi_object_t *obj, struct SPropValue *lpProps,
+ unsigned long PropCount)
+{
+ TALLOC_CTX *mem_ctx;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SetProps_req request;
+ struct mapi_session *session;
+ struct mapi_nameid *nameid;
+ struct SPropTagArray *SPropTagArray = NULL;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ unsigned long i;
+ struct mapi_SPropValue *mapi_props;
+ bool named = false;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SetProps");
+ size = 0;
+
+ /* Named property mapping */
+ nameid = mapi_nameid_new(mem_ctx);
+ retval = mapi_nameid_lookup_SPropValue(nameid, lpProps, PropCount);
+ if (retval == MAPI_E_SUCCESS) {
+ named = true;
+ SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
+ retval = GetIDsFromNames(obj, nameid->count, nameid->nameid, 0, &SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+ mapi_nameid_map_SPropValue(nameid, lpProps, PropCount, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ }
+ errno = 0;
+
+ /* build the array */
+ request.values.lpProps = talloc_array(mem_ctx, struct mapi_SPropValue, PropCount);
+ mapi_props = request.values.lpProps;
+ for (i = 0; i < PropCount; i++) {
+ size += cast_mapi_SPropValue(&mapi_props[i], &lpProps[i]);
+ size += sizeof(uint32_t);
+ }
+
+ request.values.cValues = PropCount;
+ size += sizeof(uint16_t);
+
+ /* add the size of the subcontext that will be added on ndr layer */
+ size += sizeof(uint16_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SetProps;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SetProps = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ if (named == true) {
+ mapi_nameid_unmap_SPropValue(nameid, lpProps, PropCount);
+ }
+ talloc_free(nameid);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Makes permanent any changes made to an attachment since the
+ last save operation.
+
+ \param obj_parent the parent of the object to save changes for
+ \param obj_child the object to save changes for
+ \param flags the access flags to set on the saved object
+
+ Possible flags:
+ - KeepOpenReadOnly
+ - KeepOpenReadWrite
+ - ForceSave
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetProps, ModifyRecipients, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS SaveChangesAttachment(mapi_object_t *obj_parent,
+ mapi_object_t *obj_child,
+ enum SaveFlags flags)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SaveChangesAttachment_req request;
+ struct mapi_session *session[2];
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_parent, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_child, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF((flags != 0x9) && (flags != 0xA) && (flags != 0xC),
+ MAPI_E_INVALID_PARAMETER, NULL);
+
+ session[0] = mapi_object_get_session(obj_parent);
+ session[1] = mapi_object_get_session(obj_child);
+ OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SaveChangesAttachment");
+ size = 0;
+
+ /* Fill the SaveChangesAttachment operation */
+ request.handle_idx = 0x0;
+ request.SaveFlags = flags;
+ size += sizeof(uint8_t) + sizeof(uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SaveChangesAttachment;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SaveChangesAttachment = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_child);
+ mapi_request->handles[1] = mapi_object_get_handle(obj_parent);
+
+ status = emsmdb_transaction(session[0]->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve all the properties associated with a given object
+
+ \param obj the object to retrieve properties for
+ \param proptags the resulting list of properties associated with
+ the object
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetProps, GetPropsAll, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS GetPropList(mapi_object_t *obj,
+ struct SPropTagArray *proptags)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetPropList");
+
+ /* Reset */
+ proptags->cValues = 0;
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetPropList;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 1;
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Get the repsonse */
+ proptags->cValues = mapi_response->mapi_repl->u.mapi_GetPropList.count;
+ if (proptags->cValues) {
+ size = proptags->cValues * sizeof(enum MAPITAGS);
+ proptags->aulPropTag = talloc_array((TALLOC_CTX *)session, enum MAPITAGS, proptags->cValues);
+ memcpy((void*)proptags->aulPropTag,
+ (void*)mapi_response->mapi_repl->u.mapi_GetPropList.tags,
+ size);
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve all properties and values associated with an
+ object
+
+ This function returns all the properties and and associated values
+ for a given object.
+
+ \param obj the object to get the properties for
+ \param properties the properties / values for the object
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetProps, GetPropList, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS GetPropsAll(mapi_object_t *obj,
+ struct mapi_SPropValue_array *properties)
+{
+ TALLOC_CTX *mem_ctx;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetPropsAll_req request;
+ struct GetPropsAll_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetPropsAll");
+ size = 0;
+
+ /* Fill the GetPropsAll operation */
+ request.PropertySizeLimit = 0;
+ size += sizeof (uint16_t);
+ request.WantUnicode = 0;
+ size += sizeof (uint16_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetPropsAll;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetPropsAll = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ reply = &mapi_response->mapi_repl->u.mapi_GetPropsAll;
+ properties->cValues = reply->properties.cValues;
+ properties->lpProps = talloc_steal((TALLOC_CTX *)session, reply->properties.lpProps);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Delete one or more properties from an object
+
+ \param obj the object to remove properties from
+ \param proptags the properties to remove from the given object
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetProps, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS DeleteProps(mapi_object_t *obj,
+ struct SPropTagArray *proptags)
+{
+ TALLOC_CTX *mem_ctx;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct DeleteProps_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!proptags, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "DeleteProps");
+ size = 0;
+
+ /* Fill the DeleteProps operation */
+ request.count = proptags->cValues;
+ size += sizeof(uint16_t);
+ request.tags = proptags->aulPropTag;
+ size += proptags->cValues * sizeof(enum MAPITAGS);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_DeleteProps;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_DeleteProps = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Deletes property values from an object without invoking
+ replication.
+
+ \param obj the object to remove properties from
+ \param proptags the properties to remove from the given object
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa DeleteProps
+ */
+_PUBLIC_ enum MAPISTATUS DeletePropertiesNoReplicate(mapi_object_t *obj,
+ struct SPropTagArray *proptags)
+{
+ TALLOC_CTX *mem_ctx;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct DeletePropertiesNoReplicate_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!proptags, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "DeletePropertiesNoReplicate");
+ size = 0;
+
+ /* Fill the DeletePropertiesNoReplicate operation */
+ request.PropertyTags.cValues = proptags->cValues;
+ size += sizeof (uint16_t);
+ request.PropertyTags.aulPropTag = proptags->aulPropTag;
+ size += proptags->cValues * sizeof (enum MAPITAGS);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_DeletePropertiesNoReplicate;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_DeletePropertiesNoReplicate = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Provides the property names that correspond to one
+ or more property identifiers.
+
+ \param obj the object we are retrieving the names from
+ \param ulPropTag the mapped property tag
+ \param count count of property names pointed to by the nameid
+ parameter returned by the server
+ \param nameid pointer to a pointer to property names returned by
+ the server
+
+ ulPropTag must be a property with type set to PT_NULL
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetIDsFromNames, QueryNamesFromIDs
+*/
+_PUBLIC_ enum MAPISTATUS GetNamesFromIDs(mapi_object_t *obj,
+ enum MAPITAGS ulPropTag,
+ uint16_t *count,
+ struct MAPINAMEID **nameid)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetNamesFromIDs_req request;
+ struct GetNamesFromIDs_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size= 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Initialization */
+ mem_ctx = talloc_named(NULL, 0, "GetNamesFromIDs");
+ size = 0;
+
+ /* Fill the GetNamesFromIDs operation */
+ request.ulPropTag = ulPropTag;
+ size += sizeof (uint32_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetNamesFromIDs;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetNamesFromIDs = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Fill in count */
+ reply = &mapi_response->mapi_repl->u.mapi_GetNamesFromIDs;
+ *count = reply->count;
+
+ /* Fill MAPINAMEID struct */
+ *nameid = talloc_steal((TALLOC_CTX *)session, reply->nameid);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Provides the property identifiers that correspond to one
+ or more property names.
+
+ \param obj the object we are retrieving the identifiers from
+ \param count count of property names pointed to by the nameid
+ parameter.
+ \param nameid pointer to an array of property names
+ \param ulFlags indicates how the property identifiers should be
+ returned
+ \param proptags pointer to a pointer to an array of property tags
+ containing existing or newly assigned property
+ identifiers. Property types in this array are set to PT_NULL.
+
+ ulFlags can be set to:
+ - 0 retrieves named properties from the server
+ - MAPI_CREATE create the named properties if they don't exist on
+ the server
+
+ \note count and nameid parameter can automatically be built
+ using the mapi_nameid API.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetIDsFromNames, QueryNamesFromIDs, mapi_nameid_new
+*/
+_PUBLIC_ enum MAPISTATUS GetIDsFromNames(mapi_object_t *obj,
+ uint16_t count,
+ struct MAPINAMEID *nameid,
+ uint32_t ulFlags,
+ struct SPropTagArray **proptags)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetIDsFromNames_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+ uint32_t i;
+
+ /* sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!count, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!nameid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!proptags, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!proptags[0], MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Initialization */
+ mem_ctx = talloc_named(NULL, 0, "GetIDsFromNames");
+ size = 0;
+
+ /* Fill the GetIDsFromNames operation */
+ request.ulFlags = ulFlags;
+ request.count = count;
+ size += sizeof (uint8_t) + sizeof (uint16_t);
+
+ request.nameid = nameid;
+ for (i = 0; i < count; i++) {
+ size += sizeof (uint8_t) + sizeof (request.nameid[i].lpguid);
+ switch (request.nameid[i].ulKind) {
+ case MNID_ID:
+ size += sizeof (request.nameid[i].kind.lid);
+ break;
+ case MNID_STRING:
+ size += strlen(request.nameid[i].kind.lpwstr.Name) * 2 + 2;
+ size += sizeof (uint8_t);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetIDsFromNames;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetIDsFromNames = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Fill the SPropTagArray */
+ proptags[0]->cValues = mapi_response->mapi_repl->u.mapi_GetIDsFromNames.count;
+ proptags[0]->aulPropTag = talloc_array((TALLOC_CTX *)proptags[0], uint32_t, proptags[0]->cValues);
+ for (i = 0; i < proptags[0]->cValues; i++) {
+ proptags[0]->aulPropTag[i] = (mapi_response->mapi_repl->u.mapi_GetIDsFromNames.propID[i] << 16) | PT_UNSPECIFIED;
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Provides the property names that correspond to one or more
+ property identifiers.
+
+ \param obj the object to obtain the properties for
+ \param queryFlags A set of flags that can restrict the type of properties
+ \param guid a pointer to the GUID for the property set to fetch (null for all
+ property sets.
+ \param count count of property names pointed to by the nameid and propID
+ parameters returned by the server
+ \param propID pointer to an array of property IDs returned by the server
+ \param nameid pointer to an array of property names returned by
+ the server
+
+ \note queryFlags can be NoStrings (0x1) or NoIds (0x2), neither or both.
+ NoStrings will produce only ID properties, NoIds will produce only named
+ properties, and both will result in no output.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \sa GetNamesFromIDs
+*/
+_PUBLIC_ enum MAPISTATUS QueryNamedProperties(mapi_object_t *obj,
+ uint8_t queryFlags,
+ struct GUID *guid,
+ uint16_t *count,
+ uint16_t **propID,
+ struct MAPINAMEID **nameid)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct QueryNamedProperties_req request;
+ struct QueryNamedProperties_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Initialization */
+ mem_ctx = talloc_named(NULL, 0, "QueryNamesFromIDs");
+ size = 0;
+
+ /* Fill the QueryNamedProperties operation */
+ request.QueryFlags = queryFlags;
+ size += sizeof (uint8_t);
+
+ if (guid) {
+ request.HasGuid = 0x1; /* true */
+ size += sizeof (uint8_t);
+ request.PropertyGuid.guid = *guid;
+ size += sizeof (struct GUID);
+ } else {
+ request.HasGuid = 0x0; /* false */
+ size += sizeof (uint8_t);
+ }
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_QueryNamedProperties;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_QueryNamedProperties = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx,mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Fill [out] parameters */
+ reply = &mapi_response->mapi_repl->u.mapi_QueryNamedProperties;
+
+ *count = reply->IdCount;
+ *propID = talloc_steal((TALLOC_CTX *)session, reply->PropertyIds);
+ *nameid = talloc_steal((TALLOC_CTX *)session, reply->PropertyNames);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Copy properties from one object to another
+
+ This function copies (or moves) specified properties from
+ one object to another.
+
+ \param obj_src the object to copy properties from
+ \param obj_dst the object to set properties on
+ \param copyFlags flags to determine whether to copy or
+ move, and whether to overwrite existing properties.
+ \param tags the list of properties to copy
+ \param problemCount (return value) number of entries in the problems array
+ \param problems (return value) array of problemCount entries.
+
+ The caller is responsible for freeing the \b problems array
+ using MAPIFreeBuffer(). If the \b problemCount pointer is NULL,
+ then the problems array will not be returned.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetProps, SetProps, DeleteProps, CopyTo, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS CopyProps(mapi_object_t *obj_src,
+ mapi_object_t *obj_dst,
+ struct SPropTagArray *tags,
+ uint8_t copyFlags,
+ uint16_t *problemCount,
+ struct PropertyProblem **problems)
+
+{
+ TALLOC_CTX *mem_ctx;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct CopyProperties_req request;
+ struct mapi_session *session[2];
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ int i;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_src, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_dst, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!tags, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session[0] = mapi_object_get_session(obj_src);
+ session[1] = mapi_object_get_session(obj_dst);
+ OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CopyProps");
+ size = 0;
+
+ /* Fill the CopyProperties operation */
+ request.handle_idx = 0x1;
+ size += sizeof(uint8_t);
+ request.WantAsynchronous = 0x0;
+ size += sizeof(uint8_t);
+ request.CopyFlags = copyFlags;
+ size += sizeof(uint8_t);
+ request.PropertyTags.cValues = tags->cValues;
+ size += sizeof(uint16_t);
+ request.PropertyTags.aulPropTag = tags->aulPropTag;
+ size += tags->cValues * sizeof(enum MAPITAGS);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_CopyProperties;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_CopyProperties = request;
+ size += 5; // sizeof( EcDoRpc_MAPI_REQ )
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) *2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_src);
+ mapi_request->handles[1] = mapi_object_get_handle(obj_dst);
+
+ status = emsmdb_transaction(session[0]->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ if (problemCount) {
+ *problemCount = mapi_response->mapi_repl->u.mapi_CopyProperties.PropertyProblemCount;
+ *problems = talloc_array((TALLOC_CTX *)session[0], struct PropertyProblem, *problemCount);
+ for(i=0; i < *problemCount; ++i) {
+ (*(problems[i])).index = mapi_response->mapi_repl->u.mapi_CopyProperties.PropertyProblem[i].index;
+ (*(problems[i])).property_tag = mapi_response->mapi_repl->u.mapi_CopyProperties.PropertyProblem[i].property_tag;
+ (*(problems[i])).error_code = mapi_response->mapi_repl->u.mapi_CopyProperties.PropertyProblem[i].error_code;
+ }
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Copy multiple properties from one object to another
+
+ This function copies (or moves) properties from one object to
+ another. Unlike CopyProperties, this function copies all properties
+ except those identified.
+
+ \param obj_src the object to copy properties from
+ \param obj_dst the object to set properties on
+ \param excludeTags the list of properties to \em not copy
+ \param copyFlags flags to determine whether to copy or
+ move, and whether to overwrite existing properties.
+ \param problemCount (return value) number of entries in the problems array
+ \param problems (return value) array of problemCount entries.
+
+ The caller is responsible for freeing the \b problems array
+ using MAPIFreeBuffer(). If the \b problemCount pointer is NULL,
+ then the problems array will not be returned.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetProps, SetProps, DeleteProps, CopyProps
+*/
+_PUBLIC_ enum MAPISTATUS CopyTo(mapi_object_t *obj_src,
+ mapi_object_t *obj_dst,
+ struct SPropTagArray *excludeTags,
+ uint8_t copyFlags,
+ uint16_t *problemCount,
+ struct PropertyProblem **problems)
+
+{
+ TALLOC_CTX *mem_ctx;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct CopyTo_req request;
+ struct mapi_session *session[2];
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ int i;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_src, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_dst, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!excludeTags, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session[0] = mapi_object_get_session(obj_src);
+ session[1] = mapi_object_get_session(obj_dst);
+ OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CopyProps");
+ size = 0;
+
+ /* Fill the CopyProperties operation */
+ request.handle_idx = 0x1;
+ size += sizeof(uint8_t);
+ request.WantAsynchronous = 0x0;
+ size += sizeof(uint8_t);
+ request.WantSubObjects = 0x1;
+ size += sizeof(uint8_t);
+ request.CopyFlags = copyFlags;
+ size += sizeof(uint8_t);
+ request.ExcludedTags.cValues = (uint16_t)excludeTags->cValues;
+ size += sizeof(uint16_t);
+ request.ExcludedTags.aulPropTag = excludeTags->aulPropTag;
+ size += excludeTags->cValues * sizeof(enum MAPITAGS);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_CopyTo;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_CopyTo = request;
+ size += 5; // sizeof( EcDoRpc_MAPI_REQ )
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) *2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_src);
+ mapi_request->handles[1] = mapi_object_get_handle(obj_dst);
+
+ status = emsmdb_transaction(session[0]->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ if (problemCount) {
+ *problemCount = mapi_response->mapi_repl->u.mapi_CopyTo.PropertyProblemCount;
+ *problems = talloc_array((TALLOC_CTX *)session[0], struct PropertyProblem, *problemCount);
+ for(i=0; i < *problemCount; ++i) {
+ (*(problems[i])).index = mapi_response->mapi_repl->u.mapi_CopyTo.PropertyProblem[i].index;
+ (*(problems[i])).property_tag = mapi_response->mapi_repl->u.mapi_CopyTo.PropertyProblem[i].property_tag;
+ (*(problems[i])).error_code = mapi_response->mapi_repl->u.mapi_CopyTo.PropertyProblem[i].error_code;
+ }
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IMAPISession.c
===================================================================
--- trunk/openchange/libmapi/IMAPISession.c (rev 0)
+++ trunk/openchange/libmapi/IMAPISession.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,289 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+
+/**
+ \file IMAPISession.c
+
+ \brief Session initialization options
+ */
+
+
+/**
+ \details Open the Public Folder store
+
+ This function opens the public folder store. This allows access to
+ the public folders.
+
+ \param obj_store the result of opening the store
+ \param session pointer to the MAPI session context
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MAPIInitialize which is required before opening the store
+ \sa GetLastError to check the result of a failed call, if necessary
+ \sa OpenMsgStore if you need access to the message store folders
+*/
+_PUBLIC_ enum MAPISTATUS OpenPublicFolder(struct mapi_session *session,
+ mapi_object_t *obj_store)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct Logon_req request;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_store_t *store;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session->profile, MAPI_E_NOT_INITIALIZED, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "OpenPublicFolder");
+ size = 0;
+
+ /* Fill the Logon operation */
+ request.LogonFlags = 0;
+ size += sizeof (uint8_t);
+ request.OpenFlags = PUBLIC;
+ size += sizeof (uint32_t);
+ request.StoreState = 0;
+ size += sizeof (uint32_t);
+ request.EssDN = NULL;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_Logon;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_Logon = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) + 2;
+ mapi_request->length = size + 2;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
+ mapi_request->handles[0] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* retrieve object session and handle */
+ mapi_object_set_session(obj_store, session);
+ mapi_object_set_handle(obj_store, mapi_response->handles[0]);
+
+ /* retrieve store content */
+ obj_store->private_data = talloc((TALLOC_CTX *)session, mapi_object_store_t);
+ store = (mapi_object_store_t*)obj_store->private_data;
+ OPENCHANGE_RETVAL_IF(!obj_store->private_data, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ store->fid_pf_public_root = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_pf.FolderIds[0];
+ store->fid_pf_ipm_subtree = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_pf.FolderIds[1];
+ store->fid_pf_non_ipm_subtree = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_pf.FolderIds[2];
+ store->fid_pf_EFormsRegistryRoot = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_pf.FolderIds[3];
+ store->fid_pf_FreeBusyRoot = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_pf.FolderIds[4];
+ store->fid_pf_OfflineAB = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_pf.FolderIds[5];
+ store->fid_pf_EFormsRegistry = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_pf.FolderIds[6];
+ store->fid_pf_LocalSiteFreeBusy = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_pf.FolderIds[7];
+ store->fid_pf_LocalSiteOfflineAB = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_pf.FolderIds[8];
+ store->fid_pf_NNTPArticle = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_pf.FolderIds[9];
+ store->cached_mailbox_fid = false;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Open the Message Store
+
+ This function opens the main message store. This allows access to
+ the normal user folders.
+
+ \param session pointer to the MAPI session context
+ \param obj_store the result of opening the store
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MAPIInitialize which is required before opening the store
+ \sa GetLastError to check the result of a failed call, if necessary
+ \sa OpenPublicFolder if you need access to the public folders
+*/
+_PUBLIC_ enum MAPISTATUS OpenMsgStore(struct mapi_session *session,
+ mapi_object_t *obj_store)
+{
+ enum MAPISTATUS retval;
+
+ /* sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session->profile, MAPI_E_NOT_INITIALIZED, NULL);
+
+ retval = OpenUserMailbox(session, session->profile->username, obj_store);
+
+ /* Exchange clustered case */
+ if ((retval != MAPI_E_SUCCESS) &&
+ ((GetLastError() == ecUnknownUser) || (GetLastError() == MAPI_E_LOGON_FAILED))) {
+ errno = 0;
+ retval = OpenUserMailbox(session, NULL, obj_store);
+ }
+
+ return retval;
+}
+
+
+/**
+ \details Open another user mailbox
+
+ This function opens the main message store. This allows access to
+ the normal user folders.
+
+ \param session pointer to the MAPI session context
+ \param username name of the user's mailbox to open
+ \param obj_store the result of opening the store
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MAPIInitialize which is required before opening the store
+ \sa GetLastError to check the result of a failed call, if necessary
+ \sa OpenPublicFolder if you need access to the public folders
+ */
+_PUBLIC_ enum MAPISTATUS OpenUserMailbox(struct mapi_session *session,
+ const char *username,
+ mapi_object_t *obj_store)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct Logon_req request;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_store_t *store;
+ char *mailbox;
+
+ /* sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session->profile, MAPI_E_NOT_INITIALIZED, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "OpenMsgStore");
+ size = 0;
+
+ if (!username) {
+ mailbox = talloc_strdup(mem_ctx, session->profile->mailbox);
+ } else {
+ mailbox = talloc_asprintf(mem_ctx, "/o=%s/ou=%s/cn=Recipients/cn=%s", session->profile->org,
+ session->profile->ou, username);
+ }
+
+ /* Fill the Logon operation */
+ request.LogonFlags = LogonPrivate;
+ size += sizeof (uint8_t);
+ request.OpenFlags = HOME_LOGON | TAKE_OWNERSHIP | NO_MAIL;
+ size += sizeof (uint32_t);
+ request.StoreState = 0;
+ size += sizeof (uint32_t);
+ request.EssDN = talloc_strdup(mem_ctx, mailbox);
+ size += strlen(request.EssDN) + 1;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_Logon;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_Logon = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) + 2;
+ mapi_request->length = size + 2;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
+ mapi_request->handles[0] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* set object session and handle */
+ mapi_object_set_session(obj_store, session);
+ mapi_object_set_handle(obj_store, mapi_response->handles[0]);
+
+ /* retrieve store content */
+ obj_store->private_data = talloc((TALLOC_CTX *)session, mapi_object_store_t);
+ store = (mapi_object_store_t *)obj_store->private_data;
+ OPENCHANGE_RETVAL_IF(!obj_store->private_data, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ store->fid_mailbox_root = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[0];
+ store->fid_deferred_actions = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[1];
+ store->fid_spooler_queue = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[2];
+ store->fid_top_information_store = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[3];
+ store->fid_inbox = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[4];
+ store->fid_outbox = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[5];
+ store->fid_sent_items = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[6];
+ store->fid_deleted_items = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[7];
+ store->fid_common_views = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[8];
+ store->fid_schedule = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[9];
+ store->fid_search = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[10];
+ store->fid_views = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[11];
+ store->fid_shortcuts = mapi_response->mapi_repl->u.mapi_Logon.LogonType.store_mailbox.FolderIds[12];
+ store->cached_mailbox_fid = false;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IMAPISupport.c
===================================================================
--- trunk/openchange/libmapi/IMAPISupport.c (rev 0)
+++ trunk/openchange/libmapi/IMAPISupport.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,376 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+
+
+/**
+ \file IMAPISupport.c
+
+ \brief MAPI notifications functions
+ */
+
+
+/**
+ \details Register an object to receive notifications
+
+ This function registers notifications on the Exchange server for an
+ object. The function holds the notifications intended to be
+ monitored in as a bitmask.
+
+ \param obj the object to get notifications for
+ \param connection connection identifier for callabck function
+ \param NotificationFlags mask for events to provide notifications for (see
+ below)
+ \param WholeStore whether the scope for this notification is whole
+ database
+ \param notify_callback notification callback function.
+
+ The Notification Flags can take the following values:
+ - fnevCriticalError
+ - fnevNewMail
+ - fnevObjectCreated
+ - fnevObjectDeleted
+ - fnevObjectModified
+ - fnevObjectMoved
+ - fnevObjectCopied
+ - fnevSearchComplete
+ - fnevTableModified
+ - fnevStatusObjectModified
+ - fnevReservedForMapi
+ - fnevExtended
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa RegisterNotification, Unsubscribe, MonitorNotification,
+ GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS Subscribe(mapi_object_t *obj, uint32_t *connection,
+ uint16_t NotificationFlags,
+ bool WholeStore,
+ mapi_notify_callback_t notify_callback)
+{
+ TALLOC_CTX *mem_ctx;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct RegisterNotification_req request;
+ struct notifications *notification;
+ struct mapi_notify_ctx *notify_ctx;
+ struct mapi_session *session;
+ enum MAPISTATUS retval;
+ NTSTATUS status;
+ uint32_t size = 0;
+ static uint32_t ulConnection = 0;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!connection, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "Subscribe");
+
+ /* Fill the Subscribe operation */
+ request.handle_idx = 0x1;
+ size += sizeof (uint8_t);
+
+ request.NotificationFlags = NotificationFlags;
+ size += sizeof (uint16_t);
+
+ request.WantWholeStore = WholeStore;
+ size += sizeof (uint8_t);
+
+ if (WholeStore == false) {
+ request.FolderId.ID = mapi_object_get_id(obj);
+ size += sizeof (uint64_t);
+
+ request.MessageId.ID = 0x0;
+ size += sizeof (uint64_t);
+ }
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_RegisterNotification;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_RegisterNotification = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* add the notification to the list */
+ ulConnection++;
+ notify_ctx = session->notify_ctx;
+ notification = talloc_zero((TALLOC_CTX *)session, struct notifications);
+
+ notification->ulConnection = ulConnection;
+ notification->parentID = mapi_object_get_id(obj);
+ *connection = ulConnection;
+
+ /* set notification handle */
+ mapi_object_init(¬ification->obj_notif);
+ mapi_object_set_handle(¬ification->obj_notif, mapi_response->handles[1]);
+
+ notification->NotificationFlags = NotificationFlags;
+ notification->callback = notify_callback;
+
+ DLIST_ADD(notify_ctx->notifications, notification);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Unregister notifications on a given object.
+
+ Cancel any notification registrations associated with the notify
+ object. This function unregisters notifications on the Exchange
+ server for the object specified with its connection number
+ ulConnection. The function will releases the notification on the
+ Exchange server and remove the entry from the internal
+ notifications list.
+
+ The function takes a callback to execute when such notification
+ occurs and returns the ulConnection identifier we can use in
+ further management.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa RegisterNotification, Subscribe, MonitorNotification,
+ GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS Unsubscribe(struct mapi_session *session, uint32_t ulConnection)
+{
+ enum MAPISTATUS retval;
+ struct mapi_notify_ctx *notify_ctx;
+ struct notifications *notification;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session->notify_ctx, MAPI_E_INVALID_PARAMETER, NULL);
+
+ notify_ctx = session->notify_ctx;
+ notification = notify_ctx->notifications;
+
+ while (notification) {
+ if (notification->ulConnection == ulConnection) {
+ retval = Release(¬ification->obj_notif);
+ mapi_errstr("Release", GetLastError());
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+ DLIST_REMOVE(notify_ctx->notifications, notification);
+ break;
+ }
+ notification = notification->next;
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+static enum MAPISTATUS ProcessNotification(struct mapi_notify_ctx *notify_ctx,
+ struct mapi_response *mapi_response,
+ void *private_data)
+{
+ struct notifications *notification;
+ void *NotificationData;
+ uint32_t i;
+
+ if (!mapi_response || !mapi_response->mapi_repl) return MAPI_E_INVALID_PARAMETER;
+
+ for (i = 0; mapi_response->mapi_repl[i].opnum; i++) {
+ if (mapi_response->mapi_repl[i].opnum == op_MAPI_Notify) {
+ switch(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationType) {
+ case fnevNewMail:
+ case fnevMbit|fnevNewMail:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.NewMailNotification);
+ break;
+ case fnevObjectCreated:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.FolderCreatedNotification);
+ break;
+ case fnevObjectDeleted:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.FolderDeletedNotification);
+ break;
+ case fnevObjectModified:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.FolderModifiedNotification_10);
+ break;
+ case fnevObjectMoved:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.FolderMoveNotification);
+ break;
+ case fnevObjectCopied:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.FolderCopyNotification);
+ break;
+ case fnevSearchComplete:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.SearchCompleteNotification);
+ break;
+ case fnevTableModified:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.HierarchyTableChange);
+ break;
+ case fnevStatusObjectModified:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.IcsNotification);
+ break;
+ case fnevTbit|fnevObjectModified:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.FolderModifiedNotification_1010);
+ break;
+ case fnevUbit|fnevObjectModified:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.FolderModifiedNotification_2010);
+ break;
+ case fnevTbit|fnevUbit|fnevObjectModified:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.FolderModifiedNotification_3010);
+ break;
+ case fnevMbit|fnevObjectCreated:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.MessageCreatedNotification);
+ break;
+ case fnevMbit|fnevObjectDeleted:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.MessageDeletedNotification);
+ break;
+ case fnevMbit|fnevObjectModified:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.MessageModifiedNotification);
+ break;
+ case fnevMbit|fnevObjectMoved:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.MessageMoveNotification);
+ break;
+ case fnevMbit|fnevObjectCopied:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.MessageCopyNotification);
+ break;
+ case fnevMbit|fnevTableModified:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.ContentsTableChange);
+ break;
+ case fnevMbit|fnevSbit|fnevObjectDeleted:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.SearchMessageRemovedNotification);
+ break;
+ case fnevMbit|fnevSbit|fnevObjectModified:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.SearchMessageModifiedNotification);
+ break;
+ case fnevMbit|fnevSbit|fnevTableModified:
+ NotificationData = (void *)&(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationData.SearchTableChange);
+ break;
+ default:
+ NotificationData = NULL;
+ break;
+ }
+ notification = notify_ctx->notifications;
+ while (notification->ulConnection) {
+ if (notification->NotificationFlags & mapi_response->mapi_repl[i].u.mapi_Notify.NotificationType) {
+ if (notification->callback) {
+ notification->callback(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationType,
+ (void *)NotificationData,
+ (void *)private_data);
+ }
+ }
+ notification = notification->next;
+ }
+ }
+ }
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Wait for notifications and process them
+
+ This function indefinively waits for notifications on the UDP port
+ and generates the traffic needed to receive MAPI
+ notifications. These MAPI notifications are next compared to the
+ registered ones and the callback specified in Subscribe() called if
+ it matches.
+
+ Note that the function will loop indefinitively until an error
+ occurs.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa RegisterNotification, Subscribe, Unsubscribe, GetLastError
+
+ \note This code is experimental. The current implementation is
+ non-threaded, only supports fnevNewmail and fnevCreatedObject
+ notifications and will block your process until you send a signal.
+*/
+_PUBLIC_ enum MAPISTATUS MonitorNotification(struct mapi_session *session,
+ void *private_data)
+{
+ struct mapi_response *mapi_response;
+ struct mapi_notify_ctx *notify_ctx;
+ enum MAPISTATUS retval;
+ NTSTATUS status;
+ int is_done;
+ int err;
+ char buf[512];
+
+ /* sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session->notify_ctx, MAPI_E_INVALID_PARAMETER, NULL);
+
+ notify_ctx = session->notify_ctx;
+
+ is_done = 0;
+ while (!is_done) {
+ err = read(notify_ctx->fd, buf, sizeof(buf));
+ if (err > 0) {
+ status = emsmdb_transaction_null((struct emsmdb_context *)session->emsmdb->ctx, &mapi_response);
+ if (!NT_STATUS_IS_OK(status)) {
+ err = -1;
+ } else {
+ retval = ProcessNotification(notify_ctx, mapi_response, private_data);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+ }
+ }
+ if (err <= 0) is_done = 1;
+ }
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IMAPITable.c
===================================================================
--- trunk/openchange/libmapi/IMAPITable.c (rev 0)
+++ trunk/openchange/libmapi/IMAPITable.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1842 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+ Copyright (C) Brad Hards 2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+/**
+ \file IMAPITable.c
+
+ \brief Operations on tables
+ */
+
+
+/**
+ \details Defines the particular properties and order of properties
+ to appear as columns in the table.
+
+ \param obj_table the table the function is setting columns for
+ \param properties the properties intended to be set
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_W_ERROR_RETURNED: Problem encountered while trying to set
+ one or more properties
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa QueryRows, QueryColumns, SeekRow, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS SetColumns(mapi_object_t *obj_table,
+ struct SPropTagArray *properties)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SetColumns_req request;
+ struct mapi_session *session;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ mapi_object_table_t *table;
+
+ /* sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SetColumns");
+ size = 0;
+
+ /* Fill the SetColumns operation */
+ request.SetColumnsFlags = SetColumns_TBL_SYNC;
+ request.prop_count = properties->cValues;
+ request.properties = properties->aulPropTag;
+ size += 3 + request.prop_count * sizeof (uint32_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SetColumns;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SetColumns = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval && (retval != MAPI_W_ERRORS_RETURNED), retval, mem_ctx);
+
+ /* recopy property tags into table */
+ /* fixme: obj_table->private_data should be initialized during opening, not here */
+ if (obj_table->private_data == NULL) {
+ obj_table->private_data = talloc((TALLOC_CTX *)session, mapi_object_table_t);
+ }
+
+ table = (mapi_object_table_t *)obj_table->private_data;
+ if (table) {
+ table->proptags.cValues = properties->cValues;
+ table->proptags.aulPropTag = talloc_array((TALLOC_CTX *)obj_table->private_data,
+ enum MAPITAGS, table->proptags.cValues);
+ memcpy((void*)table->proptags.aulPropTag, (void*)properties->aulPropTag,
+ table->proptags.cValues * sizeof(enum MAPITAGS));
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns the approximate cursor position
+
+ \param obj_table pointer to the table's object
+ \param Numerator pointer to the numerator of the fraction
+ identifying the table position
+ \param Denominator pointer to the denominator of the fraction
+ identifying the table position
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa QueryRows
+*/
+_PUBLIC_ enum MAPISTATUS QueryPosition(mapi_object_t *obj_table,
+ uint32_t *Numerator,
+ uint32_t *Denominator)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "QueryPosition");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_QueryPosition;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ if (Numerator) {
+ *Numerator = mapi_response->mapi_repl->u.mapi_QueryPosition.Numerator;
+ }
+
+ if (Denominator) {
+ *Denominator = mapi_response->mapi_repl->u.mapi_QueryPosition.Denominator;
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns a RowSet with the properties returned by the
+ server
+
+ \param obj_table the table we are requesting properties from
+ \param row_count the maximum number of rows to retrieve
+ \param flags flags to use for the query
+ \param rowSet the results
+
+ flags possible values:
+ - TBL_ADVANCE: index automatically increased from last rowcount
+ - TBL_NOADVANCE: should be used for a single QueryRows call
+ - TBL_ENABLEPACKEDBUFFERS: (not yet implemented)
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetColumns, QueryPosition, QueryColumns, SeekRow
+ */
+_PUBLIC_ enum MAPISTATUS QueryRows(mapi_object_t *obj_table, uint16_t row_count,
+ enum QueryRowsFlags flags,
+ struct SRowSet *rowSet)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct QueryRows_req request;
+ struct QueryRows_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_table_t *table;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "QueryRows");
+ size = 0;
+
+ /* Fill the QueryRows operation */
+ request.QueryRowsFlags = flags;
+ /* TODO: search backwards for negative row_count */
+ request.ForwardRead = 1;
+ request.RowCount = row_count;
+ size += 4;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_QueryRows;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_QueryRows = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* table contains mapitags from previous SetColumns */
+ table = (mapi_object_table_t *)obj_table->private_data;
+ OPENCHANGE_RETVAL_IF(!table, MAPI_E_INVALID_OBJECT, mem_ctx);
+
+ /* TODO: handle Origin */
+ reply = &mapi_response->mapi_repl->u.mapi_QueryRows;
+ rowSet->cRows = reply->RowCount;
+ rowSet->aRow = talloc_array((TALLOC_CTX *)table, struct SRow, rowSet->cRows);
+ emsmdb_get_SRowSet((TALLOC_CTX *)table, global_mapi_ctx->lp_ctx, rowSet, &table->proptags, &reply->RowData);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieves the set of columns defined in the current table
+ view
+
+ \param obj_table the table we are retrieving columns from
+ \param cols pointer to an array of property tags
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetColumns, QueryRows
+*/
+_PUBLIC_ enum MAPISTATUS QueryColumns(mapi_object_t *obj_table,
+ struct SPropTagArray *cols)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct QueryColumnsAll_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_table_t *table;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "QueryColumns");
+
+ cols->cValues = 0;
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_QueryColumnsAll;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* get columns SPropTagArray */
+ table = (mapi_object_table_t *)obj_table->private_data;
+ OPENCHANGE_RETVAL_IF(!table, MAPI_E_INVALID_OBJECT, mem_ctx);
+
+ reply = &mapi_response->mapi_repl->u.mapi_QueryColumnsAll;
+ cols->cValues = reply->PropertyTagCount;
+ cols->aulPropTag = talloc_array((TALLOC_CTX *)table, enum MAPITAGS, cols->cValues);
+ memcpy((void *)cols->aulPropTag, (const void *)reply->PropertyTags, cols->cValues * sizeof(enum MAPITAGS));
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Move the table cursor at a specific location
+
+ \param obj_table the table we are moving cursor on
+ \param origin the table position where we start to seek
+ \param offset a particular offset in the table
+ \param row the position of the seeked row is returned in rows
+
+ origin possible values:
+ - BOOKMARK_BEGINNING: Beginning of the table
+ - BOOKMARK_CURRENT: Current position in the table
+ - BOKMARK_END: End of the table
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetColumns, QueryRows
+*/
+_PUBLIC_ enum MAPISTATUS SeekRow(mapi_object_t *obj_table,
+ enum BOOKMARK origin,
+ int32_t offset, uint32_t *row)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SeekRow_req request;
+ struct SeekRow_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SeekRow");
+ *row = 0;
+
+ /* Fill the SeekRow operation */
+ size = 0;
+ request.origin = origin;
+ size += 1;
+ request.offset = offset;
+ size += 4;
+ request.WantRowMovedCount = 0;
+ size += 1;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SeekRow;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SeekRow = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ reply = &mapi_response->mapi_repl->u.mapi_SeekRow;
+ *row = reply->RowsSought;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Move the table cursor at a specific location given a
+ bookmark
+
+ \param obj_table the table we are moving cursor on
+ \param lpbkPosition the bookmarked position
+ \param RowCount a relative number of rows to the bookmark
+ \param row the position of the seeked row is returned in rows
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_INVALID_BOOKMARK: The bookmark specified is invalid or
+ beyond the last row requested
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa CreateBookmark, FreeBookmark
+ */
+_PUBLIC_ enum MAPISTATUS SeekRowBookmark(mapi_object_t *obj_table,
+ uint32_t lpbkPosition,
+ uint32_t RowCount,
+ uint32_t *row)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SeekRowBookmark_req request;
+ struct SeekRowBookmark_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+ struct SBinary_short bin;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ retval = mapi_object_bookmark_find(obj_table, lpbkPosition, &bin);
+ OPENCHANGE_RETVAL_IF(retval, MAPI_E_INVALID_BOOKMARK, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SeekRowBookmark");
+
+ /* Fill the SeekRowBookmark operation */
+ size = 0;
+ request.Bookmark.cb = bin.cb;
+ size += sizeof (uint16_t);
+ request.Bookmark.lpb = bin.lpb;
+ size += bin.cb;
+ request.RowCount = RowCount;
+ size += sizeof (uint32_t);
+ request.WantRowMovedCount = 0x1;
+ size += sizeof (uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SeekRowBookmark;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SeekRowBookmark = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ reply = &mapi_response->mapi_repl->u.mapi_SeekRowBookmark;
+ *row = reply->RowsSought;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Moves the cursor to an approximate fractional position in
+ the table
+
+ \param obj_table the table we are moving cursor on
+ \param ulNumerator numerator of the fraction representing the table
+ position.
+ \param ulDenominator denominator of the fraction representing the
+ table position
+
+ - If ulDenominator is NULL, then SeekRowApprox returns
+ MAPI_E_INVALID_PARAMETER.
+ - If ulNumerator is NULL, then SeekRowApprox moves the cursor to
+ the beginning of the table. In such situation, SeekRowApprox call
+ is similar to SeekRow with BOOKMARK_BEGINNING
+ - If ulNumerator and ulDenominator have the same value, then
+ SeekRowApprox moves the cursor to the end of the table. In such
+ situation, SeekRowApprox call is similar to SeekRow with
+ BOOKMARK_END
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SeekRow, SeekRowBookmark
+ */
+_PUBLIC_ enum MAPISTATUS SeekRowApprox(mapi_object_t *obj_table,
+ uint32_t ulNumerator,
+ uint32_t ulDenominator)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SeekRowApprox_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ulDenominator, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SeekRowApprox");
+
+ /* Fill the SeekRowApprox operation */
+ size = 0;
+ request.ulNumerator = ulNumerator;
+ size += sizeof (uint32_t);
+ request.ulDenominator = ulDenominator;
+ size += sizeof (uint32_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SeekRowApprox;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SeekRowApprox = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Marks the table current position
+
+ \param obj_table the table we are creating a bookmark in
+ \param lpbkPosition pointer to the bookmark value. This bookmark
+ can be passed in a call to the SeekRowBookmark method
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SeekRowBookmark, FreeBookmark
+ */
+_PUBLIC_ enum MAPISTATUS CreateBookmark(mapi_object_t *obj_table,
+ uint32_t *lpbkPosition)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct CreateBookmark_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_table_t *mapi_table;
+ mapi_object_bookmark_t *bookmark;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CreateBookmark");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_CreateBookmark;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ reply = &mapi_response->mapi_repl->u.mapi_CreateBookmark;
+
+ mapi_table = (mapi_object_table_t *)obj_table->private_data;
+ OPENCHANGE_RETVAL_IF(!mapi_table, MAPI_E_INVALID_PARAMETER, mem_ctx);
+
+ /* Store CreateBookmark data in mapi_object_table private_data */
+ bookmark = talloc_zero((TALLOC_CTX *)mapi_table->bookmark, mapi_object_bookmark_t);
+ mapi_table->bk_last++;
+ bookmark->index = mapi_table->bk_last;
+ bookmark->bin.cb = reply->bookmark.cb;
+ bookmark->bin.lpb = talloc_array((TALLOC_CTX *)bookmark, uint8_t, reply->bookmark.cb);
+ memcpy(bookmark->bin.lpb, reply->bookmark.lpb, reply->bookmark.cb);
+
+ DLIST_ADD(mapi_table->bookmark, bookmark);
+
+ *lpbkPosition = mapi_table->bk_last;
+
+ obj_table->private_data = mapi_table;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Release the resources associated with a bookmark
+
+ \param obj_table the table the bookmark is associated to
+ \param bkPosition the bookmark to be freed
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_INVALID_BOOKMARK: The bookmark specified is invalid or
+ beyond the last row requested
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa CreateBookmark
+*/
+_PUBLIC_ enum MAPISTATUS FreeBookmark(mapi_object_t *obj_table,
+ uint32_t bkPosition)
+{
+ mapi_object_table_t *table;
+ mapi_object_bookmark_t *bookmark;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct FreeBookmark_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity check */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ table = (mapi_object_table_t *)obj_table->private_data;
+ OPENCHANGE_RETVAL_IF(!table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(bkPosition > table->bk_last, MAPI_E_INVALID_BOOKMARK, NULL);
+
+ bookmark = table->bookmark;
+ OPENCHANGE_RETVAL_IF(!bookmark, MAPI_E_INVALID_BOOKMARK, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "FreeBookmark");
+
+ while (bookmark) {
+ if (bookmark->index == bkPosition) {
+ if (bookmark->index == table->bk_last) {
+ table->bk_last--;
+ }
+ size = 0;
+
+ /* Fill the FreeBookmark operation */
+ request.bookmark.cb = bookmark->bin.cb;
+ size += sizeof (uint16_t);
+ request.bookmark.lpb = bookmark->bin.lpb;
+ size += bookmark->bin.cb;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_FreeBookmark;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_FreeBookmark = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ MAPIFreeBuffer(bookmark->bin.lpb);
+ DLIST_REMOVE(table->bookmark, bookmark);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+ }
+ bookmark = bookmark->next;
+ }
+ talloc_free(mem_ctx);
+ return MAPI_E_INVALID_BOOKMARK;
+}
+
+
+/**
+ \details Order the rows of the table based on a criteria
+
+ \param obj_table the table we are ordering rows on
+ \param lpSortCriteria pointer on sort criterias to apply
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table or lpSortCriteria is NULL
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+ */
+_PUBLIC_ enum MAPISTATUS SortTable(mapi_object_t *obj_table,
+ struct SSortOrderSet *lpSortCriteria)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SortTable_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!lpSortCriteria, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SortTable");
+
+ /* Fill the SortTable operation */
+ size = 0;
+ request.SortTableFlags = 0;
+ size += sizeof (uint8_t);
+ request.lpSortCriteria.cSorts = lpSortCriteria->cSorts;
+ size += sizeof (uint16_t);
+ request.lpSortCriteria.cCategories = lpSortCriteria->cCategories;
+ size += sizeof (uint16_t);
+ request.lpSortCriteria.cExpanded = lpSortCriteria->cExpanded;
+ size += sizeof (uint16_t);
+ request.lpSortCriteria.aSort = lpSortCriteria->aSort;
+ size += lpSortCriteria->cSorts * (sizeof (uint32_t) + sizeof (uint8_t));
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SortTable;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SortTable = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Get the size associated to a mapi SRestriction
+
+ \param res pointer on the mapi_SRestriction
+
+ \return mapi_SRestriction size
+ */
+uint32_t get_mapi_SRestriction_size(struct mapi_SRestriction *res)
+{
+ uint32_t size;
+ uint32_t i;
+
+ size = 0;
+
+ size += sizeof (res->rt);
+
+ switch(res->rt) {
+ case RES_AND:
+ size += sizeof (res->res.resAnd.cRes);
+ for (i = 0; i < res->res.resAnd.cRes; i++) {
+ size += get_mapi_SRestriction_size((struct mapi_SRestriction *)&(res->res.resAnd.res[i]));
+ }
+ break;
+ case RES_OR:
+ size += sizeof (res->res.resOr.cRes);
+ for (i = 0; i < res->res.resOr.cRes; i++) {
+ size += get_mapi_SRestriction_size((struct mapi_SRestriction *)&(res->res.resOr.res[i]));
+ }
+ break;
+ case RES_CONTENT:
+ size += sizeof (res->res.resContent.fuzzy);
+ size += sizeof (res->res.resContent.ulPropTag);
+ size += sizeof (res->res.resContent.lpProp.ulPropTag);
+ size += get_mapi_property_size(&(res->res.resContent.lpProp));
+ break;
+ case RES_PROPERTY:
+ size += sizeof (res->res.resProperty.relop);
+ size += sizeof (res->res.resProperty.ulPropTag);
+ size += sizeof (res->res.resProperty.lpProp.ulPropTag);
+ size += get_mapi_property_size(&(res->res.resProperty.lpProp));
+ break;
+ case RES_COMPAREPROPS:
+ size += sizeof (uint8_t);
+ size += sizeof (res->res.resCompareProps.ulPropTag1);
+ size += sizeof (res->res.resCompareProps.ulPropTag2);
+ break;
+ case RES_BITMASK:
+ size += sizeof (uint8_t);
+ size += sizeof (res->res.resBitmask.ulPropTag);
+ size += sizeof (res->res.resBitmask.ulMask);
+ break;
+ case RES_SIZE:
+ size += sizeof (uint8_t);
+ size += sizeof (res->res.resSize.ulPropTag);
+ size += sizeof (res->res.resSize.size);
+ break;
+ case RES_EXIST:
+ size += sizeof (res->res.resExist.ulPropTag);
+ break;
+ }
+ return (size);
+}
+
+/**
+ \details Removes all filters that are currently on a table
+
+ \param obj_table the table object to reset
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa Restrict
+*/
+_PUBLIC_ enum MAPISTATUS Reset(mapi_object_t *obj_table)
+{
+ TALLOC_CTX *mem_ctx;
+ uint32_t size;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "Reset");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_ResetTable;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Applies a filter to a table, reducing the row set to only
+ those rows matching the specified criteria.
+
+ \param obj_table the object we are filtering
+ \param res the filters we want to apply
+ \param TableStatus the table status result
+
+ TableStatus can either hold:
+ - TBLSTAT_COMPLETE (0x0)
+ - TBLSTAT_SORTING (0x9)
+ - TBLSTAT_SORT_ERROR (0xA)
+ - TBLSTAT_SETTING_COLS (0xB)
+ - TBLSTAT_SETCOL_ERROR (0xD)
+ - TBLSTAT_RESTRICTING (0xE)
+ - TBLSTAT_RESTRICT_ERROR (0xF)
+
+
+ Unlike MAPI, you don't pass a null restriction argument to remove
+ the current restrictions. Use Reset() instead.
+
+ TableStatus should be set to NULL if you don't want to retrieve the
+ status of the table.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa QueryRows, Reset
+*/
+_PUBLIC_ enum MAPISTATUS Restrict(mapi_object_t *obj_table,
+ struct mapi_SRestriction *res,
+ uint8_t *TableStatus)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct Restrict_req request;
+ struct Restrict_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!res, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "Restrict");
+
+ /* Fill the Restrict operation */
+ size = 0;
+ request.handle_idx = 0;
+ size += sizeof (request.handle_idx);
+ request.restrictions = *res;
+ size += get_mapi_SRestriction_size(res);
+
+ /* add subcontext size */
+ size += sizeof (uint16_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_Restrict;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_Restrict = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ if (TableStatus) {
+ reply = &mapi_response->mapi_repl->u.mapi_Restrict;
+ *TableStatus = reply->TableStatus;
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Find the next row in a table that matches specific search
+ criteria
+
+ \param obj_table the table we are searching in
+ \param res pointer on search criterias
+ \param bkOrigin bookmark identifying the row where FindRow should
+ begin
+ \param ulFlags controls the direction of the search
+ \param SRowSet the resulting row
+
+ bkOrigin can either take the value of a bookmark created with
+ CreateBookmark or any of the default values:
+ - BOOKMARK_BEGINNING
+ - BOOKMARK_CURRENT
+ - BOOKMARK_END
+
+ ulFlags can be set either to DIR_FORWARD (0x0) or DIR_BACKWARD
+ (0x1).
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_INVALID_BOOKMARK: the bookmark specified is invalid or
+ beyond the last row requested.
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa CreateBookmark
+ */
+_PUBLIC_ enum MAPISTATUS FindRow(mapi_object_t *obj_table,
+ struct mapi_SRestriction *res,
+ uint32_t bkOrigin, uint8_t ulFlags,
+ struct SRowSet *SRowSet)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct FindRow_req request;
+ struct FindRow_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_table_t *table;
+ struct SBinary_short bin;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!res, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ if (bkOrigin >= 3) {
+ retval = mapi_object_bookmark_find(obj_table, bkOrigin, &bin);
+ OPENCHANGE_RETVAL_IF(retval, MAPI_E_INVALID_BOOKMARK, NULL);
+ }
+
+ mem_ctx = talloc_named(NULL, 0, "FindRow");
+
+ /* Fill the FindRow operation */
+ size = 0;
+ request.ulFlags = ulFlags;
+ size += sizeof (uint8_t);
+ request.res = *res;
+ size += get_mapi_SRestriction_size(res);
+ request.origin = (bkOrigin > 3) ? 3 : bkOrigin;
+ size += sizeof (uint8_t);
+ if (bkOrigin >= 3) {
+ request.bookmark.cb = bin.cb;
+ request.bookmark.lpb = bin.lpb;
+ size += sizeof (uint16_t)+ bin.cb;
+ } else {
+ request.bookmark.cb = 0;
+ request.bookmark.lpb = NULL;
+ size += sizeof (uint16_t);
+ }
+
+ /* add subcontext size */
+ size += sizeof (uint16_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_FindRow;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_FindRow = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* table contains SPropTagArray from previous SetColumns call */
+ table = (mapi_object_table_t *)obj_table->private_data;
+ OPENCHANGE_RETVAL_IF(!table, MAPI_E_INVALID_OBJECT, mem_ctx);
+
+ reply = &mapi_response->mapi_repl->u.mapi_FindRow;
+ SRowSet->cRows = 1;
+ SRowSet->aRow = talloc_array((TALLOC_CTX *)table, struct SRow, SRowSet->cRows);
+ emsmdb_get_SRowSet((TALLOC_CTX *)table, global_mapi_ctx->lp_ctx, SRowSet, &table->proptags, &reply->row);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Get the status of a table
+
+ \param obj_table the table we are retrieving the status from
+ \param TableStatus the table status result
+
+ TableStatus can either hold:
+ - TBLSTAT_COMPLETE (0x0)
+ - TBLSTAT_SORTING (0x9)
+ - TBLSTAT_SORT_ERROR (0xA)
+ - TBLSTAT_SETTING_COLS (0xB)
+ - TBLSTAT_SETCOL_ERROR (0xD)
+ - TBLSTAT_RESTRICTING (0xE)
+ - TBLSTAT_RESTRICT_ERROR (0xF)
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_INVALID_BOOKMARK: the bookmark specified is invalid or
+ beyond the last row requested.
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetColumns, Restrict, FindRow, GetHierarchyTable, GetContentsTable
+ */
+_PUBLIC_ enum MAPISTATUS GetStatus(mapi_object_t *obj_table, uint8_t *TableStatus)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetStatus_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetStatus");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetStatus;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve TableStatus */
+ reply = &mapi_response->mapi_repl->u.mapi_GetStatus;
+ *TableStatus = reply->TableStatus;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Aborts an asynchronous table operation in progress
+
+ \param obj_table the table object where we want to abort an
+ asynchronous operation
+ \param TableStatus pointer on the table status returned by the
+ operation
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table or TableStatus are null
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+ */
+_PUBLIC_ enum MAPISTATUS Abort(mapi_object_t *obj_table, uint8_t *TableStatus)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct Abort_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!TableStatus, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "Abort");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_Abort;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request stucture */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve TableStatus */
+ reply = &mapi_response->mapi_repl->u.mapi_Abort;
+ *TableStatus = reply->TableStatus;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Expand a collapsed row in a table
+
+ After a contents table has been sorted and categorized using
+ SortTable, rows can be expanded and collapsed (using ExpandRow and
+ CollapseRow repectively).
+
+ \param obj_table the table we are collapsing the category in.
+ \param categoryId the row identification for the heading row for
+ the category being expanded.
+ \param maxRows the maximum number of rows to retrieve (can be zero)
+ \param rowData (result) the data rows under this category heading
+ \param expandedRowCount (result) the number of rows that were added
+ to the table when the row was expanded
+
+ You obtain the categoryId argument from the PR_INST_ID property of
+ the heading row for the category that is being collapsed.
+
+ The maxRows argument specifies the upper limit on how many rows to
+ return (as rowData) when the category is expanded. The
+ expandedRowCount argument returns the number of rows that were
+ added to the table. As an example, consider a collapsed category
+ with 8 entries. If you set maxRows to 3, then rowData will contain
+ the data for the first three rows, and expandedRowCount will be set
+ to 8. If you now use QueryRows(), you can read the 5 additional
+ rows. If you'd specified maxRows as 8 (or more), rowData would have
+ contained all 8 rows and expandedRowCount still would have been 8.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table, rowData or rowCount are NULL
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa CollapseRow
+ */
+_PUBLIC_ enum MAPISTATUS ExpandRow(mapi_object_t *obj_table, uint64_t categoryId,
+ uint16_t maxRows, struct SRowSet *rowData,
+ uint32_t *expandedRowCount)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct ExpandRow_req request;
+ struct ExpandRow_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ mapi_object_table_t *table;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!rowData, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!expandedRowCount, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "ExpandRow");
+ size = 0;
+
+ /* Fill the ExpandRow operation */
+ request.MaxRowCount = maxRows;
+ size += sizeof (uint16_t);
+ request.CategoryId = categoryId;
+ size += sizeof (uint64_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_ExpandRow;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_ExpandRow = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* table contains mapitags from previous SetColumns */
+ table = (mapi_object_table_t *)obj_table->private_data;
+ OPENCHANGE_RETVAL_IF(!table, MAPI_E_INVALID_OBJECT, mem_ctx);
+
+ /* Retrieve the rowData and expandedRowCount */
+ reply = &mapi_response->mapi_repl->u.mapi_ExpandRow;
+ rowData->cRows = reply->RowCount;
+ rowData->aRow = talloc_array((TALLOC_CTX *)table, struct SRow, reply->RowCount);
+ emsmdb_get_SRowSet((TALLOC_CTX *)table, global_mapi_ctx->lp_ctx, rowData, &table->proptags, &reply->RowData);
+ *expandedRowCount = reply->ExpandedRowCount;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Collapse an expanded row in a table
+
+ After a contents table has been sorted and categorized using
+ SortTable, rows can be expanded and collapsed (using ExpandRow and
+ CollapseRow repectively).
+
+ \param obj_table the table we are collapsing the category in.
+ \param categoryId the row identification for the heading row for
+ the category being collapsed.
+ \param rowCount (result) the number of rows that were removed from the
+ table when the row was collapsed.
+
+ You obtain the categoryId argument from the PR_INST_ID property of
+ the heading row for the category that is being collapsed.
+
+ If you pass rowCount as null, the number of rows will not be returned.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table is NULL
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa ExpandRow
+ */
+_PUBLIC_ enum MAPISTATUS CollapseRow(mapi_object_t *obj_table, uint64_t categoryId,
+ uint32_t *rowCount)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct CollapseRow_req request;
+ struct CollapseRow_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CollapseRow");
+ size = 0;
+
+ /* Fill the CollapseRow operation */
+ request.CategoryId = categoryId;
+ size += sizeof (uint64_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_CollapseRow;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_CollapseRow = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve the RowCount */
+ reply = &mapi_response->mapi_repl->u.mapi_CollapseRow;
+ *rowCount = reply->CollapsedRowCount;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+
+}
+
+/**
+ \details Get the Collapse State of a Table
+
+ After a contents table has been sorted and categorized using
+ SortTable, rows can be expanded and collapsed (using ExpandRow() and
+ CollapseRow() repectively). You can save the state of the table using
+ this function, and restore it using SetCollapseState.
+
+ \param obj_table the table we are retrieving the state from
+ \param rowId the row number for the cursor
+ \param rowInstanceNumber the instance number for the cursor
+ \param CollapseState (result) the returned table Collapse State
+
+ You obtain the row number and row instance number arguments from
+ the PR_INST_ID and PR_INST_NUM properties of the row you want to
+ use as the cursor.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table or CollapseState are null
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetCollapseState
+ */
+_PUBLIC_ enum MAPISTATUS GetCollapseState(mapi_object_t *obj_table, uint64_t rowId,
+ uint32_t rowInstanceNumber,
+ struct SBinary_short *CollapseState)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetCollapseState_req request;
+ struct GetCollapseState_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetCollapseState");
+ size = 0;
+
+ /* Fill the GetCollapseState operation */
+ size = 0;
+ request.RowId = rowId;
+ size += sizeof (uint64_t);
+ request.RowInstanceNumber = rowInstanceNumber;
+ size += sizeof (uint32_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetCollapseState;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetCollapseState = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve the CollapseState */
+ reply = &mapi_response->mapi_repl->u.mapi_GetCollapseState;
+ CollapseState->cb = reply->CollapseState.cb;
+ CollapseState->lpb = talloc_array((TALLOC_CTX *)session, uint8_t, reply->CollapseState.cb);
+ memcpy(CollapseState->lpb, reply->CollapseState.lpb, reply->CollapseState.cb);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Set the Collapse State of a Table
+
+ After a contents table has been sorted and categorized using
+ SortTable, rows can be expanded and collapsed (using ExpandRow() and
+ CollapseRow() repectively). You can save the state of the table using
+ GetCollapseState, and restore it using this function.
+
+ \param obj_table the table we are restoring the state for
+ \param CollapseState the Collapse State to restore
+ \param lpbkPosition pointer to the bookmark value. This bookmark
+ can be passed in a call to the SeekRowBookmark method
+
+ You obtain the row number and row instance number arguments from
+ the PR_INST_ID and PR_INST_NUM properties of the row you want to
+ use as the cursor.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_table or CollapseState are null
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetCollapseState
+ */
+_PUBLIC_ enum MAPISTATUS SetCollapseState(mapi_object_t *obj_table,
+ struct SBinary_short *CollapseState,
+ uint32_t *lpbkPosition)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SetCollapseState_req request;
+ struct SetCollapseState_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_table_t *mapi_table;
+ mapi_object_bookmark_t *bookmark;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!CollapseState, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_table);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SetCollapseState");
+ size = 0;
+
+ /* Fill the SetCollapseState operation */
+ size = 0;
+ request.CollapseState.cb = CollapseState->cb;
+ size += sizeof (uint16_t);
+ request.CollapseState.lpb = CollapseState->lpb;
+ size += CollapseState->cb;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SetCollapseState;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SetCollapseState = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_table);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ reply = &mapi_response->mapi_repl->u.mapi_SetCollapseState;
+
+ mapi_table = (mapi_object_table_t *)obj_table->private_data;
+ OPENCHANGE_RETVAL_IF(!mapi_table, MAPI_E_INVALID_PARAMETER, mem_ctx);
+
+ /* Store the bookmark in the mapi_object_table private_data */
+ bookmark = talloc_zero((TALLOC_CTX *)mapi_table->bookmark, mapi_object_bookmark_t);
+ mapi_table->bk_last++;
+ bookmark->index = mapi_table->bk_last;
+ bookmark->bin.cb = reply->bookmark.cb;
+ bookmark->bin.lpb = talloc_array((TALLOC_CTX *)bookmark, uint8_t, reply->bookmark.cb);
+ memcpy(bookmark->bin.lpb, reply->bookmark.lpb, reply->bookmark.cb);
+
+ DLIST_ADD(mapi_table->bookmark, bookmark);
+
+ *lpbkPosition = mapi_table->bk_last;
+
+ obj_table->private_data = mapi_table;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IMSProvider.c
===================================================================
--- trunk/openchange/libmapi/IMSProvider.c (rev 0)
+++ trunk/openchange/libmapi/IMSProvider.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,325 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/mapicode.h>
+#include <libmapi/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+#include <gen_ndr/ndr_exchange_c.h>
+#include <core/error.h>
+#include <param.h>
+#include <credentials.h>
+
+
+/**
+ \file IMSProvider.c
+
+ \brief Provider operations
+*/
+
+
+/*
+ * Log MAPI to one instance of a message store provider
+ */
+
+static NTSTATUS provider_rpc_connection(TALLOC_CTX *parent_ctx,
+ struct dcerpc_pipe **p,
+ const char *binding,
+ struct cli_credentials *credentials,
+ const struct ndr_interface_table *table,
+ struct loadparm_context *lp_ctx)
+{
+ NTSTATUS status;
+ struct tevent_context *ev;
+
+ if (!binding) {
+ DEBUG(3, ("You must specify a ncacn binding string\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ev = tevent_context_init(talloc_autofree_context());
+
+ status = dcerpc_pipe_connect(parent_ctx,
+ p, binding, table,
+ credentials, ev, lp_ctx);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("Failed to connect to remote server: %s %s\n",
+ binding, nt_errstr(status)));
+ }
+
+ /* dcerpc_pipe_connect set errno, we have to unset it */
+ errno = 0;
+ return status;
+}
+
+
+/**
+ \details Returns the name of an NSPI server
+
+ \param session pointer to the MAPI session context
+ \param server the Exchange server address (IP or FQDN)
+ \param userDN optional user mailbox DN
+
+ \return a valid string on success, otherwise NULL
+ */
+_PUBLIC_ const char *RfrGetNewDSA(struct mapi_session *session,
+ const char *server,
+ const char *userDN)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_profile *profile;
+ struct RfrGetNewDSA r;
+ struct dcerpc_pipe *pipe;
+ char *binding;
+ const char *ppszServer = NULL;
+
+ /* Sanity Checks */
+ if (!global_mapi_ctx) return server;
+ if (!global_mapi_ctx->session) return server;
+
+ mem_ctx = (TALLOC_CTX *)session;
+ profile = session->profile;
+
+ binding = talloc_asprintf(mem_ctx, "ncacn_ip_tcp:%s%s", server, ((global_mapi_ctx->dumpdata == true) ? "[print]" : "[]"));
+ status = provider_rpc_connection(mem_ctx, &pipe, binding, profile->credentials, &ndr_table_exchange_ds_rfr, global_mapi_ctx->lp_ctx);
+ talloc_free(binding);
+
+ if (!NT_STATUS_IS_OK(status)) return server;
+
+
+ r.in.ulFlags = 0x0;
+ r.in.pUserDN = userDN ? userDN : "";
+ r.in.ppszUnused = NULL;
+ r.in.ppszServer = &ppszServer;
+
+ status = dcerpc_RfrGetNewDSA(pipe, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) return server;
+
+ return (ppszServer ? ppszServer : server);
+}
+
+
+/**
+ \details Returns the FQDN of the NSPI server corresponding to a DN
+
+ \param session pointer to the MAPI session context
+ \param serverFQDN pointer to the server FQDN string (return value)
+
+ \return MAPI_E_SUCCESS on success, otherwise a MAPI error and
+ serverFQDN content set to NULL.
+ */
+_PUBLIC_ enum MAPISTATUS RfrGetFQDNFromLegacyDN(struct mapi_session *session,
+ const char **serverFQDN)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_profile *profile;
+ struct RfrGetFQDNFromLegacyDN r;
+ struct dcerpc_pipe *pipe;
+ char *binding;
+ const char *ppszServerFQDN;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, NULL);
+
+ mem_ctx = (TALLOC_CTX *)session;
+ profile = session->profile;
+ *serverFQDN = NULL;
+
+ binding = talloc_asprintf(mem_ctx, "ncacn_ip_tcp:%s%s", profile->server, ((global_mapi_ctx->dumpdata == true) ? "[print]" : "[]"));
+ status = provider_rpc_connection(mem_ctx, &pipe, binding, profile->credentials, &ndr_table_exchange_ds_rfr, global_mapi_ctx->lp_ctx);
+ talloc_free(binding);
+
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, NULL);
+
+ r.in.ulFlags = 0x0;
+ r.in.cbMailboxServerDN = strlen(profile->homemdb) + 1;
+ r.in.szMailboxServerDN = profile->homemdb;
+ r.out.ppszServerFQDN = &ppszServerFQDN;
+
+ status = dcerpc_RfrGetFQDNFromLegacyDN(pipe, mem_ctx, &r);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+
+ if (ppszServerFQDN) {
+ *serverFQDN = ppszServerFQDN;
+ } else {
+ *serverFQDN = NULL;
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+enum MAPISTATUS Logon(struct mapi_session *session,
+ struct mapi_provider *provider,
+ enum PROVIDER_ID provider_id)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx;
+ struct dcerpc_pipe *pipe;
+ struct mapi_profile *profile;
+ char *binding;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, NULL);
+
+ mem_ctx = (TALLOC_CTX *)provider;
+ profile = session->profile;
+
+ switch(provider_id) {
+ case PROVIDER_ID_EMSMDB:
+ binding = talloc_asprintf(mem_ctx, "ncacn_ip_tcp:%s%s", profile->server, ((global_mapi_ctx->dumpdata == true) ? "[print]" : "[]"));
+ status = provider_rpc_connection(mem_ctx, &pipe, binding, profile->credentials, &ndr_table_exchange_emsmdb, global_mapi_ctx->lp_ctx);
+ talloc_free(binding);
+ OPENCHANGE_RETVAL_IF(NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED), MAPI_E_NETWORK_ERROR, NULL);
+ OPENCHANGE_RETVAL_IF(NT_STATUS_EQUAL(status, NT_STATUS_HOST_UNREACHABLE), MAPI_E_NETWORK_ERROR, NULL);
+ OPENCHANGE_RETVAL_IF(NT_STATUS_EQUAL(status, NT_STATUS_PORT_UNREACHABLE), MAPI_E_NETWORK_ERROR, NULL);
+ OPENCHANGE_RETVAL_IF(NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT), MAPI_E_NETWORK_ERROR, NULL);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_LOGON_FAILED, NULL);
+ provider->ctx = emsmdb_connect(mem_ctx, session, pipe, profile->credentials);
+ OPENCHANGE_RETVAL_IF(!provider->ctx, MAPI_E_LOGON_FAILED, NULL);
+ break;
+ case PROVIDER_ID_NSPI:
+ /* Call RfrGetNewDSA prior any NSPI call */
+ binding = talloc_asprintf(mem_ctx, "ncacn_ip_tcp:%s%s", RfrGetNewDSA(session, profile->server, profile->mailbox),
+ ((global_mapi_ctx->dumpdata == true) ? "[print]" : "[]"));
+ status = provider_rpc_connection(mem_ctx, &pipe, binding, profile->credentials, &ndr_table_exchange_nsp, global_mapi_ctx->lp_ctx);
+ talloc_free(binding);
+ OPENCHANGE_RETVAL_IF(NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED), MAPI_E_NETWORK_ERROR, NULL);
+ OPENCHANGE_RETVAL_IF(NT_STATUS_EQUAL(status, NT_STATUS_HOST_UNREACHABLE), MAPI_E_NETWORK_ERROR, NULL);
+ OPENCHANGE_RETVAL_IF(NT_STATUS_EQUAL(status, NT_STATUS_PORT_UNREACHABLE), MAPI_E_NETWORK_ERROR, NULL);
+ OPENCHANGE_RETVAL_IF(NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT), MAPI_E_NETWORK_ERROR, NULL);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_LOGON_FAILED, NULL);
+ provider->ctx = (void *)nspi_bind(provider, pipe, profile->credentials,
+ profile->codepage, profile->language, profile->method);
+ OPENCHANGE_RETVAL_IF(!provider->ctx, MAPI_E_LOGON_FAILED, NULL);
+ break;
+ default:
+ OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, NULL);
+ break;
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Logoff an Exchange store
+
+ This function uninitializes the MAPI session associated to the
+ object.
+
+ \param obj_store pointer to the store object
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
+ */
+_PUBLIC_ enum MAPISTATUS Logoff(mapi_object_t *obj_store)
+{
+ struct mapi_session *session;
+ struct mapi_session *el;
+ bool found = false;
+
+ /* Sanity checks */
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (el = global_mapi_ctx->session; el; el = el->next) {
+ if (session == el) {
+ found = true;
+ mapi_object_release(obj_store);
+ DLIST_REMOVE(global_mapi_ctx->session, el);
+ break;
+ }
+ }
+
+ return (found == true) ? MAPI_E_SUCCESS : MAPI_E_NOT_FOUND;
+}
+
+
+/**
+ \details Initialize the notification subsystem
+
+ This function initializes the notification subsystem, binds a local
+ UDP port to receive Exchange (server side) notifications and
+ configures the server to send notifications on this port.
+
+ \param ulEventMask the mask of events to provide notifications for.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa Subscribe, Unsubscribe, MonitorNotification, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS RegisterNotification(uint16_t ulEventMask)
+{
+ NTSTATUS status;
+ struct emsmdb_context *emsmdb;
+ struct mapi_session *session;
+ TALLOC_CTX *mem_ctx;
+ struct NOTIFKEY *lpKey;
+ static uint8_t rand = 0;
+ static uint8_t attempt = 0;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx->session, MAPI_E_SESSION_LIMIT, NULL);
+
+ session = (struct mapi_session *)global_mapi_ctx->session;
+ OPENCHANGE_RETVAL_IF(!session->emsmdb, MAPI_E_SESSION_LIMIT, NULL);
+
+ emsmdb = (struct emsmdb_context *)global_mapi_ctx->session->emsmdb->ctx;
+ OPENCHANGE_RETVAL_IF(!emsmdb, MAPI_E_SESSION_LIMIT, NULL);
+
+ mem_ctx = emsmdb->mem_ctx;
+
+ /* bind local udp port */
+ session->notify_ctx = emsmdb_bind_notification(mem_ctx);
+ if (!session->notify_ctx) return MAPI_E_CANCEL;
+
+ /* tell exchange where to send notifications */
+ lpKey = talloc_zero(mem_ctx, struct NOTIFKEY);
+ lpKey->cb = 8;
+ lpKey->ab = talloc_array((TALLOC_CTX *)lpKey, uint8_t, lpKey->cb);
+ memcpy(lpKey->ab, "libmapi", 7);
+retry:
+ lpKey->ab[7] = rand;
+
+ status = emsmdb_register_notification(lpKey, ulEventMask);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (attempt < 5) {
+ rand++;
+ attempt++;
+ errno = 0;
+ goto retry;
+ } else {
+ talloc_free(lpKey);
+ return MAPI_E_CALL_FAILED;
+ }
+ }
+ talloc_free(lpKey);
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IMessage.c
===================================================================
--- trunk/openchange/libmapi/IMessage.c (rev 0)
+++ trunk/openchange/libmapi/IMessage.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1435 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+#include <param.h>
+
+
+/**
+ \file IMessage.c
+
+ \brief Operations on messages
+ */
+
+
+/**
+ \details Create a new attachment
+
+ This function creates a new attachment to an existing message.
+
+ \param obj_message the message to attach to
+ \param obj_attach the attachment
+
+ Both objects need to exist before you call this message. obj_message
+ should be a valid message on the server. obj_attach needs to be
+ initialised.
+
+ \code
+ enum MAPISTATUS retval;
+ mapi_object_t obj_message;
+ mapi_object_t obj_attach;
+
+ ... open or create the obj_message ...
+
+ mapi_object_init(&obj_attach);
+ retval = CreateAttach(&obj_message, &obj_attach);
+ ... check the return value ...
+
+ ... use SetProps() to set the attachment up ...
+ ... perhaps OpenStream() / WriteStream() / CommitStream() on obj_attach ...
+
+ // Save the changes to the attachment and then the message
+ retval = SaveChangesAttachment(&obj_message, &obj_attach, KeepOpenReadOnly);
+ ... check the return value ...
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ ... check the return value ...
+ \endcode
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa CreateMessage, GetAttachmentTable, OpenAttach, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS CreateAttach(mapi_object_t *obj_message,
+ mapi_object_t *obj_attach)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct CreateAttach_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_message);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CreateAttach");
+ size = 0;
+
+ /* Fill the CreateAttach operation */
+ request.handle_idx = 0x1;
+ size += sizeof (uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_CreateAttach;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_CreateAttach = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + (sizeof (uint32_t) * 2);
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_message);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Set object session and handle */
+ mapi_object_set_session(obj_attach, session);
+ mapi_object_set_handle(obj_attach, mapi_response->handles[1]);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Delete an attachment from a message
+
+ This function deletes one attachment from a message. The attachment
+ to be deleted is specified by its PR_ATTACH_NUM
+
+ \param obj_message the message to operate on
+ \param AttachmentID the attachment number
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa CreateMessage, GetAttachmentTable, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS DeleteAttach(mapi_object_t *obj_message, uint32_t AttachmentID)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct DeleteAttach_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_message);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "DeleteAttach");
+ size = 0;
+
+ /* Fill the DeleteAttach operation */
+ request.AttachmentID = AttachmentID;
+ size += sizeof (uint32_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_DeleteAttach;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_DeleteAttach = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_message);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve the attachment table for a message
+
+ \param obj_message the message
+ \param obj_table the attachment table for the message
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa CreateMessage, OpenMessage, CreateAttach, OpenAttach, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS GetAttachmentTable(mapi_object_t *obj_message,
+ mapi_object_t *obj_table)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetAttachmentTable_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ uint32_t size = 0;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_message);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetAttachmentTable");
+ size = 0;
+
+ /* Fill the GetAttachmentTable operation */
+ request.handle_idx = 1;
+ size += sizeof (uint8_t);
+
+ request.TableFlags = 0x0;
+ size += sizeof (uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetAttachmentTable;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetAttachmentTable = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_message);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Set object session and handle */
+ mapi_object_set_session(obj_table, session);
+ mapi_object_set_handle(obj_table, mapi_response->handles[mapi_response->mapi_repl->handle_idx]);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Open an attachment to a message
+
+ This function opens one attachment from a message. The attachment
+ to be opened is specified by its PR_ATTACH_NUM.
+
+ \param obj_message the message to operate on
+ \param AttachmentID the attachment number
+ \param obj_attach the resulting attachment object
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa CreateMessage, CreateAttach, GetAttachmentTable, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS OpenAttach(mapi_object_t *obj_message, uint32_t AttachmentID,
+ mapi_object_t *obj_attach)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct OpenAttach_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_message);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "OpenAttach");
+ size = 0;
+
+ /* Fill the OpenAttach operation */
+ request.handle_idx = 0x1;
+ size += sizeof(uint8_t);
+ request.OpenAttachmentFlags = OpenAttachmentFlags_ReadOnly;
+ size += sizeof(uint8_t);
+ request.AttachmentID = AttachmentID;
+ size += sizeof(uint32_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_OpenAttach;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_OpenAttach = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_message);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Set object session and handle */
+ mapi_object_set_session(obj_attach, session);
+ mapi_object_set_handle(obj_attach, mapi_response->handles[1]);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Set the type of a recipient
+
+ The function sets the recipient type (RecipClass) in the aRow
+ parameter. ResolveNames should be used to fill the SRow structure.
+
+ \param aRow the row to set
+ \param RecipClass the type of recipient to set on the specified row
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: The aRow parameter was not set
+ properly.
+
+ \sa ResolveNames, ModifyRecipients, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS SetRecipientType(struct SRow *aRow, enum ulRecipClass RecipClass)
+{
+ enum MAPISTATUS retval;
+ struct SPropValue lpProp;
+
+ lpProp.ulPropTag = PR_RECIPIENT_TYPE;
+ lpProp.value.l = RecipClass;
+
+ retval = SRow_addprop(aRow, lpProp);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/*
+ * retrieve the organization length for Exchange recipients
+ */
+uint8_t mapi_recipients_get_org_length(struct mapi_profile *profile)
+{
+ if (profile->mailbox && profile->username)
+ return (strlen(profile->mailbox) - strlen(profile->username));
+ return 0;
+}
+
+
+/*
+ * EXPERIMENTAL:
+ * bitmask calculation for recipients headers structures
+ */
+uint16_t mapi_recipients_bitmask(struct SRow *aRow)
+{
+ uint16_t bitmask;
+ struct SPropValue *lpProp = NULL;
+
+ bitmask = 0;
+
+ /* recipient type: EXCHANGE or SMTP */
+ lpProp = get_SPropValue_SRow(aRow, PR_ADDRTYPE);
+ if (lpProp && lpProp->value.lpszA) {
+ if (!strcmp("SMTP", lpProp->value.lpszA)) {
+ bitmask |= 0xB;
+ }
+ } else {
+ /* (Bit 8) doesn't seem to work if unset */
+ bitmask |= 0x81;
+ }
+
+ /* Bit 15: DISPLAY_NAME */
+ lpProp = get_SPropValue_SRow(aRow, PR_DISPLAY_NAME);
+ if (lpProp && lpProp->value.lpszA) {
+ bitmask |= 0x400;
+ }
+
+ lpProp = get_SPropValue_SRow(aRow, PR_DISPLAY_NAME_UNICODE);
+ if (lpProp && lpProp->value.lpszW) {
+ bitmask |= 0x600;
+ }
+
+ /* Bit 6: PR_GIVEN_NAME */
+ lpProp = get_SPropValue_SRow(aRow, PR_GIVEN_NAME);
+ if (lpProp && lpProp->value.lpszA) {
+ bitmask |= 0x20;
+ }
+
+ lpProp = get_SPropValue_SRow(aRow, PR_GIVEN_NAME_UNICODE);
+ if (lpProp && lpProp->value.lpszW) {
+ bitmask |= 0x220;
+ }
+
+ /* Bit 5. PR_7BIT_DISPLAY_NAME */
+ lpProp = get_SPropValue_SRow(aRow, PR_7BIT_DISPLAY_NAME);
+ if (lpProp && lpProp->value.lpszA) {
+ bitmask |= 0x10;
+ }
+
+ lpProp = get_SPropValue_SRow(aRow, PR_7BIT_DISPLAY_NAME_UNICODE);
+ if (lpProp && lpProp->value.lpszW) {
+ bitmask |= 0x210;
+ }
+
+ /* Bit 4: PR_EMAIL_ADDRESS */
+ if (bitmask & 0xA) {
+ lpProp = get_SPropValue_SRow(aRow, PR_SMTP_ADDRESS);
+ if (lpProp && lpProp->value.lpszA) {
+ bitmask |= 0x8;
+ }
+
+ lpProp = get_SPropValue_SRow(aRow, PR_SMTP_ADDRESS_UNICODE);
+ if (lpProp && lpProp->value.lpszW) {
+ bitmask |= 0x208;
+ }
+ }
+
+ return bitmask;
+}
+
+
+/**
+ \details Adds, deletes or modifies message recipients
+
+ \param obj_message the message to change the recipients for
+ \param SRowSet the recipients to add
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \bug ModifyRecipients can only add recipients.
+
+ \sa CreateMessage, ResolveNames, SetRecipientType, GetLastError
+
+*/
+_PUBLIC_ enum MAPISTATUS ModifyRecipients(mapi_object_t *obj_message,
+ struct SRowSet *SRowSet)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct ModifyRecipients_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+ unsigned long i_prop, j;
+ unsigned long i_recip;
+ uint32_t count;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SRowSet, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!SRowSet->aRow, MAPI_E_NOT_INITIALIZED, NULL);
+
+ session = mapi_object_get_session(obj_message);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "ModifyRecipients");
+ size = 0;
+
+ /* Fill the ModifyRecipients operation */
+ request.prop_count = SRowSet->aRow[0].cValues;
+ size += sizeof(uint16_t);
+
+ /*
+ * 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, 7,
+ PR_DISPLAY_NAME,
+ PR_DISPLAY_NAME_UNICODE,
+ PR_GIVEN_NAME,
+ PR_GIVEN_NAME_UNICODE,
+ PR_GIVEN_NAME_ERROR,
+ PR_RECIPIENT_TYPE,
+ PR_ADDRTYPE);
+ size += request.prop_count * sizeof(uint32_t);
+
+ request.cValues = SRowSet->cRows;
+ size += sizeof(uint16_t);
+ request.RecipientRow = talloc_array(mem_ctx, struct ModifyRecipientRow, request.cValues);
+
+ for (i_recip = 0; i_recip < request.cValues; i_recip++) {
+ struct SRow *aRow;
+ struct RecipientRow *RecipientRow;
+ struct ndr_push *ndr;
+ struct mapi_SPropValue mapi_sprop;
+ const uint32_t *RecipClass = 0;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_push);
+ ndr->iconv_convenience = smb_iconv_convenience_init(mem_ctx, "CP850", "UTF8", true);
+
+ aRow = &(SRowSet->aRow[i_recip]);
+ RecipientRow = &(request.RecipientRow[i_recip].RecipientRow);
+
+ request.RecipientRow[i_recip].idx = i_recip;
+ size += sizeof(uint32_t);
+
+ RecipClass = (const uint32_t *) find_SPropValue_data(aRow, PR_RECIPIENT_TYPE);
+ OPENCHANGE_RETVAL_IF(!RecipClass, MAPI_E_INVALID_PARAMETER, mem_ctx);
+ request.RecipientRow[i_recip].RecipClass = (uint8_t) *RecipClass;
+ size += sizeof(uint8_t);
+
+ RecipientRow->RecipientFlags = mapi_recipients_bitmask(aRow);
+
+ /* recipient type EXCHANGE or SMTP */
+ switch (RecipientRow->RecipientFlags & 0xB) {
+ case 0x1:
+ RecipientRow->type.EXCHANGE.organization_length = mapi_recipients_get_org_length(session->profile);
+ RecipientRow->type.EXCHANGE.addr_type = 0;
+ RecipientRow->type.EXCHANGE.username = (const char *) find_SPropValue_data(aRow, PR_7BIT_DISPLAY_NAME);
+ size += sizeof(uint32_t) + strlen(RecipientRow->type.EXCHANGE.username) + 1;
+ break;
+ case 0xB:
+ size += sizeof(uint16_t);
+ break;
+ }
+
+ /* Bit 15: PR_DISPLAY_NAME */
+ switch(RecipientRow->RecipientFlags & 0x600) {
+ case (0x400):
+ RecipientRow->SimpleDisplayName.lpszA = (const char *) find_SPropValue_data(aRow, PR_DISPLAY_NAME);
+ size += strlen(RecipientRow->SimpleDisplayName.lpszA) + 1;
+ break;
+ case (0x600):
+ RecipientRow->SimpleDisplayName.lpszW = (const char *) find_SPropValue_data(aRow, PR_DISPLAY_NAME_UNICODE);
+ size += strlen(RecipientRow->SimpleDisplayName.lpszW) * 2 + 2;
+ break;
+ default:
+ break;
+ }
+
+ /* Bit 6: PR_GIVEN_NAME */
+ switch (RecipientRow->RecipientFlags & 0x220) {
+ case (0x20):
+ RecipientRow->TransmittableDisplayName.lpszA = (const char *) find_SPropValue_data(aRow, PR_GIVEN_NAME);
+ size += strlen(RecipientRow->TransmittableDisplayName.lpszA) + 1;
+ break;
+ case (0x220):
+ RecipientRow->TransmittableDisplayName.lpszW = (const char *) find_SPropValue_data(aRow, PR_GIVEN_NAME_UNICODE);
+ size += strlen(RecipientRow->TransmittableDisplayName.lpszW) * 2 + 2;
+ break;
+ default:
+ break;
+ }
+
+ /* Bit 5: PR_7BIT_DISPLAY_NAME */
+ switch (RecipientRow->RecipientFlags & 0x210) {
+ case (0x10):
+ RecipientRow->DisplayName.lpszA = (const char *) find_SPropValue_data(aRow, PR_7BIT_DISPLAY_NAME);
+ size += strlen(RecipientRow->DisplayName.lpszA) + 1;
+ break;
+ case (0x210):
+ RecipientRow->DisplayName.lpszW = (const char *) find_SPropValue_data(aRow, PR_7BIT_DISPLAY_NAME_UNICODE);
+ size += strlen(RecipientRow->DisplayName.lpszW) * 2 + 2;
+ break;
+ default:
+ break;
+ }
+
+ /* Bit 4: PR_SMTP_ADDRESS */
+ switch (RecipientRow->RecipientFlags & 0x208) {
+ case (0x8):
+ RecipientRow->EmailAddress.lpszA = (const char *) find_SPropValue_data(aRow, PR_SMTP_ADDRESS);
+ size += strlen(RecipientRow->EmailAddress.lpszA) + 1;
+ break;
+ case (0x208):
+ RecipientRow->EmailAddress.lpszW = (const char *) find_SPropValue_data(aRow, PR_SMTP_ADDRESS_UNICODE);
+ size += strlen(RecipientRow->EmailAddress.lpszW) * 2 + 2;
+ break;
+ default:
+ break;
+ }
+
+ RecipientRow->prop_count = request.prop_count;
+ size += sizeof(uint16_t);
+ RecipientRow->layout = 0;
+ size += sizeof(uint8_t);
+
+ /* for each property, we set the switch values and ndr_flags then call mapi_SPropValue_CTR */
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ for (i_prop = 0; i_prop < request.prop_count; i_prop++) {
+ for (j = 0; j < aRow->cValues; j++) {
+ if (aRow->lpProps[j].ulPropTag == request.properties[i_prop]) {
+ ndr_push_set_switch_value(ndr, &mapi_sprop.value,
+ (aRow->lpProps[j].ulPropTag & 0xFFFF));
+ cast_mapi_SPropValue(&mapi_sprop, &aRow->lpProps[j]);
+ ndr_push_mapi_SPropValue_CTR(ndr, NDR_SCALARS, &mapi_sprop.value);
+ }
+ }
+ }
+
+ RecipientRow->prop_values.length = ndr->offset;
+ RecipientRow->prop_values.data = ndr->data;
+ /* add the blob size field */
+ size += sizeof(uint16_t);
+ size += RecipientRow->prop_values.length;
+ }
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_ModifyRecipients;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_ModifyRecipients = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof(uint32_t);
+ 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_message);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ errno = 0;
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Read Recipients from a message
+
+ \param obj_message the message we want to read recipients from
+ \param RowId the row index we start reading recipients from
+ \param RowCount pointer on the number of recipients
+ \param RecipientRows pointer on the recipients array
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa ModifyRecipients, RemoveAllRecipients, GetRecipientTable,
+ OpenMessage
+ */
+_PUBLIC_ enum MAPISTATUS ReadRecipients(mapi_object_t *obj_message,
+ uint32_t RowId, uint8_t *RowCount,
+ struct ReadRecipientRow **RecipientRows)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct ReadRecipients_req request;
+ struct ReadRecipients_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_message);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "ReadRecipients");
+ size = 0;
+
+ /* Fill the ReadRecipients operation */
+ request.RowId = RowId;
+ size += sizeof (uint32_t);
+
+ request.ulReserved = 0;
+ size += sizeof (uint16_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_ReadRecipients;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_ReadRecipients = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_message);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve the recipients */
+ reply = &mapi_response->mapi_repl->u.mapi_ReadRecipients;
+ *RowCount = reply->RowCount;
+ *RecipientRows = talloc_steal((TALLOC_CTX *)session, reply->RecipientRows);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Deletes all recipients from a message
+
+ \param obj_message the message we want to remove all recipients from
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa ModifyRecipients, ReadRecipients
+*/
+_PUBLIC_ enum MAPISTATUS RemoveAllRecipients(mapi_object_t *obj_message)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct RemoveAllRecipients_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_message);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "RemoveAllRecipients");
+ size = 0;
+
+ /* Fill the RemoveAllRecipients operation */
+ request.ulReserved = 0;
+ size += sizeof (uint32_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_RemoveAllRecipients;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_RemoveAllRecipients = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_message);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Saves all changes to the message and marks it as ready for
+ sending.
+
+ This function saves all changes made to a message and marks it
+ ready to be sent.
+
+ \param obj_message the message to mark complete
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa CreateMessage, SetProps, ModifyRecipients, SetRecipientType,
+ GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS SubmitMessage(mapi_object_t *obj_message)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SubmitMessage_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_message);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SubmitMessage");
+ size = 0;
+
+ /* Fill the SubmitMessage operation */
+ request.SubmitFlags = 0x0;
+ size += sizeof(uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SubmitMessage;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SubmitMessage = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_message);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Aborts a previous message submission.
+
+ \param obj_store the store object
+ \param obj_folder the folder object where the message has been
+ submitted
+ \param obj_message the submitted message object
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+ - MAPI_E_UNABLE_TO_ABORT: The operation can not be aborted
+ - MAPI_E_NOT_IN_QUEUE: The message is no longer in the message store's
+ spooler queue
+ - MAPI_E_NO_SUPPORT: the server object associated with the input
+ handle index in the server object table is not of type Logon or
+ the current logon session is a public logon.
+
+ \sa SubmitMessage
+ */
+_PUBLIC_ enum MAPISTATUS AbortSubmit(mapi_object_t *obj_store,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_message)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct AbortSubmit_req request;
+ struct mapi_session *session[2];
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session[0] = mapi_object_get_session(obj_store);
+ session[1] = mapi_object_get_session(obj_message);
+ OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "AbortSubmit");
+ size = 0;
+
+ /* Fill the AbortSubmit operation */
+ request.FolderId = mapi_object_get_id(obj_folder);
+ size += sizeof (uint64_t);
+
+ request.MessageId = mapi_object_get_id(obj_message);
+ size += sizeof (uint64_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_AbortSubmit;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_AbortSubmit = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_store);
+
+ status = emsmdb_transaction(session[0]->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Saves all changes to the message
+
+ \param parent the parent object for the message
+ \param obj_message the message to save
+ \param SaveFlags specify how the save operation behaves
+
+ Possible value for SaveFlags:
+ -# KeepReadOnly Keep the Message object open with read-only access
+ -# KeepOpenReadWrite Keep the Message object open with read-write
+ access
+ -# ForceSave Commit the changes and keep the message object open
+ with read-write access
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetProps, ModifyRecipients, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS SaveChangesMessage(mapi_object_t *parent,
+ mapi_object_t *obj_message,
+ uint8_t SaveFlags)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SaveChangesMessage_req request;
+ struct mapi_session *session[2];
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!parent, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF((SaveFlags != 0x9) && (SaveFlags != 0xA) &&
+ (SaveFlags != 0xC), MAPI_E_INVALID_PARAMETER, NULL);
+
+ session[0] = mapi_object_get_session(parent);
+ session[1] = mapi_object_get_session(obj_message);
+ OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SaveChangesMessage");
+ size = 0;
+
+ /* Fill the SaveChangesMessage operation */
+ request.handle_idx = 0x1;
+ size += sizeof (uint8_t);
+
+ request.SaveFlags = SaveFlags;
+ size += sizeof(uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SaveChangesMessage;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SaveChangesMessage = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + (2 * sizeof (uint32_t));
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(parent);
+ mapi_request->handles[1] = mapi_object_get_handle(obj_message);
+
+ status = emsmdb_transaction(session[0]->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* store the message_id */
+ mapi_object_set_id(obj_message, mapi_response->mapi_repl->u.mapi_SaveChangesMessage.MessageId);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Sends the specified Message object out for message
+ delivery.
+
+*/
+_PUBLIC_ enum MAPISTATUS TransportSend(mapi_object_t *obj_message,
+ struct mapi_SPropValue_array *lpProps)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct TransportSend_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!lpProps, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_message);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "TransportSend");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_TransportSend;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_message);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve reply parameters */
+ reply = &mapi_response->mapi_repl->u.mapi_TransportSend;
+ if (!reply->NoPropertiesReturned) {
+ lpProps->cValues = reply->properties.lpProps.cValues;
+ lpProps->lpProps = talloc_steal((TALLOC_CTX *)session, reply->properties.lpProps.lpProps);
+ } else {
+ lpProps = NULL;
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns the message recipient table
+
+ \param obj_message the message to receive recipients from
+ \param SRowSet pointer to the recipient table
+ \param SPropTagArray pointer to the array of properties listed in
+ the recipient table
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+
+ \sa OpenMessage
+ */
+_PUBLIC_ enum MAPISTATUS GetRecipientTable(mapi_object_t *obj_message,
+ struct SRowSet *SRowSet,
+ struct SPropTagArray *SPropTagArray)
+{
+ mapi_object_message_t *message;
+
+ message = (mapi_object_message_t *)obj_message->private_data;
+
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!message, MAPI_E_NOT_INITIALIZED, NULL);
+
+ *SRowSet = message->SRowSet;
+ *SPropTagArray = message->SPropTagArray;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Clear or set the MSGFLAG_READ flag for a given message
+
+ This function clears or sets the MSGFLAG_READ flag in the
+ PR_MESSAGE_FLAGS property of a given message.
+
+ \param obj_folder the folder to operate in
+ \param obj_child the message to set flags on
+ \param flags the new flags (MSGFLAG_READ) value
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenMessage, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS SetMessageReadFlag(mapi_object_t *obj_folder,
+ mapi_object_t *obj_child,
+ uint8_t flags)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SetMessageReadFlag_req request;
+ struct mapi_session *session[2];
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_child, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session[0] = mapi_object_get_session(obj_folder);
+ session[1] = mapi_object_get_session(obj_child);
+ OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SetMessageReadFlags");
+ size = 0;
+
+ /* Fill the SetMessageReadFlags operation */
+ request.handle_idx = 0x1;
+ size += sizeof(uint8_t);
+ request.flags = flags;
+ size += sizeof(uint8_t);
+
+ request.clientdata.length = 0;
+ request.clientdata.data = NULL;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SetMessageReadFlag;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SetMessageReadFlag = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
+ mapi_request->handles[1] = mapi_object_get_handle(obj_child);
+
+ status = emsmdb_transaction(session[0]->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Opens an embedded message object and retrieves a MAPI object that
+ can be used to get or set properties on the embedded message.
+
+ This function essentially takes an attachment and gives you back
+ a message.
+
+ \param obj_attach the attachment object
+ \param obj_embeddedmsg the embedded message
+ \param ulFlags access rights on the embedded message
+
+ Possible ulFlags values:
+ - 0x0: read only access
+ - 0x1: Read / Write access
+ - 0x2: Create
+
+ \code
+ ... assume we have a message - obj_message ...
+ // Initialise the attachment object
+ mapi_object_init(&obj_attach);
+
+ // Create an attachment to the message
+ retval = CreateAttach(&obj_message, &obj_attach);
+ ... check the return value ...
+
+ // use SetProps() to set the attachment up, noting the special PR_ATTACHM_METHOD property
+ attach[0].ulPropTag = PR_ATTACH_METHOD;
+ attach[0].value.l = ATTACH_EMBEDDED_MSG;
+ attach[1].ulPropTag = PR_RENDERING_POSITION;
+ attach[1].value.l = 0;
+ retval = SetProps(&obj_attach, attach, 2);
+ ... check the return value ...
+
+ // Initialise the embedded message object
+ mapi_object_init(&obj_embeddedmsg);
+ retval = OpenEmbeddedMessage(&obj_attach, &obj_embeddedmsg, MAPI_CREATE);
+ ... check the return value ...
+
+ // Fill in the embedded message properties, just like any other message (e.g. resulting from CreateMessage())
+
+ // Save the changes to the embedded message
+ retval = SaveChangesMessage(&obj_message, &obj_embeddedmsg, KeepOpenReadOnly);
+ ... check the return value ...
+
+ // Save the changes to the attachment
+ retval = SaveChangesAttachment(&obj_message, &obj_attach, KeepOpenReadOnly);
+ ... check the return value ...
+
+ // Save the changes to the original message
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ ... check the return value ...
+ \endcode
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error. Possible
+ MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_store is undefined
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code.
+
+ \sa CreateAttach, OpenMessage, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS OpenEmbeddedMessage(mapi_object_t *obj_attach,
+ mapi_object_t *obj_embeddedmsg,
+ enum OpenEmbeddedMessage_OpenModeFlags ulFlags)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct OpenEmbeddedMessage_req request;
+ struct OpenEmbeddedMessage_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_attach, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_attach);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_embeddedmsg, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "OpenEmbeddedMessage");
+
+ /* Fill the OpenEmbeddedMessage request */
+ request.handle_idx = 0x1;
+ size += sizeof(uint8_t);
+ request.CodePageId = 0xfff;
+ size += sizeof(uint16_t);
+ request.OpenModeFlags = ulFlags;
+ size += sizeof(uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_OpenEmbeddedMessage;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_OpenEmbeddedMessage = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_attach);
+ mapi_request->handles[1] = mapi_object_get_handle(obj_embeddedmsg);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Set object session and handle */
+ mapi_object_set_session(obj_embeddedmsg, session);
+ mapi_object_set_handle(obj_embeddedmsg, mapi_response->handles[1]);
+
+ /* Store OpenEmbeddedMessage reply data */
+ reply = &mapi_response->mapi_repl->u.mapi_OpenEmbeddedMessage;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
Added: trunk/openchange/libmapi/IMsgStore.c
===================================================================
--- trunk/openchange/libmapi/IMsgStore.c (rev 0)
+++ trunk/openchange/libmapi/IMsgStore.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,813 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+
+/**
+ \file IMsgStore.c
+
+ \brief Folders related operations
+ */
+
+
+/**
+ \details Open a folder from the store
+
+ \param obj_store the store to open a folder in (i.e. the parent)
+ \param id_folder the folder identifier
+ \param obj_folder the resulting open folder
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MAPIInitialize, OpenMsgStore, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS OpenFolder(mapi_object_t *obj_store, mapi_id_t id_folder,
+ mapi_object_t *obj_folder)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct OpenFolder_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "OpenFolder");
+
+ /* Fill the OpenFolder operation */
+ request.handle_idx = 0x1;
+ request.folder_id = id_folder;
+ request.OpenModeFlags = OpenModeFlags_Folder;
+ size += sizeof (uint8_t) + sizeof(uint64_t) + sizeof(uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_OpenFolder;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_OpenFolder = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_store);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Set object session, id and handle */
+ mapi_object_set_session(obj_folder, session);
+ mapi_object_set_id(obj_folder, id_folder);
+ mapi_object_set_handle(obj_folder, mapi_response->handles[1]);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Determine if a public folder is ghosted.
+
+ This function returns whether a public folder is ghosted or not.
+
+ \param obj_store the store of the public folder
+ \param obj_folder the folder we are querying for ghost
+ \param IsGhosted pointer on the boolean value returned
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+*/
+_PUBLIC_ enum MAPISTATUS PublicFolderIsGhosted(mapi_object_t *obj_store,
+ mapi_object_t *obj_folder,
+ bool *IsGhosted)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct PublicFolderIsGhosted_req request;
+ struct mapi_session *session[2];
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+ mapi_id_t folderId;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session[0] = mapi_object_get_session(obj_store);
+ session[1] = mapi_object_get_session(obj_folder);
+ OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
+
+ folderId = mapi_object_get_id(obj_folder);
+ OPENCHANGE_RETVAL_IF(!folderId, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "PublicFolderIsGhosted");
+ size = 0;
+
+ /* Fill the PublicFolderIsGhosted operation */
+ request.FolderId = folderId;
+ size += sizeof (uint64_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_PublicFolderIsGhosted;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_PublicFolderIsGhosted = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_store);
+
+ status = emsmdb_transaction(session[0]->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ *IsGhosted = mapi_response->mapi_repl->u.mapi_PublicFolderIsGhosted.IsGhosted;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Open a NNTP Public Folder given its name
+
+ \param obj_folder the parent folder
+ \param obj_child the resulting open folder
+ \param name the folder name
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenPublicFolder
+ */
+_PUBLIC_ enum MAPISTATUS OpenPublicFolderByName(mapi_object_t *obj_folder,
+ mapi_object_t *obj_child,
+ const char *name)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct OpenPublicFolderByName_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_child, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!name, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_folder);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "OpenPublicFolderByName");
+ size = 0;
+
+ /* Fill the OpenPublicFolderByName operation */
+ request.handle_idx = 0x1;
+ size += sizeof (uint8_t);
+
+ /* name is prefixed with 32 bit [size] */
+ request.name = name;
+ size += strlen(name) + 1 + sizeof (uint32_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_OpenPublicFolderByName;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_OpenPublicFolderByName = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Set object session and handle */
+ mapi_object_set_session(obj_child, session);
+ mapi_object_set_handle(obj_child, mapi_response->handles[1]);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Sets a folder as the destination for incoming messages of
+ a particular message class.
+
+ \param obj_store the store to set the receive folder for
+ \param obj_folder the destination folder
+ \param lpszMessageClass the message class the folder will receive
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetReceiveFolder, GetReceiveFolderTable
+ */
+_PUBLIC_ enum MAPISTATUS SetReceiveFolder(mapi_object_t *obj_store,
+ mapi_object_t *obj_folder,
+ const char *lpszMessageClass)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SetReceiveFolder_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!lpszMessageClass, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SetReceiveFolder");
+
+ /* Fill the SetReceiveFolder operation */
+ size = 0;
+ request.fid = mapi_object_get_id(obj_folder);
+ size += sizeof (uint64_t);
+ request.lpszMessageClass = lpszMessageClass;
+ size += strlen(lpszMessageClass) + 1;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SetReceiveFolder;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SetReceiveFolder = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_store);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Gets the receive folder for incoming messages of a
+ particular message class.
+
+ This function obtains the folder that was established as the
+ destination for incoming messages of a specified message class, or
+ the default receive folder for the message store.
+
+ \param obj_store the store to get the receiver folder for
+ \param id_folder the resulting folder identification
+ \param MessageClass which message class to find the receivefolder
+ for
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MAPIInitialize, OpenMsgStore, GetLastError, SetReceiveFolder,
+ GetReceiveFolderTable
+*/
+_PUBLIC_ enum MAPISTATUS GetReceiveFolder(mapi_object_t *obj_store,
+ mapi_id_t *id_folder,
+ const char *MessageClass)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetReceiveFolder_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetReceiveFolder");
+
+ *id_folder = 0;
+
+ /* Fill the GetReceiveFolder operation */
+ if (!MessageClass) {
+ request.MessageClass = "";
+ size += 1;
+ } else {
+ request.MessageClass = MessageClass;
+ size += strlen (MessageClass) + 1;
+ }
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetReceiveFolder;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetReceiveFolder = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_store);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ *id_folder = mapi_response->mapi_repl->u.mapi_GetReceiveFolder.folder_id;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve the receive folder table which includes all the
+ information about the receive folders for the message store
+
+ \param obj_store the message store object
+ \param SRowSet pointer on a SRowSet structure with
+ GetReceiveFolderTable results.
+
+ Developers are required to call MAPIFreeBuffer(SRowSet.aRow) when
+ they don't need the folder table data anymore.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetReceiveFolder, SetReceiveFolder
+ */
+_PUBLIC_ enum MAPISTATUS GetReceiveFolderTable(mapi_object_t *obj_store,
+ struct SRowSet *SRowSet)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetReceiveFolderTable_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+ uint32_t i;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetReceiveFolderTable");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetReceiveFolderTable;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_store);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ reply = &mapi_response->mapi_repl->u.mapi_GetReceiveFolderTable;
+
+ /* Retrieve the ReceiveFolderTable entries */
+ SRowSet->cRows = reply->cValues;
+ SRowSet->aRow = talloc_array((TALLOC_CTX *)session, struct SRow, reply->cValues);
+
+ for (i = 0; i < reply->cValues; i++) {
+ SRowSet->aRow[i].ulAdrEntryPad = 0;
+ SRowSet->aRow[i].cValues = 3;
+ SRowSet->aRow[i].lpProps = talloc_array((TALLOC_CTX *)SRowSet->aRow, struct SPropValue,
+ SRowSet->aRow[i].cValues);
+
+ SRowSet->aRow[i].lpProps[0].ulPropTag = PR_FID;
+ SRowSet->aRow[i].lpProps[0].dwAlignPad = 0x0;
+ SRowSet->aRow[i].lpProps[0].value.d = reply->entries[i].fid;
+
+ SRowSet->aRow[i].lpProps[1].ulPropTag = PR_MESSAGE_CLASS;
+ SRowSet->aRow[i].lpProps[1].dwAlignPad = 0x0;
+ SRowSet->aRow[i].lpProps[1].value.lpszA = talloc_strdup((TALLOC_CTX *)SRowSet->aRow, reply->entries[i].lpszMessageClass);
+
+ SRowSet->aRow[i].lpProps[2].ulPropTag = PR_LAST_MODIFICATION_TIME;
+ SRowSet->aRow[i].lpProps[2].dwAlignPad = 0x0;
+ SRowSet->aRow[i].lpProps[2].value.ft.dwLowDateTime = reply->entries[i].modiftime.dwLowDateTime;
+ SRowSet->aRow[i].lpProps[2].value.ft.dwHighDateTime = reply->entries[i].modiftime.dwHighDateTime;
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieves the folder ID of the temporary transport folder.
+
+ \param obj_store the server object
+ \param FolderId pointer on the returning Folder identifier
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+ */
+_PUBLIC_ enum MAPISTATUS GetTransportFolder(mapi_object_t *obj_store,
+ mapi_id_t *FolderId)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetTransportFolder_repl *reply;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!FolderId, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetTransportFolder");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetTransportFolder;
+ mapi_req->logon_id =0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_store);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve the FolderId parameter */
+ reply = &mapi_response->mapi_repl->u.mapi_GetTransportFolder;
+ *FolderId = reply->FolderId;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Get the list of servers that host replicas of a given
+ public folder.
+
+ \param obj_store the public folder store object
+ \param obj_folder the folder object we search replica for
+ \param OwningServersCount number of OwningServers
+ \param CheapServersCount number of low-cost servers
+ \param OwningServers pointer on the list of NULL terminated ASCII
+ string representing replica servers
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note ecNoReplicaAvailable (0x469) can be returned if no replica is
+ available for the folder.
+
+ Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+ */
+_PUBLIC_ enum MAPISTATUS GetOwningServers(mapi_object_t *obj_store,
+ mapi_object_t *obj_folder,
+ uint16_t *OwningServersCount,
+ uint16_t *CheapServersCount,
+ char **OwningServers)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct GetOwningServers_req request;
+ struct GetOwningServers_repl response;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+ mapi_id_t FolderId;
+ uint32_t i;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!OwningServersCount, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!CheapServersCount, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!OwningServers, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ FolderId = mapi_object_get_id(obj_folder);
+ OPENCHANGE_RETVAL_IF(!FolderId, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetOwningServers");
+
+ size = 0;
+
+ /* Fill the GetOwningServers operation */
+ request.FolderId = FolderId;
+ size += sizeof (uint64_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetOwningServers;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_GetOwningServers = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_store);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve GetOwningServers response */
+ response = mapi_response->mapi_repl->u.mapi_GetOwningServers;
+
+ *OwningServersCount = response.OwningServersCount;
+ *CheapServersCount = response.CheapServersCount;
+ if (*OwningServersCount) {
+ OwningServers = talloc_array((TALLOC_CTX *)session, char *, *OwningServersCount + 1);
+ for (i = 0; i != *OwningServersCount; i++) {
+ OwningServers[i] = talloc_strdup((TALLOC_CTX *)OwningServers, response.OwningServers[i]);
+ }
+ OwningServers[i] = NULL;
+ } else {
+ OwningServers = NULL;
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Gets the current store state for the loggued user
+
+ \param obj_store the store object
+ \param StoreState pointer on the store state returned by the server
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+ */
+_PUBLIC_ enum MAPISTATUS GetStoreState(mapi_object_t *obj_store,
+ uint32_t *StoreState)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!StoreState, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetStoreState");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetStoreState;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_store);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve the StoreState */
+ *StoreState = mapi_response->mapi_repl->u.mapi_GetStoreState.StoreState;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieves the sending folder (OUTBOX) for a given store
+
+ This function obtains the folder that was established as the
+ destination for outgoing messages of a specified message class.
+
+ This function does not result in any network traffic.
+
+ \param obj_store the store to get the outbox folder for
+ \param outbox_id the resulting folder identification
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MAPIInitialize, OpenMsgStore, GetLastError, GetDefaultFolder
+*/
+_PUBLIC_ enum MAPISTATUS GetOutboxFolder(mapi_object_t *obj_store,
+ mapi_id_t *outbox_id)
+{
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+
+ *outbox_id = ((mapi_object_store_t *)obj_store->private_data)->fid_outbox;
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IProfAdmin.c
===================================================================
--- trunk/openchange/libmapi/IProfAdmin.c (rev 0)
+++ trunk/openchange/libmapi/IProfAdmin.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1399 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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/proto_private.h>
+#include <credentials.h>
+#include <ldb_errors.h>
+#include <ldb.h>
+
+/**
+ \file IProfAdmin.c
+
+ \brief MAPI Profiles interface
+ */
+
+/*
+ * Private functions
+ */
+
+/**
+ * Load a MAPI profile into a mapi_profile struct
+ */
+static enum MAPISTATUS ldb_load_profile(TALLOC_CTX *mem_ctx,
+ struct ldb_context *ldb_ctx,
+ struct mapi_profile *profile,
+ const char *profname, const char *password)
+{
+ int ret;
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_result *res;
+ struct ldb_message *msg;
+ const char * const attrs[] = { "*", NULL };
+
+ /* fills in profile name */
+ profile->profname = talloc_strdup(mem_ctx, profname);
+ if (!profile->profname) return MAPI_E_NOT_ENOUGH_RESOURCES;
+
+ /* ldb query */
+ ldb_ctx = global_mapi_ctx->ldb_ctx;
+
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx), scope, attrs, "(cn=%s)(cn=Profiles)", profile->profname);
+ if (ret != LDB_SUCCESS) return MAPI_E_NOT_FOUND;
+
+ /* profile not found */
+ if (!res->count) return MAPI_E_NOT_FOUND;
+ /* more than one profile */
+ if (res->count > 1) return MAPI_E_COLLISION;
+
+ /* fills in profile with query result */
+ msg = res->msgs[0];
+
+ profile->username = ldb_msg_find_attr_as_string(msg, "username", NULL);
+ profile->password = password ? password : ldb_msg_find_attr_as_string(msg, "password", "");
+ profile->workstation = ldb_msg_find_attr_as_string(msg, "workstation", NULL);
+ profile->realm = ldb_msg_find_attr_as_string(msg, "realm", NULL);
+ profile->domain = ldb_msg_find_attr_as_string(msg, "domain", NULL);
+ profile->mailbox = ldb_msg_find_attr_as_string(msg, "EmailAddress", NULL);
+ profile->homemdb = ldb_msg_find_attr_as_string(msg, "HomeMDB", NULL);
+ profile->server = ldb_msg_find_attr_as_string(msg, "binding", NULL);
+ profile->org = ldb_msg_find_attr_as_string(msg, "Organization", NULL);
+ profile->ou = ldb_msg_find_attr_as_string(msg, "OrganizationUnit", NULL);
+ profile->codepage = ldb_msg_find_attr_as_int(msg, "codepage", 0);
+ profile->language = ldb_msg_find_attr_as_int(msg, "language", 0);
+ profile->method = ldb_msg_find_attr_as_int(msg, "method", 0);
+
+ if (!profile->password) return MAPI_E_INVALID_PARAMETER;
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * Search for and attribute within profiles
+ */
+static enum MAPISTATUS ldb_clear_default_profile(TALLOC_CTX *mem_ctx)
+{
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_context *ldb_ctx;
+ struct ldb_dn *basedn;
+ struct ldb_message *msg;
+ struct ldb_result *res;
+ const char *attrs[] = { "PR_DEFAULT_PROFILE", NULL };
+ int ret;
+ uint32_t i;
+
+ ldb_ctx = global_mapi_ctx->ldb_ctx;
+
+ basedn = ldb_dn_new(ldb_ctx, ldb_ctx, "CN=Profiles");
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, basedn, scope, attrs, "(cn=*)");
+
+ if (ret != LDB_SUCCESS) return MAPI_E_NOT_FOUND;
+ if (!res->count) return MAPI_E_NOT_FOUND;
+
+ for (i = 0; i < res->count; i++) {
+ struct ldb_message *message;
+
+ msg = res->msgs[i];
+ if (msg->num_elements == 1) {
+ message = talloc_steal(mem_ctx, msg);
+ message->elements[0].flags = LDB_FLAG_MOD_DELETE;
+
+ ret = ldb_modify(ldb_ctx, message);
+ talloc_free(message);
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * Test if the password is correct
+ */
+static enum MAPISTATUS ldb_test_password(TALLOC_CTX *mem_ctx, const char *profile,
+ const char *password)
+{
+ enum ldb_scope scope = LDB_SCOPE_DEFAULT;
+ struct ldb_context *ldb_ctx;
+ struct ldb_message *msg;
+ struct ldb_result *res;
+ const char *attrs[] = {"cn", "password", NULL };
+ const char *ldb_password;
+ int ret;
+
+ ldb_ctx = global_mapi_ctx->ldb_ctx;
+
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, NULL, scope, attrs,
+ "(cn=%s)(cn=Profiles)", profile);
+
+ if (ret != LDB_SUCCESS) return MAPI_E_NO_SUPPORT;
+ if (!res->count) return MAPI_E_NOT_FOUND;
+
+ msg = res->msgs[0];
+
+ ldb_password = ldb_msg_find_attr_as_string(msg, "password", NULL);
+ if (!ldb_password) return MAPI_E_NO_SUPPORT;
+ if (strncmp(password, ldb_password, strlen(password))) return MAPI_E_LOGON_FAILED;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/*
+ * Add a profile to the database with default fields
+ */
+static enum MAPISTATUS ldb_create_profile(TALLOC_CTX *mem_ctx,
+ struct ldb_context *ldb_ctx,
+ const char *profname)
+{
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_message msg;
+ struct ldb_message_element el[2];
+ struct ldb_val vals[2][1];
+ struct ldb_result *res;
+ struct ldb_dn *basedn;
+ char *dn;
+ int ret;
+ const char * const attrs[] = { "*", NULL };
+
+ /* Sanity check */
+ if (profname == NULL)
+ return MAPI_E_BAD_VALUE;
+
+ /* Does the profile already exists? */
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
+ scope, attrs, "(cn=%s)(cn=Profiles)", profname);
+ if (res->msgs) return MAPI_E_NO_ACCESS;
+
+ /*
+ * We now prepare the entry for transaction
+ */
+
+ dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Profiles", profname);
+ basedn = ldb_dn_new(ldb_ctx, ldb_ctx, dn);
+ talloc_free(dn);
+ if (!ldb_dn_validate(basedn)) return MAPI_E_BAD_VALUE;
+
+ msg.dn = ldb_dn_copy(mem_ctx, basedn);
+ msg.num_elements = 2;
+ msg.elements = el;
+
+ el[0].flags = 0;
+ el[0].name = talloc_strdup(mem_ctx, "cn");
+ el[0].num_values = 1;
+ el[0].values = vals[0];
+ vals[0][0].data = (uint8_t *)talloc_strdup(mem_ctx, profname);
+ vals[0][0].length = strlen(profname);
+
+ el[1].flags = 0;
+ el[1].name = talloc_strdup(mem_ctx, "name");
+ el[1].num_values = 1;
+ el[1].values = vals[1];
+ vals[1][0].data = (uint8_t *)talloc_strdup(mem_ctx, profname);
+ vals[1][0].length = strlen(profname);
+
+ ret = ldb_add(ldb_ctx, &msg);
+
+ if (ret != LDB_SUCCESS) return MAPI_E_NO_SUPPORT;
+
+ return MAPI_E_SUCCESS;
+}
+
+/*
+ * delete the current profile
+ */
+static enum MAPISTATUS ldb_delete_profile(TALLOC_CTX *mem_ctx,
+ struct ldb_context *ldb_ctx,
+ const char *profname)
+{
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_result *res;
+ const char * const attrs[] = { "*", NULL };
+ int ret;
+
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx), scope, attrs, "(cn=%s)(cn=Profiles)", profname);
+ if (!res->msgs) return MAPI_E_NOT_FOUND;
+
+ ret = ldb_delete(ldb_ctx, res->msgs[0]->dn);
+ if (ret != LDB_SUCCESS) return MAPI_E_NOT_FOUND;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Rename a profile
+
+ \param mem_ctx pointer on the memory context
+ \param old_profname the old profile name string
+ \param new_profname the new profile name string
+
+ \return MAPI_E_SUCCESS on success otherwise MAPI error.
+ */
+static enum MAPISTATUS ldb_rename_profile(TALLOC_CTX *mem_ctx,
+ const char *old_profname,
+ const char *new_profname)
+{
+ int ret;
+ struct ldb_context *ldb_ctx;
+ struct ldb_dn *old_dn;
+ struct ldb_dn *new_dn;
+ char *dn;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!old_profname, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!new_profname, MAPI_E_INVALID_PARAMETER, NULL);
+
+ ldb_ctx = global_mapi_ctx->ldb_ctx;
+
+ dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Profiles", old_profname);
+ old_dn = ldb_dn_new(mem_ctx, ldb_ctx, dn);
+ talloc_free(dn);
+
+ dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Profiles", new_profname);
+ new_dn = ldb_dn_new(mem_ctx, ldb_ctx, dn);
+ talloc_free(dn);
+
+ ret = ldb_rename(ldb_ctx, old_dn, new_dn);
+ OPENCHANGE_RETVAL_IF(ret, MAPI_E_CORRUPT_STORE, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/*
+ * Public interface
+ */
+
+/**
+ \details Add an attribute to the profile
+ */
+_PUBLIC_ enum MAPISTATUS mapi_profile_add_string_attr(const char *profile,
+ const char *attr,
+ const char *value)
+{
+ TALLOC_CTX *mem_ctx;
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_message msg;
+ struct ldb_message_element el[1];
+ struct ldb_val vals[1][1];
+ struct ldb_result *res;
+ struct ldb_context *ldb_ctx;
+ struct ldb_dn *basedn;
+ char *dn;
+ int ret;
+ const char * const attrs[] = { "*", NULL };
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx->ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!profile, MAPI_E_BAD_VALUE, NULL);
+ OPENCHANGE_RETVAL_IF(!value, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "mapi_profile_add_string_attr");
+ ldb_ctx = global_mapi_ctx->ldb_ctx;
+
+ /* Retrieve the profile from the database */
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx), scope, attrs, "(cn=%s)(cn=Profiles)", profile);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_BAD_VALUE, mem_ctx);
+
+ /* Preparing for the transaction */
+ dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Profiles", profile);
+ basedn = ldb_dn_new(ldb_ctx, ldb_ctx, dn);
+ talloc_free(dn);
+ OPENCHANGE_RETVAL_IF(!ldb_dn_validate(basedn), MAPI_E_BAD_VALUE, mem_ctx);
+
+ msg.dn = ldb_dn_copy(mem_ctx, basedn);
+ msg.num_elements = 1;
+ msg.elements = el;
+
+ el[0].flags = LDB_FLAG_MOD_ADD;
+ el[0].name = talloc_strdup(mem_ctx, attr);
+ el[0].num_values = 1;
+ el[0].values = vals[0];
+ vals[0][0].data = (uint8_t *)talloc_strdup(mem_ctx, value);
+ vals[0][0].length = strlen(value);
+
+ ret = ldb_modify(ldb_ctx, &msg);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NO_SUPPORT, mem_ctx);
+
+ talloc_free(mem_ctx);
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Modify an attribute
+ */
+_PUBLIC_ enum MAPISTATUS mapi_profile_modify_string_attr(const char *profname,
+ const char *attr,
+ const char *value)
+{
+ TALLOC_CTX *mem_ctx;
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_message msg;
+ struct ldb_message_element el[1];
+ struct ldb_val vals[1][1];
+ struct ldb_result *res;
+ struct ldb_context *ldb_ctx;
+ struct ldb_dn *basedn;
+ char *dn;
+ int ret;
+ const char * const attrs[] = { "*", NULL };
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!profname, MAPI_E_BAD_VALUE, NULL);
+
+ ldb_ctx = global_mapi_ctx->ldb_ctx;
+ mem_ctx = talloc_named(NULL, 0, "mapi_profile_modify_string_attr");
+
+ /* Retrieve the profile from the database */
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx), scope, attrs, "(cn=%s)(cn=Profiles)", profname);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_BAD_VALUE, mem_ctx);
+
+ /* Preparing for the transaction */
+ dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Profiles", profname);
+ basedn = ldb_dn_new(ldb_ctx, ldb_ctx, dn);
+ talloc_free(dn);
+ OPENCHANGE_RETVAL_IF(!ldb_dn_validate(basedn), MAPI_E_BAD_VALUE, mem_ctx);
+
+ msg.dn = ldb_dn_copy(mem_ctx, basedn);
+ msg.num_elements = 1;
+ msg.elements = el;
+
+ el[0].flags = LDB_FLAG_MOD_REPLACE;
+ el[0].name = talloc_strdup(mem_ctx, attr);
+ el[0].num_values = 1;
+ el[0].values = vals[0];
+ vals[0][0].data = (uint8_t *)talloc_strdup(mem_ctx, value);
+ vals[0][0].length = strlen(value);
+
+ ret = ldb_modify(ldb_ctx, &msg);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NO_SUPPORT, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Delete an attribute
+ */
+_PUBLIC_ enum MAPISTATUS mapi_profile_delete_string_attr(const char *profname,
+ const char *attr,
+ const char *value)
+{
+ TALLOC_CTX *mem_ctx;
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_message msg;
+ struct ldb_message_element el[1];
+ struct ldb_val vals[1][1];
+ struct ldb_result *res;
+ struct ldb_context *ldb_ctx;
+ struct ldb_dn *basedn;
+ char *dn;
+ int ret;
+ const char * const attrs[] = { "*", NULL };
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!profname, MAPI_E_BAD_VALUE, NULL);
+
+ ldb_ctx = global_mapi_ctx->ldb_ctx;
+ mem_ctx = talloc_named(NULL, 0, "mapi_profile_delete_string_attr");
+
+ /* Retrieve the profile from the database */
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx), scope, attrs, "(cn=%s)(cn=Profiles)", profname);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_BAD_VALUE, mem_ctx);
+
+ /* Preparing for the transaction */
+ dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Profiles", profname);
+ basedn = ldb_dn_new(ldb_ctx, ldb_ctx, dn);
+ talloc_free(dn);
+ OPENCHANGE_RETVAL_IF(!ldb_dn_validate(basedn), MAPI_E_BAD_VALUE, mem_ctx);
+
+ msg.dn = ldb_dn_copy(mem_ctx, basedn);
+ msg.num_elements = 1;
+ msg.elements = el;
+
+ el[0].flags = LDB_FLAG_MOD_DELETE;
+ el[0].name = talloc_strdup(mem_ctx, attr);
+ el[0].num_values = 1;
+ el[0].values = vals[0];
+ vals[0][0].data = (uint8_t *)talloc_strdup(mem_ctx, value);
+ vals[0][0].length = strlen(value);
+
+ ret = ldb_modify(ldb_ctx, &msg);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NO_SUPPORT, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/*
+ * Private function which opens the profile store
+ * Should only be called within MAPIInitialize
+ */
+enum MAPISTATUS OpenProfileStore(TALLOC_CTX *mem_ctx, struct ldb_context **ldb_ctx,
+ const char *profiledb)
+{
+ int ret;
+ struct ldb_context *tmp_ctx;
+ struct tevent_context *ev;
+
+ *ldb_ctx = 0;
+
+ /* store path */
+ if (!profiledb) return MAPI_E_NOT_FOUND;
+
+ ev = tevent_context_init(mem_ctx);
+ if (!ev) return MAPI_E_NOT_ENOUGH_RESOURCES;
+
+ /* connect to the store */
+ tmp_ctx = ldb_init(mem_ctx, ev);
+ if (!tmp_ctx) return MAPI_E_NOT_ENOUGH_RESOURCES;
+
+ ret = ldb_connect(tmp_ctx, profiledb, 0, NULL);
+ if (ret != LDB_SUCCESS) return MAPI_E_NOT_FOUND;
+
+ *ldb_ctx = tmp_ctx;
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Get default ldif_path
+
+ This function returns the path for the default LDIF files.
+
+ \sa CreateProfileStore
+*/
+_PUBLIC_ const char *mapi_profile_get_ldif_path(void)
+{
+ return DEFAULT_LDIF;
+}
+
+
+/**
+ \details Create a profile database
+
+ This function creates a new profile database, including doing an
+ initial setup.
+
+ \param profiledb the absolute path to the profile database intended
+ to be created
+ \param ldif_path the absolute path to the LDIF information to use
+ for initial setup.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_CALL_FAILED: profiledb or ldif_path is not set
+ - MAPI_E_NOT_ENOUGH_RESOURCES: ldb subsystem initialization failed
+ - MAPI_E_NO_ACCESS: connection or ldif add failed
+
+ \sa GetLastError, mapi_profile_get_ldif_path
+*/
+_PUBLIC_ enum MAPISTATUS CreateProfileStore(const char *profiledb, const char *ldif_path)
+{
+ int ret;
+ TALLOC_CTX *mem_ctx;
+ struct ldb_context *ldb_ctx;
+ struct ldb_ldif *ldif;
+ char *url = NULL;
+ char *filename = NULL;
+ FILE *f;
+ struct tevent_context *ev;
+
+ OPENCHANGE_RETVAL_IF(!profiledb, MAPI_E_CALL_FAILED, NULL);
+ OPENCHANGE_RETVAL_IF(!ldif_path, MAPI_E_CALL_FAILED, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CreateProfileStore");
+
+ ev = tevent_context_init(mem_ctx);
+ OPENCHANGE_RETVAL_IF(!ev, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ ldb_ctx = ldb_init(mem_ctx, ev);
+ OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ url = talloc_asprintf(mem_ctx, "tdb://%s", profiledb);
+ ret = ldb_connect(ldb_ctx, url, 0, 0);
+ talloc_free(url);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NO_ACCESS, mem_ctx);
+
+ filename = talloc_asprintf(mem_ctx, "%s/oc_profiles_init.ldif", ldif_path);
+ f = fopen(filename, "r");
+ OPENCHANGE_RETVAL_IF(!f, MAPI_E_NO_ACCESS, mem_ctx);
+ talloc_free(filename);
+
+ while ((ldif = ldb_ldif_read_file(ldb_ctx, f))) {
+ ldif->msg = ldb_msg_canonicalize(ldb_ctx, ldif->msg);
+ ret = ldb_add(ldb_ctx, ldif->msg);
+ if (ret != LDB_SUCCESS) {
+ fclose(f);
+ OPENCHANGE_RETVAL_ERR(MAPI_E_NO_ACCESS, mem_ctx);
+ }
+ ldb_ldif_read_free(ldb_ctx, ldif);
+ }
+ fclose(f);
+
+ filename = talloc_asprintf(mem_ctx, "%s/oc_profiles_schema.ldif", ldif_path);
+ f = fopen(filename, "r");
+ OPENCHANGE_RETVAL_IF(!f, MAPI_E_NO_ACCESS, mem_ctx);
+
+ talloc_free(filename);
+ while ((ldif = ldb_ldif_read_file(ldb_ctx, f))) {
+ ldif->msg = ldb_msg_canonicalize(ldb_ctx, ldif->msg);
+ ret = ldb_add(ldb_ctx, ldif->msg);
+ if (ret != LDB_SUCCESS) {
+ fclose(f);
+ OPENCHANGE_RETVAL_ERR(MAPI_E_NO_ACCESS, mem_ctx);
+ }
+
+ ldb_ldif_read_free(ldb_ctx, ldif);
+ }
+ fclose(f);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Load a profile from the database
+
+ This function opens a named profile from the database, and fills
+ the mapi_profile structure with common profile information.
+
+ \param profile the resulting profile
+ \param profname the name of the profile to open
+ \param password the password to use with the profile
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_ENOUGH_RESOURCES: ldb subsystem initialization failed
+ - MAPI_E_NOT_FOUND: the profile was not found in the profile
+ database
+ - MAPI_E_COLLISION: profname matched more than one entry
+
+ \sa MAPIInitialize, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS OpenProfile(struct mapi_profile *profile, const char *profname, const char *password)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ mem_ctx = (TALLOC_CTX *) global_mapi_ctx->session;
+
+ /* find the profile in ldb store */
+ retval = ldb_load_profile(mem_ctx, global_mapi_ctx->ldb_ctx, profile, profname, password);
+
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Load a MAPI Profile and sets its credentials
+
+ This function loads a named MAPI profile and sets the MAPI session
+ credentials.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: The profile parameter is not
+ initialized
+ - MAPI_E_NOT_ENOUGH_RESOURCES: MAPI subsystem failed to allocate
+ the necessary resources to perform the operation
+
+ \sa OpenProfile, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS LoadProfile(struct mapi_profile *profile)
+{
+ TALLOC_CTX *mem_ctx;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!profile, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = (TALLOC_CTX *) global_mapi_ctx->session;
+
+ profile->credentials = cli_credentials_init(mem_ctx);
+ OPENCHANGE_RETVAL_IF(!profile->credentials, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+ cli_credentials_set_username(profile->credentials, profile->username, CRED_SPECIFIED);
+ cli_credentials_set_password(profile->credentials, profile->password, CRED_SPECIFIED);
+ cli_credentials_set_workstation(profile->credentials, profile->workstation, CRED_SPECIFIED);
+ cli_credentials_set_realm(profile->credentials, profile->realm, CRED_SPECIFIED);
+ cli_credentials_set_domain(profile->credentials, profile->domain, CRED_SPECIFIED);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Release a profile
+
+ This function releases the credentials associated with the profile.
+
+ \param profile the profile to release.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: The profile parameter was not set or
+ not valid
+ */
+_PUBLIC_ enum MAPISTATUS ShutDown(struct mapi_profile *profile)
+{
+ OPENCHANGE_RETVAL_IF(!profile, MAPI_E_INVALID_PARAMETER, NULL);
+
+ if (profile->credentials)
+ talloc_free(profile->credentials);
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Create a profile in the MAPI profile database
+
+ This function creates a profile named \a profile in the MAPI profile
+ database and sets the specified username in that profile.
+
+ This function may also set the password. If the flags include
+ OC_PROFILE_NOPASSWORD then the password will not be set. Otherwise,
+ the specified password argument will also be saved to the profile.
+
+ \param profile the name of the profile
+ \param username the username of the profile
+ \param password the password for the profile (if used)
+ \param flag the union of the flags.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been
+ initialized. The MAPI subsystem must be initialized (using
+ MAPIInitialize) prior to creating a profile.
+ - MAPI_E_NOT_ENOUGH_RESOURCES: MAPI subsystem failed to allocate
+ the necessary resources to operate properly
+ - MAPI_E_NO_SUPPORT: An error was encountered while setting the
+ MAPI profile attributes in the database.
+
+ \note profile information (including the password, if saved to the
+ profile) is stored unencrypted.
+
+ \sa DeleteProfile, SetDefaultProfile, GetDefaultProfile,
+ ChangeProfilePassword, GetProfileTable, ProcessNetworkProfile,
+ GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS CreateProfile(const char *profile, const char *username,
+ const char *password, uint32_t flag)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CreateProfile");
+ retval = ldb_create_profile(mem_ctx, global_mapi_ctx->ldb_ctx, profile);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = mapi_profile_add_string_attr(profile, "username", username);
+ if (flag != OC_PROFILE_NOPASSWORD) {
+ retval = mapi_profile_add_string_attr(profile, "password", password);
+ }
+ talloc_free(mem_ctx);
+
+ return retval;
+}
+
+
+/**
+ \details Delete a profile from the MAPI profile database
+
+ \param profile the name of the profile to delete
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been
+ initialized. The MAPI subsystem must be initialized (using
+ MAPIInitialize) prior to creating a profile.
+ - MAPI_E_NOT_FOUND: The profile was not found in the database.
+
+ \sa CreateProfile, ChangeProfilePassword, GetProfileTable,
+ GetProfileAttr, ProcessNetworkProfile, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS DeleteProfile(const char *profile)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "DeleteProfile");
+ retval = ldb_delete_profile(mem_ctx, global_mapi_ctx->ldb_ctx, profile);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+ talloc_free(mem_ctx);
+
+ return retval;
+}
+
+
+/**
+ \details Change the profile password of an existing MAPI profile
+
+ \param profile the name of the profile to have its password changed
+ \param old_password the old password
+ \param password the new password
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: One of the following argument was not
+ set: profile, old_password, password
+ - MAPI_E_NOT_FOUND: The profile was not found in the database
+
+ \sa CreateProfile, GetProfileTable, GetProfileAttr,
+ ProcessNetworkProfile, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS ChangeProfilePassword(const char *profile,
+ const char *old_password,
+ const char *password)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+
+ if (!profile || !old_password | !password) return MAPI_E_INVALID_PARAMETER;
+
+ mem_ctx = talloc_named(NULL, 0, "ChangeProfilePassword");
+
+ retval = ldb_test_password(mem_ctx, profile, password);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = mapi_profile_modify_string_attr(profile, "password", password);
+
+ talloc_free(mem_ctx);
+ return retval;
+}
+
+
+/**
+ \details Rename a profile
+
+ \param old_profile old profile name
+ \param profile new profile name
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+ */
+_PUBLIC_ enum MAPISTATUS RenameProfile(const char *old_profile,
+ const char *profile)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct SRowSet proftable;
+ struct SPropValue *lpProp;
+ struct ldb_message *msg = NULL;
+ bool found = false;
+ char *dn = NULL;
+ int ret;
+ int i;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!old_profile, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!profile, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = global_mapi_ctx->mem_ctx;
+
+ retval = GetProfileTable(&proftable);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 1. Check if old profile exists */
+ for (found = false, i = 0; i < proftable.cRows; i++) {
+ lpProp = get_SPropValue_SRow(&(proftable.aRow[i]), PR_DISPLAY_NAME);
+ if (lpProp && !strcmp(lpProp->value.lpszA, old_profile)) {
+ found = true;
+ }
+ }
+ OPENCHANGE_RETVAL_IF(found == false, MAPI_E_NOT_FOUND, proftable.aRow);
+
+ /* Step 2. Check if new profile already exists */
+ for (found = false, i = 0; i < proftable.cRows; i++) {
+ lpProp = get_SPropValue_SRow(&(proftable.aRow[i]), PR_DISPLAY_NAME);
+ if (lpProp && !strcmp(lpProp->value.lpszA, profile)) {
+ found = true;
+ }
+ }
+ talloc_free(proftable.aRow);
+ OPENCHANGE_RETVAL_IF(found == true, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Step 3. Rename the profile */
+ retval = ldb_rename_profile(mem_ctx, old_profile, profile);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 4. Change name and cn */
+ msg = ldb_msg_new(mem_ctx);
+ dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Profiles", profile);
+ msg->dn = ldb_dn_new(mem_ctx, global_mapi_ctx->ldb_ctx, dn);
+ talloc_free(dn);
+
+ ret = ldb_msg_add_string(msg, "cn", profile);
+ ret = ldb_msg_add_string(msg, "name", profile);
+ for (i = 0; i < msg->num_elements; i++) {
+ msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
+ }
+
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_CORRUPT_STORE, NULL);
+ ret = ldb_modify(global_mapi_ctx->ldb_ctx, msg);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_CORRUPT_STORE, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Set a default profile for the database
+
+ \param profname the name of the profile to make the default profile
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: The profile parameter was not set
+ properly.
+ - MAPI_E_NOT_FOUND: The profile was not found in the database
+
+ \sa GetDefaultProfile, GetProfileTable, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS SetDefaultProfile(const char *profname)
+{
+ TALLOC_CTX *mem_ctx;
+ struct mapi_profile profile;
+ enum MAPISTATUS retval;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!profname, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SetDefaultProfile");
+
+ /* open profile */
+ retval = ldb_load_profile(mem_ctx, global_mapi_ctx->ldb_ctx, &profile, profname, NULL);
+ OPENCHANGE_RETVAL_IF(retval && retval != MAPI_E_INVALID_PARAMETER, retval, mem_ctx);
+
+ /* search any previous default profile and unset it */
+ retval = ldb_clear_default_profile(mem_ctx);
+
+ /* set profname as the default profile */
+ retval = mapi_profile_modify_string_attr(profname, "PR_DEFAULT_PROFILE", "1");
+
+ talloc_free(mem_ctx);
+
+ return retval;
+}
+
+
+/**
+ \details Get the default profile from the database
+
+ \param profname the result of the function (name of the default
+ profile)
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_NOT_FOUND: The profile was not found in the database
+
+ \note On success GetDefaultProfile profname string is allocated. It
+ is up to the developer to free it when not needed anymore.
+
+ \sa SetDefaultProfile, GetProfileTable, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS GetDefaultProfile(char **profname)
+{
+ enum MAPISTATUS retval;
+ struct SRowSet proftable;
+ struct SPropValue *lpProp;
+ uint32_t i;
+
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ retval = GetProfileTable(&proftable);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ for (i = 0; i < proftable.cRows; i++) {
+ lpProp = get_SPropValue_SRow(&(proftable.aRow[i]), PR_DEFAULT_PROFILE);
+ if (lpProp && (lpProp->value.l == 1)) {
+ lpProp = get_SPropValue_SRow(&(proftable.aRow[i]), PR_DISPLAY_NAME);
+ if (lpProp) {
+ *profname = talloc_strdup(global_mapi_ctx->mem_ctx, lpProp->value.lpszA);
+ talloc_free(proftable.aRow);
+ return MAPI_E_SUCCESS;
+ }
+ }
+ }
+
+ OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, proftable.aRow);
+}
+
+
+/**
+ \details Retrieve the profile table
+
+ This function retrieves the profile table. Two fields are returned:
+ - PR_DISPLAY_NAME: The profile name stored as a UTF8 string
+ - PR_DEFAULT_PROFILE: Whether the profile is the default one(1) or
+ not(0), stored as an integer
+
+ \param proftable the result of the call
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_NOT_FOUND: The profile was not found in the database
+
+ \sa SetDefaultProfile, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS GetProfileTable(struct SRowSet *proftable)
+{
+ TALLOC_CTX *mem_ctx;
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_context *ldb_ctx;
+ struct ldb_result *res;
+ struct ldb_message *msg;
+ struct ldb_dn *basedn;
+ const char *attrs[] = {"cn", "PR_DEFAULT_PROFILE", NULL};
+ int ret;
+ uint32_t count;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ ldb_ctx = global_mapi_ctx->ldb_ctx;
+ mem_ctx = talloc_autofree_context();
+
+ basedn = ldb_dn_new(ldb_ctx, ldb_ctx, "CN=Profiles");
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, basedn, scope, attrs, "(cn=*)");
+ talloc_free(basedn);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, NULL);
+
+ /* Allocate Arow */
+ proftable->cRows = res->count;
+ proftable->aRow = talloc_array(global_mapi_ctx->mem_ctx, struct SRow, res->count);
+
+ /* Build Arow array */
+ for (count = 0; count < res->count; count++) {
+ msg = res->msgs[count];
+
+ proftable->aRow[count].lpProps = talloc_array((TALLOC_CTX *)proftable->aRow, struct SPropValue, 2);
+ proftable->aRow[count].cValues = 2;
+
+ proftable->aRow[count].lpProps[0].ulPropTag = PR_DISPLAY_NAME;
+ proftable->aRow[count].lpProps[0].value.lpszA = talloc_strdup((TALLOC_CTX *)proftable->aRow,
+ ldb_msg_find_attr_as_string(msg, "cn", NULL));
+
+ proftable->aRow[count].lpProps[1].ulPropTag = PR_DEFAULT_PROFILE;
+ proftable->aRow[count].lpProps[1].value.l = ldb_msg_find_attr_as_int(msg, "PR_DEFAULT_PROFILE", 0);
+ }
+
+ talloc_free(res);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve attribute values from a profile
+
+ This function retrieves all the attribute values from the given
+ profile. The number of results is stored in \a count and values
+ are stored in an allocated string array in the \a value parameter
+ that needs to be free'd using MAPIFreeBuffer().
+
+ \param profile the name of the profile to retrieve attributes from
+ \param attribute the attribute(s) to search for
+ \param count the number of results
+ \param value the resulting values
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: Either profile or attribute was not set
+ properly
+ - MAPI_E_NOT_FOUND: The profile was not found in the database
+
+ \sa SetDefaultProfile, GetDefaultProfile, MAPIFreeBuffer,
+ GetProfileTable, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS GetProfileAttr(struct mapi_profile *profile,
+ const char *attribute,
+ unsigned int *count,
+ char ***value)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_context *ldb_ctx;
+ struct ldb_result *res;
+ struct ldb_message *msg;
+ struct ldb_message_element *ldb_element;
+ struct ldb_dn *basedn;
+ const char *attrs[] = {"*", NULL};
+ int ret;
+ uint32_t i;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!profile, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!attribute, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = (TALLOC_CTX *)global_mapi_ctx->ldb_ctx;
+ ldb_ctx = global_mapi_ctx->ldb_ctx;
+
+ basedn = ldb_dn_new(ldb_ctx, ldb_ctx, "CN=Profiles");
+
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, basedn, LDB_SCOPE_SUBTREE, attrs, "(cn=%s)", profile->profname);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, NULL);
+
+ msg = res->msgs[0];
+ ldb_element = ldb_msg_find_element(msg, attribute);
+ if (!ldb_element) {
+ DEBUG(3, ("ldb_msg_find_element: NULL\n"));
+ return MAPI_E_NOT_FOUND;
+ }
+
+ *count = ldb_element[0].num_values;
+ value[0] = talloc_array(mem_ctx, char *, *count);
+
+ if (*count == 1) {
+ value[0][0] = talloc_strdup(value[0],
+ ldb_msg_find_attr_as_string(msg, attribute, NULL));
+ } else {
+ for (i = 0; i < *count; i++) {
+ value[0][i] = talloc_strdup(mem_ctx, (char *)ldb_element->values[i].data);
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details Search the value of an attribute within a given profile
+ */
+_PUBLIC_ enum MAPISTATUS FindProfileAttr(struct mapi_profile *profile, const char *attribute, const char *value)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_context *ldb_ctx;
+ struct ldb_result *res;
+ struct ldb_message *msg;
+ struct ldb_message_element *ldb_element;
+ struct ldb_val val;
+ struct ldb_dn *basedn;
+ const char *attrs[] = {"*", NULL};
+ int ret;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!profile, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!attribute, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!value, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = (TALLOC_CTX *)global_mapi_ctx->ldb_ctx;
+ ldb_ctx = global_mapi_ctx->ldb_ctx;
+
+ basedn = ldb_dn_new(ldb_ctx, ldb_ctx, "CN=Profiles");
+
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, basedn, LDB_SCOPE_SUBTREE, attrs, "(CN=%s)", profile->profname);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, NULL);
+ OPENCHANGE_RETVAL_IF(!res->count, MAPI_E_NOT_FOUND, NULL);
+
+ msg = res->msgs[0];
+ ldb_element = ldb_msg_find_element(msg, attribute);
+ OPENCHANGE_RETVAL_IF(!ldb_element, MAPI_E_NOT_FOUND, NULL);
+
+ val.data = (uint8_t *)talloc_strdup(mem_ctx, value);
+ val.length = strlen(value);
+ OPENCHANGE_RETVAL_IF(!ldb_msg_find_val(ldb_element, &val), MAPI_E_NOT_FOUND, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ Create the profile
+ */
+
+static bool set_profile_attribute(const char *profname, struct SRowSet rowset,
+ uint32_t index, uint32_t property, const char *attr)
+{
+ struct SPropValue *lpProp;
+ enum MAPISTATUS ret;
+
+ lpProp = get_SPropValue_SRow(&(rowset.aRow[index]), property);
+
+ if (!lpProp) {
+ DEBUG(3, ("MAPI Property %s not set\n", attr));
+ return true;
+ }
+
+ ret = mapi_profile_add_string_attr(profname, attr, lpProp->value.lpszA);
+
+ if (ret != MAPI_E_SUCCESS) {
+ DEBUG(3, ("Problem adding attribute %s in profile %s\n", attr, profname));
+ return false;
+ }
+ return true;
+}
+
+static bool set_profile_mvstr_attribute(const char *profname, struct SRowSet rowset,
+ uint32_t index, uint32_t property, const char *attr)
+{
+ struct SPropValue *lpProp;
+ enum MAPISTATUS ret;
+ uint32_t i;
+
+ lpProp = get_SPropValue_SRow(&(rowset.aRow[index]), property);
+
+ if (!lpProp) {
+ DEBUG(3, ("MAPI Property %s not set\n", attr));
+ return true;
+ }
+
+ for (i = 0; i < lpProp->value.MVszA.cValues; i++) {
+ ret = mapi_profile_add_string_attr(profname, attr, lpProp->value.MVszA.lppszA[i]);
+ if (ret != MAPI_E_SUCCESS) {
+ DEBUG(3, ("Problem adding attribute %s in profile %s\n", attr, profname));
+ return false;
+ }
+ }
+ return true;
+}
+
+
+/**
+ \details Process a full and automated MAPI profile creation
+
+ This function process a full and automated MAPI profile creation
+ using the \a username pattern passed as a parameter. The functions
+ takes a callback parameter which will be called when the username
+ checked matches several usernames. Private data needed by the
+ callback can be supplied using the private_data pointer.
+
+ \code
+ typedef int (*mapi_callback_t) callback(struct SRowSet *, void *private_data);
+ \endcode
+
+ The callback returns the SRow element index within the SRowSet
+ structure. If the user cancels the operation the callback return
+ value should be SRowSet->cRows or more.
+
+ \param session the session context
+ \param username the username for the network profile
+ \param callback function pointer callback function
+ \param private_data context data that will be provided to the callback
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been
+ initialized. The MAPI subsystem must be initialized (using
+ MAPIInitialize) prior to creating a profile.
+ - MAPI_E_END_OF_SESSION: The NSPI session has not been initialized
+ - MAPI_E_CANCEL_USER: The user has aborted the operation
+ - MAPI_E_INVALID_PARAMETER: The profile parameter was not set
+ properly.
+ - MAPI_E_NOT_FOUND: One of the mandatory field was not found during
+ the profile creation process.
+
+ \sa OpenProfileStore, MAPILogonProvider, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS ProcessNetworkProfile(struct mapi_session *session, const char *username,
+ mapi_profile_callback_t callback, const void *private_data)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct Restriction_r Filter;
+ struct SRowSet *SRowSet;
+ struct SPropValue *lpProp = NULL;
+ struct SPropTagArray *MIds = NULL;
+ struct SPropTagArray MIds2;
+ struct SPropTagArray *MId_server = NULL;
+ struct StringsArray_r pNames;
+ const char *profname;
+ uint32_t instance_key = 0;
+ uint32_t index = 0;
+
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session->nspi->ctx, MAPI_E_END_OF_SESSION, NULL);
+
+ nspi = (struct nspi_context *) session->nspi->ctx;
+ profname = session->profile->profname;
+ index = 0;
+
+ SRowSet = talloc_zero(nspi->mem_ctx, struct SRowSet);
+ retval = nspi_GetSpecialTable(nspi, 0x0, &SRowSet);
+ MAPIFreeBuffer(SRowSet);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ SPropTagArray = set_SPropTagArray(nspi->mem_ctx, 0xc,
+ PR_DISPLAY_NAME,
+ PR_OFFICE_TELEPHONE_NUMBER,
+ PR_OFFICE_LOCATION,
+ PR_TITLE,
+ PR_COMPANY_NAME,
+ PR_ACCOUNT,
+ PR_ADDRTYPE,
+ PR_ENTRYID,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_INSTANCE_KEY,
+ PR_EMAIL_ADDRESS
+ );
+
+ /* Retrieve the username to match */
+ if (!username) {
+ username = cli_credentials_get_username(nspi->cred);
+ OPENCHANGE_RETVAL_IF(!username, MAPI_E_INVALID_PARAMETER, NULL);
+ }
+
+ /* Build the restriction we want for NspiGetMatches */
+ lpProp = talloc_zero(nspi->mem_ctx, struct SPropValue);
+ lpProp->ulPropTag = PR_ANR_UNICODE;
+ lpProp->dwAlignPad = 0;
+ lpProp->value.lpszW = username;
+
+ Filter.rt = RES_PROPERTY;
+ Filter.res.resProperty.relop = RES_PROPERTY;
+ Filter.res.resProperty.ulPropTag = PR_ANR_UNICODE;
+ Filter.res.resProperty.lpProp = lpProp;
+
+ SRowSet = talloc_zero(nspi->mem_ctx, struct SRowSet);
+ MIds = talloc_zero(nspi->mem_ctx, struct SPropTagArray);
+ retval = nspi_GetMatches(nspi, SPropTagArray, &Filter, &SRowSet, &MIds);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPIFreeBuffer(lpProp);
+ if (retval != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ MAPIFreeBuffer(SRowSet);
+ return retval;
+ }
+
+ /* if there's no match */
+ OPENCHANGE_RETVAL_IF(!SRowSet, MAPI_E_NOT_FOUND, NULL);
+ OPENCHANGE_RETVAL_IF(!SRowSet->cRows, MAPI_E_NOT_FOUND, NULL);
+ OPENCHANGE_RETVAL_IF(!MIds, MAPI_E_NOT_FOUND, NULL);
+
+ /* if SRowSet count is superior than 1 an callback is specified, call it */
+ if (SRowSet->cRows > 1 && callback) {
+ index = callback(SRowSet, private_data);
+ OPENCHANGE_RETVAL_IF((index >= SRowSet->cRows), MAPI_E_USER_CANCEL, NULL);
+ instance_key = MIds->aulPropTag[index];
+ } else {
+ instance_key = MIds->aulPropTag[0];
+ }
+ MAPIFreeBuffer(MIds);
+
+ MIds2.cValues = 0x1;
+ MIds2.aulPropTag = &instance_key;
+
+ set_profile_attribute(profname, *SRowSet, index, PR_EMAIL_ADDRESS, "EmailAddress");
+ set_profile_attribute(profname, *SRowSet, index, PR_DISPLAY_NAME, "DisplayName");
+ set_profile_attribute(profname, *SRowSet, index, PR_ACCOUNT, "Account");
+ set_profile_attribute(profname, *SRowSet, index, PR_ADDRTYPE, "AddrType");
+
+ SPropTagArray = set_SPropTagArray(nspi->mem_ctx, 0x7,
+ PR_DISPLAY_NAME,
+ PR_EMAIL_ADDRESS,
+ PR_DISPLAY_TYPE,
+ PR_EMS_AB_HOME_MDB,
+ PR_ATTACH_NUM,
+ PR_PROFILE_HOME_SERVER_ADDRS,
+ PR_EMS_AB_PROXY_ADDRESSES
+ );
+
+ nspi->pStat->CurrentRec = 0x0;
+ nspi->pStat->Delta = 0x0;
+ nspi->pStat->NumPos = 0x0;
+ nspi->pStat->TotalRecs = 0x1;
+
+ MAPIFreeBuffer(SRowSet);
+ SRowSet = talloc(nspi->mem_ctx, struct SRowSet);
+ retval = nspi_QueryRows(nspi, SPropTagArray, &MIds2, 1, &SRowSet);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ lpProp = get_SPropValue_SRowSet(SRowSet, PR_EMS_AB_HOME_MDB);
+ OPENCHANGE_RETVAL_IF(!lpProp, MAPI_E_NOT_FOUND, NULL);
+
+ nspi->org = x500_get_dn_element(nspi->mem_ctx, lpProp->value.lpszA, ORG);
+ nspi->org_unit = x500_get_dn_element(nspi->mem_ctx, lpProp->value.lpszA, ORG_UNIT);
+
+ OPENCHANGE_RETVAL_IF(!nspi->org_unit, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!nspi->org, MAPI_E_INVALID_PARAMETER, NULL);
+
+ retval = mapi_profile_add_string_attr(profname, "Organization", nspi->org);
+ retval = mapi_profile_add_string_attr(profname, "OrganizationUnit", nspi->org_unit);
+
+ nspi->servername = x500_get_servername(lpProp->value.lpszA);
+ mapi_profile_add_string_attr(profname, "ServerName", nspi->servername);
+ set_profile_attribute(profname, *SRowSet, 0, PR_EMS_AB_HOME_MDB, "HomeMDB");
+ set_profile_mvstr_attribute(profname, *SRowSet, 0, PR_EMS_AB_PROXY_ADDRESSES, "ProxyAddress");
+ MAPIFreeBuffer(SRowSet);
+
+ pNames.Count = 0x1;
+ pNames.Strings = (const char **) talloc_array(nspi->mem_ctx, char **, 1);
+ pNames.Strings[0] = (const char *) talloc_asprintf(nspi->mem_ctx, SERVER_DN,
+ nspi->org, nspi->org_unit,
+ nspi->servername);
+ MId_server = talloc_zero(nspi->mem_ctx, struct SPropTagArray);
+ retval = nspi_DNToMId(nspi, &pNames, &MId_server);
+ MAPIFreeBuffer((char *)pNames.Strings[0]);
+ MAPIFreeBuffer((char **)pNames.Strings);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ SRowSet = talloc_zero(nspi->mem_ctx, struct SRowSet);
+ SPropTagArray = set_SPropTagArray(nspi->mem_ctx, 0x1, PR_EMS_AB_NETWORK_ADDRESS);
+ retval = nspi_GetProps(nspi, SPropTagArray, MId_server, &SRowSet);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPIFreeBuffer(MId_server);
+ if (retval != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(SRowSet);
+ return retval;
+ }
+
+ set_profile_mvstr_attribute(profname, *SRowSet, 0, PR_EMS_AB_NETWORK_ADDRESS, "NetworkAddress");
+ MAPIFreeBuffer(SRowSet);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IStoreFolder.c
===================================================================
--- trunk/openchange/libmapi/IStoreFolder.c (rev 0)
+++ trunk/openchange/libmapi/IStoreFolder.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,162 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+
+/**
+ \file IStoreFolder.c
+
+ \brief Open messages
+*/
+
+
+/**
+ \details Opens a specific message and retrieves a MAPI object that
+ can be used to get or set message properties.
+
+ This function opens a specific message defined by a combination of
+ object store, folder ID, and message ID and which read/write access
+ is defined by ulFlags.
+
+ \param obj_store the store to read from
+ \param id_folder the folder ID
+ \param id_message the message ID
+ \param obj_message the resulting message object
+ \param ulFlags
+
+ Possible ulFlags values:
+ - 0x0: read only access
+ - 0x1: ReadWrite
+ - 0x3: Create
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_store is undefined
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MAPIInitialize, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS OpenMessage(mapi_object_t *obj_store,
+ mapi_id_t id_folder,
+ mapi_id_t id_message,
+ mapi_object_t *obj_message,
+ uint8_t ulFlags)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct OpenMessage_req request;
+ struct OpenMessage_repl *reply;
+ struct mapi_session *session;
+ mapi_object_message_t *message;
+ struct SPropValue lpProp;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+ uint32_t i = 0;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "OpenMessage");
+
+ /* Fill the OpenMessage operation */
+ request.handle_idx = 0x1;
+ request.CodePageId = 0xfff;
+ request.FolderId = id_folder;
+ request.OpenModeFlags = ulFlags;
+ request.MessageId = id_message;
+ size = sizeof (uint8_t) + sizeof(uint16_t) + sizeof(mapi_id_t) + sizeof(uint8_t) + sizeof(mapi_id_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_OpenMessage;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_OpenMessage = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_store);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Set object session and handle */
+ mapi_object_set_session(obj_message, session);
+ mapi_object_set_handle(obj_message, mapi_response->handles[1]);
+
+ /* Store OpenMessage reply data */
+ reply = &mapi_response->mapi_repl->u.mapi_OpenMessage;
+
+ message = talloc_zero((TALLOC_CTX *)session, mapi_object_message_t);
+ message->cValues = reply->RecipientColumns.cValues;
+ message->SRowSet.cRows = reply->RowCount;
+ message->SRowSet.aRow = talloc_array((TALLOC_CTX *)message, struct SRow, reply->RowCount + 1);
+
+ message->SPropTagArray.cValues = reply->RecipientColumns.cValues;
+ message->SPropTagArray.aulPropTag = reply->RecipientColumns.aulPropTag;
+
+ for (i = 0; i < reply->RowCount; i++) {
+ emsmdb_get_SRow((TALLOC_CTX *)message, global_mapi_ctx->lp_ctx,
+ &(message->SRowSet.aRow[i]), &message->SPropTagArray,
+ reply->recipients[i].RecipientRow.prop_count,
+ &reply->recipients[i].RecipientRow.prop_values,
+ reply->recipients[i].RecipientRow.layout, 1);
+
+ lpProp.ulPropTag = PR_RECIPIENT_TYPE;
+ lpProp.value.l = reply->recipients[i].RecipClass;
+ SRow_addprop(&(message->SRowSet.aRow[i]), lpProp);
+
+ lpProp.ulPropTag = PR_INTERNET_CPID;
+ lpProp.value.l = reply->recipients[i].codepage;
+ SRow_addprop(&(message->SRowSet.aRow[i]), lpProp);
+ }
+
+ /* add SPropTagArray elements we automatically append to SRow */
+ SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_RECIPIENT_TYPE);
+ SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_INTERNET_CPID);
+
+ obj_message->private_data = (void *) message;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IStream.c
===================================================================
--- trunk/openchange/libmapi/IStream.c (rev 0)
+++ trunk/openchange/libmapi/IStream.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,704 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+
+/**
+ \file IStream.c
+
+ \brief Functions for operating on Streams on MAPI objects
+ */
+
+
+/**
+ \details Open a stream
+
+ This function opens a stream on the property \a prop set in \a
+ obj_related with access flags set to \a access_flags and returns an
+ object \a obj_stream.
+
+ \param obj_related the object to open.
+ \param PropertyTag the property name for the object to create a stream
+ for.
+ \param OpenModeFlags sets the access mode for the stream and is one
+ of the following values:
+ * 0x0: ReadOnly
+ * 0x1: ReadWrite
+ * 0x2: Create
+ * 0x3: BestAccess
+ \param obj_stream the resulting stream object.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error. Possible MAPI
+ error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: A problem occured obtaining the session context
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code.
+
+ \sa ReadStream, WriteStream, GetLastError
+ */
+
+_PUBLIC_ enum MAPISTATUS OpenStream(mapi_object_t *obj_related, uint32_t PropertyTag,
+ uint8_t OpenModeFlags, mapi_object_t *obj_stream)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct OpenStream_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ session = mapi_object_get_session(obj_related);
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "OpenStream");
+
+ size = 0;
+
+ /* Fill the OpenStream operation */
+ request.handle_idx = 0x1;
+ request.PropertyTag = PropertyTag;
+
+ /* STGM_XXX (obj_base.h windows header) */
+ request.OpenModeFlags = OpenModeFlags;
+ size += sizeof(uint8_t) + sizeof(uint32_t) + sizeof(uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_OpenStream;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_OpenStream = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_related);
+ mapi_request->handles[1] = 0xffffffff;
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Set object session and handle */
+ mapi_object_set_session(obj_stream, session);
+ mapi_object_set_handle(obj_stream, mapi_response->handles[1]);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Read buffer from a stream
+
+ This function reads from an open data stream. It will read up to
+ ByteCount bytes from the stream, and return the data in data_buf.
+ ByteRead is set to the number of bytes actually read.
+
+ \param obj_stream the opened stream object
+ \param buf_data the buffer where data read from the stream will be
+ stored
+ \param ByteCount the number of bytes requested to be read from the
+ stream
+ \param ByteRead the number of bytes read from the stream
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error. Possible MAPI
+ error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: A problem occured obtaining the session context
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code.
+
+ \note The data size intended to be read from the stream shouldn't
+ extend a maximum size each time you call ReadStream. This size
+ depends on Exchange server version. However 0x1000 is known to be a
+ reliable read size value.
+
+ \sa OpenStream, WriteStream, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS ReadStream(mapi_object_t *obj_stream, unsigned char *buf_data,
+ uint16_t ByteCount, uint16_t *ByteRead)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct ReadStream_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ session = mapi_object_get_session(obj_stream);
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "ReadStream");
+
+ *ByteRead = 0;
+ size = 0;
+
+ /* Fill the ReadStream operation */
+ request.ByteCount = ByteCount;
+ size += sizeof(uint16_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_ReadStream;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_ReadStream = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 1;
+ 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_stream);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* copy no more than sz_data into buffer */
+ *ByteRead = mapi_response->mapi_repl->u.mapi_ReadStream.data.length;
+ if (*ByteRead > 0) {
+ if (*ByteRead > ByteCount) {
+ *ByteRead = ByteCount;
+ }
+ memcpy(buf_data, mapi_response->mapi_repl->u.mapi_ReadStream.data.data, *ByteRead);
+ }
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Write buffer to the stream
+
+ This function writes the stream specified as a DATA_BLOB in data to
+ the stream obj_stream.
+
+ \param obj_stream the opened stream object
+ \param blob the DATA_BLOB to write to the stream
+ \param WrittenSize the actual number of bytes written to the
+ stream
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: A problem occured obtaining the session
+ context, or blob was null.
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+ - MAPI_E_TOO_BIG: the data blob was too large to process
+
+ \note The data size intended to be written to the stream should not
+ exceed a maximum size each time you call WriteStream. This size
+ depends on Exchange server version. However 0x1000 is known to be a
+ reliable write size value.
+
+ \sa OpenStream, ReadStream, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS WriteStream(mapi_object_t *obj_stream, DATA_BLOB *blob, uint16_t *WrittenSize)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct WriteStream_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ uint32_t size;
+
+ /* Sanity Checks */
+ session = mapi_object_get_session(obj_stream);
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!blob, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(blob->length > 0x7000, MAPI_E_TOO_BIG, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "WriteStream");
+
+ size = 0;
+
+ /* Fill the WriteStream operation */
+ request.data = *blob;
+ size += blob->length;
+ /* size for subcontext(2) */
+ size += 2;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_WriteStream;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_WriteStream = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_stream);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ *WrittenSize = mapi_response->mapi_repl->u.mapi_WriteStream.WrittenSize;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ errno = 0;
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Commits stream operations
+
+ \param obj_stream the stream object to commit
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: Either the network stream or session
+ context are not valid.
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenStream, ReadStream, WriteStream
+ */
+_PUBLIC_ enum MAPISTATUS CommitStream(mapi_object_t *obj_stream)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ session = mapi_object_get_session(obj_stream);
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_stream, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CommitStream");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_CommitStream;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_stream);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Gets the size of a stream
+
+ \param obj_stream the stream object we retrieve size from
+ \param StreamSize pointer on the stream size
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_stream is not initialized, or there
+ was a problem obtaining the session context
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenStream, ReadStream
+ */
+_PUBLIC_ enum MAPISTATUS GetStreamSize(mapi_object_t *obj_stream, uint32_t *StreamSize)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_stream, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_stream);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetStreamSize");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_GetStreamSize;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_stream);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ *StreamSize = mapi_response->mapi_repl->u.mapi_GetStreamSize.StreamSize;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Seek a specific position within the stream
+
+ \param obj_stream the stream object
+ \param Origin origin location for the seek operation
+ \param Offset the seek offset
+ \param NewPosition pointer on the new position after the operation
+
+ Origin can either take one of the following values:
+
+ * 0x0 The new seek pointer is an offset relative to the beginning
+ of the stream.
+ * 0x1 The new seek pointer is an offset relative to the current
+ seek pointer location.
+ * 0x2 The new seek pointer is an offset relative to the end of the
+ stream.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_BOOKMARK: the bookmark specified is invalid or
+ beyond the last row requested.
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenStream, ReadStream
+ */
+_PUBLIC_ enum MAPISTATUS SeekStream(mapi_object_t *obj_stream, uint8_t Origin, uint64_t Offset,
+ uint64_t *NewPosition)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SeekStream_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ uint32_t size;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_stream, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_stream);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF((Origin > 2), MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!NewPosition, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SeekStream");
+ size = 0;
+
+ /* Fill the SeekStream operation */
+ request.Origin = Origin;
+ size += sizeof (uint8_t);
+
+ request.Offset = Offset;
+ size += sizeof (uint64_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SeekStream;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SeekStream = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_stream);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ *NewPosition = mapi_response->mapi_repl->u.mapi_SeekStream.NewPosition;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Set the stream size
+
+ \param obj_stream the stream object
+ \param SizeStream the size of the stream
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_BOOKMARK: the bookmark specified is invalid or
+ beyond the last row requested.
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenStream, GetStreamSize
+ */
+_PUBLIC_ enum MAPISTATUS SetStreamSize(mapi_object_t *obj_stream, uint64_t SizeStream)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SetStreamSize_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ uint32_t size;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_stream, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj_stream);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SetStreamSize");
+ size = 0;
+
+ /* Fill the SetStreamSize operation */
+ request.SizeStream = SizeStream;
+ size += sizeof (uint64_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SetStreamSize;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SetStreamSize = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_stream);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Copy a number of bytes from a source stream to another
+ stream
+
+ \param obj_src the source stream object
+ \param obj_dst the destination stream object
+ \param ByteCount the number of bytes to copy
+ \param ReadByteCount pointer on the number of bytes read from the
+ source object
+ \param WrittenByteCount pointer on the number of bytes written to
+ the destination object
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_BOOKMARK: the bookmark specified is invalid or
+ beyond the last row requested.
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa OpenStream
+*/
+_PUBLIC_ enum MAPISTATUS CopyToStream(mapi_object_t *obj_src, mapi_object_t *obj_dst,
+ uint64_t ByteCount, uint64_t *ReadByteCount,
+ uint64_t *WrittenByteCount)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct CopyToStream_req request;
+ struct mapi_session *session[2];
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ uint32_t size;
+
+ /* Sanity Check */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_src, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_dst, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session[0] = mapi_object_get_session(obj_src);
+ session[1] = mapi_object_get_session(obj_dst);
+
+ OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
+
+ OPENCHANGE_RETVAL_IF(!ByteCount, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ReadByteCount, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!WrittenByteCount, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "CopyToStream");
+ size = 0;
+
+ /* Fill the CopyToStream operation */
+ request.handle_idx = 0x1;
+ size += sizeof (uint8_t);
+
+ request.ByteCount = ByteCount;
+ size += sizeof (uint64_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_CopyToStream;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_CopyToStream = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
+ mapi_request->length = size;
+ mapi_request->mapi_req = mapi_req;
+ mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_src);
+ mapi_request->handles[1] = mapi_object_get_handle(obj_dst);
+
+ status = emsmdb_transaction(session[0]->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ *ReadByteCount = mapi_response->mapi_repl->u.mapi_CopyToStream.ReadByteCount;
+ *WrittenByteCount = mapi_response->mapi_repl->u.mapi_CopyToStream.WrittenByteCount;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IUnknown.c
===================================================================
--- trunk/openchange/libmapi/IUnknown.c (rev 0)
+++ trunk/openchange/libmapi/IUnknown.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,328 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+
+/**
+ \file IUnknown.c
+
+ \brief Various miscellaneous (ungrouped) functions
+ */
+
+
+/**
+ \details Allocate memory using the MAPI memory context
+
+ \param size the number of bytes to allocate
+ \param ptr pointer to the allocated byte region
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_SESSION_LIMIT: No session has been opened on the provider
+ - MAPI_E_NOT_ENOUGH_RESOURCES: MAPI subsystem failed to allocate
+ the necessary resources to operate properly
+ - MAPI_E_INVALID_PARAMER: size is not set properly.
+
+ \sa MAPIFreeBuffer, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS MAPIAllocateBuffer(uint32_t size, void **ptr)
+{
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = (TALLOC_CTX *) global_mapi_ctx->mem_ctx;
+
+ *ptr = talloc_size(mem_ctx, size);
+ OPENCHANGE_RETVAL_IF(!ptr, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Free allocated memory
+
+ This function frees memory previously allocated with
+ MAPIAllocateBuffer.
+
+ \param ptr memory region to free
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMER: ptr is not set properly.
+
+ \sa MAPIAllocateBuffer, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS MAPIFreeBuffer(void *ptr)
+{
+ int ret;
+
+ OPENCHANGE_RETVAL_IF(!ptr, MAPI_E_INVALID_PARAMETER, NULL);
+
+ ret = talloc_free(ptr);
+ OPENCHANGE_RETVAL_IF(ret == -1, MAPI_E_INVALID_PARAMETER, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Release an object on the server
+
+ The function releases the object \a obj on the server.
+
+ \param obj the object to release
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS Release(mapi_object_t *obj)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct mapi_session *session;
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx;
+ uint32_t size = 0;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "Release");
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_Release;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ mapi_request->length = (uint16_t)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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ errno = 0;
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns the latest error code.
+
+ This function returns the error code set by a previous function
+ call.
+
+ \note Calls to the function won't work in multi-threaded or
+ multisession code.
+*/
+_PUBLIC_ enum MAPISTATUS GetLastError(void)
+{
+ return errno;
+}
+
+
+/**
+ \details Convert an ID to a Long Term Id
+
+ The function looks up the Long Term Id for a specified ID value.
+
+ \param obj the object to look up on
+ \param id the id to look up
+ \param long_term_id the long term ID returned from the server
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj is null
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetIdFromLongTermId
+*/
+_PUBLIC_ enum MAPISTATUS GetLongTermIdFromId(mapi_object_t *obj, mapi_id_t id,
+ struct LongTermId *long_term_id)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct LongTermIdFromId_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx;
+ uint32_t size = 0;
+ enum MAPISTATUS retval;
+ int i;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "LongTermIdFromId");
+
+ /* Fill the LongTermIdFromId operation */
+ request.Id = id;
+ size += sizeof(mapi_id_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_LongTermIdFromId;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_LongTermIdFromId = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ mapi_request->length = (uint16_t)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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ long_term_id->DatabaseGuid = mapi_response->mapi_repl->u.mapi_LongTermIdFromId.LongTermId.DatabaseGuid;
+ for (i = 0; i < 6; ++i) {
+ long_term_id->GlobalCounter[i] = mapi_response->mapi_repl->u.mapi_LongTermIdFromId.LongTermId.GlobalCounter[i];
+ }
+ long_term_id->padding = 0x0;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ errno = 0;
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Convert an Long Term Id into an Id
+
+ The function looks up the Id for a specified Long Term Id value.
+
+ \param obj the object to look up on
+ \param long_term_id the id to look up
+ \param id the id returned by the server
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj is null
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetLongTermIdFromId
+*/
+_PUBLIC_ enum MAPISTATUS GetIdFromLongTermId(mapi_object_t *obj, struct LongTermId long_term_id,
+ mapi_id_t *id)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct IdFromLongTermId_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx;
+ uint32_t size = 0;
+ enum MAPISTATUS retval;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+ session = mapi_object_get_session(obj);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "IdFromLongTermId");
+ size = 0;
+
+ /* Fill the IdFromLongTermId operation */
+ request.LongTermId = long_term_id;
+ size += sizeof(struct LongTermId);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_IdFromLongTermId;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_IdFromLongTermId = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ mapi_request->length = (uint16_t)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);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ *id = mapi_response->mapi_repl->u.mapi_IdFromLongTermId.Id;
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ errno = 0;
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/IXPLogon.c
===================================================================
--- trunk/openchange/libmapi/IXPLogon.c (rev 0)
+++ trunk/openchange/libmapi/IXPLogon.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,256 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+
+/**
+ \file IXPLogon.c
+
+ \brief Transport provider status information
+*/
+
+
+/**
+ \details Returns the types of recipients that the transport
+ provider handles.
+
+ \param obj_store the object to get recipients types from
+ \param lpcAdrType the count of recipients types returned
+ \param lpAdrTypeArray pointer on pointer of returned transport
+ provider types
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_store is not initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ */
+_PUBLIC_ enum MAPISTATUS AddressTypes(mapi_object_t *obj_store,
+ uint16_t *lpcAdrType,
+ struct mapi_LPSTR **lpAdrTypeArray)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct AddressTypes_repl *response;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "AddressTypes");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_AddressTypes;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_store);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Retrieve Address Types */
+ response = &mapi_response->mapi_repl->u.mapi_AddressTypes;
+ *lpcAdrType = response->cValues;
+ *lpAdrTypeArray = talloc_steal((TALLOC_CTX *)session, response->transport);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Informs the server that the client intends to act as a
+ mail spooler.
+
+ \param obj_store: the object server store object
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_store is not initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SpoolerLockMessage
+ */
+_PUBLIC_ enum MAPISTATUS SetSpooler(mapi_object_t *obj_store)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SetSpooler");
+ size = 0;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SetSpooler;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_store);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Locks the specified message for spooling.
+
+ \param obj_store the store object
+ \param obj_message the message object we want to lock
+ \param LockState the lock state
+
+ Possible values for the lock state:
+ -# LockState_1stLock (0x0): Mark the message as locked
+ -# LockState_1stUnlock (0x1): Mark the message as unlocked
+ -# LockState_1stFinished (0x2): Mark the message as ready for
+ processing by the server
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_store is not initialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa SetSPooler
+ */
+_PUBLIC_ enum MAPISTATUS SpoolerLockMessage(mapi_object_t *obj_store,
+ mapi_object_t *obj_message,
+ uint8_t LockState)
+{
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct SpoolerLockMessage_req request;
+ struct mapi_session *session;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t size = 0;
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(LockState > 2, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "SpoolerLockMessage");
+ size = 0;
+
+ /* Fill the SpoolerLockMessage operation */
+ request.MessageId = mapi_object_get_id(obj_message);
+ size += sizeof (uint64_t);
+
+ request.LockState = LockState;
+ size += sizeof (uint8_t);
+
+ /* Fill the MAPI_REQ request */
+ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ mapi_req->opnum = op_MAPI_SpoolerLockMessage;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_SpoolerLockMessage = request;
+ size += 5;
+
+ /* Fill the mapi_request structure */
+ mapi_request = talloc_zero(mem_ctx, struct mapi_request);
+ mapi_request->mapi_len = size + sizeof (uint32_t);
+ 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_store);
+
+ status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
+ retval = mapi_response->mapi_repl->error_code;
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mapi_response);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/cdo_mapi.c
===================================================================
--- trunk/openchange/libmapi/cdo_mapi.c (rev 0)
+++ trunk/openchange/libmapi/cdo_mapi.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,353 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2009.
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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/proto_private.h>
+#include <libmapi/dlinklist.h>
+#include <param.h>
+#include <ldb_errors.h>
+#include <ldb.h>
+
+struct mapi_ctx *global_mapi_ctx = NULL;
+
+
+/**
+ \file cdo_mapi.c
+
+ \brief MAPI subsystem related operations
+*/
+
+
+/**
+ \details Create a full MAPI session
+
+ Open providers stored in the profile and return a pointer on a
+ IMAPISession object.
+
+ \param session pointer to a pointer to a MAPI session object
+ \param profname profile name to use
+ \param password password to use for the profile
+
+ password should be set to NULL if the password has been stored in
+ the profile.
+
+ \return MAPI_E_SUCCESS on success otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_NOT_ENOUGH_RESOURCES: MAPI subsystem failed to allocate
+ the necessary resources to operate properly
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MAPIInitialize, OpenProfile, MapiLogonProvider
+*/
+_PUBLIC_ enum MAPISTATUS MapiLogonEx(struct mapi_session **session,
+ const char *profname, const char *password)
+{
+ struct mapi_session *tmp_session = NULL;
+ enum MAPISTATUS retval;
+
+ retval = MapiLogonProvider(&tmp_session, profname, password, PROVIDER_ID_NSPI);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ retval = MapiLogonProvider(&tmp_session, profname, password, PROVIDER_ID_EMSMDB);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ *session = tmp_session;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Initialize a session on the specified provider
+
+ \param session pointer to a pointer to a MAPI session object
+ \param profname profile name
+ \param password profile password
+ \param provider provider we want to establish a connection on
+
+ password should be set to NULL if the password has been stored in
+ the profile.
+
+ Supported providers are:
+ - PROVIDER_ID_NSPI: Address Book provider
+ - PROVIDER_ID_EMSMDB: MAPI Store provider
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_NOT_ENOUGH_RESOURCES: MAPI subsystem failed to allocate
+ the necessary resources to operate properly
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MapiLogonEx, OpenProfile, LoadProfile
+*/
+_PUBLIC_ enum MAPISTATUS MapiLogonProvider(struct mapi_session **session,
+ const char *profname,
+ const char *password,
+ enum PROVIDER_ID provider)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct mapi_provider *provider_emsmdb;
+ struct mapi_provider *provider_nspi;
+ struct mapi_profile *profile;
+ struct mapi_session *el;
+ bool found = false;
+ bool exist = false;
+
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, NULL);
+
+ /* If no MAPI session has already been created */
+ if (!global_mapi_ctx->session) {
+ global_mapi_ctx->session = talloc_zero(global_mapi_ctx->mem_ctx, struct mapi_session);
+ }
+
+ /* If the session doesn't exist, create a new one */
+ if (!*session) {
+ el = talloc_zero((TALLOC_CTX *)global_mapi_ctx->session, struct mapi_session);
+ OPENCHANGE_RETVAL_IF(!el, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+ } else {
+ /* Lookup the session within the chained list */
+ for (el = global_mapi_ctx->session; el; el = el->next) {
+ if (*session == el) {
+ found = true;
+ break;
+ }
+ }
+ OPENCHANGE_RETVAL_IF(found == false, MAPI_E_NOT_FOUND, NULL);
+ exist = true;
+ }
+
+ mem_ctx = (TALLOC_CTX *) el;
+
+ /* Open the profile */
+ if (!el->profile) {
+ profile = talloc_zero(mem_ctx, struct mapi_profile);
+ OPENCHANGE_RETVAL_IF(!profile, MAPI_E_NOT_ENOUGH_RESOURCES, el);
+
+ retval = OpenProfile(profile, profname, password);
+ OPENCHANGE_RETVAL_IF(retval, retval, el);
+
+ retval = LoadProfile(profile);
+ OPENCHANGE_RETVAL_IF(retval, retval, el);
+
+ el->profile = profile;
+ }
+
+ switch (provider) {
+ case PROVIDER_ID_EMSMDB:
+ provider_emsmdb = talloc_zero(mem_ctx, struct mapi_provider);
+ OPENCHANGE_RETVAL_IF(!provider_emsmdb, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+ talloc_set_destructor((void *)provider_emsmdb, (int (*)(void *))emsmdb_disconnect_dtor);
+ retval = Logon(el, provider_emsmdb, PROVIDER_ID_EMSMDB);
+ if (retval) return retval;
+ el->emsmdb = provider_emsmdb;
+ break;
+ case PROVIDER_ID_NSPI:
+ provider_nspi = talloc_zero(mem_ctx, struct mapi_provider);
+ OPENCHANGE_RETVAL_IF(!provider_nspi, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+ talloc_set_destructor((void *)provider_nspi, (int (*)(void *))nspi_disconnect_dtor);
+ retval = Logon(el, provider_nspi, PROVIDER_ID_NSPI);
+ if (retval) return retval;
+ el->nspi = provider_nspi;
+ break;
+ default:
+ OPENCHANGE_RETVAL_IF(1, MAPI_E_NO_SUPPORT, el);
+ break;
+ }
+
+ /* Add the element to the session list */
+ if (exist == false) {
+ DLIST_ADD(global_mapi_ctx->session, el);
+ *session = el;
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Initialize mapi context global structure
+
+ This function inititalizes the MAPI subsystem and open the profile
+ database pointed by profiledb .
+
+ \param profiledb profile database path
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_NOT_ENOUGH_RESOURCES: MAPI subsystem failed to allocate
+ the necessary resources to operate properly
+ - MAPI_E_NOT_FOUND: No suitable profile database was found in the
+ path pointed by profiledb
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa MAPIUninitialize
+*/
+_PUBLIC_ enum MAPISTATUS MAPIInitialize(const char *profiledb)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+
+ /* Set the initial errno value for GetLastError */
+ errno = 0;
+
+ OPENCHANGE_RETVAL_IF(global_mapi_ctx, MAPI_E_SESSION_LIMIT, NULL);
+ OPENCHANGE_RETVAL_IF(!profiledb, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "MAPIInitialize");
+ OPENCHANGE_RETVAL_IF(!mem_ctx, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+
+ /* global context */
+ global_mapi_ctx = talloc_zero(mem_ctx, struct mapi_ctx);
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+ global_mapi_ctx->mem_ctx = mem_ctx;
+ global_mapi_ctx->dumpdata = false;
+ global_mapi_ctx->session = NULL;
+ global_mapi_ctx->lp_ctx = loadparm_init(global_mapi_ctx->mem_ctx);
+ lp_load_default(global_mapi_ctx->lp_ctx);
+
+ /* Enable logging on stdout */
+ setup_logging(NULL, DEBUG_STDOUT);
+
+ /* profile store */
+ retval = OpenProfileStore(mem_ctx, &global_mapi_ctx->ldb_ctx, profiledb);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Initialize dcerpc subsystem */
+ dcerpc_init(global_mapi_ctx->lp_ctx);
+
+ errno = 0;
+ return MAPI_E_SUCCESS;
+}
+
+
+
+/**
+ \details Uninitialize MAPI subsystem
+
+ This function uninitializes the MAPI context and destroy
+ recursively the whole mapi session and associated objects hierarchy
+
+ \sa MAPIInitialize, GetLastError
+ */
+_PUBLIC_ void MAPIUninitialize(void)
+{
+ TALLOC_CTX *mem_ctx;
+ struct mapi_session *session;
+
+ if (!global_mapi_ctx) return;
+
+ session = global_mapi_ctx->session;
+ if (session && session->notify_ctx && session->notify_ctx->fd != -1) {
+ DEBUG(3, ("emsmdb_disconnect_dtor: unbind udp\n"));
+ shutdown(session->notify_ctx->fd, SHUT_RDWR);
+ close(session->notify_ctx->fd);
+ }
+
+ mem_ctx = global_mapi_ctx->mem_ctx;
+ talloc_free(mem_ctx);
+ global_mapi_ctx = NULL;
+}
+
+
+/**
+ \details Enable MAPI network trace output
+
+ \param status the status
+
+ possible status values/behavior:
+ -# true: Network traces are displayed on stdout
+ -# false: Network traces are not displayed on stdout
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_INITIALIZED
+ */
+_PUBLIC_ enum MAPISTATUS SetMAPIDumpData(bool status)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ global_mapi_ctx->dumpdata = status;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Set MAPI debug level
+
+ \param level the debug level to set
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: the function parameter is invalid
+ */
+_PUBLIC_ enum MAPISTATUS SetMAPIDebugLevel(uint32_t level)
+{
+ char *debuglevel;
+ bool ret;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ debuglevel = talloc_asprintf(talloc_autofree_context(), "%u", level);
+ ret = lp_set_cmdline(global_mapi_ctx->lp_ctx, "log level", debuglevel);
+ talloc_free(debuglevel);
+
+ return (ret == true) ? MAPI_E_SUCCESS : MAPI_E_INVALID_PARAMETER;
+}
+
+
+/**
+ \details Retrieve the global MAPI loadparm context
+
+ \param lp_ctx pointer to a pointer to the loadparm context that the
+ function returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_INITIALIZED
+ or MAPI_E_INVALID_PARAMETER
+ */
+_PUBLIC_ enum MAPISTATUS GetLoadparmContext(struct loadparm_context **lp_ctx)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!lp_ctx, MAPI_E_INVALID_PARAMETER, NULL);
+
+ *lp_ctx = global_mapi_ctx->lp_ctx;
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/conf/build.sh
===================================================================
--- trunk/openchange/libmapi/conf/build.sh (rev 0)
+++ trunk/openchange/libmapi/conf/build.sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+./libmapi/conf/mparse.pl --parser=mapitags --outputdir=libmapi/ libmapi/conf/mapi-properties
+./libmapi/conf/mparse.pl --parser=mapicodes --outputdir=libmapi/ libmapi/conf/mapi-codes
+./libmapi/conf/mparse.pl --parser=mapi_nameid --outputdir=libmapi/ libmapi/conf/mapi-named-properties
Property changes on: trunk/openchange/libmapi/conf/build.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/libmapi/conf/mapi-codes
===================================================================
--- trunk/openchange/libmapi/conf/mapi-codes (rev 0)
+++ trunk/openchange/libmapi/conf/mapi-codes 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,292 @@
+#
+# OpenChange MAPI implementation.
+# MAPI error codes
+#
+# 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/>.
+#
+
+0x00000000 MAPI_E_SUCCESS
+0x80004002 MAPI_E_INTERFACE_NO_SUPPORT
+0x80004005 MAPI_E_CALL_FAILED
+0x80040102 MAPI_E_NO_SUPPORT
+0x80040103 MAPI_E_BAD_CHARWIDTH
+0x80040105 MAPI_E_STRING_TOO_LONG
+0x80040106 MAPI_E_UNKNOWN_FLAGS
+0x80040107 MAPI_E_INVALID_ENTRYID
+0x80040108 MAPI_E_INVALID_OBJECT
+0x80040109 MAPI_E_OBJECT_CHANGED
+0x8004010A MAPI_E_OBJECT_DELETED
+0x8004010B MAPI_E_BUSY
+0x8004010D MAPI_E_NOT_ENOUGH_DISK
+0x8004010E MAPI_E_NOT_ENOUGH_RESOURCES
+0x8004010F MAPI_E_NOT_FOUND
+0x80040110 MAPI_E_VERSION
+0x80040111 MAPI_E_LOGON_FAILED
+0x80040112 MAPI_E_SESSION_LIMIT
+0x80040113 MAPI_E_USER_CANCEL
+0x80040114 MAPI_E_UNABLE_TO_ABORT
+0x80040115 MAPI_E_NETWORK_ERROR
+0x80040116 MAPI_E_DISK_ERROR
+0x80040117 MAPI_E_TOO_COMPLEX
+0x80040118 MAPI_E_BAD_COLUMN
+0x80040119 MAPI_E_EXTENDED_ERROR
+0x8004011A MAPI_E_COMPUTED
+0x8004011B MAPI_E_CORRUPT_DATA
+0x8004011C MAPI_E_UNCONFIGURED
+0x8004011D MAPI_E_FAILONEPROVIDER
+0x8004011E MAPI_E_UNKNOWN_CPID
+0x8004011F MAPI_E_UNKNOWN_LCID
+0x80040120 MAPI_E_PASSWORD_CHANGE_REQUIRED
+0x80040121 MAPI_E_PASSWORD_EXPIRED
+0x80040122 MAPI_E_INVALID_WORKSTATION_ACCOUNT
+0x80040123 MAPI_E_INVALID_ACCESS_TIME
+0x80040124 MAPI_E_ACCOUNT_DISABLED
+0x80040200 MAPI_E_END_OF_SESSION
+0x80040201 MAPI_E_UNKNOWN_ENTRYID
+0x80040202 MAPI_E_MISSING_REQUIRED_COLUMN
+0x80040203 MAPI_W_NO_SERVICE
+0x80040301 MAPI_E_BAD_VALUE
+0x80040302 MAPI_E_INVALID_TYPE
+0x80040303 MAPI_E_TYPE_NO_SUPPORT
+0x80040304 MAPI_E_UNEXPECTED_TYPE
+0x80040305 MAPI_E_TOO_BIG
+0x80040306 MAPI_E_DECLINE_COPY
+0x80040307 MAPI_E_UNEXPECTED_ID
+0x80040380 MAPI_W_ERRORS_RETURNED
+0x80040400 MAPI_E_UNABLE_TO_COMPLETE
+0x80040401 MAPI_E_TIMEOUT
+0x80040402 MAPI_E_TABLE_EMPTY
+0x80040403 MAPI_E_TABLE_TOO_BIG
+0x80040405 MAPI_E_INVALID_BOOKMARK
+0x80040481 MAPI_W_POSITION_CHANGED
+0x80040482 MAPI_W_APPROX_COUNT
+0x80040500 MAPI_E_WAIT
+0x80040501 MAPI_E_CANCEL
+0x80040502 MAPI_E_NOT_ME
+0x80040580 MAPI_W_CANCEL_MESSAGE
+0x80040600 MAPI_E_CORRUPT_STORE
+0x80040601 MAPI_E_NOT_IN_QUEUE
+0x80040602 MAPI_E_NO_SUPPRESS
+0x80040604 MAPI_E_COLLISION
+0x80040605 MAPI_E_NOT_INITIALIZED
+0x80040606 MAPI_E_NON_STANDARD
+0x80040607 MAPI_E_NO_RECIPIENTS
+0x80040608 MAPI_E_SUBMITTED
+0x80040609 MAPI_E_HAS_FOLDERS
+0x8004060A MAPI_E_HAS_MESAGES
+0x8004060B MAPI_E_FOLDER_CYCLE
+0x8004060D MAPI_E_LOCKID_LIMIT
+0x80040680 MAPI_W_PARTIAL_COMPLETION
+0x80040700 MAPI_E_AMBIGUOUS_RECIP
+0x80040800 SYNC_E_OBJECT_DELETED
+0x80040801 SYNC_E_IGNORE
+0x80040802 SYNC_E_CONFLICT
+0x80040803 SYNC_E_NO_PARENT
+0x80040804 SYNC_E_CYCLE_DETECTED
+0x80040805 SYNC_E_UNSYNCHRONIZED
+0x80040820 SYNC_W_PROGRESS
+0x80040821 SYNC_W_CLIENT_CHANGE_NEWER
+0x80040900 MAPI_E_NAMED_PROP_QUOTA_EXCEEDED
+0x80070005 MAPI_E_NO_ACCESS
+0x8007000E MAPI_E_NOT_ENOUGH_MEMORY
+0x80070057 MAPI_E_INVALID_PARAMETER
+
+#
+# Additional Error Codes
+#
+
+0x000003EA ecJetError
+0x000003EB ecUnknownUser
+0x000003ED ecExiting
+0x000003EE ecBadConfig
+0x000003EF ecUnknownCodePage
+0x000003F0 ecMemory
+0x000003F2 ecLoginPerm
+0x000003F3 ecDatabaseRolledBack
+0x000003F4 ecDatabaseCopiedError
+0x000003F5 ecAuditNotAllowed
+0x000003F6 ecZombieUser
+0x000003F7 ecUnconvertableACL
+0x0000044C ecNoFreeJses
+0x0000044D ecDifferentJses
+0x0000044F ecFileRemove
+0x00000450 ecParameterOverflow
+0x00000451 ecBadVersion
+0x00000452 ecTooManyCols
+0x00000453 ecHaveMore
+0x00000454 ecDatabaseError
+0x00000455 ecIndexNameTooBig
+0x00000456 ecUnsupportedProp
+0x00000457 ecMsgNotSaved
+0x00000459 ecUnpubNotif
+0x0000045B ecDifferentRoot
+0x0000045C ecBadFolderName
+0x0000045D ecAttachOpen
+0x0000045E ecInvClpsState
+0x0000045F ecSkipMyChildren
+0x00000460 ecSearchFolder
+0x00000461 ecNotSearchFolder
+0x00000462 ecFolderSetReceive
+0x00000463 ecNoReceiveFolder
+0x00000465 ecNoDelSubmitMsg
+0x00000467 ecInvalidRecips
+0x00000468 ecNoReplicaHere
+0x00000469 ecNoReplicaAvailable
+0x0000046A ecPublicMDB
+0x0000046B ecNotPublicMDB
+0x0000046C ecRecordNotFound
+0x0000046D ecReplConflict
+0x00000470 ecFxBufferOverrun
+0x00000471 ecFxBufferEmpty
+0x00000472 ecFxPartialValue
+0x00000473 ecFxNoRoom
+0x00000474 ecMaxTimeExpired
+0x00000475 ecDstError
+0x00000476 ecMDBNotInit
+0x00000478 ecWrongServer
+0x0000047D ecBufferTooSmall
+0x0000047E ecRequiresRefResolve
+0x0000047F ecServerPaused
+0x00000480 ecServerBusy
+0x00000481 ecNoSuchLogon
+0x00000482 ecLoadLibFailed
+0x00000483 ecObjAlreadyConfig
+0x00000484 ecObjNotConfig
+0x00000485 ecDataLoss
+0x00000488 ecMaxSendThreadExceeded
+0x00000489 ecFxErrorMarker
+0x0000048A ecNoFreeJtabs
+0x0000048B ecNotPrivateMDB
+0x0000048C ecIsintegMDB
+0x0000048D ecRecoveryMDBMismatch
+0x0000048E ecTableMayNotBeDeleted
+0x000004B1 ecRpcRegisterIf
+0x000004B2 ecRpcListen
+0x000004B6 ecRpcFormat
+0x000004B7 ecNoCopyTo
+0x000004B9 ecNullObject
+0x000004BC ecRpcAuthentication
+0x000004BD ecRpcBadAuthenticationLevel
+0x000004BE ecNullCommentRestriction
+0x000004CC ecRulesLoadError
+0x000004CD ecRulesDelivErr
+0x000004CE ecRulesParsingErr
+0x000004CF ecRulesCreateDaeErr
+0x000004D0 ecRulesCreateDamErr
+0x000004D1 ecRulesNoMoveCopyFolder
+0x000004D2 ecRulesNoFolderRights
+0x000004D4 ecMessageTooBig
+0x000004D5 ecFormNotValid
+0x000004D6 ecNotAuthorized
+0x000004D7 ecDeleteMessage
+0x000004D8 ecBounceMessage
+0x000004D9 ecQuotaExceeded
+0x000004DA ecMaxSubmissionExceeded
+0x000004DB ecMaxAttachmentExceeded
+0x000004DC ecSendAsDenied
+0x000004DD ecShutoffQuotaExceeded
+0x000004DE ecMaxObjsExceeded
+0x000004DF ecClientVerDisallowed
+0x000004E0 ecRpcHttpDisallowed
+0x000004E1 ecCachedModeRequired
+0x000004E3 ecFolderNotCleanedUp
+0x000004ED ecFmtError
+0x000004F7 ecNotExpanded
+0x000004F8 ecNotCollapsed
+0x000004F9 ecLeaf
+0x000004FA ecUnregisteredNamedProp
+0x000004FB ecFolderDisabled
+0x000004FC ecDomainError
+0x000004FF ecNoCreateRight
+0x00000500 ecPublicRoot
+0x00000501 ecNoReadRight
+0x00000502 ecNoCreateSubfolderRight
+0x00000503 ecDstNullObject
+0x00000504 ecMsgCycle
+0x00000505 ecTooManyRecips
+0x0000050A ecVirusScanInProgress
+0x0000050B ecVirusDetected
+0x0000050C ecMailboxInTransit
+0x0000050D ecBackupInProgress
+0x0000050E ecVirusMessageDeleted
+0x0000050F ecInvalidBackupSequence
+0x00000510 ecInvalidBackupSize
+0x00000511 ecTooManyBackupsInProgress
+0x00000512 ecRestoreInProgress
+0x00000579 ecDuplicateObject
+0x0000057A ecObjectNotFound
+0x0000057B ecFixupReplyRule
+0x0000057C ecTemplateNotFound
+0x0000057D ecRuleException
+0x0000057E ecDSNoSuchObject
+0x0000057F ecMessageAlreadyTombstoned
+0x00000596 ecRequiresRWTransaction
+0x0000060E ecPaused
+0x00000648 ecWrongMailbox
+0x0000064C ecChgPassword
+0x0000064D ecPwdExpired
+0x0000064E ecInvWkstn
+0x0000064F ecInvLogonHrs
+0x00000650 ecAcctDisabled
+0x000006A4 ecRuleVersion
+0x000006A5 ecRuleFormat
+0x000006A6 ecRuleSendAsDenied
+0x000006B9 ecNoServerSupport
+0x000006BA ecLockTimedOut
+0x000006BB ecObjectLocked
+0x000006BD ecInvalidLockNamespace
+0x000007D6 ecMessageDeleted
+0x000007D8 ecProtocolDisabled
+0x000007D9 ecClearTextLogonDisabled
+0x000007EE ecRejected
+0x0000089A ecAmbiguousAlias
+0x0000089B ecUnknownMailbox
+0x000008FC ecExpReserved
+0x000008FD ecExpParseDepth
+0x000008FE ecExpFuncArgType
+0x000008FF ecExpSyntax
+0x00000900 ecExpBadStrToken
+0x00000901 ecExpBadColToken
+0x00000902 ecExpTypeMismatch
+0x00000903 ecExpOpNotSupported
+0x00000904 ecExpDivByZero
+0x00000905 ecExpUnaryArgType
+0x00000960 ecNotLocked
+0x00000961 ecClientEvent
+0x00000965 ecCorruptEvent
+0x00000966 ecCorruptWatermark
+0x00000967 ecEventError
+0x00000968 ecWatermarkError
+0x00000969 ecNonCanonicalACL
+0x0000096C ecMailboxDisabled
+0x0000096D ecRulesFolderOverQuota
+0x0000096E ecADUnavailable
+0x0000096F ecADError
+0x00000971 ecADNotFound
+0x00000972 ecADPropertyError
+0x00000970 ecNotEncrypted
+0x00000973 ecRpcServerTooBusy
+0x00000974 ecRpcOutOfMemory
+0x00000975 ecRpcServerOutOfMemory
+0x00000976 ecRpcOutOfResources
+0x00000977 ecRpcServerUnavailable
+0x0000097A ecSecureSubmitError
+0x0000097C ecEventsDeleted
+0x0000097D ecSubsystemStopping
+0x0000097E ecSAUnavailable
+0x00000A28 ecCIStopping
+0x00000A29 ecFxInvalidState
+0x00000A2A ecFxUnexpectedMarker
+0x00000A2B ecDuplicateDelivery
+0x00000A2C ecConditionViolation
Added: trunk/openchange/libmapi/conf/mapi-named-properties
===================================================================
--- trunk/openchange/libmapi/conf/mapi-named-properties (rev 0)
+++ trunk/openchange/libmapi/conf/mapi-named-properties 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,456 @@
+#
+# OpenChange MAPI implementation.
+#
+# Copyright (C) Julien Kerihuel 2007-2008.
+#
+# 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/>.
+#
+
+
+### Canonical name OOM propID propName propType Kind OLEGUID
+
+### Meeting Properties
+PidLidAttendeeCriticalChange LID_ATTENDEE_CRITICAL_CHANGE 0x0001 NULL PT_SYSTIME MNID_ID PSETID_Meeting
+PidLidWhere LID_WHERE 0x0002 NULL PT_UNICODE MNID_ID PSETID_Meeting
+PidLidGlobalObjectId LID_GLOBAL_OBJID 0x0003 NULL PT_BINARY MNID_ID PSETID_Meeting
+PidLidIsSilent LID_IS_SILENT 0x0004 NULL PT_BOOLEAN MNID_ID PSETID_Meeting
+PidLidIsRecurring LID_IS_RECURRING 0x0005 NULL PT_BOOLEAN MNID_ID PSETID_Meeting
+PidLidRequiredAttendees LID_REQUIRED_ATTENDEES 0x0006 NULL PT_UNICODE MNID_ID PSETID_Meeting
+PidLidOptionalAttendees LID_OPTIONAL_ATTENDEES 0x0007 NULL PT_UNICODE MNID_ID PSETID_Meeting
+PidLidResourceAttendees LID_RESOURCE_ATTENDEES 0x0008 NULL PT_UNICODE MNID_ID PSETID_Meeting
+PidLidDelegateMail LID_DELEGATE_MAIL 0x0009 NULL PT_BOOLEAN MNID_ID PSETID_Meeting
+PidLidIsException LID_IS_EXCEPTION 0x000A NULL PT_BOOLEAN MNID_ID PSETID_Meeting
+PidLidSingleInvite LID_SINGLE_INVITE 0x000B NULL PT_BOOLEAN MNID_ID PSETID_Meeting
+PidLidTimeZone LID_TIME_ZONE 0x000C NULL PT_LONG MNID_ID PSETID_Meeting
+PidLidDayInterval LID_DAY_INTERVAL 0x0011 NULL PT_SHORT MNID_ID PSETID_Meeting
+PidLidWeekInterval LID_WEEK_INTERVAL 0x0012 NULL PT_SHORT MNID_ID PSETID_Meeting
+PidLidMonthInterval LID_MONTH_INTERVAL 0x0013 NULL PT_SHORT MNID_ID PSETID_Meeting
+PidLidYearInterval LID_YEAR_INTERVAL 0x0014 NULL PT_SHORT MNID_ID PSETID_Meeting
+PidLidOwnerCriticalChange LID_OWNER_CRITICAL_CHANGE 0x001A NULL PT_SYSTIME MNID_ID PSETID_Meeting
+PidLidCalendarType LID_CALENDAR_TYPE 0x001C NULL PT_LONG MNID_ID PSETID_Meeting
+PidLidAllAttendeesList LID_ALL_ATTENDEES_LIST 0x001D NULL PT_UNICODE MNID_ID PSETID_Meeting
+PidLidCleanGlobalObjectId CleanGlobalObjId 0x0023 NULL PT_BINARY MNID_ID PSETID_Meeting
+PidLidAppointmentMessageClass ApptMessageClass 0x0024 NULL PT_UNICODE MNID_ID PSETID_Meeting
+PidLidMeetingType MeetingType 0x0026 NULL PT_LONG MNID_ID PSETID_Meeting
+PidLidOldLocation OldLocation 0x0028 NULL PT_UNICODE MNID_ID PSETID_Meeting
+PidLidOldWhenStartWhole OldWhenStartWhole 0x0029 NULL PT_SYSTIME MNID_ID PSETID_Meeting
+PidLidOldWhenEndWhole OldWhenEndWhole 0x002A NULL PT_SYSTIME MNID_ID PSETID_Meeting
+
+
+### Address Named Properties
+PidLidYomiCompanyName YomiCompanyName 0x8002 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidFileUnder FileUnder 0x8005 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidFileUnderId FileUnderId 0x8006 NULL PT_LONG MNID_ID PSETID_Address
+PidLidContactItemData ContactItemData 0x8007 NULL PT_MV_LONG MNID_ID PSETID_Address
+NULL NULL 0x800E NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidDepartment Department 0x8010 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidHasPicture HasPicture 0x8015 NULL PT_BOOLEAN MNID_ID PSETID_Address
+PidLidHomeAddress HomeAddress 0x801A NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidWorkAddress WorkAddress 0x801B NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidOtherAddress OtherAddress 0x801C NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidPostalAddressId PostalAddressId 0x8022 NULL PT_LONG MNID_ID PSETID_Address
+PidLidContactCharacterSet ContactCharSet 0x8023 NULL PT_LONG MNID_ID PSETID_Address
+PidLidAutoLog AutoLog 0x8025 NULL PT_BOOLEAN MNID_ID PSETID_Address
+PidLidFileUnderList FileUnderList 0x8026 NULL PT_MV_LONG MNID_ID PSETID_Address
+PidLidEmailList EmailList 0x8027 NULL PT_MV_LONG MNID_ID PSETID_Address
+PidLidAddressBookProviderEmailList ABPEmailList 0x8028 NULL PT_MV_LONG MNID_ID PSETID_Address
+PidLidAddressBookProviderArrayType ABPArrayType 0x8029 NULL PT_LONG MNID_ID PSETID_Address
+PidLidHtml HTML 0x802B NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidYomiFirstName YomiFirstName 0x802C NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidYomiLastName YomiLastName 0x802D NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidBusinessCardDisplayDefinition BCDisplayDefinition 0x8040 NULL PT_BINARY MNID_ID PSETID_Address
+PidLidBusinessCardCardPicture BCCardPicture 0x8041 NULL PT_BINARY MNID_ID PSETID_Address
+PidLidWorkAddressStreet WorkAddressStreet 0x8045 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidWorkAddressCity WorkAddressCity 0x8046 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidWorkAddressState WorkAddressState 0x8047 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidWorkAddressPostalCode WorkAddressPostalCode 0x8048 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidWorkAddressCountry WorkAddressCountry 0x8049 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidWorkAddressPostOfficeBox WorkAddressPostOfficeBox 0x804A NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidDistributionListChecksum DLChecksum 0x804C NULL PT_LONG MNID_ID PSETID_Address
+PidLidBirthdayEventEntryId BirthdayEventEID 0x804D NULL PT_BINARY MNID_ID PSETID_Address
+PidLidAnniversaryEventEntryId AnniversaryEventEID 0x804E NULL PT_BINARY MNID_ID PSETID_Address
+PidLidContactUserField1 ContactUserField1 0x804F NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidContactUserField2 ContactUserField2 0x8050 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidContactUserField3 ContactUserField3 0x8051 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidContactUserField4 ContactUserField4 0x8052 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidDistributionListName DLName 0x8053 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidDistributionListOneOffMembers DLOneOffMembers 0x8054 NULL PT_MV_BINARY MNID_ID PSETID_Address
+PidLidDistributionListMembers DLMembers 0x8055 NULL PT_MV_BINARY MNID_ID PSETID_Address
+PidLidInstantMessagingAddress InstMsg 0x8062 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail1DisplayName Email1DisplayName 0x8080 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail1AddressType Email1AddrType 0x8082 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail1EmailAddress Email1EmailAddress 0x8083 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail1OriginalDisplayName Email1OriginalDisplayName 0x8084 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail1OriginalEntryId Email1OriginalEntryID 0x8085 NULL PT_BINARY MNID_ID PSETID_Address
+PidLidEmail1EmailType Email1EmailType 0x8087 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail2DisplayName Email2DisplayName 0x8090 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail2EntryId Email2EntryID 0x8091 NULL PT_BINARY MNID_ID PSETID_Address
+PidLidEmail2AddressType Email2AddrType 0x8092 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail2EmailAddress Email2EmailAddress 0x8093 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail2OriginalDisplayName Email2OriginalDisplayName 0x8094 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail2OriginalEntryId Email2OriginalEntryID 0x8095 NULL PT_BINARY MNID_ID PSETID_Address
+PidLidEmail3DisplayName Email3DisplayName 0x80A0 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail3EntryId Email3EntryID 0x80A1 NULL PT_BINARY MNID_ID PSETID_Address
+PidLidEmail3AddressType Email3AddrType 0x80A2 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail3EmailAddress Email3EmailAddress 0x80A3 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail3OriginalDisplayName Email3OriginalDisplayName 0x80A4 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidEmail3OriginalEntryId Email3OriginalEntryID 0x80A5 NULL PT_BINARY MNID_ID PSETID_Address
+PidLidFax1AddressType Fax1AddrType 0x80B2 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidFax1EmailAddress Fax1EmailAddress 0x80B3 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidFax1OriginalDisplayName Fax1OriginalDisplayName 0x80B4 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidFax1OriginalEntryId Fax1OriginalEntryID 0x80B5 NULL PT_BINARY MNID_ID PSETID_Address
+PidLidFax2AddressType Fax2AddrType 0x80C2 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidFax2EmailAddress Fax2EmailAddress 0x80C3 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidFax2OriginalDisplayName Fax2OriginalDisplayName 0x80C4 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidFax2OriginalEntryId Fax2OriginalEntryID 0x80C5 NULL PT_BINARY MNID_ID PSETID_Address
+PidLidFax3AddressType Fax3AddrType 0x80D2 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidFax3EmailAddress Fax3EmailAddress 0x80D3 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidFax3OriginalDisplayName Fax3OriginalDisplayName 0x80D4 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidFax3OriginalEntryId Fax3OriginalEntryID 0x80D5 NULL PT_BINARY MNID_ID PSETID_Address
+PidLidFreeBusyLocation FreeBusyLocation 0x80D8 NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidHomeAddressCountryCode HomeAddressCountryCode 0x80DA NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidWorkAddressCountryCode WorkAddressCountryCode 0x80DB NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidOtherAddressCountryCode OtherAddressCountryCode 0x80DC NULL PT_UNICODE MNID_ID PSETID_Address
+PidLidAddressCountryCode AddressCountryCode 0x80DD NULL PT_UNICODE MNID_ID PSETID_Address
+
+
+
+### Task Named Properties
+PidLidTaskStatus TaskStatus 0x8101 NULL PT_LONG MNID_ID PSETID_Task
+PidLidPercentComplete PercentComplete 0x8102 NULL PT_DOUBLE MNID_ID PSETID_Task
+PidLidTeamTask TeamTask 0x8103 NULL PT_BOOLEAN MNID_ID PSETID_Task
+PidLidTaskStartDate TaskStartDate 0x8104 NULL PT_SYSTIME MNID_ID PSETID_Task
+PidLidTaskDueDate TaskDueDate 0x8105 NULL PT_SYSTIME MNID_ID PSETID_Task
+PidLidTaskResetReminder TaskResetReminder 0x8107 NULL PT_BOOLEAN MNID_ID PSETID_Task
+PidLidTaskAccepted TaskAccepted 0x8108 NULL PT_BOOLEAN MNID_ID PSETID_Task
+PidLidTaskDeadOccurrence TaskDeadOccur 0x8109 NULL PT_BOOLEAN MNID_ID PSETID_Task
+PidLidTaskDateCompleted TaskDateCompleted 0x810F NULL PT_SYSTIME MNID_ID PSETID_Task
+PidLidTaskActualEffort TaskActualEffort 0x8110 NULL PT_LONG MNID_ID PSETID_Task
+PidLidTaskEstimatedEffort TaskEstimatedEffort 0x8111 NULL PT_LONG MNID_ID PSETID_Task
+PidLidTaskVersion TaskVersion 0x8112 NULL PT_LONG MNID_ID PSETID_Task
+PidLidTaskState TaskState 0x8113 NULL PT_LONG MNID_ID PSETID_Task
+PidLidTaskLastUpdate TaskLastUpdate 0x8115 NULL PT_SYSTIME MNID_ID PSETID_Task
+PidLidTaskRecurrence TaskRecur 0x8116 NULL PT_BINARY MNID_ID PSETID_Task
+PidLidTaskAssigners TaskMyDelegators 0x8117 NULL PT_BINARY MNID_ID PSETID_Task
+PidLidTaskStatusOnComplete TaskSOC 0x8119 NULL PT_BOOLEAN MNID_ID PSETID_Task
+PidLidTaskHistory TaskHistory 0x811A NULL PT_LONG MNID_ID PSETID_Task
+PidLidTaskUpdates TaskUpdates 0x811B NULL PT_BOOLEAN MNID_ID PSETID_Task
+PidLidTaskComplete TaskComplete 0x811C NULL PT_BOOLEAN MNID_ID PSETID_Task
+PidLidTaskFCreator TaskFCreator 0x811E NULL PT_BOOLEAN MNID_ID PSETID_Task
+PidLidTaskOwner TaskOwner 0x811F NULL PT_UNICODE MNID_ID PSETID_Task
+PidLidTaskMultipleRecipients TaskMultRecips 0x8120 NULL PT_LONG MNID_ID PSETID_Task
+PidLidTaskAssigner TaskDelegator 0x8121 NULL PT_UNICODE MNID_ID PSETID_Task
+PidLidTaskLastUser TaskLastUser 0x8122 NULL PT_UNICODE MNID_ID PSETID_Task
+PidLidTaskOrdinal TaskOrdinal 0x8123 NULL PT_LONG MNID_ID PSETID_Task
+PidLidTaskNoCompute TaskNoCompute 0x8124 NULL PT_BOOLEAN MNID_ID PSETID_Task
+PidLidTaskLastDelegate TaskLastDelegate 0x8125 NULL PT_UNICODE MNID_ID PSETID_Task
+PidLidTaskFRecurring TaskFRecur 0x8126 NULL PT_BOOLEAN MNID_ID PSETID_Task
+PidLidTaskRole TaskRole 0x8127 NULL PT_UNICODE MNID_ID PSETID_Task
+PidLidTaskOwnership TaskOwnership 0x8129 NULL PT_LONG MNID_ID PSETID_Task
+PidLidAcceptanceState TaskDelegValue 0x812A NULL PT_LONG MNID_ID PSETID_Task
+PidLidTaskFFixOffline TaskFFixOffline 0x812C NULL PT_BOOLEAN MNID_ID PSETID_Task
+
+
+### Appointment Named Properties
+PidLidSendMeetingAsIcal SendMtgAsICAL 0x8200 NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidAppointmentSequence ApptSequence 0x8201 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidAppointmentSequenceTime ApptSeqTime 0x8202 NULL PT_SYSTIME MNID_ID PSETID_Appointment
+PidLidAppointmentLastSequence ApptLastSequence 0x8203 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidChangeHighlight ChangeHighlight 0x8204 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidBusyStatus BusyStatus 0x8205 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidFExceptionalBody FExceptionalBody 0x8206 NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidAppointmentAuxiliaryFlags ApptAuxFlags 0x8207 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidLocation Location 0x8208 NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidMeetingWorkspaceUrl MWSURL 0x8209 NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidForwardInstance FwrdInstance 0x820A NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidLinkedTaskItems LinkedTaskItems 0x820C NULL PT_MV_BINARY MNID_ID PSETID_Appointment
+PidLidAppointmentStartWhole ApptStartWhole 0x820D NULL PT_SYSTIME MNID_ID PSETID_Appointment
+PidLidAppointmentEndWhole ApptEndWhole 0x820E NULL PT_SYSTIME MNID_ID PSETID_Appointment
+NULL NULL 0x820F NULL PT_SYSTIME MNID_ID PSETID_Appointment
+NULL NULL 0x8210 NULL PT_SYSTIME MNID_ID PSETID_Appointment
+NULL NULL 0x8211 NULL PT_SYSTIME MNID_ID PSETID_Appointment
+NULL NULL 0x8212 NULL PT_SYSTIME MNID_ID PSETID_Appointment
+PidLidAppointmentDuration ApptDuration 0x8213 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidAppointmentColor ApptColor 0x8214 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidAppointmentSubType ApptSubType 0x8215 NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidAppointmentRecur ApptRecur 0x8216 NULL PT_BINARY MNID_ID PSETID_Appointment
+PidLidAppointmentStateFlags ApptStateFlags 0x8217 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidResponseStatus ResponseStatus 0x8218 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidAppointmentReplyTime ApptReplyTime 0x8220 NULL PT_SYSTIME MNID_ID PSETID_Appointment
+PidLidRecurring Recurring 0x8223 NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidIntendedBusyStatus IntendedBusyStatus 0x8224 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidExceptionReplaceTime ExceptionReplaceTime 0x8228 NULL PT_SYSTIME MNID_ID PSETID_Appointment
+PidLidFInvited FInvited 0x8229 NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidFExceptionalAttendees FExceptionalAttendees 0x822B NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidAppointmentReplyName ApptReplyName 0x8230 NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidRecurrenceType RecurType 0x8231 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidRecurrencePattern RecurPattern 0x8232 NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidTimeZoneStruct TimeZoneStruct 0x8233 NULL PT_BINARY MNID_ID PSETID_Appointment
+PidLidTimeZoneDescription TimeZoneDesc 0x8234 NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidClipStart ClipStart 0x8235 NULL PT_SYSTIME MNID_ID PSETID_Appointment
+PidLidClipEnd ClipEnd 0x8236 NULL PT_SYSTIME MNID_ID PSETID_Appointment
+PidLidOriginalStoreEntryId OrigStoreEid 0x8237 NULL PT_BINARY MNID_ID PSETID_Appointment
+PidLidAllAttendeesString AllAttendeesString 0x8238 NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidAutoFillLocation AutoFillLocation 0x823A NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidToAttendeesString ToAttendeesString 0x823B NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidCcAttendeesString CcAttendeesString 0x823C NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidAppointmentUnsendableRecipients ApptUnsendableRecips 0x823D NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidConferencingCheck ConfCheck 0x8240 NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidConferencingType ConfType 0x8241 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidDirectory Directory 0x8242 NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidOrganizerAlias OrgAlias 0x8243 NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidAutoStartCheck AutoStartCheck 0x8244 NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidAutoStartWhen AutoStartWhen 0x8245 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidAllowExternalCheck AllowExternCheck 0x8246 NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidCollaborateDoc CollaborateDoc 0x8247 NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidNetShowUrl NetShowURL 0x8248 NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidOnlinePassword OnlinePassword 0x8249 NULL PT_UNICODE MNID_ID PSETID_Appointment
+PidLidAppointmentProposedStartWhole ApptProposedStartWhole 0x8250 NULL PT_SYSTIME MNID_ID PSETID_Appointment
+PidLidAppointmentProposedEndWhole ApptProposedEndWhole 0x8251 NULL PT_SYSTIME MNID_ID PSETID_Appointment
+PidLidAPpointmentProposedDuration ApptProposedDuration 0x8256 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidAppointmentCounterProposal ApptCounterProposal 0x8257 NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidAppointmentProposalNumber ApptProposalNum 0x8259 NULL PT_LONG MNID_ID PSETID_Appointment
+PidLidAppointmentNotAllowPropose ApptNotAllowPropose 0x825A NULL PT_BOOLEAN MNID_ID PSETID_Appointment
+PidLidAppointmentTimeZoneDefinitionStartDisplay ApptTZDefStartDisplay 0x825E NULL PT_BINARY MNID_ID PSETID_Appointment
+PidLidAppointmentTimeZoneDefinitionEndDisplay ApptTZDefEndDisplay 0x825F NULL PT_BINARY MNID_ID PSETID_Appointment
+PidLidAppointmentTimeZoneDefinitionRecur ApptTZDefRecur 0x8260 NULL PT_BINARY MNID_ID PSETID_Appointment
+
+
+### Common Named properties
+PidLidReminderDelta ReminderDelta 0x8501 NULL PT_LONG MNID_ID PSETID_Common
+PidLidReminderTime ReminderTime 0x8502 NULL PT_SYSTIME MNID_ID PSETID_Common
+PidLidReminderSet ReminderSet 0x8503 NULL PT_BOOLEAN MNID_ID PSETID_Common
+PidLidPrivate Private 0x8506 NULL PT_BOOLEAN MNID_ID PSETID_Common
+PidLidAgingDontAgeMe AgingDontAgeMe 0x850E NULL PT_BOOLEAN MNID_ID PSETID_Common
+PidLidSideEffects SideEffects 0x8510 NULL PT_LONG MNID_ID PSETID_Common
+PidLidSmartNoAttach SmartNoAttach 0x8514 NULL PT_BOOLEAN MNID_ID PSETID_Common
+PidLidCommonStart CommonStart 0x8516 NULL PT_SYSTIME MNID_ID PSETID_Common
+PidLidCommonEnd CommonEnd 0x8517 NULL PT_SYSTIME MNID_ID PSETID_Common
+PidLidTaskMode TaskMode 0x8518 NULL PT_LONG MNID_ID PSETID_Common
+PidLidTaskGlobalId TaskGlobalObjId 0x8519 NULL PT_BINARY MNID_ID PSETID_Common
+PidLidAutoProcessState SniffState 0x851A NULL PT_LONG MNID_ID PSETID_Common
+PidLidReminderOverride ReminderOverride 0x851C NULL PT_BOOLEAN MNID_ID PSETID_Common
+PidLidReminderType ReminderType 0x851D NULL PT_LONG MNID_ID PSETID_Common
+PidLidReminderPlaySound ReminderPlaySound 0x851E NULL PT_BOOLEAN MNID_ID PSETID_Common
+PidLidReminderFileParameter ReminderFileParam 0x851F NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidVerbStream VerbStream 0x8520 NULL PT_BINARY MNID_ID PSETID_Common
+PidLidVerbResponse VerbResponse 0x8524 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidFlagRequest Request 0x8530 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidMileage MileAge 0x8534 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidBillingInformation BillingInformation 0x8535 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidNonSendtableTo NonSendableTo 0x8536 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidNonSendableCc NonSendableCC 0x8537 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidNonSendableBcc NonSendableBCC 0x8538 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidCompanies Companies 0x8539 NULL PT_MV_STRING8 MNID_ID PSETID_Common
+PidLidContacts Contacts 0x853A NULL PT_MV_STRING8 MNID_ID PSETID_Common
+PidLidNonSendToTrackStatus NonSendToTrackStatus 0x8543 NULL PT_MV_LONG MNID_ID PSETID_Common
+PidLidNonSendCcTrackStatus NonSendCcTrackStatus 0x8544 NULL PT_MV_LONG MNID_ID PSETID_Common
+PidLidNonSendBccTrackStatus NonSendBccTrackStatus 0x8545 NULL PT_MV_LONG MNID_ID PSETID_Common
+PidLidCurrentVersion CurrentVersion 0x8552 NULL PT_LONG MNID_ID PSETID_Common
+PidLidCurrentVersionName CurrentVersionName 0x8554 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidReminderSignalTime ReminderNextTime 0x8560 NULL PT_SYSTIME MNID_ID PSETID_Common
+PidLidInternetAccountName InetAcctName 0x8580 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidInternetAccountStamp InetAcctStamp 0x8581 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidUseTnef UseTNEF 0x8582 NULL PT_BOOLEAN MNID_ID PSETID_Common
+NULL NULL 0x8583 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidContactLinkSearchKey ContactLinkSearchKey 0x8584 NULL PT_BINARY MNID_ID PSETID_Common
+PidLidContactLinkEntry ContactLinkEntry 0x8585 NULL PT_BINARY MNID_ID PSETID_Common
+PidLidContactLinkName ContactLinkName 0x8586 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidSpamOriginalFolder SpamOriginalFolder 0x859C NULL PT_BINARY MNID_ID PSETID_Common
+PidLidToDoOrdinalDate ToDoOrdinalDate 0x85A0 NULL PT_SYSTIME MNID_ID PSETID_Common
+PidLidToDoSubOrdinal ToDoSubOrdinal 0x85A1 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidToDoTitle ToDoTitle 0x85A4 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidInfoPathFormName InfoPathFormName 0x85B1 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidClassified Classified 0x85B5 NULL PT_BOOLEAN MNID_ID PSETID_Common
+PidLidClassification Classification 0x85B6 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidClassificationDescription ClassDesc 0x85B7 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidClassificationGuid ClassGuid 0x85B8 NULL PT_UNICODE MNID_ID PSETID_Common
+PidLidClassificationKeep ClassKeep 0x85BA NULL PT_BOOLEAN MNID_ID PSETID_Common
+PidLidReferenceEntryId ReferenceEID 0x85BD NULL PT_BINARY MNID_ID PSETID_Common
+PidLidValidFlagStringProof ValidFlagStringProof 0x85BF NULL PT_SYSTIME MNID_ID PSETID_Common
+PidLidFlagString FlagStringEnum 0x85C0 NULL PT_LONG MNID_ID PSETID_Common
+
+### Log Named Properties
+PidLidLogType LogType 0x8700 NULL PT_UNICODE MNID_ID PSETID_Log
+PidLidLogStart LogStart 0x8706 NULL PT_SYSTIME MNID_ID PSETID_Log
+PidLidLogDuration LogDuration 0x8707 NULL PT_LONG MNID_ID PSETID_Log
+PidLidLogEnd LogEnd 0x8708 NULL PT_SYSTIME MNID_ID PSETID_Log
+PidLidLogFlags LogFlags 0x870C NULL PT_LONG MNID_ID PSETID_Log
+PidLidDocumentPrinted LogDocPrinted 0x870E NULL PT_BOOLEAN MNID_ID PSETID_Log
+PidLidDocumentSaved LogDocSaved 0x870F NULL PT_BOOLEAN MNID_ID PSETID_Log
+PidLidDocumentRouted LogDocRouted 0x8710 NULL PT_BOOLEAN MNID_ID PSETID_Log
+PidLidDocumentPosted LogDocPosted 0x8711 NULL PT_BOOLEAN MNID_ID PSETID_Log
+PidLidLogTypeDesc LogTypeDesc 0x8712 NULL PT_UNICODE MNID_ID PSETID_Log
+
+
+### Post RSS Named Properties
+PidLidPostRssChannelLink PostRssChannelLink 0x8900 NULL PT_UNICODE MNID_ID PSETID_PostRss
+PidLidPostRssItemLink PostRssItemLink 0x8901 NULL PT_UNICODE MNID_ID PSETID_PostRss
+PidLidPostRssItemHash PostRssItemHash 0x8902 NULL PT_LONG MNID_ID PSETID_PostRss
+PidLidPostRssItemGuid PostRssItemGuid 0x8903 NULL PT_UNICODE MNID_ID PSETID_PostRss
+PidLidPostRssChannel PostRssChannel 0x8904 NULL PT_UNICODE MNID_ID PSETID_PostRss
+PidLidPostRssItemXml PostRssItemXml 0x8905 NULL PT_UNICODE MNID_ID PSETID_PostRss
+PidLidPostRssSubscription PostRssSubscription 0x8906 NULL PT_UNICODE MNID_ID PSETID_PostRss
+
+
+### Sharing Named Properties
+PidLidSharingStatus SharingStatus 0x8A00 NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingProviderGuid SharingProviderGuid 0x8A01 NULL PT_BINARY MNID_ID PSETID_Sharing
+PidLidSharingProviderName SharingProviderName 0x8A02 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingProviderUrl SharingProviderUrl 0x8A03 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingRemotePath SharingRemotePath 0x8A04 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingRemoteName SharingRemoteName 0x8A05 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingRemoteUid SharingRemoteUid 0x8A06 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingInitiatorName SharingInitiatorName 0x8A07 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingInitiatorSmtp SharingInitiatorSmtp 0x8A08 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingInitiatorEntryId SharingInitiatorEid 0x8A09 NULL PT_BINARY MNID_ID PSETID_Sharing
+PidLidSharingFlags SharingFlags 0x8A0A NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingProviderExtension SharingProviderExtension 0x8A0B NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingRemoteUser SharingRemoteUser 0x8A0C NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingRemotePass SharingRemotePass 0x8A0D NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingLocalPath SharingLocalPath 0x8A0E NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingLocalName SharingLocalName 0x8A0F NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingLocalUid SharingLocalUid 0x8A10 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingFilter SharingFilter 0x8A13 NULL PT_BINARY MNID_ID PSETID_Sharing
+PidLidSharingLocalType SharingLocalType 0x8A14 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingFolderEntryId SharingFolderEid 0x8A15 NULL PT_BINARY MNID_ID PSETID_Sharing
+PidLidSharingCapabilities SharingCaps 0x8A17 NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingFlavor SharingFlavor 0x8A18 NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingAnonymity SharingAnonymity 0x8A19 NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingReciprocation SharingReciprocation 0x8A1A NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingPermissions SharingPermissions 0x8A1B NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingInstanceGuid SharingInstanceGuid 0x8A1C NULL PT_BINARY MNID_ID PSETID_Sharing
+PidLidSharingRemoteType SharingRemoteType 0x8A1D NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingParticipants SharingParticipants 0x8A1E NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingLastSyncTime SharingLastSync 0x8A1F NULL PT_SYSTIME MNID_ID PSETID_Sharing
+PidLidSharingExtensionXml SharingExtXml 0x8A21 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingRemoteLastModificationTime SharingRemoteLastMod 0x8A22 NULL PT_SYSTIME MNID_ID PSETID_Sharing
+PidLidSharingLocalLastModificationTime SharingLocalLastMod 0x8A23 NULL PT_SYSTIME MNID_ID PSETID_Sharing
+PidLidSharingConfigurationUrl SharingConfigUrl 0x8A24 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingStart SharingStart 0x8A25 NULL PT_SYSTIME MNID_ID PSETID_Sharing
+PidLidSharingStop SharingStop 0x8A26 NULL PT_SYSTIME MNID_ID PSETID_Sharing
+PidLidSharingResponseType SharingResponseType 0x8A27 NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingResponseTime SharingResponseTime 0x8A28 NULL PT_SYSTIME MNID_ID PSETID_Sharing
+PidLidSharingOriginalMessageEntryId SharingOriginalMessageEid 0x8A29 NULL PT_BINARY MNID_ID PSETID_Sharing
+PidLidSharingSyncInterval SharingSyncInterval 0x8A2A NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingDetail SharingDetail 0x8A2B NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingTimeToLive SharingTimeToLive 0x8A2C NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingBindingEntryId SharingBindingEid 0x8A2D NULL PT_BINARY MNID_ID PSETID_Sharing
+PidLidSharingIndexEntryId SharingIndexEid 0x8A2E NULL PT_BINARY MNID_ID PSETID_Sharing
+PidLidSharingRemoteComment SharingRemoteComment 0x8A2F NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingWorkingHoursStart SharingWorkingHoursStart 0x8A40 NULL PT_SYSTIME MNID_ID PSETID_Sharing
+PidLidSharingWorkingHoursEnd SharingWorkingHoursEnd 0x8A41 NULL PT_SYSTIME MNID_ID PSETID_Sharing
+PidLidSharingWorkingHoursDay SharingWorkingHoursDays 0x8A42 NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingWorkingHoursTimeZone SharingWorkingHoursTZ 0x8A43 NULL PT_BINARY MNID_ID PSETID_Sharing
+PidLidSharingDataRangeStart SharingDataRangeStart 0x8A44 NULL PT_SYSTIME MNID_ID PSETID_Sharing
+PidLidSharingDataRangeEnd SharingDataRangeEnd 0x8A45 NULL PT_SYSTIME MNID_ID PSETID_Sharing
+PidLidSharingRangeStart SharingRangeStart 0x8A46 NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingRangeEnd SharingRangeEnd 0x8A47 NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingRemoteStoreUid SharingRemoteStoreUid 0x8A48 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingLocalStoreUid SharingLocalStoreUid 0x8A49 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingRemoteByteSize SharingRemoteByteSize 0x8A4B NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingRemoteCrc SharingRemoteCrc 0x8A4C NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingLocalComment SharingLocalComment 0x8A4D NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingRoamLog SharingRoamLog 0x8A4E NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingRemoteMessageCount SharingRemoteMsgCount 0x8A4F NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingBrowseUrl SharingBrowseUrl 0x8A51 NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingLastAutoSyncTime SharingLastAutoSync 0x8A55 NULL PT_SYSTIME MNID_ID PSETID_Sharing
+PidLidSharingTimeToLiveAuto SharingTimeToLiveAuto 0x8A56 NULL PT_LONG MNID_ID PSETID_Sharing
+PidLidSharingRemoteVersion SharingRemoteVersion 0x8A5B NULL PT_UNICODE MNID_ID PSETID_Sharing
+PidLidSharingParentBindingEntryId SharingParentBindingEid 0x8A5C NULL PT_BINARY MNID_ID PSETID_Sharing
+PidLidSharingSyncFlags SharingSyncFlags 0x8A60 NULL PT_LONG MNID_ID PSETID_Sharing
+
+### Note Named Properties
+PidLidNoteColor NoteColor 0x8B00 NULL PT_LONG MNID_ID PSETID_Note
+PidLidNoteWidth NoteWidth 0x8B02 NULL PT_LONG MNID_ID PSETID_Note
+PidLidNoteHeight NoteHeight 0x8B03 NULL PT_LONG MNID_ID PSETID_Note
+PidLidNoteX NoteX 0x8B04 NULL PT_LONG MNID_ID PSETID_Note
+PidLidNoteY NoteY 0x8B05 NULL PT_LONG MNID_ID PSETID_Note
+
+
+
+### PS_PUBLIC_STRINGS
+PidLidCategories Categories 0x2328 NULL PT_MV_STRING8 MNID_ID PS_PUBLIC_STRINGS
+PidNameApplicationName NULL 0x0000 AppName PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameAuthor NULL 0x0000 Author PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameByteCount NULL 0x0000 ByteCount PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNameCategory NULL 0x0000 Category PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameCharacterCount NULL 0x0000 CharCount PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNameComments NULL 0x0000 Comments PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameCompany NULL 0x0000 Company PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameCreateDateTimeReadOnly NULL 0x0000 CreateDtmRo PT_SYSTIME MNID_STRING PS_PUBLIC_STRINGS
+PidNameRightsManagementLicense NULL 0x0000 DRMLicense PT_MV_BINARY MNID_STRING PS_PUBLIC_STRINGS
+PidNameEditTime NULL 0x0000 EditTime PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameJunkEmailMoveStamp NULL 0x0000 http://schemas.microsoft.com/exchange/junkemailmovestamp PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNameHiddenCount NULL 0x0000 HiddenCount PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNameKeywords NULL 0x0000 Keywords PT_MV_STRING8 MNID_STRING PS_PUBLIC_STRINGS
+PidNameLastAuthor NULL 0x0000 LastAuthor PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameLastPrinted NULL 0x0000 LastPrinted PT_SYSTIME MNID_STRING PS_PUBLIC_STRINGS
+PidNameLastSaveDateTime NULL 0x0000 LastSaveDtm PT_SYSTIME MNID_STRING PS_PUBLIC_STRINGS
+PidNameLineCount NULL 0x0000 LineCount PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNameManager NULL 0x0000 Manager PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameMultimediaClipCount NULL 0x0000 MMClipCount PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNameNoteCount NULL 0x0000 NoteCount PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNameOMSAccountGuid NULL 0x0000 OMSAccountGuid PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameOMSMobileModel NULL 0x0000 OMSMobileModel PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameOMSGScheduleTime NULL 0x0000 OMSScheduleTime PT_SYSTIME MNID_STRING PS_PUBLIC_STRINGS
+PidNameOMSServiceType NULL 0x0000 OMSServiceType PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNameOMSSourceType NULL 0x0000 OMSSourceType PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNamePhishingStamp NULL 0x0000 http://schemas.microsoft.com/outlook/phishingstamp PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNamePageCount NULL 0x0000 PageCount PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNameParagraphCount NULL 0x0000 ParCount PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNamePresentationFormat NULL 0x0000 PresFormat PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameSecurity NULL 0x0000 Security PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNameSlideCount NULL 0x0000 SlideCount PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+PidNameSubject NULL 0x0000 Subject PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameTemplate NULL 0x0000 Template PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameTitle NULL 0x0000 Title PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+PidNameWordCount NULL 0x0000 WordCount PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+NULL NULL 0x0000 urn:schemas:contacts:fileas PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+NULL NULL 0x0000 urn:schemas:calendar:sequence PT_LONG MNID_STRING PS_PUBLIC_STRINGS
+NULL NULL 0x0000 urn:schemas:calendar:version PT_UNICODE MNID_STRING PS_PUBLIC_STRINGS
+
+
+### PS_INTERNET_HEADERS
+PidNameAcceptLanguage AcceptLanguage 0x0000 Accept-Language PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameBodyContentBase BodyContentBase 0x0000 Content-Base PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameContentClass NULL 0x0000 Content-Class PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameContentTransferEncoding NULL 0x0000 Content-Transfer-Encoding PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameContentType NULL 0x0000 Content-Type PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameCrossReference NULL 0x0000 Xref PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingBrowseUrl NULL 0x0000 X-Sharing-Browse-Url PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingCapabilities NULL 0x0000 X-Sharing-Capabilities PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingConfigUrl NULL 0x0000 X-Sharing-Config-Url PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingExtendedCaps NULL 0x0000 X-Sharing-Extended-Caps PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingFlavor NULL 0x0000 X-Sharing-Flavor PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingInstanceGuid NULL 0x0000 X-Sharing-Instance-Guid PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingLocalType NULL 0x0000 X-Sharing-Local-Type PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingProviderGuid NULL 0x0000 X-Sharing-Provider-Guid PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingProviderName NULL 0x0000 X-Sharing-Provider-Name PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingProviderUrl NULL 0x0000 X-Sharing-Provider-Url PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingRemoteName NULL 0x0000 X-Sharing-Remote-Name PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingRemotePath NULL 0x0000 X-Sharing-Remote-Path PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingRemoteStoreUid NULL 0x0000 X-Sharing-Remote-Store-Uid PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingRemoteType NULL 0x0000 X-Sharing-Remote-Type PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+PidNameXSharingRemoteUid NULL 0x0000 X-Sharing-Remote-Uid PT_UNICODE MNID_STRING PS_INTERNET_HEADERS
+
+
+
+### PSETID_Attachment
+PidNameAttachmentMacContentType NULL 0x0000 AttachmentMacContentType PT_UNICODE MNID_STRING PSETID_Attachment
+PidNameAttachmentMacInfo NULL 0x0000 AttachmentMacInfo PT_BINARY MNID_STRING PSETID_Attachment
+
+
+### PSETID_UnifiedMessaging
+PidNameAudioNotes UMAudioNotes 0x0000 UMAudioNotes PT_UNICODE MNID_STRING PSETID_UnifiedMessaging
Added: trunk/openchange/libmapi/conf/mapi-properties
===================================================================
--- trunk/openchange/libmapi/conf/mapi-properties (rev 0)
+++ trunk/openchange/libmapi/conf/mapi-properties 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1545 @@
+#
+# OpenChange MAPI implementation.
+# MAPI property tags
+#
+# This file was originally taken from the Gnome Evolution project.
+# evolution/evolution-exchange/docs/mapi-properties
+#
+# For the OpenChange project, UNICODE properties (1f) have been
+# replaced by PT_STRING8 ones (1e)
+#
+# 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/>.
+#
+
+0x00010003 PR_ACKNOWLEDGEMENT_MODE
+0x0002000b PR_ALTERNATE_RECIPIENT_ALLOWED
+0x00030102 PR_AUTHORIZING_USERS
+0x0004001e PR_AUTO_FORWARD_COMMENT
+0x0005000b PR_AUTO_FORWARDED
+0x00060102 PR_CONTENT_CONFIDENTIALITY_ALGORITHM_ID
+0x00070102 PR_CONTENT_CORRELATOR
+0x0008001e PR_CONTENT_IDENTIFIER
+0x00090003 PR_CONTENT_LENGTH
+0x000a000b PR_CONTENT_RETURN_REQUESTED
+0x000b0102 PR_CONVERSATION_KEY
+0x000c0102 PR_CONVERSION_EITS
+0x000d000b PR_CONVERSION_WITH_LOSS_PROHIBITED
+0x000e0102 PR_CONVERTED_EITS
+0x000f0040 PR_DEFERRED_DELIVERY_TIME
+0x00100040 PR_DELIVER_TIME
+0x00110003 PR_DISCARD_REASON
+0x0012000b PR_DISCLOSURE_OF_RECIPIENTS
+0x00130102 PR_DL_EXPANSION_HISTORY
+0x0014000b PR_DL_EXPANSION_PROHIBITED
+0x00150040 PR_EXPIRY_TIME
+0x0016000b PR_IMPLICIT_CONVERSION_PROHIBITED
+0x00170003 PR_IMPORTANCE
+0x00180102 PR_IPM_ID
+0x00190040 PR_LATEST_DELIVERY_TIME
+0x001a001e PR_MESSAGE_CLASS
+0x001b0102 PR_MESSAGE_DELIVERY_ID
+0x001e0102 PR_MESSAGE_SECURITY_LABEL
+0x001f0102 PR_OBSOLETED_IPMS
+0x00200102 PR_ORIGINALLY_INTENDED_RECIPIENT_NAME
+0x00210102 PR_ORIGINAL_EITS
+0x00220102 PR_ORIGINATOR_CERTIFICATE
+0x0023000b PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED
+0x00240102 PR_ORIGINATOR_RETURN_ADDRESS
+0x00250102 PR_PARENT_KEY
+0x00260003 PR_PRIORITY
+0x00270102 PR_ORIGIN_CHECK
+0x0028000b PR_PROOF_OF_SUBMISSION_REQUESTED
+0x0029000b PR_READ_RECEIPT_REQUESTED
+0x002a0040 PR_RECEIPT_TIME
+0x002b000b PR_RECIPIENT_REASSIGNMENT_PROHIBITED
+0x002c0102 PR_REDIRECTION_HISTORY
+0x002d0102 PR_RELATED_IPMS
+0x002e0003 PR_ORIGINAL_SENSITIVITY
+0x002f001e PR_LANGUAGES
+0x00300040 PR_REPLY_TIME
+0x00310102 PR_REPORT_TAG
+0x00320040 PR_REPORT_TIME
+0x0033000b PR_RETURNED_IPM
+0x00340003 PR_SECURITY
+0x0035000b PR_INCOMPLETE_COPY
+0x00360003 PR_SENSITIVITY
+0x0037001e PR_SUBJECT
+0x00380102 PR_SUBJECT_IPM
+0x00390040 PR_CLIENT_SUBMIT_TIME
+0x003a001e PR_REPORT_NAME
+0x003b0102 PR_SENT_REPRESENTING_SEARCH_KEY
+0x003c0102 PR_X400_CONTENT_TYPE
+0x003d001e PR_SUBJECT_PREFIX
+0x003e0003 PR_NON_RECEIPT_REASON
+0x003f0102 PR_RECEIVED_BY_ENTRYID
+0x0040001e PR_RECEIVED_BY_NAME
+0x00410102 PR_SENT_REPRESENTING_ENTRYID
+0x0042001e PR_SENT_REPRESENTING_NAME
+0x00430102 PR_RCVD_REPRESENTING_ENTRYID
+0x0044001e PR_RCVD_REPRESENTING_NAME
+0x00450102 PR_REPORT_ENTRYID
+0x00460102 PR_READ_RECEIPT_ENTRYID
+0x00470102 PR_MESSAGE_SUBMISSION_ID
+0x00480040 PR_PROVIDER_SUBMIT_TIME
+0x0049001e PR_ORIGINAL_SUBJECT
+0x004a000b PR_DISC_VAL
+0x004b001e PR_ORIG_MESSAGE_CLASS
+0x004c0102 PR_ORIGINAL_AUTHOR_ENTRYID
+0x004d001e PR_ORIGINAL_AUTHOR_NAME
+0x004e0040 PR_ORIGINAL_SUBMIT_TIME
+0x004f0102 PR_REPLY_RECIPIENT_ENTRIES
+0x0050001e PR_REPLY_RECIPIENT_NAMES
+0x00510102 PR_RECEIVED_BY_SEARCH_KEY
+0x00520102 PR_RCVD_REPRESENTING_SEARCH_KEY
+0x00530102 PR_READ_RECEIPT_SEARCH_KEY
+0x00540102 PR_REPORT_SEARCH_KEY
+0x00550040 PR_ORIGINAL_DELIVERY_TIME
+0x00560102 PR_ORIGINAL_AUTHOR_SEARCH_KEY
+0x0057000b PR_MESSAGE_TO_ME
+0x0058000b PR_MESSAGE_CC_ME
+0x0059000b PR_MESSAGE_RECIP_ME
+0x005a001e PR_ORIGINAL_SENDER_NAME
+0x005b0102 PR_ORIGINAL_SENDER_ENTRYID
+0x005c0102 PR_ORIGINAL_SENDER_SEARCH_KEY
+0x005d001e PR_ORIGINAL_SENT_REPRESENTING_NAME
+0x005e0102 PR_ORIGINAL_SENT_REPRESENTING_ENTRYID
+0x005f0102 PR_ORIGINAL_SENT_REPRESENTING_SEARCH_KEY
+0x00600040 PR_START_DATE
+0x00610040 PR_END_DATE
+0x00620003 PR_OWNER_APPT_ID
+0x0063000b PR_RESPONSE_REQUESTED
+0x0064001e PR_SENT_REPRESENTING_ADDRTYPE
+0x0065001e PR_SENT_REPRESENTING_EMAIL_ADDRESS
+0x0066001e PR_ORIGINAL_SENDER_ADDRTYPE
+0x0067001e PR_ORIGINAL_SENDER_EMAIL_ADDRESS
+0x0068001e PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE
+0x0069001e PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS
+0x0070001e PR_CONVERSATION_TOPIC
+0x00710102 PR_CONVERSATION_INDEX
+0x0072001e PR_ORIGINAL_DISPLAY_BCC
+0x0073001e PR_ORIGINAL_DISPLAY_CC
+0x0074001e PR_ORIGINAL_DISPLAY_TO
+0x0075001e PR_RECEIVED_BY_ADDRTYPE
+0x0076001e PR_RECEIVED_BY_EMAIL_ADDRESS
+0x0077001e PR_RCVD_REPRESENTING_ADDRTYPE
+0x0078001e PR_RCVD_REPRESENTING_EMAIL_ADDRESS
+0x0079001e PR_ORIGINAL_AUTHOR_ADDRTYPE
+0x007a001e PR_ORIGINAL_AUTHOR_EMAIL_ADDRESS
+0x007b001e PR_ORIGINALLY_INTENDED_RECIP_ADDRTYPE
+0x007c001e PR_ORIGINALLY_INTENDED_RECIP_EMAIL_ADDRESS
+0x007d001e PR_TRANSPORT_MESSAGE_HEADERS
+0x007e0102 PR_DELEGATION
+0x007f0102 PR_TNEF_CORRELATION_KEY
+0x0c000102 PR_CONTENT_INTEGRITY_CHECK
+0x0c010003 PR_EXPLICIT_CONVERSION
+0x0c02000b PR_IPM_RETURN_REQUESTED
+0x0c030102 PR_MESSAGE_TOKEN
+0x0c040003 PR_NDR_REASON_CODE
+0x0c050003 PR_NDR_DIAG_CODE
+0x0c06000b PR_NON_RECEIPT_NOTIFICATION_REQUESTED
+0x0c070003 PR_DELIVERY_POINT
+0x0c08000b PR_ORIGINATOR_NON_DELIVERY_REPORT_REQUESTED
+0x0c090102 PR_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT
+0x0c0a000b PR_PHYSICAL_DELIVERY_BUREAU_FAX_DELIVERY
+0x0c0b0003 PR_PHYSICAL_DELIVERY_MODE
+0x0c0c0003 PR_PHYSICAL_DELIVERY_REPORT_REQUEST
+0x0c0d0102 PR_PHYSICAL_FORWARDING_ADDRESS
+0x0c0e000b PR_PHYSICAL_FORWARDING_ADDRESS_REQUESTED
+0x0c0f000b PR_PHYSICAL_FORWARDING_PROHIBITED
+0x0c100102 PR_PHYSICAL_RENDITION_ATTRIBUTES
+0x0c110102 PR_PROOF_OF_DELIVERY
+0x0c12000b PR_PROOF_OF_DELIVERY_REQUESTED
+0x0c130102 PR_RECIPIENT_CERTIFICATE
+0x0c14001e PR_RECIPIENT_NUMBER_FOR_ADVICE
+0x0c150003 PR_RECIPIENT_TYPE
+0x0c160003 PR_REGISTERED_MAIL_TYPE
+0x0c17000b PR_REPLY_REQUESTED
+0x0c180003 PR_REQUESTED_DELIVERY_METHOD
+0x0c190102 PR_SENDER_ENTRYID
+0x0c1a001e PR_SENDER_NAME
+0x0c1b001e PR_SUPPLEMENTARY_INFO
+0x0c1c0003 PR_TYPE_OF_MTS_USER
+0x0c1d0102 PR_SENDER_SEARCH_KEY
+0x0c1e001e PR_SENDER_ADDRTYPE
+0x0c1f001e PR_SENDER_EMAIL_ADDRESS
+0x0c200003 PR_NDR_STATUS_CODE
+0x0e000014 PR_CURRENT_VERSION
+0x0e01000b PR_DELETE_AFTER_SUBMIT
+0x0e02001e PR_DISPLAY_BCC
+0x0e03001e PR_DISPLAY_CC
+0x0e04001e PR_DISPLAY_TO
+0x0e05001e PR_PARENT_DISPLAY
+0x0e060040 PR_MESSAGE_DELIVERY_TIME
+0x0e070003 PR_MESSAGE_FLAGS
+0x0e080003 PR_MESSAGE_SIZE
+0x0e080014 PR_MESSAGE_SIZE_EXTENDED
+0x0e090102 PR_PARENT_ENTRYID
+0x0e0a0102 PR_SENTMAIL_ENTRYID
+0x0e0c000b PR_CORRELATE
+0x0e0d0102 PR_CORRELATE_MTSID
+0x0e0e000b PR_DISCRETE_VALUES
+0x0e0f000b PR_RESPONSIBILITY
+0x0e100003 PR_SPOOLER_STATUS
+0x0e110003 PR_TRANSPORT_STATUS
+0x0e12000d PR_MESSAGE_RECIPIENTS
+0x0e13000d PR_MESSAGE_ATTACHMENTS
+0x0e140003 PR_SUBMIT_FLAGS
+0x0e150003 PR_RECIPIENT_STATUS
+0x0e160003 PR_TRANSPORT_KEY
+0x0e170003 PR_MSG_STATUS
+0x0e180003 PR_MESSAGE_DOWNLOAD_TIME
+0x0e190014 PR_CREATION_VERSION
+0x0e1a0014 PR_MODIFY_VERSION
+0x0e1b000b PR_HASATTACH
+0x0e1c0003 PR_BODY_CRC
+0x0e1d001e PR_NORMALIZED_SUBJECT
+0x0e1f000b PR_RTF_IN_SYNC
+0x0e200003 PR_ATTACH_SIZE
+0x0e210003 PR_ATTACH_NUM
+0x0e22000b PR_PREPROCESS
+0x0e230003 PR_INTERNET_ARTICLE_NUMBER
+0x0e24001e PR_NEWSGROUP_NAME
+0x0e250102 PR_ORIGINATING_MTA_CERTIFICATE
+0x0e260102 PR_PROOF_OF_SUBMISSION
+0x0e270102 PR_NT_SECURITY_DESCRIPTOR
+0x0e580102 PR_CREATOR_SID
+0x0e590102 PR_LAST_MODIFIER_SID
+0x0e5e0048 PR_MIME_HANDLER_CLASSIDS
+0x0e610003 PR_URL_COMP_NAME_POSTFIX
+0x0e62000b PR_URL_COMP_NAME_SET
+0x0e630003 PR_SUBFOLDER_CT
+0x0e640003 PR_DELETED_SUBFOLDER_CT
+0x0e660040 PR_DELETE_TIME
+0x0e670102 PR_AGE_LIMIT
+0x0e790003 PR_TRUST_SENDER
+0x0e960102 PR_ATTACH_VIRUS_SCAN_INFO
+0x0ff40003 PR_ACCESS PidTagAccess
+0x0ff50003 PR_ROW_TYPE
+0x0ff60102 PR_INSTANCE_KEY
+0x0ff70003 PR_ACCESS_LEVEL
+0x0ff80102 PR_MAPPING_SIGNATURE
+0x0ff90102 PR_RECORD_KEY
+0x0ffa0102 PR_STORE_RECORD_KEY
+0x0ffb0102 PR_STORE_ENTRYID
+0x0ffc0102 PR_MINI_ICON
+0x0ffd0102 PR_ICON
+0x0ffe0003 PR_OBJECT_TYPE
+0x0fff0102 PR_ENTRYID
+0x1000001e PR_BODY
+0x1001001e PR_REPORT_TEXT
+0x10020102 PR_ORIGINATOR_AND_DL_EXPANSION_HISTORY
+0x10030102 PR_REPORTING_DL_NAME
+0x10040102 PR_REPORTING_MTA_CERTIFICATE
+0x10060003 PR_RTF_SYNC_BODY_CRC
+0x10070003 PR_RTF_SYNC_BODY_COUNT
+0x1008001e PR_RTF_SYNC_BODY_TAG
+0x10090102 PR_RTF_COMPRESSED
+0x10100003 PR_RTF_SYNC_PREFIX_COUNT
+0x10110003 PR_RTF_SYNC_TRAILING_COUNT
+0x10120102 PR_ORIGINALLY_INTENDED_RECIP_ENTRYID
+0x1013001e PR_BODY_HTML
+0x10130102 PR_HTML
+0x1030001e PR_INTERNET_APPROVED
+0x1031001e PR_INTERNET_CONTROL
+0x1032001e PR_INTERNET_DISTRIBUTION
+0x1033001e PR_INTERNET_FOLLOWUP_TO
+0x10340003 PR_INTERNET_LINES
+0x1035001e PR_INTERNET_MESSAGE_ID
+0x1036001e PR_INTERNET_NEWSGROUPS
+0x1037001e PR_INTERNET_ORGANIZATION
+0x1038001e PR_INTERNET_NNTP_PATH
+0x1039001e PR_INTERNET_REFERENCES
+0x103a001e PR_SUPERSEDES
+0x103b0102 PR_POST_FOLDER_ENTRIES
+0x103c001e PR_POST_FOLDER_NAMES
+0x103d0102 PR_POST_REPLY_FOLDER_ENTRIES
+0x103e001e PR_POST_REPLY_FOLDER_NAMES
+0x103f0102 PR_POST_REPLY_DENIED
+0x1040001e PR_NNTP_XREF
+0x1041001e PR_INTERNET_PRECEDENCE
+0x1042001e PR_IN_REPLY_TO_ID
+0x1043001e PR_LIST_HELP
+0x1044001e PR_LIST_SUBSCRIBE
+0x1045001e PR_LIST_UNSUBSCRIBE
+0x10800003 PR_ICON_INDEX
+0x10810003 PR_ACTION_FLAG
+0x10820040 PR_ACTION_DATE
+0x10900003 PR_FLAG_STATUS
+0x10910040 PR_FLAG_COMPLETE
+0x10c00102 PR_SMTP_TEMP_TBL_DATA
+0x10c10003 PR_SMTP_TEMP_TBL_DATA_2
+0x10c20102 PR_SMTP_TEMP_TBL_DATA_3
+0x10c30040 PR_CAL_START_TIME
+0x10c40040 PR_CAL_END_TIME
+0x10c50040 PR_CAL_RECURRING_ID
+0x10c6001e PR_DAV_SUBMIT_DATA
+0x10c70003 PR_CDO_EXPANSION_INDEX
+0x10c80102 PR_IFS_INTERNAL_DATA
+0x10ca0040 PR_CAL_REMINDER_NEXT_TIME
+0x10f1001e PR_OWA_URL
+0x10f2000b PR_DISABLE_FULL_FIDELITY
+0x10f3001e PR_URL_COMP_NAME
+0x10f4000b PR_ATTR_HIDDEN
+0x10f5000b PR_ATTR_SYSTEM
+0x10f6000b PR_ATTR_READONLY
+0x11000102 PR_P1_CONTENT
+0x11010102 PR_P1_CONTENT_TYPE
+0x30000003 PR_ROWID
+0x3001001e PR_DISPLAY_NAME PidTagDisplayName
+0x3002001e PR_ADDRTYPE
+0x3003001e PR_EMAIL_ADDRESS
+0x3004001e PR_COMMENT
+0x30050003 PR_DEPTH
+0x3006001e PR_PROVIDER_DISPLAY
+0x30070040 PR_CREATION_TIME
+0x30080040 PR_LAST_MODIFICATION_TIME
+0x30090003 PR_RESOURCE_FLAGS
+0x300a001e PR_PROVIDER_DLL_NAME
+0x300b0102 PR_SEARCH_KEY
+0x300c0102 PR_PROVIDER_UID
+0x300d0003 PR_PROVIDER_ORDINAL
+0x3301001e PR_FORM_VERSION
+0x33020048 PR_FORM_CLSID
+0x3303001e PR_FORM_CONTACT_NAME
+0x3304001e PR_FORM_CATEGORY
+0x3305001e PR_FORM_CATEGORY_SUB
+0x33061003 PR_FORM_HOST_MAP
+0x3307000b PR_FORM_HIDDEN
+0x3308001e PR_FORM_DESIGNER_NAME
+0x33090048 PR_FORM_DESIGNER_GUID
+0x330a0003 PR_FORM_MESSAGE_BEHAVIOR
+0x3400000b PR_DEFAULT_STORE
+0x340d0003 PR_STORE_SUPPORT_MASK
+0x340e0003 PR_STORE_STATE
+0x34100102 PR_IPM_SUBTREE_SEARCH_KEY
+0x34110102 PR_IPM_OUTBOX_SEARCH_KEY
+0x34120102 PR_IPM_WASTEBASKET_SEARCH_KEY
+0x34130102 PR_IPM_SENTMAIL_SEARCH_KEY
+0x34140102 PR_MDB_PROVIDER
+0x3415000d PR_RECEIVE_FOLDER_SETTINGS
+0x35df0003 PR_VALID_FOLDER_MASK
+0x35e00102 PR_IPM_SUBTREE_ENTRYID
+0x35e20102 PR_IPM_OUTBOX_ENTRYID
+0x35e30102 PR_IPM_WASTEBASKET_ENTRYID
+0x35e40102 PR_IPM_SENTMAIL_ENTRYID
+0x35e50102 PR_VIEWS_ENTRYID
+0x35e60102 PR_COMMON_VIEWS_ENTRYID
+0x35e70102 PR_FINDER_ENTRYID
+0x36000003 PR_CONTAINER_FLAGS
+0x36010003 PR_FOLDER_TYPE
+0x36020003 PR_CONTENT_COUNT PidTagContentCount
+0x36030003 PR_CONTENT_UNREAD PidTagContentUnreadCount
+0x3604000d PR_CREATE_TEMPLATES
+0x3605000d PR_DETAILS_TABLE
+0x3607000d PR_SEARCH
+0x3609000b PR_SELECTABLE
+0x360a000b PR_SUBFOLDERS PidTagSubFolders
+0x360b0003 PR_STATUS
+0x360c001e PR_ANR
+0x360d1003 PR_CONTENTS_SORT_ORDER
+0x360e000d PR_CONTAINER_HIERARCHY
+0x360f000d PR_CONTAINER_CONTENTS
+0x3610000d PR_FOLDER_ASSOCIATED_CONTENTS
+0x36110102 PR_DEF_CREATE_DL
+0x36120102 PR_DEF_CREATE_MAILUSER
+0x3613001e PR_CONTAINER_CLASS
+0x36140014 PR_CONTAINER_MODIFY_VERSION
+0x36150102 PR_AB_PROVIDER_ID
+0x36160102 PR_DEFAULT_VIEW_ENTRYID
+0x36170003 PR_ASSOC_CONTENT_COUNT
+0x361c0102 PR_PACKED_NAME_PROPS
+0x36d00102 PR_IPM_APPOINTMENT_ENTRYID PidTagIpmAppointmentEntryId
+0x36d10102 PR_IPM_CONTACT_ENTRYID PidTagIpmContactEntryId
+0x36d20102 PR_IPM_JOURNAL_ENTRYID PidTagIpmJournalEntryId
+0x36d30102 PR_IPM_NOTE_ENTRYID PidTagIpmNoteEntryId
+0x36d40102 PR_IPM_TASK_ENTRYID PidTagIpmTaskEntryId
+0x36d50102 PR_REMINDERS_ONLINE_ENTRYID PidTagRemindersOnlineEntryId
+0x36d60102 PR_REMINDERS_OFFLINE_ENTRYID
+0x36d70102 PR_IPM_DRAFTS_ENTRYID PidTagIpmDraftsEntryId
+0x36d81102 PR_OUTLOOK_2003_ENTRYIDS
+0x36df0102 PR_FOLDER_WEBVIEWINFO
+0x36e00102 PR_FOLDER_XVIEWINFO_E
+0x36e10003 PR_FOLDER_VIEWS_ONLY
+0x36e41102 PR_FREEBUSY_ENTRYIDS
+0x36e5001e PR_DEF_MSG_CLASS
+0x36e6001e PR_DEF_FORM_NAME
+0x36e9000b PR_GENERATE_EXCHANGE_VIEWS
+0x36eb0102 PR_FOLDER_VIEWLIST
+0x36ec0003 PR_AGING_PERIOD
+0x36ee0003 PR_AGING_GRANULARITY
+0x37000102 PR_ATTACHMENT_X400_PARAMETERS
+0x3701000d PR_ATTACH_DATA_OBJ
+0x37010102 PR_ATTACH_DATA_BIN
+0x37020102 PR_ATTACH_ENCODING
+0x3703001e PR_ATTACH_EXTENSION
+0x3704001e PR_ATTACH_FILENAME
+0x37050003 PR_ATTACH_METHOD
+0x3707001e PR_ATTACH_LONG_FILENAME
+0x3708001e PR_ATTACH_PATHNAME
+0x37090102 PR_ATTACH_RENDERING
+0x370a0102 PR_ATTACH_TAG
+0x370b0003 PR_RENDERING_POSITION
+0x370c001e PR_ATTACH_TRANSPORT_NAME
+0x370d001e PR_ATTACH_LONG_PATHNAME
+0x370e001e PR_ATTACH_MIME_TAG
+0x370f0102 PR_ATTACH_ADDITIONAL_INFO
+0x3712001e PR_ATTACH_CONTENT_ID
+0x3713001e PR_ATTACH_CONTENT_LOCATION
+0x37140003 PR_ATTACH_FLAGS
+0x3716001e PR_ATTACH_CONTENT_DISPOSITION
+0x38800102 PR_SYNCEVENT_SUPPRESS_GUID
+0x39000003 PR_DISPLAY_TYPE
+0x39020102 PR_TEMPLATEID
+0x39040102 PR_PRIMARY_CAPABILITY
+0x39fe001e PR_SMTP_ADDRESS
+0x39ff001e PR_7BIT_DISPLAY_NAME
+0x3a00001e PR_ACCOUNT
+0x3a010102 PR_ALTERNATE_RECIPIENT
+0x3a02001e PR_CALLBACK_TELEPHONE_NUMBER
+0x3a03000b PR_CONVERSION_PROHIBITED
+0x3a04000b PR_DISCLOSE_RECIPIENTS
+0x3a05001e PR_GENERATION
+0x3a06001e PR_GIVEN_NAME
+0x3a07001e PR_GOVERNMENT_ID_NUMBER
+0x3a08001e PR_OFFICE_TELEPHONE_NUMBER
+0x3a09001e PR_HOME_TELEPHONE_NUMBER
+0x3a0a001e PR_INITIALS
+0x3a0b001e PR_KEYWORD
+0x3a0c001e PR_LANGUAGE
+0x3a0d001e PR_LOCATION
+0x3a0e000b PR_MAIL_PERMISSION
+0x3a0f001e PR_MHS_COMMON_NAME
+0x3a10001e PR_ORGANIZATIONAL_ID_NUMBER
+0x3a11001e PR_SURNAME
+0x3a120102 PR_ORIGINAL_ENTRYID
+0x3a13001e PR_ORIGINAL_DISPLAY_NAME
+0x3a140102 PR_ORIGINAL_SEARCH_KEY
+0x3a15001e PR_POSTAL_ADDRESS
+0x3a16001e PR_COMPANY_NAME
+0x3a17001e PR_TITLE
+0x3a18001e PR_DEPARTMENT_NAME
+0x3a19001e PR_OFFICE_LOCATION
+0x3a1a001e PR_PRIMARY_TELEPHONE_NUMBER
+0x3a1b001e PR_OFFICE2_TELEPHONE_NUMBER
+0x3a1c001e PR_MOBILE_TELEPHONE_NUMBER
+0x3a1d001e PR_RADIO_TELEPHONE_NUMBER
+0x3a1e001e PR_CAR_TELEPHONE_NUMBER
+0x3a1f001e PR_OTHER_TELEPHONE_NUMBER
+0x3a20001e PR_TRANSMITTABLE_DISPLAY_NAME
+0x3a21001e PR_PAGER_TELEPHONE_NUMBER
+0x3a220102 PR_USER_CERTIFICATE
+0x3a23001e PR_PRIMARY_FAX_NUMBER
+0x3a24001e PR_BUSINESS_FAX_NUMBER
+0x3a25001e PR_HOME_FAX_NUMBER
+0x3a26001e PR_COUNTRY
+0x3a27001e PR_LOCALITY
+0x3a28001e PR_STATE_OR_PROVINCE
+0x3a29001e PR_STREET_ADDRESS
+0x3a2a001e PR_POSTAL_CODE
+0x3a2b001e PR_POST_OFFICE_BOX
+0x3a2c001e PR_TELEX_NUMBER
+0x3a2d001e PR_ISDN_NUMBER
+0x3a2e001e PR_ASSISTANT_TELEPHONE_NUMBER
+0x3a2f001e PR_HOME2_TELEPHONE_NUMBER
+0x3a30001e PR_ASSISTANT
+0x3a40000b PR_SEND_RICH_INFO
+0x3a410040 PR_WEDDING_ANNIVERSARY
+0x3a420040 PR_BIRTHDAY
+0x3a43001e PR_HOBBIES
+0x3a44001e PR_MIDDLE_NAME
+0x3a45001e PR_DISPLAY_NAME_PREFIX
+0x3a46001e PR_PROFESSION
+0x3a47001e PR_PREFERRED_BY_NAME
+0x3a48001e PR_SPOUSE_NAME
+0x3a49001e PR_COMPUTER_NETWORK_NAME
+0x3a4a001e PR_CUSTOMER_ID
+0x3a4b001e PR_TTYTDD_PHONE_NUMBER
+0x3a4c001e PR_FTP_SITE
+0x3a4d0002 PR_GENDER
+0x3a4e001e PR_MANAGER_NAME
+0x3a4f001e PR_NICKNAME
+0x3a50001e PR_PERSONAL_HOME_PAGE
+0x3a51001e PR_BUSINESS_HOME_PAGE
+0x3a520048 PR_CONTACT_VERSION
+0x3a531102 PR_CONTACT_ENTRYIDS
+0x3a54101e PR_CONTACT_ADDRTYPES
+0x3a550003 PR_CONTACT_DEFAULT_ADDRESS_INDEX
+0x3a56101e PR_CONTACT_EMAIL_ADDRESSES
+0x3a57001e PR_COMPANY_MAIN_PHONE_NUMBER
+0x3a58101e PR_CHILDRENS_NAMES
+0x3a59001e PR_HOME_ADDRESS_CITY
+0x3a5a001e PR_HOME_ADDRESS_COUNTRY
+0x3a5b001e PR_HOME_ADDRESS_POSTAL_CODE
+0x3a5c001e PR_HOME_ADDRESS_STATE_OR_PROVINCE
+0x3a5d001e PR_HOME_ADDRESS_STREET
+0x3a5e001e PR_HOME_ADDRESS_POST_OFFICE_BOX
+0x3a5f001e PR_OTHER_ADDRESS_CITY
+0x3a60001e PR_OTHER_ADDRESS_COUNTRY
+0x3a61001e PR_OTHER_ADDRESS_POSTAL_CODE
+0x3a62001e PR_OTHER_ADDRESS_STATE_OR_PROVINCE
+0x3a63001e PR_OTHER_ADDRESS_STREET
+0x3a64001e PR_OTHER_ADDRESS_POST_OFFICE_BOX
+0x3a701102 PR_USER_X509_CERTIFICATE
+0x3a710003 PR_SEND_INTERNET_ENCODING
+0x3d000102 PR_STORE_PROVIDERS
+0x3d010102 PR_AB_PROVIDERS
+0x3d020102 PR_TRANSPORT_PROVIDERS
+0x3d04000b PR_DEFAULT_PROFILE
+0x3d051102 PR_AB_SEARCH_PATH
+0x3d060102 PR_AB_DEFAULT_DIR
+0x3d070102 PR_AB_DEFAULT_PAB
+0x3d080102 PR_FILTERING_HOOKS
+0x3d09001e PR_SERVICE_NAME
+0x3d0a001e PR_SERVICE_DLL_NAME
+0x3d0b001e PR_SERVICE_ENTRY_NAME
+0x3d0c0102 PR_SERVICE_UID
+0x3d0d0102 PR_SERVICE_EXTRA_UIDS
+0x3d0e0102 PR_SERVICES
+0x3d0f101e PR_SERVICE_SUPPORT_FILES
+0x3d10101e PR_SERVICE_DELETE_FILES
+0x3d110102 PR_AB_SEARCH_PATH_UPDATE
+0x3d12001e PR_PROFILE_NAME
+0x3d13001e PR_SERVICE_INSTALL_ID
+0x3d210102 PR_ADMIN_SECURITY_DESCRIPTOR
+0x3e00001e PR_IDENTITY_DISPLAY
+0x3e010102 PR_IDENTITY_ENTRYID
+0x3e020003 PR_RESOURCE_METHODS
+0x3e030003 PR_RESOURCE_TYPE
+0x3e040003 PR_STATUS_CODE
+0x3e050102 PR_IDENTITY_SEARCH_KEY
+0x3e060102 PR_OWN_STORE_ENTRYID
+0x3e07001e PR_RESOURCE_PATH
+0x3e08001e PR_STATUS_STRING
+0x3e09000b PR_X400_DEFERRED_DELIVERY_CANCEL
+0x3e0a0102 PR_HEADER_FOLDER_ENTRYID
+0x3e0b0003 PR_REMOTE_PROGRESS
+0x3e0c001e PR_REMOTE_PROGRESS_TEXT
+0x3e0d000b PR_REMOTE_VALIDATE_OK
+0x3f000003 PR_CONTROL_FLAGS
+0x3f010102 PR_CONTROL_STRUCTURE
+0x3f020003 PR_CONTROL_TYPE
+0x3f030003 PR_DELTAX
+0x3f040003 PR_DELTAY
+0x3f050003 PR_XPOS
+0x3f060003 PR_YPOS
+0x3f070102 PR_CONTROL_ID
+0x3f080003 PR_INITIAL_DETAILS_PANE
+0x3f800014 PR_DID
+0x3f810014 PR_SEQID
+0x3f820014 PR_DRAFTID
+0x3f830040 PR_CHECK_IN_TIME
+0x3f84001e PR_CHECK_IN_COMMENT
+0x3f850003 PR_VERSION_OP_CODE
+0x3f860102 PR_VERSION_OP_DATA
+0x3f870003 PR_VERSION_SEQUENCE_NUMBER
+0x3f880014 PR_ATTACH_ID
+0x3f8d001e PR_PKM_DOC_STATUS
+0x3f8e101e PR_MV_PKM_OPERATION_REQ
+0x3f8f001e PR_PKM_DOC_INTERNAL_STATE
+0x3f900002 PR_VERSIONING_FLAGS
+0x3f910102 PR_PKM_LAST_UNAPPROVED_VID
+0x3f92101e PR_MV_PKM_VERSION_LABELS
+0x3f93101e PR_MV_PKM_VERSION_STATUS
+0x3f940102 PR_PKM_INTERNAL_DATA
+0x3fc90102 PR_LAST_CONFLICT
+0x3fca0102 PR_CONFLICT_MSG_KEY
+0x3fd00102 PR_REPL_HEADER
+0x3fd10102 PR_REPL_STATUS
+0x3fd20102 PR_REPL_CHANGES
+0x3fd30102 PR_REPL_RGM
+0x3fd40102 PR_RMI
+0x3fd50102 PR_INTERNAL_POST_REPLY
+0x3fd60040 PR_NTSD_MODIFICATION_TIME
+0x3fd8001e PR_PREVIEW_UNREAD
+0x3fd9001e PR_PREVIEW
+0x3fda001e PR_ABSTRACT
+0x3fdb0003 PR_DL_REPORT_FLAGS
+0x3fdc0102 PR_BILATERAL_INFO
+0x3fdd0003 PR_MSG_BODY_ID
+0x3fde0003 PR_INTERNET_CPID
+0x3fdf0003 PR_AUTO_RESPONSE_SUPPRESS
+0x3fe0000d PR_ACL_TABLE
+0x3fe00102 PR_ACL_DATA
+0x3fe1000d PR_RULES_TABLE
+0x3fe10102 PR_RULES_DATA
+0x3fe20003 PR_FOLDER_DESIGN_FLAGS
+0x3fe3000b PR_DELEGATED_BY_RULE
+0x3fe4000b PR_DESIGN_IN_PROGRESS
+0x3fe5000b PR_SECURE_ORIGINATION
+0x3fe6000b PR_PUBLISH_IN_ADDRESS_BOOK
+0x3fe70003 PR_RESOLVE_METHOD
+0x3fe8001e PR_ADDRESS_BOOK_DISPLAY_NAME
+0x3fe90003 PR_EFORMS_LOCALE_ID
+0x3fea000b PR_HAS_DAMS
+0x3feb0003 PR_DEFERRED_SEND_NUMBER
+0x3fec0003 PR_DEFERRED_SEND_UNITS
+0x3fed0003 PR_EXPIRY_NUMBER
+0x3fee0003 PR_EXPIRY_UNITS
+0x3fef0040 PR_DEFERRED_SEND_TIME
+0x3ff00102 PR_CONFLICT_ENTRYID
+0x3ff10003 PR_MESSAGE_LOCALE_ID
+0x3ff20102 PR_RULE_TRIGGER_HISTORY
+0x3ff30102 PR_MOVE_TO_STORE_ENTRYID
+0x3ff40102 PR_MOVE_TO_FOLDER_ENTRYID
+0x3ff50003 PR_STORAGE_QUOTA_LIMIT
+0x3ff60003 PR_EXCESS_STORAGE_USED
+0x3ff7001e PR_SVR_GENERATING_QUOTA_MSG
+0x3ff8001e PR_CREATOR_NAME
+0x3ff90102 PR_CREATOR_ENTRYID
+0x3ffa001e PR_LAST_MODIFIER_NAME
+0x3ffb0102 PR_LAST_MODIFIER_ENTRYID
+0x3ffc001e PR_REPLY_RECIPIENT_SMTP_PROXIES
+0x3ffd0003 PR_MESSAGE_CODEPAGE
+0x3ffe0102 PR_EXTENDED_ACL_DATA
+0x3fff000b PR_FROM_I_HAVE
+0x40000003 PR_NEW_ATTACH
+0x40010003 PR_START_EMBED
+0x40020003 PR_END_EMBED
+0x40030003 PR_START_RECIP
+0x40040003 PR_END_RECIP
+0x40050003 PR_END_CC_RECIP
+0x40060003 PR_END_BCC_RECIP
+0x40070003 PR_END_P1_RECIP
+0x40090003 PR_START_TOP_FLD
+0x400a0003 PR_START_SUB_FLD
+0x400b0003 PR_END_FOLDER
+0x400c0003 PR_START_MESSAGE
+0x400d0003 PR_END_MESSAGE
+0x400e0003 PR_END_ATTACH
+0x400f0003 PR_EC_WARNING
+0x40100003 PR_START_FAI_MSG
+0x40110102 PR_NEW_FX_FOLDER
+0x40120003 PR_INCR_SYNC_CHG
+0x40130003 PR_INCR_SYNC_DEL
+0x40140003 PR_INCR_SYNC_END
+0x40150003 PR_INCR_SYNC_MSG
+0x40160003 PR_FX_DEL_PROP
+0x40170003 PR_IDSET_GIVEN
+0x40190003 PR_SENDER_FLAGS
+0x401a0003 PR_SENT_REPRESENTING_FLAGS
+0x401b0003 PR_RCVD_BY_FLAGS
+0x401c0003 PR_RCVD_REPRESENTING_FLAGS
+0x401d0003 PR_ORIGINAL_SENDER_FLAGS
+0x401e0003 PR_ORIGINAL_SENT_REPRESENTING_FLAGS
+0x401f0003 PR_REPORT_FLAGS
+0x40200003 PR_READ_RECEIPT_FLAGS
+0x4021000b PR_SOFT_DELETES
+0x402c0102 PR_MESSAGE_SUBMISSION_ID_FROM_CLIENT
+0x4030001e PR_SENDER_SIMPLE_DISP_NAME
+0x4031001e PR_SENT_REPRESENTING_SIMPLE_DISP_NAME
+0x4038001e PR_CREATOR_SIMPLE_DISP_NAME
+0x403d001e PR_ORG_ADDR_TYPE
+0x403e001e PR_ORG_EMAIL_ADDR
+0x40590003 PR_CREATOR_FLAGS
+0x405a0003 PR_MODIFIER_FLAGS
+0x405b0003 PR_ORIGINATOR_FLAGS
+0x405c0003 PR_REPORT_DESTINATION_FLAGS
+0x405d0003 PR_ORIGINAL_AUTHOR_FLAGS
+0x40610102 PR_ORIGINATOR_SEARCH_KEY
+0x40640102 PR_REPORT_DESTINATION_SEARCH_KEY
+0x40650003 PR_ER_FLAG
+0x40680102 PR_INTERNET_SUBJECT
+0x40690102 PR_INTERNET_SENT_REPRESENTING_NAME
+0x40760003 PR_CONTENT_FILTER_SCL
+0x59020003 PR_INET_MAIL_OVERRIDE_FORMAT
+0x59090003 PR_MSG_EDITOR_FORMAT
+0x5ff6001e PR_RECIPIENT_DISPLAY_NAME
+0x5ff70102 PR_RECIPIENT_ENTRYID
+0x5ffb0040 PR_RECIPIENT_TRACKSTATUS_ME
+0x5ffd0003 PR_RECIPIENTS_FLAGS
+0x5fff0003 PR_RECIPIENT_TRACKSTATUS
+0x60010003 PR_DOTSTUFF_STATE
+0x65a00014 PR_RULE_SERVER_RULE_ID
+0x65c20102 PR_REPLY_TEMPLATE_ID
+0x65e00102 PR_SOURCE_KEY
+0x65e10102 PR_PARENT_SOURCE_KEY
+0x65e20102 PR_CHANGE_KEY
+0x65e30102 PR_PREDECESSOR_CHANGE_LIST
+0x65e40003 PR_SYNCHRONIZE_FLAGS
+0x65e5000b PR_AUTO_ADD_NEW_SUBS
+0x65e6000b PR_NEW_SUBS_GET_AUTO_ADD
+0x65e7001e PR_MESSAGE_SITE_NAME
+0x65e8000b PR_MESSAGE_PROCESSED
+0x65e90003 PR_RULE_MSG_STATE
+0x65ea0003 PR_RULE_MSG_USER_FLAGS
+0x65eb001e PR_RULE_MSG_PROVIDER
+0x65ec001e PR_RULE_MSG_NAME
+0x65ed0003 PR_RULE_MSG_LEVEL
+0x65ee0102 PR_RULE_MSG_PROVIDER_DATA
+0x65ef0102 PR_RULE_MSG_ACTIONS
+0x65f00102 PR_RULE_MSG_CONDITION
+0x65f10003 PR_RULE_MSG_CONDITION_LCID
+0x65f20002 PR_RULE_MSG_VERSION
+0x65f30003 PR_RULE_MSG_SEQUENCE
+0x65f4000b PR_PREVENT_MSG_CREATE
+0x65f50040 PR_IMAP_INTERNAL_DATE
+0x66000003 PR_PROFILE_VERSION
+0x66010003 PR_PROFILE_CONFIG_FLAGS
+0x6602001e PR_PROFILE_HOME_SERVER
+0x6603001e PR_PROFILE_USER
+0x66040003 PR_PROFILE_CONNECT_FLAGS
+0x66050003 PR_PROFILE_TRANSPORT_FLAGS
+0x66060003 PR_PROFILE_UI_STATE
+0x6607001e PR_PROFILE_UNRESOLVED_NAME
+0x6608001e PR_PROFILE_UNRESOLVED_SERVER
+0x66090003 PR_PROFILE_OPEN_FLAGS
+0x6609001e PR_PROFILE_BINDING_ORDER
+0x660a0003 PR_PROFILE_TYPE
+0x660b001e PR_PROFILE_MAILBOX
+0x660c001e PR_PROFILE_SERVER
+0x660d0003 PR_PROFILE_MAX_RESTRICT
+0x660e001e PR_PROFILE_AB_FILES_PATH
+0x660f001e PR_PROFILE_FAVFLD_DISPLAY_NAME
+0x6610001e PR_PROFILE_OFFLINE_STORE_PATH
+0x66110102 PR_PROFILE_OFFLINE_INFO
+0x6612001e PR_PROFILE_HOME_SERVER_DN
+0x6613101e PR_PROFILE_HOME_SERVER_ADDRS
+0x6614001e PR_PROFILE_SERVER_DN
+0x6615001e PR_PROFILE_FAVFLD_COMMENT
+0x6616001e PR_PROFILE_ALLPUB_DISPLAY_NAME
+0x6617001e PR_PROFILE_ALLPUB_COMMENT
+0x66180003 PR_DISABLE_WINSOCK
+0x6618000b PR_IN_TRANSIT
+0x66190003 PR_PROFILE_AUTH_PACKAGE
+0x66190102 PR_USER_ENTRYID
+0x661a001e PR_USER_NAME
+0x661b0102 PR_MAILBOX_OWNER_ENTRYID
+0x661c001e PR_MAILBOX_OWNER_NAME
+0x661d000b PR_OOF_STATE
+0x661e0102 PR_SCHEDULE_FOLDER_ENTRYID
+0x661f0102 PR_IPM_DAF_ENTRYID
+0x66200102 PR_NON_IPM_SUBTREE_ENTRYID
+0x66210102 PR_EFORMS_REGISTRY_ENTRYID
+0x66220102 PR_SPLUS_FREE_BUSY_ENTRYID
+0x6623001e PR_HIERARCHY_SERVER
+0x66230102 PR_OFFLINE_ADDRBOOK_ENTRYID
+0x66240102 PR_EFORMS_FOR_LOCALE_ENTRYID
+0x66250102 PR_FREE_BUSY_FOR_LOCAL_SITE_ENTRYID
+0x66260102 PR_ADDRBOOK_FOR_LOCAL_SITE_ENTRYID
+0x66270102 PR_OFFLINE_MESSAGE_ENTRYID
+0x66280102 PR_GW_MTSIN_ENTRYID
+0x66290102 PR_GW_MTSOUT_ENTRYID
+0x662a000b PR_TRANSFER_ENABLED
+0x662b0102 PR_TEST_LINE_SPEED
+0x662c000d PR_HIERARCHY_SYNCHRONIZER
+0x662d000d PR_CONTENTS_SYNCHRONIZER
+0x662e000d PR_COLLECTOR
+0x662f000d PR_FAST_TRANSFER
+0x66300102 PR_IPM_FAVORITES_ENTRYID
+0x66310102 PR_IPM_PUBLIC_FOLDERS_ENTRYID
+0x6632000b PR_STORE_OFFLINE
+0x6634000d PR_CHANGE_ADVISOR
+0x6635001e PR_FAVORITES_DEFAULT_NAME
+0x66360102 PR_SYS_CONFIG_FOLDER_ENTRYID
+0x66370048 PR_CHANGE_NOTIFICATION_GUID
+0x66380003 PR_FOLDER_CHILD_COUNT
+0x66390003 PR_RIGHTS
+0x663a000b PR_HAS_RULES
+0x663b0102 PR_ADDRESS_BOOK_ENTRYID
+0x663c0102 PR_PUBLIC_FOLDER_ENTRYID
+0x663d0003 PR_OFFLINE_FLAGS
+0x663e0003 PR_HIERARCHY_CHANGE_NUM
+0x663f000b PR_HAS_MODERATOR_RULES
+0x66400003 PR_DELETED_MSG_COUNT
+0x66410003 PR_DELETED_FOLDER_COUNT
+0x66420040 PR_OLDEST_DELETED_ON
+0x66430003 PR_DELETED_ASSOC_MSG_COUNT
+0x6644001e PR_REPLICA_SERVER
+0x66450102 PR_CLIENT_ACTIONS
+0x66460102 PR_DAM_ORIGINAL_ENTRYID
+0x6647000b PR_DAM_BACK_PATCHED
+0x66480003 PR_RULE_ERROR
+0x66490003 PR_RULE_ACTION_TYPE
+0x664a000b PR_HAS_NAMED_PROPERTIES
+0x664b0014 PR_REPLICA_VERSION
+0x66500003 PR_RULE_ACTION_NUMBER
+0x66510102 PR_RULE_FOLDER_ENTRYID
+0x66520102 PR_ACTIVE_USER_ENTRYID
+0x66530003 PR_0X400_ENVELOPE_TYPE
+0x66540040 PR_MSG_FOLD_TIME
+0x66550102 PR_ICS_CHANGE_KEY
+0x66580003 PR_GW_ADMIN_OPERATIONS
+0x66590102 PR_INTERNET_CONTENT
+0x665a000b PR_HAS_ATTACH_FROM_IMAIL
+0x665b001e PR_ORIGINATOR_NAME
+0x665c001e PR_ORIGINATOR_ADDR
+0x665d001e PR_ORIGINATOR_ADDRTYPE
+0x665e0102 PR_ORIGINATOR_ENTRYID
+0x665f0040 PR_ARRIVAL_TIME
+0x66600102 PR_TRACE_INFO
+0x66610102 PR_SUBJECT_TRACE_INFO
+0x66620003 PR_RECIPIENT_NUMBER
+0x66630102 PR_MTS_SUBJECT_ID
+0x6664001e PR_REPORT_DESTINATION_NAME
+0x66650102 PR_REPORT_DESTINATION_ENTRYID
+0x66660102 PR_CONTENT_SEARCH_KEY
+0x66670102 PR_FOREIGN_ID
+0x66680102 PR_FOREIGN_REPORT_ID
+0x66690102 PR_FOREIGN_SUBJECT_ID
+0x666a0102 PR_INTERNAL_TRACE_INFO
+0x666c000b PR_IN_CONFLICT
+0x66700102 PR_LONGTERM_ENTRYID_FROM_TABLE
+0x66710014 PR_MEMBER_ID
+0x6672001e PR_MEMBER_NAME
+0x66730003 PR_MEMBER_RIGHTS
+0x66740014 PR_RULE_ID
+0x66750102 PR_RULE_IDS
+0x66760003 PR_RULE_SEQUENCE
+0x66770003 PR_RULE_STATE
+0x66780003 PR_RULE_USER_FLAGS
+0x667900fd PR_RULE_CONDITION
+0x667b001e PR_PROFILE_MOAB
+0x667c001e PR_PROFILE_MOAB_GUID
+0x667d0003 PR_PROFILE_MOAB_SEQ
+0x667f1102 PR_IMPLIED_RESTRICTIONS
+0x668000fe PR_RULE_ACTIONS
+0x6681001e PR_RULE_PROVIDER
+0x6682001e PR_RULE_NAME
+0x66830003 PR_RULE_LEVEL
+0x66840102 PR_RULE_PROVIDER_DATA
+0x66850040 PR_LAST_FULL_BACKUP
+0x66870102 PR_PROFILE_ADDR_INFO
+0x66890102 PR_PROFILE_OPTIONS_DATA
+0x668a0102 PR_EVENTS_ROOT_FOLDER_ENTRYID
+0x668d001e PR_INBOUND_NEWSFEED_DN
+0x668e001e PR_OUTBOUND_NEWSFEED_DN
+0x668f0040 PR_DELETED_ON
+0x66900003 PR_REPLICATION_STYLE
+0x66910102 PR_REPLICATION_SCHEDULE
+0x66920003 PR_REPLICATION_MESSAGE_PRIORITY
+0x66930003 PR_OVERALL_MSG_AGE_LIMIT
+0x66940003 PR_REPLICATION_ALWAYS_INTERVAL
+0x66950003 PR_REPLICATION_MSG_SIZE
+0x6696000b PR_IS_NEWSGROUP_ANCHOR
+0x6697000b PR_IS_NEWSGROUP
+0x66980102 PR_REPLICA_LIST
+0x66990003 PR_OVERALL_AGE_LIMIT
+0x669a001e PR_INTERNET_CHARSET
+0x669b0014 PR_DELETED_MESSAGE_SIZE_EXTENDED
+0x669c0014 PR_DELETED_NORMAL_MESSAGE_SIZE_EXTENDED
+0x669d0014 PR_DELETED_ASSOC_MESSAGE_SIZE_EXTENDED
+0x669e000b PR_SECURE_IN_SITE
+0x66a0001e PR_NT_USER_NAME
+0x66a10003 PR_LOCALE_ID
+0x66a20040 PR_LAST_LOGON_TIME
+0x66a30040 PR_LAST_LOGOFF_TIME
+0x66a40003 PR_STORAGE_LIMIT_INFORMATION
+0x66a5001e PR_NEWSGROUP_COMPONENT
+0x66a60102 PR_NEWSFEED_INFO
+0x66a7001e PR_INTERNET_NEWSGROUP_NAME
+0x66a80003 PR_FOLDER_FLAGS
+0x66a90040 PR_LAST_ACCESS_TIME
+0x66aa0003 PR_RESTRICTION_COUNT
+0x66ab0003 PR_CATEG_COUNT
+0x66ac0003 PR_CACHED_COLUMN_COUNT
+0x66ad0003 PR_NORMAL_MSG_W_ATTACH_COUNT
+0x66ae0003 PR_ASSOC_MSG_W_ATTACH_COUNT
+0x66af0003 PR_RECIPIENT_ON_NORMAL_MSG_COUNT
+0x66b00003 PR_RECIPIENT_ON_ASSOC_MSG_COUNT
+0x66b10003 PR_ATTACH_ON_NORMAL_MSG_COUNT
+0x66b20003 PR_ATTACH_ON_ASSOC_MSG_COUNT
+0x66b30003 PR_NORMAL_MESSAGE_SIZE
+0x66b30014 PR_NORMAL_MESSAGE_SIZE_EXTENDED
+0x66b40003 PR_ASSOC_MESSAGE_SIZE
+0x66b40014 PR_ASSOC_MESSAGE_SIZE_EXTENDED
+0x66b5001e PR_FOLDER_PATHNAME
+0x66b60003 PR_OWNER_COUNT
+0x66b70003 PR_CONTACT_COUNT
+0x66c30003 PR_CODE_PAGE_ID
+0x66c40003 PR_RETENTION_AGE_LIMIT
+0x66c5000b PR_DISABLE_PERUSER_READ
+0x66c60102 PR_INTERNET_PARSE_STATE
+0x66c70102 PR_INTERNET_MESSAGE_INFO
+0x6700001e PR_PST_PATH
+0x6701000b PR_PST_REMEMBER_PW
+0x67020003 PR_OST_ENCRYPTION
+0x6703001e PR_PST_PW_SZ_OLD
+0x6704001e PR_PST_PW_SZ_NEW
+0x67050003 PR_SORT_LOCALE_ID
+0x6707001e PR_URL_NAME
+0x67090040 PR_LOCAL_COMMIT_TIME
+0x670a0040 PR_LOCAL_COMMIT_TIME_MAX
+0x670b0003 PR_DELETED_COUNT_TOTAL
+0x670c0048 PR_AUTO_RESET
+0x67100003 PR_URL_COMP_NAME_HASH
+0x67110003 PR_MSG_FOLDER_TEMPLATE_RES_2
+0x67120003 PR_RANK
+0x6713000b PR_MSG_FOLDER_TEMPLATE_RES_4
+0x6714000b PR_MSG_FOLDER_TEMPLATE_RES_5
+0x6715000b PR_MSG_FOLDER_TEMPLATE_RES_6
+0x67160102 PR_MSG_FOLDER_TEMPLATE_RES_7
+0x67170102 PR_MSG_FOLDER_TEMPLATE_RES_8
+0x67180102 PR_MSG_FOLDER_TEMPLATE_RES_9
+0x6719001e PR_MSG_FOLDER_TEMPLATE_RES_10
+0x671a001e PR_MSG_FOLDER_TEMPLATE_RES_11
+0x671b001e PR_MSG_FOLDER_TEMPLATE_RES_12
+0x671e000b PR_PF_PLATINUM_HOME_MDB
+0x671f000b PR_PF_PROXY_REQUIRED
+0x67200102 PR_INTERNET_FREE_DOC_INFO
+0x67210003 PR_PF_OVER_HARD_QUOTA_LIMIT
+0x67220003 PR_PF_MSG_SIZE_LIMIT
+0x67430003 PR_CONNECTION_MODULUS
+0x6744001e PR_DELIVER_TO_DN
+0x67460003 PR_MIME_SIZE
+0x67470014 PR_FILE_SIZE_EXTENDED
+0x67480014 PR_FID PidTagFolderId
+0x67490014 PR_PARENT_FID PidTagParentFolderId
+0x674a0014 PR_MID
+0x674b0014 PR_CATEG_ID
+0x674c0014 PR_PARENT_CATEG_ID
+0x674d0014 PR_INST_ID
+0x674e0003 PR_INSTANCE_NUM
+0x674f0014 PR_ADDRBOOK_MID
+0x67500003 PR_ICS_NOTIF
+0x67510003 PR_ARTICLE_NUM_NEXT
+0x67520003 PR_IMAP_LAST_ARTICLE_ID
+0x6753000b PR_NOT_822_RENDERABLE
+0x67580102 PR_LTID
+0x67590102 PR_CN_EXPORT
+0x675a0102 PR_PCL_EXPORT
+0x675b1102 PR_CN_MV_EXPORT
+0x67790003 PR_PF_QUOTA_STYLE
+0x677b0003 PR_PF_STORAGE_QUOTA
+0x67830003 PR_SEARCH_FLAGS
+0x67aa000b PR_ASSOCIATED
+0x67f00102 PR_PROFILE_SECURE_MAILBOX
+0x6800001e PR_MAILBEAT_BOUNCE_SERVER
+0x68010040 PR_MAILBEAT_REQUEST_SENT
+0x6802001e PR_USENET_SITE_NAME
+0x68030040 PR_MAILBEAT_REQUEST_RECEIVED
+0x68040040 PR_MAILBEAT_REQUEST_PROCESSED
+0x68050003 PR_SHUTOFFQUOTA
+0x68060040 PR_MAILBEAT_REPLY_SENT
+0x68070040 PR_MAILBEAT_REPLY_SUBMIT
+0x68080040 PR_MAILBEAT_REPLY_RECEIVED
+0x68090040 PR_MAILBEAT_REPLY_PROCESSED
+0x68340003 PR_VIEW_STYLE
+0x683A0003 PR_VIEW_MAJORVERSION
+0x6844101e PR_DELEGATES_DISPLAY_NAMES
+0x68451102 PR_DELEGATES_ENTRYIDS
+0x68470003 PR_FREEBUSY_START_RANGE
+0x68480003 PR_FREEBUSY_END_RANGE
+0x6849001e PR_FREEBUSY_EMAIL_ADDRESS
+0x684f1003 PR_FREEBUSY_ALL_MONTHS
+0x68501102 PR_FREEBUSY_ALL_EVENTS
+0x68511003 PR_FREEBUSY_TENTATIVE_MONTHS
+0x68521102 PR_FREEBUSY_TENTATIVE_EVENTS
+0x68531003 PR_FREEBUSY_BUSY_MONTHS
+0x68541102 PR_FREEBUSY_BUSY_EVENTS
+0x68551003 PR_FREEBUSY_OOF_MONTHS
+0x68561102 PR_FREEBUSY_OOF_EVENTS
+0x68680040 PR_FREEBUSY_LAST_MODIFIED
+0x68690003 PR_FREEBUSY_NUM_MONTHS
+0x686b1003 PR_DELEGATES_SEE_PRIVATE
+0x686c0102 PR_PERSONAL_FREEBUSY
+0x686d000b PR_PROCESS_MEETING_REQUESTS
+0x686e000b PR_DECLINE_RECURRING_MEETING_REQUESTS
+0x686f000b PR_DECLINE_CONFLICTING_MEETING_REQUESTS
+0x70010102 PR_VD_BINARY
+0x7002001e PR_VD_STRINGS
+0x70030003 PR_VD_FLAGS
+0x70040102 PR_VD_LINK_TO
+0x70050102 PR_VD_VIEW_FOLDER
+0x7006001e PR_VD_NAME
+0x70070003 PR_VD_VERSION
+0x7c00001e PR_FAV_DISPLAY_NAME_A
+0x7c020102 PR_FAV_PUBLIC_SOURCE_KEY
+0x7c040102 PR_OST_OSTID
+0x7c0a000b PR_STORE_SLOWLINK
+0x7d010003 PR_FAV_AUTOSUBFOLDERS
+0x7d01000b PR_PROCESSED
+0x7d020102 PR_FAV_PARENT_SOURCE_KEY
+0x7d030003 PR_FAV_LEVEL_MASK
+0x7d070003 PR_FAV_INHERIT_AUTO
+0x7d080102 PR_FAV_DEL_SUBS
+0x7ffa0003 PR_ATTACHMENT_LINKID
+0x7ffb0040 PR_EXCEPTION_STARTTIME
+0x7ffc0040 PR_EXCEPTION_ENDTIME
+0x7ffd0003 PR_ATTACHMENT_FLAGS
+0x7ffe000b PR_ATTACHMENT_HIDDEN
+0x8001000b PR_EMS_AB_DISPLAY_NAME_OVERRIDE
+0x80031102 PR_EMS_AB_CA_CERTIFICATE
+0x8004001e PR_EMS_AB_FOLDER_PATHNAME
+0x8005000d PR_EMS_AB_MANAGER
+0x8005001e PR_EMS_AB_MANAGER_T
+0x8006000d PR_EMS_AB_HOME_MDB_O
+0x8006001e PR_EMS_AB_HOME_MDB
+0x8007000d PR_EMS_AB_HOME_MTA_O
+0x8007001e PR_EMS_AB_HOME_MTA
+0x8008000d PR_EMS_AB_IS_MEMBER_OF_DL
+0x8008001e PR_EMS_AB_IS_MEMBER_OF_DL_T
+0x8009000d PR_EMS_AB_MEMBER
+0x8009001e PR_EMS_AB_MEMBER_T
+0x800a001e PR_EMS_AB_AUTOREPLY_MESSAGE
+0x800b000b PR_EMS_AB_AUTOREPLY
+0x800c000d PR_EMS_AB_OWNER_O
+0x800c001e PR_EMS_AB_OWNER
+0x800d000d PR_EMS_AB_KM_SERVER_O
+0x800d001e PR_EMS_AB_KM_SERVER
+0x800e000d PR_EMS_AB_REPORTS
+0x800f101e PR_EMS_AB_PROXY_ADDRESSES
+0x80100102 PR_EMS_AB_HELP_DATA32
+0x8011001e PR_EMS_AB_TARGET_ADDRESS
+0x8012101e PR_EMS_AB_TELEPHONE_NUMBER
+0x80130102 PR_EMS_AB_NT_SECURITY_DESCRIPTOR
+0x8014000d PR_EMS_AB_HOME_MDB_BL_O
+0x8014101e PR_EMS_AB_HOME_MDB_BL
+0x8015000d PR_EMS_AB_PUBLIC_DELEGATES
+0x8015001e PR_EMS_AB_PUBLIC_DELEGATES_T
+0x80160102 PR_EMS_AB_CERTIFICATE_REVOCATION_LIST
+0x80170102 PR_EMS_AB_ADDRESS_ENTRY_DISPLAY_TABLE
+0x80180102 PR_EMS_AB_ADDRESS_SYNTAX
+0x80230102 PR_EMS_AB_BUSINESS_ROLES
+0x8024000d PR_EMS_AB_OWNER_BL_O
+0x8024101e PR_EMS_AB_OWNER_BL
+0x80251102 PR_EMS_AB_CROSS_CERTIFICATE_PAIR
+0x80261102 PR_EMS_AB_AUTHORITY_REVOCATION_LIST
+0x80270102 PR_EMS_AB_ASSOC_NT_ACCOUNT
+0x80280040 PR_EMS_AB_EXPIRATION_TIME
+0x80290003 PR_EMS_AB_USN_CHANGED
+0x802d001e PR_EMS_AB_EXTENSION_ATTRIBUTE_1
+0x802e001e PR_EMS_AB_EXTENSION_ATTRIBUTE_2
+0x802f001e PR_EMS_AB_EXTENSION_ATTRIBUTE_3
+0x8030001e PR_EMS_AB_EXTENSION_ATTRIBUTE_4
+0x8031001e PR_EMS_AB_EXTENSION_ATTRIBUTE_5
+0x8032001e PR_EMS_AB_EXTENSION_ATTRIBUTE_6
+0x8033001e PR_EMS_AB_EXTENSION_ATTRIBUTE_7
+0x8034001e PR_EMS_AB_EXTENSION_ATTRIBUTE_8
+0x8035001e PR_EMS_AB_EXTENSION_ATTRIBUTE_9
+0x8036001e PR_EMS_AB_EXTENSION_ATTRIBUTE_10
+0x80371102 PR_EMS_AB_SECURITY_PROTOCOL
+0x8038000d PR_EMS_AB_PF_CONTACTS_O
+0x8038101e PR_EMS_AB_PF_CONTACTS
+0x803a0102 PR_EMS_AB_HELP_DATA16
+0x803b001e PR_EMS_AB_HELP_FILE_NAME
+0x803c000d PR_EMS_AB_OBJ_DIST_NAME_O
+0x803c001e PR_EMS_AB_OBJ_DIST_NAME
+0x803d001e PR_EMS_AB_ENCRYPT_ALG_SELECTED_OTHER
+0x803e001e PR_EMS_AB_AUTOREPLY_SUBJECT
+0x803f000d PR_EMS_AB_HOME_PUBLIC_SERVER_O
+0x803f001e PR_EMS_AB_HOME_PUBLIC_SERVER
+0x8040101e PR_EMS_AB_ENCRYPT_ALG_LIST_NA
+0x8041101e PR_EMS_AB_ENCRYPT_ALG_LIST_OTHER
+0x8042001e PR_EMS_AB_IMPORTED_FROM
+0x8043001e PR_EMS_AB_ENCRYPT_ALG_SELECTED_NA
+0x80440003 PR_EMS_AB_ACCESS_CATEGORY
+0x80450102 PR_EMS_AB_ACTIVATION_SCHEDULE
+0x80460003 PR_EMS_AB_ACTIVATION_STYLE
+0x80470102 PR_EMS_AB_ADDRESS_ENTRY_DISPLAY_TABLE_MSDOS
+0x8048001e PR_EMS_AB_ADDRESS_TYPE
+0x8049001e PR_EMS_AB_ADMD
+0x804a001e PR_EMS_AB_ADMIN_DESCRIPTION
+0x804b001e PR_EMS_AB_ADMIN_DISPLAY_NAME
+0x804c001e PR_EMS_AB_ADMIN_EXTENSION_DLL
+0x804d000d PR_EMS_AB_ALIASED_OBJECT_NAME_O
+0x804d001e PR_EMS_AB_ALIASED_OBJECT_NAME
+0x804e000d PR_EMS_AB_ALT_RECIPIENT_O
+0x804e001e PR_EMS_AB_ALT_RECIPIENT
+0x804f000d PR_EMS_AB_ALT_RECIPIENT_BL_O
+0x804f101e PR_EMS_AB_ALT_RECIPIENT_BL
+0x80500102 PR_EMS_AB_ANCESTOR_ID
+0x8051000d PR_EMS_AB_ASSOC_REMOTE_DXA_O
+0x8051101e PR_EMS_AB_ASSOC_REMOTE_DXA
+0x80520003 PR_EMS_AB_ASSOCIATION_LIFETIME
+0x8053000d PR_EMS_AB_AUTH_ORIG_BL_O
+0x8053101e PR_EMS_AB_AUTH_ORIG_BL
+0x8054001e PR_EMS_AB_AUTHORIZED_DOMAIN
+0x80550102 PR_EMS_AB_AUTHORIZED_PASSWORD
+0x8056001e PR_EMS_AB_AUTHORIZED_USER
+0x8057101e PR_EMS_AB_BUSINESS_CATEGORY
+0x8058000d PR_EMS_AB_CAN_CREATE_PF_O
+0x8058101e PR_EMS_AB_CAN_CREATE_PF
+0x8059000d PR_EMS_AB_CAN_CREATE_PF_BL_O
+0x8059101e PR_EMS_AB_CAN_CREATE_PF_BL
+0x805a000d PR_EMS_AB_CAN_CREATE_PF_DL_O
+0x805a101e PR_EMS_AB_CAN_CREATE_PF_DL
+0x805b000d PR_EMS_AB_CAN_CREATE_PF_DL_BL_O
+0x805b101e PR_EMS_AB_CAN_CREATE_PF_DL_BL
+0x805c000d PR_EMS_AB_CAN_NOT_CREATE_PF_O
+0x805c101e PR_EMS_AB_CAN_NOT_CREATE_PF
+0x805d000d PR_EMS_AB_CAN_NOT_CREATE_PF_BL_O
+0x805d101e PR_EMS_AB_CAN_NOT_CREATE_PF_BL
+0x805e000d PR_EMS_AB_CAN_NOT_CREATE_PF_DL_O
+0x805e101e PR_EMS_AB_CAN_NOT_CREATE_PF_DL
+0x805f000d PR_EMS_AB_CAN_NOT_CREATE_PF_DL_BL_O
+0x805f101e PR_EMS_AB_CAN_NOT_CREATE_PF_DL_BL
+0x8060000b PR_EMS_AB_CAN_PRESERVE_DNS
+0x80610003 PR_EMS_AB_CLOCK_ALERT_OFFSET
+0x8062000b PR_EMS_AB_CLOCK_ALERT_REPAIR
+0x80630003 PR_EMS_AB_CLOCK_WARNING_OFFSET
+0x8064000b PR_EMS_AB_CLOCK_WARNING_REPAIR
+0x8065001e PR_EMS_AB_COMPUTER_NAME
+0x8066101e PR_EMS_AB_CONNECTED_DOMAINS
+0x80670003 PR_EMS_AB_CONTAINER_INFO
+0x80680003 PR_EMS_AB_COST
+0x8069001e PR_EMS_AB_COUNTRY_NAME
+0x806a0003 PR_EMS_AB_DELIV_CONT_LENGTH
+0x806b1102 PR_EMS_AB_DELIV_EITS
+0x806c1102 PR_EMS_AB_DELIV_EXT_CONT_TYPES
+0x806d000b PR_EMS_AB_DELIVER_AND_REDIRECT
+0x806e0003 PR_EMS_AB_DELIVERY_MECHANISM
+0x806f101e PR_EMS_AB_DESCRIPTION
+0x8070101e PR_EMS_AB_DESTINATION_INDICATOR
+0x8071001e PR_EMS_AB_DIAGNOSTIC_REG_KEY
+0x8072000d PR_EMS_AB_DL_MEM_REJECT_PERMS_BL_O
+0x8072101e PR_EMS_AB_DL_MEM_REJECT_PERMS_BL
+0x8073000d PR_EMS_AB_DL_MEM_SUBMIT_PERMS_BL_O
+0x8073101e PR_EMS_AB_DL_MEM_SUBMIT_PERMS_BL
+0x80741102 PR_EMS_AB_DL_MEMBER_RULE
+0x8075000d PR_EMS_AB_DOMAIN_DEF_ALT_RECIP_O
+0x8075001e PR_EMS_AB_DOMAIN_DEF_ALT_RECIP
+0x8076001e PR_EMS_AB_DOMAIN_NAME
+0x80770102 PR_EMS_AB_DSA_SIGNATURE
+0x8078000b PR_EMS_AB_DXA_ADMIN_COPY
+0x8079000b PR_EMS_AB_DXA_ADMIN_FORWARD
+0x807a0003 PR_EMS_AB_DXA_ADMIN_UPDATE
+0x807b000b PR_EMS_AB_DXA_APPEND_REQCN
+0x807c000d PR_EMS_AB_DXA_CONF_CONTAINER_LIST_O
+0x807c101e PR_EMS_AB_DXA_CONF_CONTAINER_LIST
+0x807d0040 PR_EMS_AB_DXA_CONF_REQ_TIME
+0x807e001e PR_EMS_AB_DXA_CONF_SEQ
+0x807f0003 PR_EMS_AB_DXA_CONF_SEQ_USN
+0x80800003 PR_EMS_AB_DXA_EXCHANGE_OPTIONS
+0x8081000b PR_EMS_AB_DXA_EXPORT_NOW
+0x80820003 PR_EMS_AB_DXA_FLAGS
+0x8083001e PR_EMS_AB_DXA_IMP_SEQ
+0x80840040 PR_EMS_AB_DXA_IMP_SEQ_TIME
+0x80850003 PR_EMS_AB_DXA_IMP_SEQ_USN
+0x8086000b PR_EMS_AB_DXA_IMPORT_NOW
+0x8087101e PR_EMS_AB_DXA_IN_TEMPLATE_MAP
+0x8088000d PR_EMS_AB_DXA_LOCAL_ADMIN_O
+0x8088001e PR_EMS_AB_DXA_LOCAL_ADMIN
+0x80890003 PR_EMS_AB_DXA_LOGGING_LEVEL
+0x808a001e PR_EMS_AB_DXA_NATIVE_ADDRESS_TYPE
+0x808b101e PR_EMS_AB_DXA_OUT_TEMPLATE_MAP
+0x808c001e PR_EMS_AB_DXA_PASSWORD
+0x808d0003 PR_EMS_AB_DXA_PREV_EXCHANGE_OPTIONS
+0x808e000b PR_EMS_AB_DXA_PREV_EXPORT_NATIVE_ONLY
+0x808f0003 PR_EMS_AB_DXA_PREV_IN_EXCHANGE_SENSITIVITY
+0x8090000d PR_EMS_AB_DXA_PREV_REMOTE_ENTRIES_O
+0x8090001e PR_EMS_AB_DXA_PREV_REMOTE_ENTRIES
+0x80910003 PR_EMS_AB_DXA_PREV_REPLICATION_SENSITIVITY
+0x80920003 PR_EMS_AB_DXA_PREV_TEMPLATE_OPTIONS
+0x80930003 PR_EMS_AB_DXA_PREV_TYPES
+0x8094001e PR_EMS_AB_DXA_RECIPIENT_CP
+0x8095000d PR_EMS_AB_DXA_REMOTE_CLIENT_O
+0x8095001e PR_EMS_AB_DXA_REMOTE_CLIENT
+0x8096001e PR_EMS_AB_DXA_REQ_SEQ
+0x80970040 PR_EMS_AB_DXA_REQ_SEQ_TIME
+0x80980003 PR_EMS_AB_DXA_REQ_SEQ_USN
+0x8099001e PR_EMS_AB_DXA_REQNAME
+0x809a001e PR_EMS_AB_DXA_SVR_SEQ
+0x809b0040 PR_EMS_AB_DXA_SVR_SEQ_TIME
+0x809c0003 PR_EMS_AB_DXA_SVR_SEQ_USN
+0x809d0003 PR_EMS_AB_DXA_TASK
+0x809e0003 PR_EMS_AB_DXA_TEMPLATE_OPTIONS
+0x809f0040 PR_EMS_AB_DXA_TEMPLATE_TIMESTAMP
+0x80a00003 PR_EMS_AB_DXA_TYPES
+0x80a1000d PR_EMS_AB_DXA_UNCONF_CONTAINER_LIST_O
+0x80a1101e PR_EMS_AB_DXA_UNCONF_CONTAINER_LIST
+0x80a20003 PR_EMS_AB_ENCAPSULATION_METHOD
+0x80a3000b PR_EMS_AB_ENCRYPT
+0x80a4000b PR_EMS_AB_EXPAND_DLS_LOCALLY
+0x80a5000d PR_EMS_AB_EXPORT_CONTAINERS_O
+0x80a5101e PR_EMS_AB_EXPORT_CONTAINERS
+0x80a6000b PR_EMS_AB_EXPORT_CUSTOM_RECIPIENTS
+0x80a7000b PR_EMS_AB_EXTENDED_CHARS_ALLOWED
+0x80a81102 PR_EMS_AB_EXTENSION_DATA
+0x80a9101e PR_EMS_AB_EXTENSION_NAME
+0x80aa101e PR_EMS_AB_EXTENSION_NAME_INHERITED
+0x80ab1102 PR_EMS_AB_FACSIMILE_TELEPHONE_NUMBER
+0x80ac0102 PR_EMS_AB_FILE_VERSION
+0x80ad000b PR_EMS_AB_FILTER_LOCAL_ADDRESSES
+0x80ae000d PR_EMS_AB_FOLDERS_CONTAINER_O
+0x80ae001e PR_EMS_AB_FOLDERS_CONTAINER
+0x80af0003 PR_EMS_AB_GARBAGE_COLL_PERIOD
+0x80b0001e PR_EMS_AB_GATEWAY_LOCAL_CRED
+0x80b1001e PR_EMS_AB_GATEWAY_LOCAL_DESIG
+0x80b2101e PR_EMS_AB_GATEWAY_PROXY
+0x80b30102 PR_EMS_AB_GATEWAY_ROUTING_TREE
+0x80b40040 PR_EMS_AB_GWART_LAST_MODIFIED
+0x80b5000d PR_EMS_AB_HAS_FULL_REPLICA_NCS_O
+0x80b5101e PR_EMS_AB_HAS_FULL_REPLICA_NCS
+0x80b6000d PR_EMS_AB_HAS_MASTER_NCS_O
+0x80b6101e PR_EMS_AB_HAS_MASTER_NCS
+0x80b70003 PR_EMS_AB_HEURISTICS
+0x80b8000b PR_EMS_AB_HIDE_DL_MEMBERSHIP
+0x80b9000b PR_EMS_AB_HIDE_FROM_ADDRESS_BOOK
+0x80ba000d PR_EMS_AB_IMPORT_CONTAINER_O
+0x80ba001e PR_EMS_AB_IMPORT_CONTAINER
+0x80bb0003 PR_EMS_AB_IMPORT_SENSITIVITY
+0x80bc000d PR_EMS_AB_INBOUND_SITES_O
+0x80bc101e PR_EMS_AB_INBOUND_SITES
+0x80bd0003 PR_EMS_AB_INSTANCE_TYPE
+0x80be101e PR_EMS_AB_INTERNATIONAL_ISDN_NUMBER
+0x80bf0102 PR_EMS_AB_INVOCATION_ID
+0x80c0000b PR_EMS_AB_IS_DELETED
+0x80c1000b PR_EMS_AB_IS_SINGLE_VALUED
+0x80c21102 PR_EMS_AB_KCC_STATUS
+0x80c3101e PR_EMS_AB_KNOWLEDGE_INFORMATION
+0x80c40003 PR_EMS_AB_LINE_WRAP
+0x80c50003 PR_EMS_AB_LINK_ID
+0x80c6001e PR_EMS_AB_LOCAL_BRIDGE_HEAD
+0x80c7001e PR_EMS_AB_LOCAL_BRIDGE_HEAD_ADDRESS
+0x80c8000b PR_EMS_AB_LOCAL_INITIAL_TURN
+0x80c9000d PR_EMS_AB_LOCAL_SCOPE_O
+0x80c9101e PR_EMS_AB_LOCAL_SCOPE
+0x80ca001e PR_EMS_AB_LOG_FILENAME
+0x80cb0003 PR_EMS_AB_LOG_ROLLOVER_INTERVAL
+0x80cc000b PR_EMS_AB_MAINTAIN_AUTOREPLY_HISTORY
+0x80cd0003 PR_EMS_AB_MAPI_DISPLAY_TYPE
+0x80ce0003 PR_EMS_AB_MAPI_ID
+0x80cf0003 PR_EMS_AB_MDB_BACKOFF_INTERVAL
+0x80d00003 PR_EMS_AB_MDB_MSG_TIME_OUT_PERIOD
+0x80d10003 PR_EMS_AB_MDB_OVER_QUOTA_LIMIT
+0x80d20003 PR_EMS_AB_MDB_STORAGE_QUOTA
+0x80d30003 PR_EMS_AB_MDB_UNREAD_LIMIT
+0x80d4000b PR_EMS_AB_MDB_USE_DEFAULTS
+0x80d5000b PR_EMS_AB_MESSAGE_TRACKING_ENABLED
+0x80d6000b PR_EMS_AB_MONITOR_CLOCK
+0x80d7000b PR_EMS_AB_MONITOR_SERVERS
+0x80d8000b PR_EMS_AB_MONITOR_SERVICES
+0x80d9000d PR_EMS_AB_MONITORED_CONFIGURATIONS_O
+0x80d9101e PR_EMS_AB_MONITORED_CONFIGURATIONS
+0x80da000d PR_EMS_AB_MONITORED_SERVERS_O
+0x80da101e PR_EMS_AB_MONITORED_SERVERS
+0x80db101e PR_EMS_AB_MONITORED_SERVICES
+0x80dc0003 PR_EMS_AB_MONITORING_ALERT_DELAY
+0x80dd0003 PR_EMS_AB_MONITORING_ALERT_UNITS
+0x80de0003 PR_EMS_AB_MONITORING_AVAILABILITY_STYLE
+0x80df0102 PR_EMS_AB_MONITORING_AVAILABILITY_WINDOW
+0x80e0000d PR_EMS_AB_MONITORING_CACHED_VIA_MAIL_O
+0x80e0101e PR_EMS_AB_MONITORING_CACHED_VIA_MAIL
+0x80e1000d PR_EMS_AB_MONITORING_CACHED_VIA_RPC_O
+0x80e1101e PR_EMS_AB_MONITORING_CACHED_VIA_RPC
+0x80e21102 PR_EMS_AB_MONITORING_ESCALATION_PROCEDURE
+0x80e30003 PR_EMS_AB_MONITORING_HOTSITE_POLL_INTERVAL
+0x80e40003 PR_EMS_AB_MONITORING_HOTSITE_POLL_UNITS
+0x80e50003 PR_EMS_AB_MONITORING_MAIL_UPDATE_INTERVAL
+0x80e60003 PR_EMS_AB_MONITORING_MAIL_UPDATE_UNITS
+0x80e70003 PR_EMS_AB_MONITORING_NORMAL_POLL_INTERVAL
+0x80e80003 PR_EMS_AB_MONITORING_NORMAL_POLL_UNITS
+0x80e9000d PR_EMS_AB_MONITORING_RECIPIENTS_O
+0x80e9101e PR_EMS_AB_MONITORING_RECIPIENTS
+0x80ea000d PR_EMS_AB_MONITORING_RECIPIENTS_NDR_O
+0x80ea101e PR_EMS_AB_MONITORING_RECIPIENTS_NDR
+0x80eb0003 PR_EMS_AB_MONITORING_RPC_UPDATE_INTERVAL
+0x80ec0003 PR_EMS_AB_MONITORING_RPC_UPDATE_UNITS
+0x80ed0003 PR_EMS_AB_MONITORING_WARNING_DELAY
+0x80ee0003 PR_EMS_AB_MONITORING_WARNING_UNITS
+0x80ef001e PR_EMS_AB_MTA_LOCAL_CRED
+0x80f0001e PR_EMS_AB_MTA_LOCAL_DESIG
+0x80f10102 PR_EMS_AB_N_ADDRESS
+0x80f20003 PR_EMS_AB_N_ADDRESS_TYPE
+0x80f3001e PR_EMS_AB_NT_MACHINE_NAME
+0x80f40003 PR_EMS_AB_NUM_OF_OPEN_RETRIES
+0x80f50003 PR_EMS_AB_NUM_OF_TRANSFER_RETRIES
+0x80f60003 PR_EMS_AB_OBJECT_CLASS_CATEGORY
+0x80f70003 PR_EMS_AB_OBJECT_VERSION
+0x80f8000d PR_EMS_AB_OFF_LINE_AB_CONTAINERS_O
+0x80f8101e PR_EMS_AB_OFF_LINE_AB_CONTAINERS
+0x80f90102 PR_EMS_AB_OFF_LINE_AB_SCHEDULE
+0x80fa000d PR_EMS_AB_OFF_LINE_AB_SERVER_O
+0x80fa001e PR_EMS_AB_OFF_LINE_AB_SERVER
+0x80fb0003 PR_EMS_AB_OFF_LINE_AB_STYLE
+0x80fc0003 PR_EMS_AB_OID_TYPE
+0x80fd0102 PR_EMS_AB_OM_OBJECT_CLASS
+0x80fe0003 PR_EMS_AB_OM_SYNTAX
+0x80ff000b PR_EMS_AB_OOF_REPLY_TO_ORIGINATOR
+0x81000003 PR_EMS_AB_OPEN_RETRY_INTERVAL
+0x8101101e PR_EMS_AB_ORGANIZATION_NAME
+0x8102101e PR_EMS_AB_ORGANIZATIONAL_UNIT_NAME
+0x81030102 PR_EMS_AB_ORIGINAL_DISPLAY_TABLE
+0x81040102 PR_EMS_AB_ORIGINAL_DISPLAY_TABLE_MSDOS
+0x8105000d PR_EMS_AB_OUTBOUND_SITES_O
+0x8105101e PR_EMS_AB_OUTBOUND_SITES
+0x81060102 PR_EMS_AB_P_SELECTOR
+0x81070102 PR_EMS_AB_P_SELECTOR_INBOUND
+0x81080102 PR_EMS_AB_PER_MSG_DIALOG_DISPLAY_TABLE
+0x81090102 PR_EMS_AB_PER_RECIP_DIALOG_DISPLAY_TABLE
+0x810a0102 PR_EMS_AB_PERIOD_REP_SYNC_TIMES
+0x810b0003 PR_EMS_AB_PERIOD_REPL_STAGGER
+0x810c1102 PR_EMS_AB_POSTAL_ADDRESS
+0x810d1003 PR_EMS_AB_PREFERRED_DELIVERY_METHOD
+0x810e001e PR_EMS_AB_PRMD
+0x810f001e PR_EMS_AB_PROXY_GENERATOR_DLL
+0x8110000d PR_EMS_AB_PUBLIC_DELEGATES_BL_O
+0x8110101e PR_EMS_AB_PUBLIC_DELEGATES_BL
+0x81110102 PR_EMS_AB_QUOTA_NOTIFICATION_SCHEDULE
+0x81120003 PR_EMS_AB_QUOTA_NOTIFICATION_STYLE
+0x81130003 PR_EMS_AB_RANGE_LOWER
+0x81140003 PR_EMS_AB_RANGE_UPPER
+0x8115001e PR_EMS_AB_RAS_CALLBACK_NUMBER
+0x8116001e PR_EMS_AB_RAS_PHONE_NUMBER
+0x8117001e PR_EMS_AB_RAS_PHONEBOOK_ENTRY_NAME
+0x8118001e PR_EMS_AB_RAS_REMOTE_SRVR_NAME
+0x81191102 PR_EMS_AB_REGISTERED_ADDRESS
+0x811a001e PR_EMS_AB_REMOTE_BRIDGE_HEAD
+0x811b001e PR_EMS_AB_REMOTE_BRIDGE_HEAD_ADDRESS
+0x811c000d PR_EMS_AB_REMOTE_OUT_BH_SERVER_O
+0x811c001e PR_EMS_AB_REMOTE_OUT_BH_SERVER
+0x811d000d PR_EMS_AB_REMOTE_SITE_O
+0x811d001e PR_EMS_AB_REMOTE_SITE
+0x811e0003 PR_EMS_AB_REPLICATION_SENSITIVITY
+0x811f0003 PR_EMS_AB_REPLICATION_STAGGER
+0x8120000b PR_EMS_AB_REPORT_TO_ORIGINATOR
+0x8121000b PR_EMS_AB_REPORT_TO_OWNER
+0x81220003 PR_EMS_AB_REQ_SEQ
+0x8123000d PR_EMS_AB_RESPONSIBLE_LOCAL_DXA_O
+0x8123001e PR_EMS_AB_RESPONSIBLE_LOCAL_DXA
+0x8124000d PR_EMS_AB_RID_SERVER_O
+0x8124001e PR_EMS_AB_RID_SERVER
+0x8125000d PR_EMS_AB_ROLE_OCCUPANT_O
+0x8125101e PR_EMS_AB_ROLE_OCCUPANT
+0x8126101e PR_EMS_AB_ROUTING_LIST
+0x81270003 PR_EMS_AB_RTS_CHECKPOINT_SIZE
+0x81280003 PR_EMS_AB_RTS_RECOVERY_TIMEOUT
+0x81290003 PR_EMS_AB_RTS_WINDOW_SIZE
+0x812a000d PR_EMS_AB_RUNS_ON_O
+0x812a101e PR_EMS_AB_RUNS_ON
+0x812b0102 PR_EMS_AB_S_SELECTOR
+0x812c0102 PR_EMS_AB_S_SELECTOR_INBOUND
+0x812d0003 PR_EMS_AB_SEARCH_FLAGS
+0x812e1102 PR_EMS_AB_SEARCH_GUIDE
+0x812f000d PR_EMS_AB_SEE_ALSO_O
+0x812f101e PR_EMS_AB_SEE_ALSO
+0x8130101e PR_EMS_AB_SERIAL_NUMBER
+0x81310003 PR_EMS_AB_SERVICE_ACTION_FIRST
+0x81320003 PR_EMS_AB_SERVICE_ACTION_OTHER
+0x81330003 PR_EMS_AB_SERVICE_ACTION_SECOND
+0x81340003 PR_EMS_AB_SERVICE_RESTART_DELAY
+0x8135001e PR_EMS_AB_SERVICE_RESTART_MESSAGE
+0x81360003 PR_EMS_AB_SESSION_DISCONNECT_TIMER
+0x8137101e PR_EMS_AB_SITE_AFFINITY
+0x8138101e PR_EMS_AB_SITE_PROXY_SPACE
+0x81390040 PR_EMS_AB_SPACE_LAST_COMPUTED
+0x813a001e PR_EMS_AB_STREET_ADDRESS
+0x813b000d PR_EMS_AB_SUB_REFS_O
+0x813b101e PR_EMS_AB_SUB_REFS
+0x813c0003 PR_EMS_AB_SUBMISSION_CONT_LENGTH
+0x813d1102 PR_EMS_AB_SUPPORTED_APPLICATION_CONTEXT
+0x813e000d PR_EMS_AB_SUPPORTING_STACK_O
+0x813e101e PR_EMS_AB_SUPPORTING_STACK
+0x813f000d PR_EMS_AB_SUPPORTING_STACK_BL_O
+0x813f101e PR_EMS_AB_SUPPORTING_STACK_BL
+0x81400102 PR_EMS_AB_T_SELECTOR
+0x81410102 PR_EMS_AB_T_SELECTOR_INBOUND
+0x8142101e PR_EMS_AB_TARGET_MTAS
+0x81431102 PR_EMS_AB_TELETEX_TERMINAL_IDENTIFIER
+0x81440003 PR_EMS_AB_TEMP_ASSOC_THRESHOLD
+0x81450003 PR_EMS_AB_TOMBSTONE_LIFETIME
+0x8146001e PR_EMS_AB_TRACKING_LOG_PATH_NAME
+0x81470003 PR_EMS_AB_TRANS_RETRY_MINS
+0x81480003 PR_EMS_AB_TRANS_TIMEOUT_MINS
+0x81490003 PR_EMS_AB_TRANSFER_RETRY_INTERVAL
+0x814a0003 PR_EMS_AB_TRANSFER_TIMEOUT_NON_URGENT
+0x814b0003 PR_EMS_AB_TRANSFER_TIMEOUT_NORMAL
+0x814c0003 PR_EMS_AB_TRANSFER_TIMEOUT_URGENT
+0x814d0003 PR_EMS_AB_TRANSLATION_TABLE_USED
+0x814e000b PR_EMS_AB_TRANSPORT_EXPEDITED_DATA
+0x814f0003 PR_EMS_AB_TRUST_LEVEL
+0x81500003 PR_EMS_AB_TURN_REQUEST_THRESHOLD
+0x8151000b PR_EMS_AB_TWO_WAY_ALTERNATE_FACILITY
+0x8152000d PR_EMS_AB_UNAUTH_ORIG_BL_O
+0x8152101e PR_EMS_AB_UNAUTH_ORIG_BL
+0x81531102 PR_EMS_AB_USER_PASSWORD
+0x81540003 PR_EMS_AB_USN_CREATED
+0x81550003 PR_EMS_AB_USN_DSA_LAST_OBJ_REMOVED
+0x81560003 PR_EMS_AB_USN_LAST_OBJ_REM
+0x81570003 PR_EMS_AB_USN_SOURCE
+0x8158101e PR_EMS_AB_X121_ADDRESS
+0x81590102 PR_EMS_AB_X25_CALL_USER_DATA_INCOMING
+0x815a0102 PR_EMS_AB_X25_CALL_USER_DATA_OUTGOING
+0x815b0102 PR_EMS_AB_X25_FACILITIES_DATA_INCOMING
+0x815c0102 PR_EMS_AB_X25_FACILITIES_DATA_OUTGOING
+0x815d0102 PR_EMS_AB_X25_LEASED_LINE_PORT
+0x815e000b PR_EMS_AB_X25_LEASED_OR_SWITCHED
+0x815f001e PR_EMS_AB_X25_REMOTE_MTA_PHONE
+0x81600102 PR_EMS_AB_X400_ATTACHMENT_TYPE
+0x81610003 PR_EMS_AB_X400_SELECTOR_SYNTAX
+0x81620102 PR_EMS_AB_X500_ACCESS_CONTROL_LIST
+0x81630003 PR_EMS_AB_XMIT_TIMEOUT_NON_URGENT
+0x81640003 PR_EMS_AB_XMIT_TIMEOUT_NORMAL
+0x81650003 PR_EMS_AB_XMIT_TIMEOUT_URGENT
+0x81660102 PR_EMS_AB_SITE_FOLDER_GUID
+0x8167000d PR_EMS_AB_SITE_FOLDER_SERVER_O
+0x8167001e PR_EMS_AB_SITE_FOLDER_SERVER
+0x81680003 PR_EMS_AB_REPLICATION_MAIL_MSG_SIZE
+0x81690102 PR_EMS_AB_MAXIMUM_OBJECT_ID
+0x8170101e PR_EMS_AB_NETWORK_ADDRESS
+0x8171101e PR_EMS_AB_LDAP_DISPLAY_NAME
+0x81730003 PR_EMS_AB_SCHEMA_FLAGS
+0x8174000d PR_EMS_AB_BRIDGEHEAD_SERVERS_O
+0x8174101e PR_EMS_AB_BRIDGEHEAD_SERVERS
+0x8175001e PR_EMS_AB_WWW_HOME_PAGE
+0x8176001e PR_EMS_AB_NNTP_CONTENT_FORMAT
+0x8177001e PR_EMS_AB_POP_CONTENT_FORMAT
+0x81780003 PR_EMS_AB_LANGUAGE
+0x8179001e PR_EMS_AB_POP_CHARACTER_SET
+0x817a0003 PR_EMS_AB_USN_INTERSITE
+0x817b001e PR_EMS_AB_SUB_SITE
+0x817c1003 PR_EMS_AB_SCHEMA_VERSION
+0x817d001e PR_EMS_AB_NNTP_CHARACTER_SET
+0x817e000b PR_EMS_AB_USE_SERVER_VALUES
+0x817f0003 PR_EMS_AB_ENABLED_PROTOCOLS
+0x81800102 PR_EMS_AB_CONNECTION_LIST_FILTER
+0x8181101e PR_EMS_AB_AVAILABLE_AUTHORIZATION_PACKAGES
+0x8182101e PR_EMS_AB_CHARACTER_SET_LIST
+0x8183000b PR_EMS_AB_USE_SITE_VALUES
+0x8184101e PR_EMS_AB_ENABLED_AUTHORIZATION_PACKAGES
+0x8185001e PR_EMS_AB_CHARACTER_SET
+0x81860003 PR_EMS_AB_CONTENT_TYPE
+0x8187000b PR_EMS_AB_ANONYMOUS_ACCESS
+0x81880102 PR_EMS_AB_CONTROL_MSG_FOLDER_ID
+0x8189001e PR_EMS_AB_USENET_SITE_NAME
+0x818a0102 PR_EMS_AB_CONTROL_MSG_RULES
+0x818b001e PR_EMS_AB_AVAILABLE_DISTRIBUTIONS
+0x818d0102 PR_EMS_AB_OUTBOUND_HOST
+0x818e101e PR_EMS_AB_INBOUND_HOST
+0x818f0003 PR_EMS_AB_OUTGOING_MSG_SIZE_LIMIT
+0x81900003 PR_EMS_AB_INCOMING_MSG_SIZE_LIMIT
+0x8191000b PR_EMS_AB_SEND_TNEF
+0x81920102 PR_EMS_AB_AUTHORIZED_PASSWORD_CONFIRM
+0x8193001e PR_EMS_AB_INBOUND_NEWSFEED
+0x81940003 PR_EMS_AB_NEWSFEED_TYPE
+0x8195001e PR_EMS_AB_OUTBOUND_NEWSFEED
+0x81960102 PR_EMS_AB_NEWSGROUP_LIST
+0x8197101e PR_EMS_AB_NNTP_DISTRIBUTIONS
+0x8198001e PR_EMS_AB_NEWSGROUP
+0x8199001e PR_EMS_AB_MODERATOR
+0x819a001e PR_EMS_AB_AUTHENTICATION_TO_USE
+0x819b000b PR_EMS_AB_HTTP_PUB_GAL
+0x819c0003 PR_EMS_AB_HTTP_PUB_GAL_LIMIT
+0x819e1102 PR_EMS_AB_HTTP_PUB_PF
+0x81a1001e PR_EMS_AB_X500_RDN
+0x81a2001e PR_EMS_AB_X500_NC
+0x81a3101e PR_EMS_AB_REFERRAL_LIST
+0x81a4000b PR_EMS_AB_NNTP_DISTRIBUTIONS_FLAG
+0x81a5000d PR_EMS_AB_ASSOC_PROTOCOL_CFG_NNTP_O
+0x81a5001e PR_EMS_AB_ASSOC_PROTOCOL_CFG_NNTP
+0x81a6000d PR_EMS_AB_NNTP_NEWSFEEDS_O
+0x81a6101e PR_EMS_AB_NNTP_NEWSFEEDS
+0x81a8000b PR_EMS_AB_ENABLED_PROTOCOL_CFG
+0x81a9101e PR_EMS_AB_HTTP_PUB_AB_ATTRIBUTES
+0x81ab101e PR_EMS_AB_HTTP_SERVERS
+0x81ac000b PR_EMS_AB_MODERATED
+0x81ad001e PR_EMS_AB_RAS_ACCOUNT
+0x81ae0102 PR_EMS_AB_RAS_PASSWORD
+0x81af0102 PR_EMS_AB_INCOMING_PASSWORD
+0x81b0000b PR_EMS_AB_OUTBOUND_HOST_TYPE
+0x81b1000b PR_EMS_AB_PROXY_GENERATION_ENABLED
+0x81b20102 PR_EMS_AB_ROOT_NEWSGROUPS_FOLDER_ID
+0x81b3000b PR_EMS_AB_CONNECTION_TYPE
+0x81b40003 PR_EMS_AB_CONNECTION_LIST_FILTER_TYPE
+0x81b50003 PR_EMS_AB_PORT_NUMBER
+0x81b6101e PR_EMS_AB_PROTOCOL_SETTINGS
+0x81b7001e PR_EMS_AB_GROUP_BY_ATTR_1
+0x81b8001e PR_EMS_AB_GROUP_BY_ATTR_2
+0x81b9001e PR_EMS_AB_GROUP_BY_ATTR_3
+0x81ba001e PR_EMS_AB_GROUP_BY_ATTR_4
+0x81be001e PR_EMS_AB_VIEW_SITE
+0x81bf001e PR_EMS_AB_VIEW_CONTAINER_1
+0x81c0001e PR_EMS_AB_VIEW_CONTAINER_2
+0x81c1001e PR_EMS_AB_VIEW_CONTAINER_3
+0x81c20040 PR_EMS_AB_PROMO_EXPIRATION
+0x81c3101e PR_EMS_AB_DISABLED_GATEWAY_PROXY
+0x81c40102 PR_EMS_AB_COMPROMISED_KEY_LIST
+0x81c5000d PR_EMS_AB_INSADMIN_O
+0x81c5001e PR_EMS_AB_INSADMIN
+0x81c6000b PR_EMS_AB_OVERRIDE_NNTP_CONTENT_FORMAT
+0x81c7000d PR_EMS_AB_OBJ_VIEW_CONTAINERS_O
+0x81c7101e PR_EMS_AB_OBJ_VIEW_CONTAINERS
+0x8c180003 PR_EMS_AB_VIEW_FLAGS
+0x8c19001e PR_EMS_AB_GROUP_BY_ATTR_VALUE_STR
+0x8c1a000d PR_EMS_AB_GROUP_BY_ATTR_VALUE_DN_O
+0x8c1a001e PR_EMS_AB_GROUP_BY_ATTR_VALUE_DN
+0x8c1b1102 PR_EMS_AB_VIEW_DEFINITION
+0x8c1c0102 PR_EMS_AB_MIME_TYPES
+0x8c1d0003 PR_EMS_AB_LDAP_SEARCH_CFG
+0x8c1e000d PR_EMS_AB_INBOUND_DN_O
+0x8c1e001e PR_EMS_AB_INBOUND_DN
+0x8c1f000b PR_EMS_AB_INBOUND_NEWSFEED_TYPE
+0x8c20000b PR_EMS_AB_INBOUND_ACCEPT_ALL
+0x8c21000b PR_EMS_AB_ENABLED
+0x8c22000b PR_EMS_AB_PRESERVE_INTERNET_CONTENT
+0x8c23000b PR_EMS_AB_DISABLE_DEFERRED_COMMIT
+0x8c24000b PR_EMS_AB_CLIENT_ACCESS_ENABLED
+0x8c25000b PR_EMS_AB_REQUIRE_SSL
+0x8c26001e PR_EMS_AB_ANONYMOUS_ACCOUNT
+0x8c270102 PR_EMS_AB_CERTIFICATE_CHAIN_V3
+0x8c280102 PR_EMS_AB_CERTIFICATE_REVOCATION_LIST_V3
+0x8c290102 PR_EMS_AB_CERTIFICATE_REVOCATION_LIST_V1
+0x8c301102 PR_EMS_AB_CROSS_CERTIFICATE_CRL
+0x8c31000b PR_EMS_AB_SEND_EMAIL_MESSAGE
+0x8c32000b PR_EMS_AB_ENABLE_COMPATIBILITY
+0x8c33101e PR_EMS_AB_SMIME_ALG_LIST_NA
+0x8c34101e PR_EMS_AB_SMIME_ALG_LIST_OTHER
+0x8c35001e PR_EMS_AB_SMIME_ALG_SELECTED_NA
+0x8c36001e PR_EMS_AB_SMIME_ALG_SELECTED_OTHER
+0x8c37000b PR_EMS_AB_DEFAULT_MESSAGE_FORMAT
+0x8c38001e PR_EMS_AB_TYPE
+0x8c3a0003 PR_EMS_AB_DO_OAB_VERSION
+0x8c3b0102 PR_EMS_AB_VOICE_MAIL_SYSTEM_GUID
+0x8c3c001e PR_EMS_AB_VOICE_MAIL_USER_ID
+0x8c3d001e PR_EMS_AB_VOICE_MAIL_PASSWORD
+0x8c3e0102 PR_EMS_AB_VOICE_MAIL_RECORDED_NAME
+0x8c3f101e PR_EMS_AB_VOICE_MAIL_GREETINGS
+0x8c401102 PR_EMS_AB_VOICE_MAIL_FLAGS
+0x8c410003 PR_EMS_AB_VOICE_MAIL_VOLUME
+0x8c420003 PR_EMS_AB_VOICE_MAIL_SPEED
+0x8c431003 PR_EMS_AB_VOICE_MAIL_RECORDING_LENGTH
+0x8c44001e PR_EMS_AB_DISPLAY_NAME_SUFFIX
+0x8c451102 PR_EMS_AB_ATTRIBUTE_CERTIFICATE
+0x8c461102 PR_EMS_AB_DELTA_REVOCATION_LIST
+0x8c471102 PR_EMS_AB_SECURITY_POLICY
+0x8c48000b PR_EMS_AB_SUPPORT_SMIME_SIGNATURES
+0x8c49000b PR_EMS_AB_DELEGATE_USER
+0x8c50000b PR_EMS_AB_LIST_PUBLIC_FOLDERS
+0x8c51001e PR_EMS_AB_LABELEDURI
+0x8c52000b PR_EMS_AB_RETURN_EXACT_MSG_SIZE
+0x8c53001e PR_EMS_AB_GENERATION_QUALIFIER
+0x8c54001e PR_EMS_AB_HOUSE_IDENTIFIER
+0x8c550102 PR_EMS_AB_SUPPORTED_ALGORITHMS
+0x8c56001e PR_EMS_AB_DMD_NAME
+0x8c57001e PR_EMS_AB_EXTENSION_ATTRIBUTE_11
+0x8c58001e PR_EMS_AB_EXTENSION_ATTRIBUTE_12
+0x8c59001e PR_EMS_AB_EXTENSION_ATTRIBUTE_13
+0x8c60001e PR_EMS_AB_EXTENSION_ATTRIBUTE_14
+0x8c61001e PR_EMS_AB_EXTENSION_ATTRIBUTE_15
+0x8c620003 PR_EMS_AB_REPLICATED_OBJECT_VERSION
+0x8c63001e PR_EMS_AB_MAIL_DROP
+0x8c64001e PR_EMS_AB_FORWARDING_ADDRESS
+0x8c650102 PR_EMS_AB_FORM_DATA
+0x8c66001e PR_EMS_AB_OWA_SERVER
+0x8c67001e PR_EMS_AB_EMPLOYEE_NUMBER
+0x8c68001e PR_EMS_AB_TELEPHONE_PERSONAL_PAGER
+0x8c69001e PR_EMS_AB_EMPLOYEE_TYPE
+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
+0x8c8e001e PR_EMS_AB_PHONETIC_GIVEN_NAME
+0x8c8f001e PR_EMS_AB_PHONETIC_SURNAME
+0x8c90001e PR_EMS_AB_PHONETIC_DEPARTMENT_NAME
+0x8c91001e PR_EMS_AB_PHONETIC_COMPANY_NAME
+0x8c92001e PR_EMS_AB_PHONETIC_DISPLAY_NAME
+0x8c96001e PR_EMS_AB_ROOM_CONTAINERS
+0xf000000d PR_EMS_AB_OTHER_RECIPS
+0xfff8101e PR_EMS_AB_CHILD_RDNS
+0xfff9001e PR_EMS_AB_HIERARCHY_PATH
+0xfffa0102 PR_EMS_AB_OBJECT_OID
+0xfffb000b PR_EMS_AB_IS_MASTER
+0xfffc0102 PR_EMS_AB_PARENT_ENTRYID
+0xfffd0003 PR_EMS_AB_CONTAINERID
+0xfffe001e PR_EMS_AB_SERVER
Added: trunk/openchange/libmapi/conf/mparse.pl
===================================================================
--- trunk/openchange/libmapi/conf/mparse.pl (rev 0)
+++ trunk/openchange/libmapi/conf/mparse.pl 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,877 @@
+#!/usr/bin/perl -w
+
+###################################################
+# package to parse the mapi-properties files and
+# generate code for libmapi in OpenChange
+#
+# Perl code based on pidl one from Andrew Tridgell and the Samba team
+#
+# Copyright (C) Julien Kerihuel 2005-2008
+# released under the GNU GPL
+
+use strict;
+use Getopt::Long;
+
+my $ret = "";
+my $tabs = "";
+
+sub indent() { $tabs.="\t"; }
+sub deindent() { $tabs = substr($tabs, 1); }
+sub mparse($) { $ret .= $tabs.(shift)."\n"; }
+
+my($opt_outputdir) = '.';
+my($opt_parser) = '';
+
+my %prop_types = (
+ 0x0 => "PT_UNSPECIFIED",
+ 0x1 => "PT_NULL",
+ 0x2 => "PT_SHORT",
+ 0x3 => "PT_LONG",
+ 0x4 => "PT_FLOAT",
+ 0x5 => "PT_DOUBLE",
+ 0x6 => "PT_CURRENCY",
+ 0x7 => "PT_APPTIME",
+ 0xa => "PT_ERROR",
+ 0xb => "PT_BOOLEAN",
+ 0xd => "PT_OBJECT",
+ 0x14 => "PT_I8",
+ 0x1e => "PT_STRING8",
+ 0x1f => "PT_UNICODE",
+ 0x40 => "PT_SYSTIME",
+ 0x48 => "PT_CLSID",
+ 0x102 => "PT_BINARY",
+# Multi-valued property types
+ 0x1002 => "PT_MV_SHORT",
+ 0x1003 => "PT_MV_LONG",
+ 0x1004 => "PT_MV_FLOAT",
+ 0x1005 => "PT_MV_DOUBLE",
+ 0x1006 => "PT_MV_CURRENCY",
+ 0x1007 => "PT_MV_APPTIME",
+ 0x1014 => "PT_MV_I8",
+ 0x101e => "PT_MV_STRING8",
+ 0x101f => "PT_MV_UNICODE",
+ 0x1040 => "PT_MV_SYSTIME",
+ 0x1048 => "PT_MV_CLSID",
+ 0x1102 => "PT_MV_BINARY"
+);
+
+my %prop_names = (
+ "PT_UNSPECIFIED" => 0x0,
+ "PT_NULL" => 0x1,
+ "PT_SHORT" => 0x2,
+ "PT_LONG" => 0x3,
+ "PT_FLOAT" => 0x4,
+ "PT_DOUBLE" => 0x5,
+ "PT_CURRENCY" => 0x6,
+ "PT_APPTIME" => 0x7,
+ "PT_ERROR" => 0xa,
+ "PT_BOOLEAN" => 0xb,
+ "PT_OBJECT" => 0xd,
+ "PT_I8" => 0x14,
+ "PT_STRING8" => 0x1e,
+ "PT_UNICODE" => 0x1f,
+ "PT_SYSTIME" => 0x40,
+ "PT_CLSID" => 0x48,
+ "PT_BINARY" => 0x102,
+# Multi-valued property types
+ "PT_MV_SHORT" => 0x1002,
+ "PT_MV_LONG" => 0x1003,
+ "PT_MV_FLOAT" => 0x1004,
+ "PT_MV_DOUBLE" => 0x1005,
+ "PT_MV_CURRENCY" => 0x1006,
+ "PT_MV_APPTIME" => 0x1007,
+ "PT_MV_I8" => 0x1014,
+ "PT_MV_STRING8" => 0x101e,
+ "PT_MV_UNICODE" => 0x101f,
+ "PT_MV_SYSTIME" => 0x1040,
+ "PT_MV_CLSID" => 0x1048,
+ "PT_MV_BINARY" => 0x1102
+);
+
+# main program
+
+my $result = GetOptions (
+ 'outputdir=s' => \$opt_outputdir,
+ 'parser=s' => \$opt_parser
+ );
+
+if (not $result) {
+ exit(1);
+}
+
+#####################################################################
+# read a file into a string
+sub FileLoad($)
+{
+ my($filename) = shift;
+ local(*INPUTFILE);
+ open(INPUTFILE, $filename) || return undef;
+ my($saved_delim) = $/;
+ undef $/;
+ my($data) = <INPUTFILE>;
+ close(INPUTFILE);
+ $/ = $saved_delim;
+ return $data;
+}
+
+#####################################################################
+# write a string into a file
+sub FileSave($$)
+{
+ my($filename) = shift;
+ my($v) = shift;
+ local(*FILE);
+ open(FILE, ">$filename") || die "can't open $filename";
+ print FILE $v;
+ close(FILE);
+}
+
+#####################################################################
+# generate mapitags.h file
+sub mapitags_header($)
+{
+ my $contents = shift;
+ my $line;
+ my @lines;
+ my @prop;
+ my $prop_type;
+ my $prop_value;
+
+ mparse "/* parser auto-generated by mparse */";
+ mparse "#ifndef __MAPITAGS_H__";
+ mparse "#define __MAPITAGS_H__";
+ mparse "";
+
+ @lines = split(/\n/, $contents);
+ foreach $line (@lines) {
+ $line =~ s/^\#+.*$//;
+ if ($line) {
+ @prop = split(/\s+/, $line);
+ $prop_type = hex $prop[0];
+ $prop_type &= 0xFFFF;
+ $prop_value = hex $prop[0];
+ $prop_value = ($prop_value >> 16) & 0xFFFF;
+
+ mparse sprintf "#define %-51s PROP_TAG(%-13s, 0x%.04x) /* %s */", $prop[1], $prop_types{$prop_type}, $prop_value, $prop[0] if ($prop_types{$prop_type});
+ if (($prop_type == 0x1e) || ($prop_type == 0x101e)){
+ $prop_type++;
+ $prop[0] = sprintf "0x%.8x", ((hex $prop[0]) & 0xFFFF0000) + $prop_type;
+ mparse sprintf "#define %-51s PROP_TAG(%-13s, 0x%.04x) /* %s */", "$prop[1]_UNICODE", $prop_types{$prop_type}, $prop_value, $prop[0] if ($prop_types{$prop_type});
+ }
+ $prop_type = 0xa;
+ $prop[0] = sprintf "0x%.8x", ((hex $prop[0]) & 0xFFFF0000) + $prop_type;
+ mparse sprintf "#define %-51s PROP_TAG(%-13s, 0x%.04x) /* %s */", "$prop[1]_ERROR", $prop_types{$prop_type}, $prop_value, $prop[0] if ($prop_types{$prop_type});
+ }
+ }
+ mparse "";
+ mparse "#endif /* !__MAPITAGS_H__ */";
+
+ return $ret;
+
+}
+
+
+#####################################################################
+# generate mapitags.c file
+sub mapitags_interface($)
+{
+ my $contents = shift;
+ my $line;
+ my @lines;
+ my @prop;
+ my $prop_type;
+ my $prop_value;
+
+ mparse "/* parser auto-generated by mparse */";
+ mparse "#include <libmapi/libmapi.h>";
+ mparse "#include <libmapi/proto_private.h>";
+ mparse "#include <gen_ndr/ndr_exchange.h>";
+ mparse "#include <libmapi/mapitags.h>";
+ mparse "";
+ mparse "struct mapi_proptags";
+ mparse "{";
+ indent;
+ mparse "uint32_t proptag;";
+ mparse "uint32_t proptype;";
+ mparse "const char *propname;";
+ deindent;
+ mparse "};";
+ mparse "";
+ mparse "static struct mapi_proptags mapitags[] = {";
+ indent;
+
+ @lines = split(/\n/, $contents);
+ foreach $line (@lines) {
+ $line =~ s/^\#+.*$//;
+ if ($line) {
+ @prop = split(/\s+/, $line);
+ $prop_type = hex $prop[0];
+ $prop_type &= 0xFFFF;
+ $prop_value = hex $prop[0];
+ $prop_value = ($prop_value >> 16) & 0xFFFF;
+ if ($prop_types{$prop_type}) {
+ mparse sprintf "{ %-51s, %-13s, \"%s\" },", $prop[1], $prop_types{$prop_type}, $prop[1];
+ if (($prop_type == 0x1e) || ($prop_type == 0x101e)) {
+ $prop_type++;
+ mparse sprintf "{ %-51s, %-13s, \"%s\" },", "$prop[1]_UNICODE", $prop_types{$prop_type}, "$prop[1]_UNICODE";
+ }
+ $prop_type = 0xa;
+ mparse sprintf "{ %-51s, %-13s, \"%s\" },", "$prop[1]_ERROR", $prop_types{$prop_type}, $prop[1];
+ }
+ }
+ }
+
+ mparse sprintf "{ %-51s, %-13d, \"NULL\"}", 0, 0;
+ deindent;
+ mparse "};";
+ mparse "";
+ mparse "_PUBLIC_ const char *get_proptag_name(uint32_t proptag)";
+ mparse "{";
+ indent;
+ mparse "uint32_t idx;";
+ mparse "";
+ mparse "for (idx = 0; mapitags[idx].proptag; idx++) {";
+ indent;
+ mparse "if (mapitags[idx].proptag == proptag) { ";
+ indent;
+ mparse "return mapitags[idx].propname;";
+ deindent;
+ mparse "}";
+ deindent;
+ mparse "}";
+ mparse "";
+ mparse "return NULL;";
+ deindent;
+ mparse "}";
+ mparse "";
+ mparse "_PUBLIC_ uint32_t get_proptag_value(const char *propname)";
+ mparse "{";
+ indent;
+ mparse "uint32_t idx;";
+ mparse "";
+ mparse "for (idx = 0; mapitags[idx].proptag; idx++) {";
+ indent;
+ mparse "if (!strcmp(mapitags[idx].propname, propname)) { ";
+ indent;
+ mparse "return mapitags[idx].proptag;";
+ deindent;
+ mparse "}";
+ deindent;
+ mparse "}";
+ mparse "";
+ mparse "return 0;";
+ deindent;
+ mparse "}";
+ mparse "";
+
+ return $ret;
+
+}
+
+#####################################################################
+# generate mapitags_enum.idl file
+sub mapitags_enum($)
+{
+ my $contents = shift;
+ my $line;
+ my @lines;
+ my @prop;
+ my $prop_type;
+ my %hash;
+
+ mparse "/* parser auto-generated by mparse */";
+ mparse "";
+
+ mparse "typedef [v1_enum, flag(NDR_PAHEX)] enum {";
+ indent;
+
+ @lines = split(/\n/, $contents);
+ foreach $line (@lines) {
+ $line =~ s/^\#+.*$//;
+ if ($line) {
+ @prop = split(/\s+/, $line);
+ $prop_type = hex $prop[0];
+ $prop_type &= 0xFFFF;
+
+ mparse sprintf "%-51s = %s,", $prop[1], $prop[0];
+
+ if (($prop_type == 0x1e) || ($prop_type == 0x101e)) {
+ $prop_type = hex $prop[0];
+ $prop_type++;
+ mparse sprintf "%-51s = 0x%.8x,", "$prop[1]_UNICODE", $prop_type;
+ }
+ if (!exists($hash{((hex $prop[0]) & 0xFFFF0000)})) {
+ $prop_type = 0xa;
+ $prop_type += ((hex $prop[0]) & 0xFFFF0000);
+ mparse sprintf "%-51s = 0x%.8x,", "$prop[1]_ERROR", $prop_type;
+ $hash{((hex $prop[0]) & 0xFFFF0000)} = 1;
+ }
+ }
+ }
+ mparse sprintf "%-51s = %s", "MAPI_PROP_RESERVED", "0xFFFFFFFF";
+ deindent;
+ mparse "} MAPITAGS;";
+ mparse "";
+
+ return $ret;
+}
+
+#####################################################################
+# generate swig_mapitags.h file
+sub mapitags_swig($)
+{
+ my $contents = shift;
+ my $line;
+ my @lines;
+ my @prop;
+ my $prop_type;
+ my $prop_value;
+ my %hash;
+
+ mparse "/* parser auto-generated by mparse */";
+ mparse "#ifndef __SWIG_MAPITAGS_H__";
+ mparse "#define __SWIG_MAPITAGS_H__";
+ mparse "";
+
+ @lines = split(/\n/, $contents);
+ foreach $line (@lines) {
+ $line =~ s/^\#+.*$//;
+ if ($line) {
+ @prop = split(/\s+/, $line);
+ $prop_type = hex $prop[0];
+ $prop_type &= 0xFFFF;
+
+ mparse sprintf "#define %-51s %s", $prop[1], $prop[0];
+
+ if (($prop_type == 0x1e) || ($prop_type == 0x101e)) {
+ $prop_type = hex $prop[0];
+ $prop_type++;
+ mparse sprintf "#define %-51s 0x%.8x", "$prop[1]_UNICODE", $prop_type;
+ }
+ if (!exists($hash{((hex $prop[0]) & 0xFFFF0000)})) {
+ $prop_type = 0xa;
+ $prop_type += ((hex $prop[0]) & 0xFFFF0000);
+ mparse sprintf "#define %-51s 0x%.8x", "$prop[1]_ERROR", $prop_type;
+ $hash{((hex $prop[0]) & 0xFFFF0000)} = 1;
+ }
+ }
+ }
+
+ mparse "";
+ mparse "#endif /* !__SWIG_MAPITAGS_H__ */";
+
+ return $ret;
+}
+
+#####################################################################
+# generate mapi_nameid_private.h file
+sub mapi_nameid_private_header($)
+{
+ my $contents = shift;
+ my $line;
+ my @lines;
+ my @prop;
+ my $prop_OOM;
+ my $prop_ID;
+ my $prop_Type;
+ my $prop_name;
+ my $prop_Kind;
+ my $prop_OLEGUID;
+
+ mparse "/* parser auto-generated by mparse */";
+ mparse "#ifndef __MAPI_NAMEID_PRIVATE_H__";
+ mparse "#define __MAPI_NAMEID_PRIVATE_H__";
+ mparse "";
+ mparse "static struct mapi_nameid_tags mapi_nameid_tags[] = {";
+ indent;
+
+ @lines = split(/\n/, $contents);
+ foreach $line (@lines) {
+ $line =~ s/^\#+.*$//;
+ if ($line) {
+ @prop = split(/\s+/, $line);
+
+ if ($prop[1] ne "NULL") {
+ $prop[1] = sprintf "\"%s\"", $prop[1];
+ }
+ if ($prop[3] ne "NULL") {
+ $prop[3] = sprintf "\"%s\"", $prop[3]
+ }
+ if ($prop[0] eq "NULL") {
+ $prop[0] = "0x00000000";
+ }
+ mparse sprintf "{ %-51s, %-40s, %-15s, %-30s, %-30s, %-15s, %-20s, 0x0 },",
+ $prop[0], $prop[1], $prop[2], $prop[3], $prop[4], $prop[5], $prop[6];
+ }
+ }
+
+ mparse sprintf "{ 0x00000000, NULL, 0x0, NULL, PT_UNSPECIFIED, 0x0, NULL, 0x0 }";
+ deindent;
+ mparse "};";
+ mparse "";
+ mparse "#endif /* !MAPI_NAMEID_PRIVATE_H__ */";
+
+ return $ret;
+}
+
+#####################################################################
+# generate mapi_nameid.h file
+sub mapi_nameid_header($)
+{
+ my $contents = shift;
+ my $line;
+ my @lines;
+ my @prop;
+ my $propID;
+ my $proptype;
+ my $property;
+ my $counter = 0;
+
+ mparse "/* parser auto-generated by mparse */";
+ mparse "#ifndef __MAPI_NAMEID_H__";
+ mparse "#define __MAPI_NAMEID_H__";
+ mparse "";
+
+ mparse "/* NOTE TO DEVELOPERS: If this is a MNID_STRING named property,";
+ mparse " * then we use the arbitrary 0xa000-0afff property ID range for";
+ mparse " * internal mapping purpose only.";
+ mparse " */";
+
+ mparse "";
+ mparse "struct mapi_nameid_tags {";
+ indent;
+ mparse "uint32_t proptag;";
+ mparse "const char *OOM;";
+ mparse "uint16_t lid;";
+ mparse "const char *Name;";
+ mparse "uint32_t propType;";
+ mparse "uint8_t ulKind;";
+ mparse "const char *OLEGUID;";
+ mparse "uint32_t position;";
+ deindent;
+ mparse "};";
+ mparse "";
+ mparse "struct mapi_nameid {";
+ indent;
+ mparse "struct MAPINAMEID *nameid;";
+ mparse "uint16_t count;";
+ mparse "struct mapi_nameid_tags *entries;";
+ deindent;
+ mparse "};";
+ mparse "";
+
+ @lines = split(/\n/, $contents);
+ foreach $line (@lines) {
+ $line =~ s/^\#+.*$//;
+ if ($line) {
+ @prop = split(/\s+/, $line);
+ if ($prop[0] ne "NULL") {
+ $proptype = $prop_names{$prop[4]};
+ $propID = hex $prop[2];
+ if ($propID == 0) {
+ # 40960 == 0xa000
+ $propID = 40960 + $counter;
+ $counter++;
+ }
+ $property = sprintf "0x%.8x", ($propID << 16) | $proptype;
+ mparse sprintf "#define %-51s %s", $prop[0], $property;
+ }
+ }
+ }
+
+ mparse "";
+ mparse "#endif /* !MAPI_NAMEID_H__ */";
+
+ return $ret;
+}
+
+#####################################################################
+# generate mapicode.h file
+sub mapicodes_header($)
+{
+ my $contents = shift;
+ my $line;
+ my @lines;
+ my @prop;
+ my $error;
+
+ mparse "/* parser auto-generated by mparse */";
+ mparse "#ifndef __MAPICODE_H__";
+ mparse "#define __MAPICODE_H__";
+ mparse "";
+ mparse "#define MAPI_RETVAL_IF(x,e,c) \\";
+ mparse "do { \\";
+ mparse " if (x) { \\";
+ mparse " errno = (e); \\";
+ mparse " if (c) { \\";
+ mparse " talloc_free(c); \\";
+ mparse " } \\";
+ mparse " return -1; \\";
+ mparse " } \\";
+ mparse "} while (0);";
+ mparse "";
+ mparse "#define OPENCHANGE_RETVAL_IF(x,e,c) \\";
+ mparse "do { \\";
+ mparse " if (x) { \\";
+ mparse " set_errno(e); \\";
+ mparse " if (c) { \\";
+ mparse " talloc_free(c); \\";
+ mparse " } \\";
+ mparse " return (e); \\";
+ mparse " } \\";
+ mparse "} while (0);";
+ mparse "";
+ mparse "#define OPENCHANGE_RETVAL_ERR(e,c) \\";
+ mparse "do { \\";
+ mparse " set_errno(e); \\";
+ mparse " if (c) { \\";
+ mparse " talloc_free(c); \\";
+ mparse " } \\";
+ mparse " return (e); \\";
+ mparse "} while (0);";
+ mparse "";
+ mparse "/* Status macros for MAPI */";
+ mparse "typedef unsigned long SCODE;";
+ mparse "";
+ mparse "";
+ mparse "#define SEVERITY_ERROR 1";
+ mparse "#define SEVERITY_WARN 0";
+ mparse "";
+ mparse "#define FACILITY_ITF 4";
+ mparse "#define MAKE_MAPI_CODE(sev, fac, code) \\";
+ mparse "(((SCODE)(sev)<<31)|((SCODE)(fac)<<16)|((SCODE)(code)))";
+ mparse "";
+ mparse "#define MAKE_MAPI_E(code) (MAKE_MAPI_CODE(SEVERITY_ERROR, FACILITY_ITF, code))";
+ mparse "#define MAKE_MAPI_S(code) (MAKE_MAPI_CODE(SEVERITY_WARN, FACILITY_ITF, code))";
+ mparse "";
+ mparse "#define MAPI_STATUS_V(x) ((SCODE)x)";
+ mparse "";
+ mparse "#define MAPI_STATUS_IS_OK(x) (MAPI_STATUS_V(x) == 0)";
+ mparse "#define MAPI_STATUS_IS_ERR(x) ((MAPI_STATUS_V(x) & 0xc0000000) == 0xc0000000)";
+ mparse "#define MAPI_STATUS_EQUAL(x,y) (MAPI_STATUS_V(x) == MAPI_STATUS_V(y))";
+ mparse "";
+ mparse "#define MAPI_STATUS_IS_OK_RETURN(x) do { \\";
+ mparse " if (MAPI_STATUS_IS_OK(x)) {\\";
+ mparse " return x;\\";
+ mparse " }\\";
+ mparse "} while (0)";
+ mparse "";
+ mparse "#define MAPI_STATUS_NOT_OK_RETURN(x) do { \\";
+ mparse " if (!MAPI_STATUS_IS_OK(x)) {\\";
+ mparse " return x;\\";
+ mparse " }\\";
+ mparse "} while (0)";
+ mparse "";
+ mparse "#define MAPI_STATUS_IS_ERR_RETURN(x) do { \\";
+ mparse " if (MAPI_STATUS_IS_ERR(x)) {\\";
+ mparse " return x;\\";
+ mparse " }\\";
+ mparse "} while (0)";
+ mparse "";
+ mparse "#define MAPI_STATUS_NOT_ERR_RETURN(x) do { \\";
+ mparse " if (!MAPI_STATUS_IS_ERR(x)) {\\";
+ mparse " return x;\\";
+ mparse " }\\";
+ mparse "} while (0)";
+ mparse "";
+ mparse "";
+ mparse "#endif /* !__MAPICODE_H__ */";
+
+ return $ret;
+
+}
+
+#####################################################################
+# generate mapicode.c file
+
+sub mapicodes_interface($)
+{
+ my $contents = shift;
+ my $line;
+ my @lines;
+ my @errors;
+
+ mparse "/* parser auto-generated by mparse */";
+ mparse "#include <libmapi/libmapi.h>";
+ mparse "#include <libmapi/proto_private.h>";
+ mparse "#include <gen_ndr/ndr_exchange.h>";
+ mparse "";
+ mparse "void set_errno(enum MAPISTATUS status)";
+ mparse "{";
+ indent;
+ mparse "errno = status;";
+ deindent;
+ mparse "}";
+ mparse "";
+ mparse "struct mapi_retval {";
+ indent;
+ mparse "uint32_t err;";
+ mparse "const char *name;";
+ deindent;
+ mparse "};";
+ mparse "";
+ mparse "static const struct mapi_retval mapi_retval[] = {";
+ indent;
+
+ @lines = split(/\n/, $contents);
+ foreach $line (@lines) {
+ $line =~ s/^\#+.*$//;
+ if ($line) {
+ @errors = split(/\s+/, $line);
+ mparse sprintf "{ %8s, \"%s\" },", $errors[0], $errors[1];
+ }
+ }
+
+
+ mparse " { 0x00000000, NULL }";
+ deindent;
+ mparse "};";
+ mparse "";
+ mparse "_PUBLIC_ void mapi_errstr(const char *function, uint32_t mapi_code)";
+ mparse "{";
+ indent;
+ mparse "struct ndr_print ndr_print;";
+ mparse "";
+ mparse "ndr_print.depth = 1;";
+ mparse "ndr_print.print = ndr_print_debug_helper;";
+ mparse "ndr_print_MAPISTATUS(&ndr_print, function, mapi_code);";
+ deindent;
+ mparse "}";
+ mparse "";
+ mparse "_PUBLIC_ const char *mapi_get_errstr(uint32_t mapi_code)";
+ mparse "{";
+ indent;
+ mparse "uint32_t i;";
+ mparse "";
+ mparse "for (i = 0; mapi_retval[i].name; i++) {";
+ indent;
+ mparse "if (mapi_retval[i].err == mapi_code) {";
+ indent;
+ mparse "return mapi_retval[i].name;";
+ deindent;
+ mparse "}";
+ deindent;
+ mparse "}";
+ mparse "";
+ mparse "return NULL;";
+ deindent;
+ mparse "}";
+}
+
+#####################################################################
+# generate mapicodes_enum.idl file
+sub mapicodes_enum($)
+{
+ my $contents = shift;
+ my $line;
+ my @lines;
+ my @prop;
+ my $prop_type;
+
+ mparse "/* parser auto-generated by mparse */";
+ mparse "";
+
+ mparse "typedef [public, v1_enum, flag(NDR_PAHEX)] enum {";
+ indent;
+
+ @lines = split(/\n/, $contents);
+ foreach $line (@lines) {
+ $line =~ s/^\#+.*$//;
+ if ($line) {
+ @prop = split(/\s+/, $line);
+ mparse sprintf "%-51s = %s,", $prop[1], $prop[0];
+ }
+ }
+ mparse sprintf "%-51s = %s", "MAPI_E_RESERVED", "0xFFFFFFFF";
+ deindent;
+ mparse "} MAPISTATUS;";
+ mparse "";
+
+ return $ret;
+}
+
+#####################################################################
+# generate openchangedb_property.c file
+sub openchangedb_property($)
+{
+ my $contents = shift;
+ my $line;
+ my @lines;
+ my @prop;
+ my $prop_type;
+ my $prop_value;
+ my $pidtag;
+
+ mparse "/* parser auto-generated by mparse */";
+ mparse "#include <mapiproxy/dcesrv_mapiproxy.h>";
+ mparse "#include \"libmapiproxy.h\"";
+ mparse "#include <libmapi/libmapi.h>";
+ mparse "#include <libmapi/proto_private.h>";
+ mparse "#include <libmapi/defs_private.h>";
+ mparse "";
+ mparse "struct pidtags {";
+ mparse " uint32_t proptag;";
+ mparse " const char *pidtag;";
+ mparse "};";
+ mparse "";
+ mparse "static struct pidtags pidtags[] = {";
+ indent;
+
+ @lines = split(/\n/, $contents);
+ foreach $line (@lines) {
+ $line =~ s/^\#+.*$//;
+ if ($line) {
+ @prop = split(/\s+/, $line);
+ $prop_type = hex $prop[0];
+ $prop_type &= 0xFFFF;
+ $prop_value = hex $prop[0];
+ $prop_value = ($prop_value >> 16) & 0xFFFF;
+ if ($prop_types{$prop_type}) {
+ if ($prop[2]) {
+ mparse sprintf "{ %-51s, \"%s\"},", $prop[1], $prop[2];
+ } else {
+ mparse sprintf "{ %-51s, \"0x%.8x\"},", $prop[1], hex $prop[0];
+ }
+
+ if (($prop_type == 0x1e) || ($prop_type == 0x101e)) {
+ if ($prop[2]) {
+ mparse sprintf "{ %-51s, \"%s\"},", "$prop[1]_UNICODE", $prop[2];
+ } else {
+ mparse sprintf "{ %-51s, \"0x%.8x\"},", "$prop[1]_UNICODE", hex $prop[0];
+ }
+ }
+ }
+ }
+ }
+
+ mparse sprintf "{ %-51s, NULL }", 0;
+ deindent;
+ mparse "};";
+ mparse "";
+ mparse "_PUBLIC_ const char *openchangedb_property_get_attribute(uint32_t proptag)";
+ mparse "{";
+ indent;
+ mparse "uint32_t i;";
+ mparse "";
+ mparse "for (i = 0; pidtags[i].pidtag; i++) {";
+ indent;
+ mparse "if (pidtags[i].proptag == proptag) {";
+ indent;
+ mparse "return pidtags[i].pidtag;";
+ deindent;
+ mparse "}";
+ deindent;
+ mparse "}";
+ mparse "DEBUG(0, (\"[%s:%d]: Unsupported property tag '0x%.8x'\\n\", __FUNCTION__, __LINE__, proptag));";
+ mparse "";
+ mparse "return NULL;";
+ deindent;
+ mparse "}";
+}
+
+#####################################################################
+# generate swig_mapicodes.h file
+sub mapicodes_swig($)
+{
+ my $contents = shift;
+ my $line;
+ my @lines;
+ my @prop;
+ my $prop_type;
+ my $prop_value;
+
+ mparse "/* parser auto-generated by mparse */";
+ mparse "#ifndef __SWIG_MAPICODES_H__";
+ mparse "#define __SWIG_MAPICODES_H__";
+ mparse "";
+
+ @lines = split(/\n/, $contents);
+ foreach $line (@lines) {
+ $line =~ s/^\#+.*$//;
+ if ($line) {
+ @prop = split(/\s+/, $line);
+ mparse sprintf "#define %-51s %s", $prop[1], $prop[0];
+ }
+ }
+ mparse sprintf "#define %-51s %s", "MAPI_E_RESERVED", "0xFFFFFFFF";
+ mparse "";
+ mparse "#endif /* !__SWIG_MAPITAGS_H__ */";
+
+ return $ret;
+}
+
+sub process_file($)
+{
+ my $mapi_file = shift;
+ my $outputdir = $opt_outputdir;
+
+ print "Parsing $mapi_file\n";
+ my $contents = FileLoad($mapi_file);
+ defined $contents || return undef;
+
+
+ if ($opt_parser eq "mapitags") {
+ print "Generating $outputdir" . "mapitags.h\n";
+ my $parser = ("$outputdir/mapitags.h");
+ FileSave($parser, mapitags_header($contents));
+
+ print "Generating $outputdir" . "mapitags.c\n";
+ $ret = '';
+ my $code_parser = ("$outputdir/mapitags.c");
+ FileSave($code_parser, mapitags_interface($contents));
+
+ print "Generating mapitags_enum.h\n";
+ $ret = '';
+ my $enum_parser = ("mapitags_enum.h");
+ FileSave($enum_parser, mapitags_enum($contents));
+ }
+
+ if ($opt_parser eq "mapicodes") {
+ print "Generating $outputdir" . "mapicode.h\n";
+ my $parser = ("$outputdir/mapicode.h");
+ FileSave($parser, mapicodes_header($contents));
+
+ print "Generating $outputdir" . "mapicode.c\n";
+ $ret = '';
+ my $code_parser = ("$outputdir/mapicode.c");
+ FileSave($code_parser, mapicodes_interface($contents));
+
+ print "Generating mapicodes_enum.h\n";
+ $ret = '';
+ my $enum_parser = ("mapicodes_enum.h");
+ FileSave($enum_parser, mapicodes_enum($contents));
+ }
+
+ if ($opt_parser eq "mapi_nameid") {
+ print "Generating $outputdir" . "mapi_nameid_private.h\n";
+ $ret = '';
+ my $parser = ("$outputdir/mapi_nameid_private.h");
+ FileSave($parser, mapi_nameid_private_header($contents));
+
+ print "Generating $outputdir" . "mapi_nameid.h\n";
+ $ret = '';
+ my $nameid_parser = ("$outputdir/mapi_nameid.h");
+ FileSave($nameid_parser, mapi_nameid_header($contents));
+ }
+
+ if ($opt_parser eq "swig_mapitags") {
+ print "Generating $outputdir" . "swig_mapitags.h\n";
+ $ret = '';
+ my $swig_parser_tag = ("$outputdir/swig_mapitags.h");
+ FileSave($swig_parser_tag, mapitags_swig($contents));
+ }
+
+ if ($opt_parser eq "swig_mapicodes") {
+ print "Generating $outputdir" . "swig_mapicodes.h\n";
+ my $swig_parser_code = ("$outputdir/swig_mapicodes.h");
+ FileSave($swig_parser_code, mapicodes_swig($contents));
+ }
+
+ if ($opt_parser eq "openchangedb_property") {
+ print "Generating $outputdir" . "openchangedb_property.c\n";
+ my $openchangedb_parser = ("$outputdir/openchangedb_property.c");
+ FileSave($openchangedb_parser, openchangedb_property($contents));
+ }
+}
+
+process_file($_) foreach (@ARGV);
Property changes on: trunk/openchange/libmapi/conf/mparse.pl
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/libmapi/defs_private.h
===================================================================
--- trunk/openchange/libmapi/defs_private.h (rev 0)
+++ trunk/openchange/libmapi/defs_private.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,43 @@
+/*
+ OpenChange MAPI implementation.
+ Private definitions
+
+ Copyright (C) Brad Hards <bradh at frogmouth.net> 2008.
+
+ 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 _DEFS_PRIVATE_H
+#define _DEFS_PRIVATE_H
+
+/* These are essentially local versions of part of the
+ C99 __STDC_FORMAT_MACROS */
+#ifndef PRIx64
+#if __WORDSIZE == 64
+ #define PRIx64 "lx"
+#else
+ #define PRIx64 "llx"
+#endif
+#endif
+
+#ifndef PRIX64
+#if __WORDSIZE == 64
+ #define PRIX64 "lX"
+#else
+ #define PRIX64 "llX"
+#endif
+#endif
+
+
+#endif /* ! _DEFS_PRIVATE_H */
Added: trunk/openchange/libmapi/dlinklist.h
===================================================================
--- trunk/openchange/libmapi/dlinklist.h (rev 0)
+++ trunk/openchange/libmapi/dlinklist.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,110 @@
+/*
+ Unix SMB/CIFS implementation.
+ some simple double linked list macros
+ Copyright (C) Andrew Tridgell 1998
+
+ 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/>.
+*/
+
+/* To use these macros you must have a structure containing a next and
+ prev pointer */
+
+
+/* hook into the front of the list */
+#define DLIST_ADD(list, p) \
+do { \
+ if (!(list)) { \
+ (list) = (p); \
+ (p)->next = (p)->prev = NULL; \
+ } else { \
+ (list)->prev = (p); \
+ (p)->next = (list); \
+ (p)->prev = NULL; \
+ (list) = (p); \
+ }\
+} while (0)
+
+/* remove an element from a list - element doesn't have to be in list. */
+#ifndef DLIST_REMOVE
+#define DLIST_REMOVE(list, p) \
+do { \
+ if ((p) == (list)) { \
+ (list) = (p)->next; \
+ if (list) (list)->prev = NULL; \
+ } else { \
+ if ((p)->prev) (p)->prev->next = (p)->next; \
+ if ((p)->next) (p)->next->prev = (p)->prev; \
+ } \
+ if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
+} while (0)
+#endif
+
+/* promote an element to the top of the list */
+#define DLIST_PROMOTE(list, p) \
+do { \
+ DLIST_REMOVE(list, p); \
+ DLIST_ADD(list, p); \
+} while (0)
+
+/* hook into the end of the list - needs a tmp pointer */
+#define DLIST_ADD_END(list, p, type) \
+do { \
+ if (!(list)) { \
+ (list) = (p); \
+ (p)->next = (p)->prev = NULL; \
+ } else { \
+ type tmp; \
+ for (tmp = (list); tmp->next; tmp = tmp->next) ; \
+ tmp->next = (p); \
+ (p)->next = NULL; \
+ (p)->prev = tmp; \
+ } \
+} while (0)
+
+/* insert 'p' after the given element 'el' in a list. If el is NULL then
+ this is the same as a DLIST_ADD() */
+#define DLIST_ADD_AFTER(list, p, el) \
+do { \
+ if (!(list) || !(el)) { \
+ DLIST_ADD(list, p); \
+ } else { \
+ p->prev = el; \
+ p->next = el->next; \
+ el->next = p; \
+ if (p->next) p->next->prev = p; \
+ }\
+} while (0)
+
+/* demote an element to the end of the list, needs a tmp pointer */
+#define DLIST_DEMOTE(list, p, tmp) \
+do { \
+ DLIST_REMOVE(list, p); \
+ DLIST_ADD_END(list, p, tmp); \
+} while (0)
+
+/* concatenate two lists - putting all elements of the 2nd list at the
+ end of the first list */
+#define DLIST_CONCATENATE(list1, list2, type) \
+do { \
+ if (!(list1)) { \
+ (list1) = (list2); \
+ } else { \
+ type tmp; \
+ for (tmp = (list1); tmp->next; tmp = tmp->next) ; \
+ tmp->next = (list2); \
+ if (list2) { \
+ (list2)->prev = tmp; \
+ } \
+ } \
+} while (0)
Added: trunk/openchange/libmapi/emsmdb.c
===================================================================
--- trunk/openchange/libmapi/emsmdb.c (rev 0)
+++ trunk/openchange/libmapi/emsmdb.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,835 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2005 - 2008.
+ Copyright (C) Jelmer Vernooij 2005.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+#include <gen_ndr/ndr_exchange_c.h>
+#include <gen_ndr/ndr_misc.h>
+
+#include <param.h>
+#include <credentials.h>
+
+/**
+ \file emsmdb.c
+
+ \brief EMSMDB stack functions
+ */
+
+
+/**
+ \details Hash a string and returns a unsigned integer hash value
+
+ \param str the string to hash
+
+ \return a hash value greater than 0 on success, otherwise 0
+
+ \note This function is based on the hash algorithm from gdbm and
+ from Samba4 TDB code.
+ */
+static unsigned int emsmdb_hash(const char *str)
+{
+ uint32_t value; /* Used to compute the hash value. */
+ uint32_t i; /* Used to cycle through random values. */
+ uint32_t len;
+
+ /* Sanity check */
+ if (!str) return 0;
+
+ len = strlen(str);
+
+ /* Set the initial value from the key size. */
+ for (value = 0x238F13AF * len, i = 0; i < len; i++)
+ value = (value + (str[i] << (i * 5 % 24)));
+
+ return (1103515243 * value + 12345);
+}
+
+
+/**
+ \details Establishes a new Session Context with the server on the
+ exchange_emsmdb pipe
+
+ \param parent_mem_ctx pointer to the memory context
+ \param session pointer to the MAPI session context
+ \param p pointer to the DCERPC pipe
+ \param cred pointer to the user credentials
+
+ \return an allocated emsmdb_context on success, otherwise NULL
+ */
+struct emsmdb_context *emsmdb_connect(TALLOC_CTX *parent_mem_ctx,
+ struct mapi_session *session,
+ struct dcerpc_pipe *p,
+ struct cli_credentials *cred)
+{
+ TALLOC_CTX *mem_ctx;
+ struct EcDoConnect r;
+ struct emsmdb_context *ret;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t pullTimeStamp = 0;
+
+ /* Sanity Checks */
+ if (!session) return NULL;
+ if (!p) return NULL;
+ if (!cred) return NULL;
+
+ mem_ctx = talloc_named(NULL, 0, "emsmdb_connect");
+
+ ret = talloc_zero(parent_mem_ctx, struct emsmdb_context);
+ ret->rpc_connection = p;
+ ret->mem_ctx = parent_mem_ctx;
+
+ ret->cache_requests = talloc(parent_mem_ctx, struct EcDoRpc_MAPI_REQ *);
+ ret->info.szDisplayName = NULL;
+ ret->info.szDNPrefix = NULL;
+
+ r.in.szUserDN = session->profile->mailbox;
+ r.in.ulFlags = 0x00000000;
+ r.in.ulConMod = emsmdb_hash(r.in.szUserDN);
+ r.in.cbLimit = 0x00000000;
+ r.in.ulCpid = session->profile->codepage;
+ r.in.ulLcidString = session->profile->language;
+ r.in.ulLcidSort = session->profile->method;
+ r.in.ulIcxrLink = 0xFFFFFFFF;
+ r.in.usFCanConvertCodePages = 0x1;
+ r.in.rgwClientVersion[0] = 0x000c;
+ r.in.rgwClientVersion[1] = 0x183e;
+ r.in.rgwClientVersion[2] = 0x03e8;
+ r.in.pullTimeStamp = &pullTimeStamp;
+
+ r.out.handle = &ret->handle;
+ r.out.pcmsPollsMax = &ret->info.pcmsPollsMax;
+ r.out.pcRetry = &ret->info.pcRetry;
+ r.out.pcmsRetryDelay = &ret->info.pcmsRetryDelay;
+ r.out.picxr = &ret->info.picxr;
+ r.out.rgwServerVersion[0] = ret->info.rgwServerVersion[0];
+ r.out.rgwServerVersion[1] = ret->info.rgwServerVersion[1];
+ r.out.rgwServerVersion[2] = ret->info.rgwServerVersion[2];
+ r.out.pullTimeStamp = &pullTimeStamp;
+
+ status = dcerpc_EcDoConnect(p, mem_ctx, &r);
+ retval = r.out.result;
+ if (!NT_STATUS_IS_OK(status) || retval) {
+ mapi_errstr("EcDoConnect", retval);
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ ret->info.szDisplayName = talloc_strdup(parent_mem_ctx, r.out.szDisplayName);
+ ret->info.szDNPrefix = talloc_strdup(parent_mem_ctx, r.out.szDNPrefix);
+
+ ret->cred = cred;
+ ret->max_data = 0xFFF0;
+ ret->setup = false;
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+
+/**
+ \details Destructor for the EMSMDB context. Call the EcDoDisconnect
+ function.
+
+ \param data generic pointer to data with mapi_provider information
+
+ \return MAPI_E_SUCCESS on success, otherwise -1
+ */
+int emsmdb_disconnect_dtor(void *data)
+{
+ struct mapi_provider *provider = (struct mapi_provider *)data;
+ struct emsmdb_context *emsmdb_ctx;
+
+ emsmdb_ctx = (struct emsmdb_context *)provider->ctx;
+ emsmdb_disconnect(provider->ctx);
+
+ talloc_free(emsmdb_ctx->cache_requests);
+
+ if (emsmdb_ctx->info.szDisplayName) {
+ talloc_free(emsmdb_ctx->info.szDisplayName);
+ }
+
+ if (emsmdb_ctx->info.szDNPrefix) {
+ talloc_free(emsmdb_ctx->info.szDNPrefix);
+ }
+
+ return 0;
+}
+
+
+/**
+ \details Destroy the EMSMDB context handle
+
+ \param emsmdb_ctx pointer to the EMSMDB context
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+enum MAPISTATUS emsmdb_disconnect(struct emsmdb_context *emsmdb_ctx)
+{
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ struct EcDoDisconnect r;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!emsmdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ r.in.handle = r.out.handle = &emsmdb_ctx->handle;
+
+ status = dcerpc_EcDoDisconnect(emsmdb_ctx->rpc_connection, emsmdb_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Send an empty MAPI packet - useful to keep connection up
+ or force notifications.
+
+ \param emsmdb_ctx pointer to the EMSMDB connection context
+ \param res pointer on pointer to a MAPI response structure
+
+ \return NT_STATUS_OK on success, otherwise NT status error
+ */
+_PUBLIC_ NTSTATUS emsmdb_transaction_null(struct emsmdb_context *emsmdb_ctx,
+ struct mapi_response **res)
+{
+ struct EcDoRpc r;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ NTSTATUS status;
+ uint16_t *length;
+
+ /* Sanity checks */
+ if(!emsmdb_ctx) return NT_STATUS_INVALID_PARAMETER;
+ if (!res) return NT_STATUS_INVALID_PARAMETER;
+
+ mapi_request = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_request);
+ mapi_response = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_response);
+
+ r.in.mapi_request = mapi_request;
+ r.in.mapi_request->mapi_len = 2;
+ r.in.mapi_request->length = 2;
+
+ r.in.handle = r.out.handle = &emsmdb_ctx->handle;
+ r.in.size = emsmdb_ctx->max_data;
+ r.in.offset = 0x0;
+ r.in.max_data = emsmdb_ctx->max_data;
+ length = talloc_zero(emsmdb_ctx->mem_ctx, uint16_t);
+ *length = r.in.mapi_request->mapi_len;
+ r.in.length = r.out.length = length;
+
+ r.out.mapi_response = mapi_response;
+
+ status = dcerpc_EcDoRpc(emsmdb_ctx->rpc_connection, emsmdb_ctx->mem_ctx, &r);
+ if (!MAPI_STATUS_IS_OK(NT_STATUS_V(status))) {
+ return status;
+ }
+
+ *res = mapi_response;
+
+ return status;
+}
+
+
+static int mapi_response_destructor(void *data)
+{
+ struct mapi_response *mapi_response = (struct mapi_response *)data;
+
+ if (mapi_response->handles) {
+ talloc_free(mapi_response->handles);
+ }
+
+ if (mapi_response->mapi_repl) {
+ talloc_free(mapi_response->mapi_repl);
+ }
+
+ return 0;
+}
+
+
+/**
+ \details Make a EMSMDB transaction.
+
+ \param emsmdb_ctx pointer to the EMSMDB connection context
+ \param req pointer to the MAPI request to send
+ \param repl pointer on pointer to the MAPI reply returned by the
+ server
+
+ \return NT_STATUS_OK on success, otherwise NT status error
+ */
+_PUBLIC_ NTSTATUS emsmdb_transaction(struct emsmdb_context *emsmdb_ctx,
+ struct mapi_request *req,
+ struct mapi_response **repl)
+{
+ TALLOC_CTX *mem_ctx;
+ struct EcDoRpc r;
+ struct mapi_response *mapi_response;
+ uint16_t *length;
+ NTSTATUS status;
+ struct EcDoRpc_MAPI_REQ *multi_req;
+ uint8_t i = 0;
+
+start:
+ mem_ctx = talloc_named(NULL, 0, "emsmdb_transaction");
+
+ r.in.handle = r.out.handle = &emsmdb_ctx->handle;
+ r.in.size = emsmdb_ctx->max_data;
+ r.in.offset = 0x0;
+
+ mapi_response = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_response);
+ talloc_set_destructor((void *)mapi_response, (int (*)(void *))mapi_response_destructor);
+ r.out.mapi_response = mapi_response;
+
+ /* process cached data */
+ if (emsmdb_ctx->cache_count) {
+ multi_req = talloc_array(mem_ctx, struct EcDoRpc_MAPI_REQ, emsmdb_ctx->cache_count + 2);
+ for (i = 0; i < emsmdb_ctx->cache_count; i++) {
+ multi_req[i] = *emsmdb_ctx->cache_requests[i];
+ }
+ multi_req[i] = req->mapi_req[0];
+ req->mapi_req = multi_req;
+ }
+
+ req->mapi_req = talloc_realloc(mem_ctx, req->mapi_req, struct EcDoRpc_MAPI_REQ, emsmdb_ctx->cache_count + 2);
+ req->mapi_req[i+1].opnum = 0;
+
+ r.in.mapi_request = req;
+ r.in.mapi_request->mapi_len += emsmdb_ctx->cache_size;
+ r.in.mapi_request->length += emsmdb_ctx->cache_size;
+ length = talloc_zero(mem_ctx, uint16_t);
+ *length = r.in.mapi_request->mapi_len;
+ r.in.length = r.out.length = length;
+ r.in.max_data = (*length >= 0x4000) ? 0x7FFF : emsmdb_ctx->max_data;
+
+ status = dcerpc_EcDoRpc(emsmdb_ctx->rpc_connection, emsmdb_ctx->mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (emsmdb_ctx->setup == false) {
+ errno = 0;
+ emsmdb_ctx->max_data = 0x7FFF;
+ emsmdb_ctx->setup = true;
+ talloc_free(mem_ctx);
+ goto start;
+ } else {
+ talloc_free(mem_ctx);
+ return status;
+ }
+ } else {
+ emsmdb_ctx->setup = true;
+ }
+ emsmdb_ctx->cache_size = emsmdb_ctx->cache_count = 0;
+
+ *repl = r.out.mapi_response;
+
+ talloc_free(mem_ctx);
+
+ return status;
+}
+
+
+/**
+ \details Initialize the notify context structure and bind a local
+ UDP port to receive notifications from the server
+
+ \param mem_ctx pointer to the memory context
+
+ \return an allocated mapi_notify_ctx structure on success,
+ otherwise NULL
+ */
+struct mapi_notify_ctx *emsmdb_bind_notification(TALLOC_CTX *mem_ctx)
+{
+ struct interface *ifaces;
+ struct mapi_notify_ctx *notify_ctx = NULL;
+ unsigned short port = DFLT_NOTIF_PORT;
+ const char *ipaddr = NULL;
+ uint32_t try = 0;
+
+ /* Sanity Checks */
+ if (!global_mapi_ctx) return NULL;
+ if (!global_mapi_ctx->session) return NULL;
+ if (!global_mapi_ctx->session->profile) return NULL;
+
+ notify_ctx = talloc_zero(mem_ctx, struct mapi_notify_ctx);
+
+ notify_ctx->notifications = talloc_zero((TALLOC_CTX *)notify_ctx, struct notifications);
+ notify_ctx->notifications->prev = NULL;
+ notify_ctx->notifications->next = NULL;
+
+ load_interfaces(mem_ctx, lp_interfaces(global_mapi_ctx->lp_ctx), &ifaces);
+ ipaddr = iface_best_ip(ifaces, global_mapi_ctx->session->profile->server);
+ if (!ipaddr) {
+ talloc_free(notify_ctx->notifications);
+ talloc_free(notify_ctx);
+ return NULL;
+ }
+ notify_ctx->addr = talloc_zero(mem_ctx, struct sockaddr);
+ notify_ctx->addr->sa_family = AF_INET;
+ ((struct sockaddr_in *)(notify_ctx->addr))->sin_addr.s_addr = inet_addr(ipaddr);
+retry:
+ if (try) port++;
+ ((struct sockaddr_in *)(notify_ctx->addr))->sin_port = htons(port);
+
+ notify_ctx->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (notify_ctx->fd == -1) {
+ talloc_free(notify_ctx->notifications);
+ talloc_free(notify_ctx->addr);
+ talloc_free(notify_ctx);
+ return NULL;
+ }
+
+ if (bind(notify_ctx->fd, notify_ctx->addr, sizeof(struct sockaddr)) == -1) {
+ shutdown(notify_ctx->fd, SHUT_RDWR);
+ close(notify_ctx->fd);
+ if (try < 3) {
+ try++;
+ errno = 0;
+ goto retry;
+ }
+
+ talloc_free(notify_ctx->notifications);
+ talloc_free(notify_ctx->addr);
+ talloc_free(notify_ctx);
+ return NULL;
+ }
+
+ return notify_ctx;
+}
+
+
+/**
+ \details Register for notifications on the server
+
+ \param notifkey The opaque client-generated context data
+ \param ulEventMask Notification flags. Exchange completely ignores
+ this value and it should be set to 0
+
+ \return NTSTATUS_OK on success, otherwise NT status error
+ */
+NTSTATUS emsmdb_register_notification(struct NOTIFKEY *notifkey,
+ uint16_t ulEventMask)
+{
+ struct EcRRegisterPushNotification request;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct emsmdb_context *emsmdb_ctx;
+ struct mapi_session *session;
+ struct mapi_notify_ctx *notify_ctx;
+ struct policy_handle handle;
+ uint32_t hNotification = 0;
+
+ /* Sanity Checks*/
+ if (!global_mapi_ctx) return NT_STATUS_INVALID_PARAMETER;
+ if (!global_mapi_ctx->session) return NT_STATUS_INVALID_PARAMETER;
+ if (!global_mapi_ctx->session->emsmdb) return NT_STATUS_INVALID_PARAMETER;
+ if (!global_mapi_ctx->session->emsmdb->ctx) return NT_STATUS_INVALID_PARAMETER;
+ if (!notifkey) return NT_STATUS_INVALID_PARAMETER;
+
+ session = (struct mapi_session *)global_mapi_ctx->session;
+ emsmdb_ctx = (struct emsmdb_context *)session->emsmdb->ctx;
+ notify_ctx = (struct mapi_notify_ctx *)session->notify_ctx;
+ mem_ctx = talloc_named(NULL, 0, "emsmdb_register_notification");
+
+ request.in.handle = &emsmdb_ctx->handle;
+ request.in.ulEventMask = ulEventMask;
+ request.in.cbContext = notifkey->cb;
+ request.in.rgbContext = talloc_array(mem_ctx, uint8_t, request.in.cbContext);
+ memcpy(request.in.rgbContext, notifkey->ab, request.in.cbContext);
+ request.in.grbitAdviseBits = 0xffffffff;
+ request.in.rgCallbackAddress = talloc_array(mem_ctx, uint8_t, sizeof (struct sockaddr));
+ /* cp address family and length */
+ request.in.rgCallbackAddress[0] = (notify_ctx->addr->sa_family & 0xFF);
+ request.in.rgCallbackAddress[1] = (notify_ctx->addr->sa_family & 0xFF00) >> 8;
+ memcpy(&request.in.rgCallbackAddress[2], notify_ctx->addr->sa_data, 14);
+ request.in.cbCallbackAddress = sizeof (struct sockaddr);
+
+ request.out.handle = &handle;
+ request.out.hNotification = &hNotification;
+
+ status = dcerpc_EcRRegisterPushNotification(emsmdb_ctx->rpc_connection, emsmdb_ctx->mem_ctx, &request);
+ retval = request.out.result;
+ if (!NT_STATUS_IS_OK(status) || retval) {
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ talloc_free(mem_ctx);
+
+ return status;
+}
+
+
+/**
+ \details Retrieves the EMSMDB context server information structure
+
+ \param session pointer to the MAPI session context
+
+ \return the server info structure on success, otherwise NULL
+ */
+_PUBLIC_ struct emsmdb_info *emsmdb_get_info(struct mapi_session *session)
+{
+ if (!global_mapi_ctx || !session->emsmdb->ctx) {
+ return NULL;
+ }
+
+ return &((struct emsmdb_context *)session->emsmdb->ctx)->info;
+}
+
+
+/**
+ \details Retrieves a property value from a DATA blob
+
+ \param mem_ctx pointer to the memory context
+ \param lp_ctx pointer to the loadparm context
+ \param offset pointer on pointer to the current offset
+ \param tag the property tag which value is to be retrieved
+ \param data pointer to the data
+
+ \return pointer on constant generic data on success, otherwise NULL
+ */
+const void *pull_emsmdb_property(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ uint32_t *offset,
+ enum MAPITAGS tag,
+ DATA_BLOB *data)
+{
+ struct ndr_pull *ndr;
+ const char *pt_string8;
+ const char *pt_unicode;
+ uint16_t *pt_i2;
+ uint64_t *pt_i8;
+ uint32_t *pt_long;
+ uint8_t *pt_boolean;
+ struct FILETIME *pt_filetime;
+ struct GUID *pt_clsid;
+ struct SBinary_short pt_binary;
+ struct Binary_r *sbin;
+ struct mapi_SLPSTRArray pt_slpstr;
+ struct StringArray_r *slpstr;
+ struct mapi_MV_LONG_STRUCT pt_MVl;
+ struct LongArray_r *MVl;
+ struct mapi_SBinaryArray pt_MVbin;
+ struct BinaryArray_r *MVbin;
+ uint32_t i;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_pull);
+ ndr->offset = *offset;
+ ndr->data = data->data;
+ ndr->data_size = data->length;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ ndr->iconv_convenience = lp_iconv_convenience(lp_ctx);
+
+ switch(tag & 0xFFFF) {
+ case PT_I2:
+ pt_i2 = talloc_zero(mem_ctx, uint16_t);
+ ndr_pull_uint16(ndr, NDR_SCALARS, pt_i2);
+ *offset = ndr->offset;
+ talloc_free(ndr);
+ return (void *) pt_i2;
+ case PT_ERROR:
+ case PT_LONG:
+ pt_long = talloc_zero(mem_ctx, uint32_t);
+ ndr_pull_uint32(ndr, NDR_SCALARS, pt_long);
+ *offset = ndr->offset;
+ talloc_free(ndr);
+ return (void *) pt_long;
+ case PT_BOOLEAN:
+ pt_boolean = talloc_zero(mem_ctx, uint8_t);
+ ndr_pull_uint8(ndr, NDR_SCALARS, pt_boolean);
+ *offset = ndr->offset;
+ talloc_free(ndr);
+ return (void *) pt_boolean;
+ case PT_I8:
+ pt_i8 = talloc_zero(mem_ctx, uint64_t);
+ ndr_pull_hyper(ndr, NDR_SCALARS, pt_i8);
+ *offset = ndr->offset;
+ talloc_free(ndr);
+ return (void *) pt_i8;
+ case PT_UNICODE:
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ ndr_pull_string(ndr, NDR_SCALARS, &pt_unicode);
+ *offset = ndr->offset;
+ talloc_free(ndr);
+ return (const void *) pt_unicode;
+ case PT_STRING8:
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
+ ndr_pull_string(ndr, NDR_SCALARS, &pt_string8);
+ *offset = ndr->offset;
+ talloc_free(ndr);
+ return (const void *) pt_string8;
+ case PT_SYSTIME:
+ pt_filetime = talloc_zero(mem_ctx, struct FILETIME);
+ ndr_pull_hyper(ndr, NDR_SCALARS, (uint64_t *) pt_filetime);
+ *offset = ndr->offset;
+ talloc_free(ndr);
+ return (void *) pt_filetime;
+ case PT_CLSID:
+ pt_clsid = talloc_zero(mem_ctx, struct GUID);
+ ndr_pull_GUID(ndr, NDR_SCALARS, pt_clsid);
+ *offset = ndr->offset;
+ talloc_free(ndr);
+ return (void *) pt_clsid;
+ case 0xFB:
+ case PT_BINARY:
+ ndr_pull_SBinary_short(ndr, NDR_SCALARS, &pt_binary);
+ *offset = ndr->offset;
+ sbin = talloc_zero(mem_ctx, struct Binary_r);
+ sbin->cb = pt_binary.cb;
+ sbin->lpb = talloc_memdup(sbin, pt_binary.lpb, pt_binary.cb);
+ talloc_free(ndr);
+ return (void *) sbin;
+ case PT_MV_LONG:
+ ndr_pull_mapi_MV_LONG_STRUCT(ndr, NDR_SCALARS, &pt_MVl);
+ *offset = ndr->offset;
+ MVl = talloc_zero(mem_ctx, struct LongArray_r);
+ MVl->cValues = pt_MVl.cValues;
+ MVl->lpl = talloc_array(mem_ctx, uint32_t, pt_MVl.cValues);
+ for (i = 0; i < MVl->cValues; i++) {
+ MVl->lpl[i] = pt_MVl.lpl[i];
+ }
+ talloc_free(ndr);
+ return (const void *) MVl;
+ case PT_MV_STRING8:
+ ndr_pull_mapi_SLPSTRArray(ndr, NDR_SCALARS, &pt_slpstr);
+ *offset = ndr->offset;
+ slpstr = talloc_zero(mem_ctx, struct StringArray_r);
+ slpstr->cValues = pt_slpstr.cValues;
+ slpstr->lppszA = talloc_array(mem_ctx, const char *, pt_slpstr.cValues);
+ for (i = 0; i < slpstr->cValues; i++) {
+ slpstr->lppszA[i] = talloc_strdup(mem_ctx, pt_slpstr.strings[i].lppszA);
+ }
+ talloc_free(ndr);
+ return (const void *) slpstr;
+ case PT_MV_BINARY:
+ ndr_pull_mapi_SBinaryArray(ndr, NDR_SCALARS, &pt_MVbin);
+ *offset = ndr->offset;
+ MVbin = talloc_zero(mem_ctx, struct BinaryArray_r);
+ MVbin->cValues = pt_MVbin.cValues;
+ MVbin->lpbin = talloc_array(mem_ctx, struct Binary_r, pt_MVbin.cValues);
+ for (i = 0; i < MVbin->cValues; i++) {
+ MVbin->lpbin[i].cb = pt_MVbin.bin[i].cb;
+ MVbin->lpbin[i].lpb = talloc_size(mem_ctx, MVbin->lpbin[i].cb);
+ memcpy(MVbin->lpbin[i].lpb, pt_MVbin.bin[i].lpb, MVbin->lpbin[i].cb);
+ }
+ talloc_free(ndr);
+ return (const void *) MVbin;
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ \details Get a SPropValue array from a DATA blob
+
+ \param mem_ctx pointer to the memory context
+ \param lp_ctx pointer to the loadparm context
+ \param content pointer to the DATA blob content
+ \param tags pointer to a list of property tags to lookup
+ \param propvals pointer on pointer to the returned SPropValues
+ \param cn_propvals pointer to the number of propvals
+ \param flag describes the type data
+
+ \return MAPI_E_SUCCESS on success
+ */
+enum MAPISTATUS emsmdb_get_SPropValue(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ DATA_BLOB *content,
+ struct SPropTagArray *tags,
+ struct SPropValue **propvals,
+ uint32_t *cn_propvals,
+ uint8_t flag)
+{
+ struct SPropValue *p_propval;
+ uint32_t i_propval;
+ uint32_t i_tag;
+ uint32_t cn_tags;
+ uint32_t offset = 0;
+ const void *data;
+
+ i_propval = 0;
+ cn_tags = tags->cValues;
+ *cn_propvals = 0;
+ *propvals = talloc_array(mem_ctx, struct SPropValue, cn_tags + 1);
+
+ for (i_tag = 0; i_tag < cn_tags; i_tag++) {
+ if (flag) {
+ if (((uint8_t)(*(content->data + offset))) == PT_ERROR) {
+ tags->aulPropTag[i_tag] &= 0xFFFF0000;
+ tags->aulPropTag[i_tag] |= PT_ERROR;
+ }
+ offset += sizeof (uint8_t);
+ }
+
+ data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, tags->aulPropTag[i_tag], content);
+ if (data) {
+ p_propval = &((*propvals)[i_propval]);
+ p_propval->ulPropTag = tags->aulPropTag[i_tag];
+ p_propval->dwAlignPad = 0x0;
+ set_SPropValue(p_propval, data);
+ i_propval++;
+ }
+ }
+
+ (*propvals)[i_propval].ulPropTag = 0x0;
+ *cn_propvals = i_propval;
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Get a SRowSet from a DATA blob
+
+ \param mem_ctx pointer on the memory context
+ \param lp_ctx pointer on the loadparm context
+ \param rowset pointer on the returned SRowSe
+ \param proptags pointer on a list of property tags to lookup
+ \param content pointer on the DATA blob content
+
+ \return MAPI_E_SUCCESS on success
+
+ \note TODO: this doesn't yet handle the TypedPropertyValue and
+ FlaggedPropertyValueWithTypeSpecified variants
+ */
+_PUBLIC_ void emsmdb_get_SRowSet(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ struct SRowSet *rowset,
+ struct SPropTagArray *proptags,
+ DATA_BLOB *content)
+{
+ struct SRow *rows;
+ struct SPropValue *lpProps;
+ uint32_t idx;
+ uint32_t prop;
+ uint32_t offset = 0;
+ const void *data;
+ uint32_t row_count;
+ bool is_FlaggedPropertyRow = false;
+ bool havePropertyValue;
+ uint8_t flag;
+
+ /* caller allocated */
+ rows = rowset->aRow;
+ row_count = rowset->cRows;
+
+ for (idx = 0; idx < row_count; idx++) {
+ if (0x1 == *(content->data + offset)) {
+ is_FlaggedPropertyRow = true;
+ } else {
+ is_FlaggedPropertyRow = false;
+ }
+ ++offset;
+
+ lpProps = talloc_array(mem_ctx, struct SPropValue, proptags->cValues);
+ for (prop = 0; prop < proptags->cValues; prop++) {
+ havePropertyValue = true;
+ lpProps[prop].ulPropTag = proptags->aulPropTag[prop];
+ if (is_FlaggedPropertyRow) {
+ flag = (uint8_t)(*(content->data + offset));
+ ++offset; /* advance offset for the flag */
+ switch (flag) {
+ case 0x0:
+ /* Property Value is valid */
+ break;
+ case 0x1:
+ /* Property Value is not present */
+ havePropertyValue = false;
+ break;
+ case PT_ERROR:
+ lpProps[prop].ulPropTag = proptags->aulPropTag[prop];
+ lpProps[prop].ulPropTag &= 0xFFFF0000;
+ lpProps[prop].ulPropTag |= PT_ERROR;
+ break;
+ default:
+ /* unknown FlaggedPropertyValue flag */
+ break;
+
+ }
+ }
+ if (havePropertyValue) {
+ lpProps[prop].dwAlignPad = 0x0;
+ data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, lpProps[prop].ulPropTag, content);
+ set_SPropValue(&lpProps[prop], data);
+ }
+ }
+
+ rows[idx].ulAdrEntryPad = 0;
+ rows[idx].cValues = proptags->cValues;
+ rows[idx].lpProps = lpProps;
+ }
+}
+
+
+/**
+ \details Get a SRow from a DATA blob
+
+ \param mem_ctx pointer on the memory context
+ \param lp_ctx pointer on the loadparm context
+ \param aRow pointer on the returned SRow
+ \param proptags pointer on a list of property tags to lookup
+ \param propcount number of SPropValue entries in aRow
+ \param content pointer on the DATA blob content
+ \param flag the type data
+ \param align alignment pad
+
+ \return MAPI_E_SUCCESS on success
+
+ \note TODO: We shouldn't have any alignment pad here
+ */
+void emsmdb_get_SRow(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ struct SRow *aRow,
+ struct SPropTagArray *proptags,
+ uint16_t propcount,
+ DATA_BLOB *content,
+ uint8_t flag,
+ uint8_t align)
+{
+ uint32_t i;
+ uint32_t offset = 0;
+ uint32_t aulPropTag = 0;
+ const void *data;
+
+ aRow->cValues = propcount;
+ aRow->lpProps = talloc_array(mem_ctx, struct SPropValue, propcount);
+
+ for (i = 0; i < propcount; i++) {
+ aulPropTag = proptags->aulPropTag[i];
+ if (flag) {
+ if (((uint8_t)(*(content->data + offset))) == PT_ERROR) {
+ aulPropTag &= 0xFFFF0000;
+ aulPropTag |= 0xA;
+ }
+ offset += align;
+ }
+
+ data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, aulPropTag, content);
+ aRow->lpProps[i].ulPropTag = aulPropTag;
+ aRow->lpProps[i].dwAlignPad = 0x0;
+ set_SPropValue(&(aRow->lpProps[i]), data);
+ }
+ if (align) {
+ offset += align;
+ }
+}
Added: trunk/openchange/libmapi/emsmdb.h
===================================================================
--- trunk/openchange/libmapi/emsmdb.h (rev 0)
+++ trunk/openchange/libmapi/emsmdb.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,52 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Jelmer Vernooij 2005.
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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 __EMSMDB_H__
+#define __EMSMDB_H__
+
+struct emsmdb_info {
+ char *szDisplayName;
+ char *szDNPrefix;
+ uint32_t pcmsPollsMax;
+ uint32_t pcRetry;
+ uint32_t pcmsRetryDelay;
+ uint32_t picxr;
+ uint16_t rgwServerVersion[3];
+};
+
+struct emsmdb_context {
+ struct dcerpc_pipe *rpc_connection;
+ struct policy_handle handle;
+ struct nspi_context *nspi;
+ struct cli_credentials *cred;
+ TALLOC_CTX *mem_ctx;
+ struct EcDoRpc_MAPI_REQ **cache_requests;
+ uint32_t cache_size;
+ uint8_t cache_count;
+ uint16_t prop_count;
+ enum MAPITAGS *properties;
+ uint16_t max_data;
+ bool setup;
+ struct emsmdb_info info;
+};
+
+#define MAILBOX_PATH "/o=%s/ou=%s/cn=Recipients/cn=%s"
+
+#endif /* __EMSMDB_H__ */
Added: trunk/openchange/libmapi/freebusy.c
===================================================================
--- trunk/openchange/libmapi/freebusy.c (rev 0)
+++ trunk/openchange/libmapi/freebusy.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,366 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+#include <ctype.h>
+#include <time.h>
+
+/**
+ \file freebusy.c
+
+ \brief Convenient API to access FreeBusy
+ */
+
+
+/**
+ \details Retrieve FreeBusy data associated with the specified
+ recipient
+
+ \param obj_store pointer to the public folder MAPI object
+ \param recipient name of the recipient to fetch freebusy data
+ \param pSRow pointer to the returned properties
+
+ \note The function returns a SRow structure with the following
+ property tags:
+ -# PR_NORMALIZED_SUBJECT
+ -# PR_FREEBUSY_LAST_MODIFIED
+ -# PR_FREEBUSY_START_RANGE
+ -# PR_FREEBUSY_END_RANGE
+ -# PR_FREEBUSY_ALL_MONTHS
+ -# PR_FREEBUSY_ALL_EVENTS
+ -# PR_FREEBUSY_TENTATIVE_MONTHS
+ -# PR_FREEBUSY_TENTATIVE_EVENTS
+ -# PR_FREEBUSY_BUSY_MONTHS
+ -# PR_FREEBUSY_BUSY_EVENTS
+ -# PR_FREEBUSY_OOF_MONTHS
+ -# PR_FREEBUSY_OOF_EVENTS
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS GetUserFreeBusyData(mapi_object_t *obj_store,
+ const char *recipient,
+ struct SRow *pSRow)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_session *session;
+ mapi_id_t id_freebusy;
+ mapi_object_t obj_freebusy;
+ mapi_object_t obj_exfreebusy;
+ mapi_object_t obj_message;
+ mapi_object_t obj_htable;
+ mapi_object_t obj_ctable;
+ struct SRowSet *pRowSet;
+ struct SRowSet SRowSet;
+ struct SPropValue *lpProps;
+ struct mapi_SRestriction res;
+ struct SSortOrderSet criteria;
+ struct SPropTagArray *SPropTagArray = NULL;
+ char *message_name;
+ char *folder_name;
+ const char *email = NULL;
+ char *o = NULL;
+ char *ou = NULL;
+ char *username;
+ const uint64_t *fid;
+ const uint64_t *mid;
+ uint32_t i;
+ uint32_t count;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!recipient, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!pSRow, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_SESSION_LIMIT, NULL);
+
+ mem_ctx = (TALLOC_CTX *) session;
+
+ /* Step 0. Retrieve the user Email Address and build FreeBusy strings */
+ pRowSet = talloc_zero(mem_ctx, struct SRowSet);
+ retval = GetABRecipientInfo(session, recipient, NULL, &pRowSet);
+ OPENCHANGE_RETVAL_IF(retval, retval, pRowSet);
+
+ email = get_SPropValue_SRowSet_data(pRowSet, PR_EMAIL_ADDRESS_UNICODE);
+ o = x500_get_dn_element(mem_ctx, email, ORG);
+ ou = x500_get_dn_element(mem_ctx, email, ORG_UNIT);
+ username = x500_get_dn_element(mem_ctx, email, "/cn=Recipients/cn=");
+
+ /* toupper username */
+ for (i = 0; username[i]; i++) {
+ username[i] = toupper((unsigned char)username[i]);
+ }
+
+ message_name = talloc_asprintf(mem_ctx, FREEBUSY_USER, username);
+ folder_name = talloc_asprintf(mem_ctx, FREEBUSY_FOLDER, o, ou);
+
+ MAPIFreeBuffer(username);
+ MAPIFreeBuffer(o);
+ MAPIFreeBuffer(ou);
+ MAPIFreeBuffer(pRowSet);
+
+ /* Step 1. Open the FreeBusy root folder */
+ retval = GetDefaultPublicFolder(obj_store, &id_freebusy, olFolderPublicFreeBusyRoot);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ mapi_object_init(&obj_freebusy);
+ retval = OpenFolder(obj_store, id_freebusy, &obj_freebusy);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 2. Open the hierarchy table */
+ mapi_object_init(&obj_htable);
+ retval = GetHierarchyTable(&obj_freebusy, &obj_htable, 0, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 3. Customize Hierarchy Table view */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x2,
+ PR_FID,
+ PR_DISPLAY_NAME);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 4. Find FreeBusy folder row */
+ res.rt = RES_PROPERTY;
+ res.res.resProperty.relop = RELOP_EQ;
+ res.res.resProperty.ulPropTag = PR_DISPLAY_NAME;
+ res.res.resProperty.lpProp.ulPropTag = PR_DISPLAY_NAME;
+ res.res.resProperty.lpProp.value.lpszA = folder_name;
+ retval = FindRow(&obj_htable, &res, 0, 0, &SRowSet);
+ MAPIFreeBuffer(folder_name);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 5. Open the folder */
+ fid = (const uint64_t *) get_SPropValue_SRowSet_data(&SRowSet, PR_FID);
+ if (!fid || *fid == MAPI_E_NOT_FOUND) return MAPI_E_NOT_FOUND;
+
+ mapi_object_init(&obj_exfreebusy);
+ retval = OpenFolder(&obj_freebusy, *fid, &obj_exfreebusy);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 6. Open the contents table */
+ mapi_object_init(&obj_ctable);
+ retval = GetContentsTable(&obj_exfreebusy, &obj_ctable, 0, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 7. Customize Contents Table view */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
+ PR_FID,
+ PR_MID,
+ PR_ADDRBOOK_MID,
+ PR_INSTANCE_NUM,
+ PR_NORMALIZED_SUBJECT);
+ retval = SetColumns(&obj_ctable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 8. Sort the table */
+ memset(&criteria, 0x0, sizeof (struct SSortOrderSet));
+ criteria.cSorts = 1;
+ criteria.aSort = talloc_array(mem_ctx, struct SSortOrder, criteria.cSorts);
+ criteria.aSort[0].ulPropTag = PR_NORMALIZED_SUBJECT;
+ criteria.aSort[0].ulOrder = TABLE_SORT_ASCEND;
+ retval = SortTable(&obj_ctable, &criteria);
+ MAPIFreeBuffer(criteria.aSort);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 9. Find the user FreeBusy message row */
+ res.rt = RES_PROPERTY;
+ res.res.resProperty.relop = RELOP_EQ;
+ res.res.resProperty.ulPropTag = PR_NORMALIZED_SUBJECT;
+ res.res.resProperty.lpProp.ulPropTag = PR_NORMALIZED_SUBJECT;
+ res.res.resProperty.lpProp.value.lpszA = message_name;
+ retval = FindRow(&obj_ctable, &res, 0, 0, &SRowSet);
+ MAPIFreeBuffer(message_name);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 10. Open the message */
+ fid = (const uint64_t *)get_SPropValue_SRowSet_data(&SRowSet, PR_FID);
+ mid = (const uint64_t *)get_SPropValue_SRowSet_data(&SRowSet, PR_MID);
+ OPENCHANGE_RETVAL_IF(!fid || *fid == MAPI_E_NOT_FOUND, MAPI_E_NOT_FOUND, NULL);
+ OPENCHANGE_RETVAL_IF(!mid || *mid == MAPI_E_NOT_FOUND, MAPI_E_NOT_FOUND, NULL);
+
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(obj_store, *fid, *mid, &obj_message, 0x0);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ /* Step 11. Get FreeBusy properties */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0xc,
+ PR_NORMALIZED_SUBJECT,
+ PR_FREEBUSY_LAST_MODIFIED,
+ PR_FREEBUSY_START_RANGE,
+ PR_FREEBUSY_END_RANGE,
+ PR_FREEBUSY_ALL_MONTHS,
+ PR_FREEBUSY_ALL_EVENTS,
+ PR_FREEBUSY_TENTATIVE_MONTHS,
+ PR_FREEBUSY_TENTATIVE_EVENTS,
+ PR_FREEBUSY_BUSY_MONTHS,
+ PR_FREEBUSY_BUSY_EVENTS,
+ PR_FREEBUSY_OOF_MONTHS,
+ PR_FREEBUSY_OOF_EVENTS);
+ retval = GetProps(&obj_message, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ pSRow->cValues = count;
+ pSRow->lpProps = lpProps;
+
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_ctable);
+ mapi_object_release(&obj_exfreebusy);
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&obj_freebusy);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Check if a date conflicts with existing FreeBusy Busy/Out
+ Of Office events
+
+ \param obj_store pointer to the public folder MAPI object
+ \param date pointer to the date to check
+ \param conflict pointer to the returned boolean value
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS IsFreeBusyConflict(mapi_object_t *obj_store,
+ struct FILETIME *date,
+ bool *conflict)
+{
+ enum MAPISTATUS retval;
+ struct mapi_session *session;
+ struct SRow aRow;
+ const struct LongArray_r *all_months;
+ const struct BinaryArray_r *all_events;
+ struct Binary_r bin;
+ const uint32_t *publish_start;
+ NTTIME nttime;
+ time_t time;
+ struct tm *tm;
+ uint32_t fbusytime;
+ uint32_t fmonth;
+ uint32_t month;
+ int year;
+ uint32_t idx;
+ uint32_t i;
+ bool found = false;
+ uint32_t start;
+ uint32_t end;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!date, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!conflict, MAPI_E_INVALID_PARAMETER, NULL);
+
+ session = mapi_object_get_session(obj_store);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_SESSION_LIMIT, NULL);
+
+ *conflict = false;
+
+ /* Step 1. Retrieve the freebusy data for the user */
+ retval = GetUserFreeBusyData(obj_store, session->profile->username, &aRow);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ publish_start = (const uint32_t *) find_SPropValue_data(&aRow, PR_FREEBUSY_START_RANGE);
+ all_months = (const struct LongArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_ALL_MONTHS);
+ all_events = (const struct BinaryArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_ALL_EVENTS);
+
+ if (!all_months || (*(const uint32_t *)all_months) == MAPI_E_NOT_FOUND ||
+ !all_events || (*(const uint32_t *)all_events) == MAPI_E_NOT_FOUND) {
+ return MAPI_E_SUCCESS;
+ }
+
+ /* Step 2. Convert the input date to freebusy */
+ nttime = ((uint64_t) date->dwHighDateTime << 32);
+ nttime |= (uint64_t) date->dwLowDateTime;
+ time = nt_time_to_unix(nttime);
+ tm = localtime(&time);
+
+ fmonth = tm->tm_mon + 1;
+ fbusytime = ((tm->tm_mday - 1) * 60 * 24) + (tm->tm_hour * 60);
+
+ /* Step 3. Check if the years matches */
+ year = GetFreeBusyYear(publish_start);
+
+ if (year != (tm->tm_year + 1900)) {
+ return MAPI_E_SUCCESS;
+ }
+
+ /* Step 4. Check if we have already registered events for the month */
+
+ for (idx = 0; idx < all_months->cValues; idx++) {
+ month = all_months->lpl[idx] - (year * 16);
+ if (month == fmonth) {
+ found = true;
+ break;
+ }
+ }
+ if (found == false) return MAPI_E_SUCCESS;
+
+ /* Step 5. Check if one this months events conflicts with the date */
+ bin = all_events->lpbin[idx];
+ if (bin.cb % 4) {
+ return MAPI_E_INVALID_PARAMETER;
+ }
+
+ for (i = 0; i < bin.cb; i += 4) {
+ start = (bin.lpb[i + 1] << 8) | bin.lpb[i];
+ end = (bin.lpb[i + 3] << 8) | bin.lpb[i + 2];
+ if ((fbusytime >= start) && (fbusytime <= end)) {
+ *conflict = true;
+ return MAPI_E_SUCCESS;
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Return the year associated with the FreeBusy start range
+
+ \param publish_start pointer to the publish start integer
+
+ \return a valid year on success, otherwise 0
+ */
+_PUBLIC_ int GetFreeBusyYear(const uint32_t *publish_start)
+{
+ struct tm *tm;
+ uint32_t year;
+ time_t time;
+ NTTIME nttime;
+
+ if (!publish_start) return 0;
+
+ nttime = *publish_start;
+ nttime *= 60;
+ nttime *= 10000000;
+ time = nt_time_to_unix(nttime);
+ tm = localtime(&time);
+ year = (tm->tm_year + 1900);
+
+ return year;
+}
Added: trunk/openchange/libmapi/libmapi.h
===================================================================
--- trunk/openchange/libmapi/libmapi.h (rev 0)
+++ trunk/openchange/libmapi/libmapi.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,75 @@
+/*
+ OpenChange MAPI implementation.
+ libmapi public header file
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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_H__
+#define __LIBMAPI_H__
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+
+/* Samba4 includes */
+#include <talloc.h>
+#include <dcerpc.h>
+#include <util/debug.h>
+#include <tevent.h>
+#include <param.h>
+
+/* OpenChange includes */
+#include <gen_ndr/exchange.h>
+#include <gen_ndr/property.h>
+
+#include <libmapi/dlinklist.h>
+#include <libmapi/version.h>
+#include <libmapi/nspi.h>
+#include <libmapi/emsmdb.h>
+#include <libmapi/mapi_ctx.h>
+#include <libmapi/mapi_provider.h>
+#include <libmapi/mapi_object.h>
+#include <libmapi/mapi_id_array.h>
+#include <libmapi/mapi_notification.h>
+#include <libmapi/mapi_profile.h>
+#include <libmapi/mapi_nameid.h>
+#include <libmapi/mapidefs.h>
+#include <libmapi/mapicode.h>
+#include <libmapi/socket/netif.h>
+#include <libmapi/proto.h>
+
+extern struct mapi_ctx *global_mapi_ctx;
+
+#endif /* __LIBMAPI_H__ */
Added: trunk/openchange/libmapi/lzfu.c
===================================================================
--- trunk/openchange/libmapi/lzfu.c (rev 0)
+++ trunk/openchange/libmapi/lzfu.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,237 @@
+/*
+ OpenChange MAPI implementation.
+
+ This work is based on libpst-0.5.2, and the author(s) of
+ that code will also hold appropriate copyrights.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+
+/**
+ \file lzfu.c
+
+ \brief Compressed RTF related functions
+*/
+
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define LE32_CPU(x) \
+ x = ((((x) & 0xff000000) >> 24) | \
+ (((x) & 0x00ff0000) >> 8 ) | \
+ (((x) & 0x0000ff00) << 8 ) | \
+ (((x) & 0x000000ff) << 24));
+#define LE16_CPU(x) \
+ x = ((((x) & 0xff00) >> 8) | \
+ (((x) & 0x00ff) << 8));
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define LE32_CPU(x) {}
+#define LE16_CPU(x) {}
+#else
+#error Byte order not supported
+#endif /* BYTE_ORDER */
+
+#define LZFU_COMPRESSED 0x75465a4c
+#define LZFU_UNCOMPRESSED 0x414c454d
+
+/* Initial directory */
+#define LZFU_INITDICT \
+ "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \
+ "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \
+ "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \
+ "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \
+ "\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \
+ "\\tx"
+
+/* initial length of dictionary */
+#define LZFU_INITLENGTH 207
+
+#define LZFU_DICTLENGTH 0x1000
+#define LZFU_HEADERLENGTH 0x10
+
+/* header for compressed rtf */
+typedef struct _lzfuheader {
+ uint32_t cbSize;
+ uint32_t cbRawSize;
+ uint32_t dwMagic;
+ uint32_t dwCRC;
+} lzfuheader;
+
+
+/**
+ \details creates a DATA_BLOB in uncompressed Rich Text Format (RTF)
+ from the compressed format used in the PR_RTF_COMPRESSED property
+ opened in the stream.
+
+ \param obj_stream stream object with RTF stream content
+ \param rtf the output blob with uncompressed content
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error. Possible
+ MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: obj_stream is not a valid pointer
+ - MAPI_E_CORRUPT_DATA: a problem was encountered while
+ decompressing the RTF compressed data
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code.
+
+ \note rtf->data needs to be freed with MAPIFreeBuffer
+
+ \sa OpenStream
+*/
+_PUBLIC_ enum MAPISTATUS WrapCompressedRTFStream(mapi_object_t *obj_stream,
+ DATA_BLOB *rtf)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ uint32_t in_size;
+ uint8_t *rtfcomp;
+ uint16_t read_size;
+ unsigned char buf[0x1000];
+
+ /* sanity check and init */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_stream, MAPI_E_INVALID_PARAMETER, NULL);
+ mem_ctx = global_mapi_ctx->mem_ctx;
+
+ /* Read the stream pointed by obj_stream */
+ read_size = 0;
+ in_size = 0;
+ rtfcomp = talloc_zero(mem_ctx, uint8_t);
+ do {
+ retval = ReadStream(obj_stream, buf, 0x1000, &read_size);
+ OPENCHANGE_RETVAL_IF(retval, GetLastError(), rtf->data);
+ if (read_size) {
+ rtfcomp = talloc_realloc(mem_ctx, rtfcomp, uint8_t,
+ in_size + read_size);
+ memcpy(&(rtfcomp[in_size]), buf, read_size);
+ in_size += read_size;
+ }
+ } while (read_size);
+
+ return uncompress_rtf(mem_ctx, rtfcomp, in_size, rtf);
+}
+
+_PUBLIC_ enum MAPISTATUS uncompress_rtf(TALLOC_CTX *mem_ctx,
+ uint8_t *rtfcomp, uint32_t in_size,
+ DATA_BLOB *rtf)
+{
+ lzfuheader lzfuhdr;
+ uint8_t dict[4096];
+ uint32_t out_size = 0;
+ uint32_t in_pos = 16;
+ uint32_t out_pos = 0;
+ uint32_t dict_writeoffset = LZFU_INITLENGTH;
+ uint8_t bitmask_pos;
+
+ if (in_size < sizeof(lzfuhdr)+1) {
+ OPENCHANGE_RETVAL_ERR(MAPI_E_CORRUPT_DATA, NULL);
+ }
+
+ memcpy(dict, LZFU_INITDICT, LZFU_INITLENGTH);
+
+ memcpy(&lzfuhdr, rtfcomp, sizeof(lzfuhdr));
+ LE32_CPU(lzfuhdr.cbSize);
+ LE32_CPU(lzfuhdr.cbRawSize);
+ LE32_CPU(lzfuhdr.dwMagic);
+ LE32_CPU(lzfuhdr.dwCRC);
+
+#if 0
+ printf("lzfuhdr.cbSize = %u\n", lzfuhdr.cbSize);
+ printf("lzfuhdr.cbRawSize = %u\n", lzfuhdr.cbRawSize);
+ printf("lzfuhdr.dwMagic = 0x%x\n", lzfuhdr.dwMagic);
+ printf("lzfuhdr.dwCRC = 0x%x\n", lzfuhdr.dwCRC);
+#endif
+
+ if (lzfuhdr.cbSize != in_size - 4) {
+ printf("in_size mismatch:%u\n", in_size);
+ OPENCHANGE_RETVAL_ERR(MAPI_E_CORRUPT_DATA, NULL);
+ }
+
+ if ((lzfuhdr.dwMagic != LZFU_COMPRESSED) && (lzfuhdr.dwMagic != LZFU_UNCOMPRESSED)) {
+ printf("bad magic: 0x%x\n", lzfuhdr.dwMagic);
+ OPENCHANGE_RETVAL_ERR(MAPI_E_CORRUPT_DATA, NULL);
+ }
+
+ if (lzfuhdr.dwMagic == LZFU_UNCOMPRESSED) {
+ // TODO: handle uncompressed case
+ }
+
+ out_size = lzfuhdr.cbRawSize + LZFU_HEADERLENGTH + 4;
+ rtf->data = talloc_size(mem_ctx, out_size);
+
+ while ((in_pos + 1) < in_size) {
+ uint8_t control;
+ control = rtfcomp[in_pos];
+ ++ in_pos;
+ // printf("control: 0x%x\n", control);
+
+ for(bitmask_pos = 0; bitmask_pos < 8; ++bitmask_pos) {
+ if (in_pos > in_size) {
+ break;
+ }
+ if (control & ( 1 << bitmask_pos)) {
+ // it is a dictionary reference
+ uint8_t dictreflength;
+ uint16_t dictrefoffset;
+ int i;
+ dictrefoffset= (rtfcomp[in_pos] << 8) + rtfcomp[in_pos + 1];
+ in_pos += 2; /* for the two bytes we just consumed */
+ dictreflength = dictrefoffset & 0x000F; /* low 4 bits */
+ dictreflength += 2; /* stored as two less than actual length */
+ dictrefoffset &= 0xFFF0; /* high twelve bits */
+ dictrefoffset >>= 4;
+ if (dictrefoffset == dict_writeoffset) {
+ rtf->length = out_pos;
+ OPENCHANGE_RETVAL_ERR(MAPI_E_SUCCESS, NULL);
+ }
+ for (i = 0; i < dictreflength; ++i) {
+ if (out_pos > out_size ) {
+ printf(" overrun on out_pos: %u > %u\n", out_pos, out_size);
+ printf(" overrun data: %s\n", rtf->data);
+ OPENCHANGE_RETVAL_ERR(MAPI_E_CORRUPT_DATA, rtf->data);
+ }
+ char c = dict[(dictrefoffset + i) % LZFU_DICTLENGTH];
+ rtf->data[out_pos] = c;
+ dict[dict_writeoffset] = c;
+ dict_writeoffset = (dict_writeoffset + 1) % LZFU_DICTLENGTH;
+ ++ out_pos;
+ }
+ } else {
+ // its a literal
+ if ( (out_pos > out_size) || (in_pos > in_size) ) {
+ OPENCHANGE_RETVAL_ERR(MAPI_E_CORRUPT_DATA, rtf->data);
+ }
+ char c = rtfcomp[in_pos];
+ ++ in_pos;
+ rtf->data[out_pos] = c;
+ dict[dict_writeoffset] = c;
+ dict_writeoffset = (dict_writeoffset + 1) % LZFU_DICTLENGTH;
+ ++ out_pos;
+ }
+ }
+ }
+
+ rtf->length = lzfuhdr.cbRawSize;
+
+ OPENCHANGE_RETVAL_ERR(MAPI_E_SUCCESS, NULL);
+
+}
Added: trunk/openchange/libmapi/mapi_ctx.h
===================================================================
--- trunk/openchange/libmapi/mapi_ctx.h (rev 0)
+++ trunk/openchange/libmapi/mapi_ctx.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,44 @@
+/*
+ OpenChange MAPI implementation.
+ Status codes returned by MAPI
+
+ Copyright (C) Julien Kerihuel 2007.
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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 _MAPI_CTX_H
+#define _MAPI_CTX_H
+
+#include <talloc.h>
+
+/**
+ * mapi global context
+ */
+
+struct ldb_context;
+struct mapi_session;
+
+typedef struct mapi_ctx
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_context *ldb_ctx;
+ struct mapi_session *session;
+ bool dumpdata;
+ struct loadparm_context *lp_ctx;
+} mapi_ctx_t;
+
+
+#endif /* ! _MAPI_CTX_H */
Added: trunk/openchange/libmapi/mapi_id_array.c
===================================================================
--- trunk/openchange/libmapi/mapi_id_array.c (rev 0)
+++ trunk/openchange/libmapi/mapi_id_array.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,297 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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/proto_private.h>
+
+/**
+ \file mapi_id_array.c
+
+ \brief mapi_id_array support functions
+*/
+
+
+/**
+ \details Initialize a mapi_id_array structure
+
+ \param id pointer to a mapi_id_array structure
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: The mapi_id_array_t is uninitialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa mapi_id_array_release
+ */
+_PUBLIC_ enum MAPISTATUS mapi_id_array_init(mapi_id_array_t *id)
+{
+ TALLOC_CTX *mem_ctx;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!id, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = global_mapi_ctx->mem_ctx;
+
+ id->count = 0;
+ id->lpContainerList = talloc_zero((TALLOC_CTX *)mem_ctx, mapi_container_list_t);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Uninitialize a mapi_id_array structure
+
+ \param id pointer to a mapi_id_array structure
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: The mapi_id_array_t is uninitialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa mapi_id_array_init
+ */
+_PUBLIC_ enum MAPISTATUS mapi_id_array_release(mapi_id_array_t *id)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!id, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!id->lpContainerList, MAPI_E_INVALID_PARAMETER, NULL);
+
+ id->count = 0;
+ talloc_free(id->lpContainerList);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve the ContainerList and store it within a uint64_t
+ array.
+
+ \param mem_ctx allocated talloc pointer
+ \param id pointer to a mapi_id_array structure
+ \param ContainerList pointer on a pointer of uint64_t values
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: The mapi_id_array_t is uninitialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa GetSearchCriteria
+ */
+_PUBLIC_ enum MAPISTATUS mapi_id_array_get(TALLOC_CTX *mem_ctx,
+ mapi_id_array_t *id,
+ mapi_id_t **ContainerList)
+{
+ mapi_container_list_t *element;
+ uint32_t i = 0;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!id, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!id->lpContainerList, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ContainerList, MAPI_E_INVALID_PARAMETER, NULL);
+
+ *ContainerList = talloc_array(mem_ctx, uint64_t, id->count + 1);
+
+ element = id->lpContainerList;
+ while (element) {
+ ContainerList[0][i] = element->id;
+ i++;
+ element = element->next;
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Add a container ID to the list given its mapi_object_t
+
+ \param id pointer to a mapi_id_array structure
+ \param obj pointer on the mapi object we retrieve the container ID
+ from
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: The mapi_id_array_t is uninitialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa mapi_id_array_add_id
+ */
+_PUBLIC_ enum MAPISTATUS mapi_id_array_add_obj(mapi_id_array_t *id,
+ mapi_object_t *obj)
+{
+ mapi_container_list_t *element;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!id, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!id->lpContainerList, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+
+ element = talloc_zero((TALLOC_CTX *)id->lpContainerList, mapi_container_list_t);
+ element->id = mapi_object_get_id(obj);
+ DLIST_ADD(id->lpContainerList, element);
+
+ id->count++;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Add a container ID to the list given its container ID
+
+ \param id pointer to a mapi_id_array structure
+ \param fid the container ID
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: The mapi_id_array_t is uninitialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa mapi_id_array_add_obj
+ */
+_PUBLIC_ enum MAPISTATUS mapi_id_array_add_id(mapi_id_array_t *id, mapi_id_t fid)
+{
+ mapi_container_list_t *element;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!id, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!id->lpContainerList, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!fid, MAPI_E_INVALID_PARAMETER, NULL);
+
+ element = talloc_zero((TALLOC_CTX *)id->lpContainerList, mapi_container_list_t);
+ element->id = fid;
+ DLIST_ADD(id->lpContainerList, element);
+
+ id->count++;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Delete a container ID from the list given its container ID
+
+ \param id pointer to a mapi_id_array structure
+ \param fid the container ID
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: The mapi_id_array_t is uninitialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa mapi_id_array_add_id
+ */
+_PUBLIC_ enum MAPISTATUS mapi_id_array_del_id(mapi_id_array_t *id, mapi_id_t fid)
+{
+ mapi_container_list_t *element;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!id, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!id->count, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!id->lpContainerList, MAPI_E_NOT_INITIALIZED, NULL);
+
+ element = id->lpContainerList;
+
+ while (element) {
+ if (element->id == fid) {
+ DLIST_REMOVE(id->lpContainerList, element);
+ return MAPI_E_SUCCESS;
+ }
+ element = element->next;
+ }
+ return MAPI_E_NOT_FOUND;
+}
+
+
+/**
+ \details Delete a container ID from the list given its mapi_object_t
+
+ \param id pointer to a mapi_id_array structure
+ \param obj pointer on the mapi object we retrieve the container ID
+ from
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: The mapi_id_array_t is uninitialized
+ - MAPI_E_CALL_FAILED: A network problem was encountered during the
+ transaction
+
+ \sa mapi_id_array_add_id
+ */
+_PUBLIC_ enum MAPISTATUS mapi_id_array_del_obj(mapi_id_array_t *id, mapi_object_t *obj)
+{
+ mapi_container_list_t *element;
+ mapi_id_t fid;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!id, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!id->count, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!id->lpContainerList, MAPI_E_NOT_INITIALIZED, NULL);
+
+ fid = mapi_object_get_id(obj);
+ OPENCHANGE_RETVAL_IF(!fid, MAPI_E_NOT_INITIALIZED, NULL);
+
+ element = id->lpContainerList;
+
+ while (element) {
+ if (element->id == fid) {
+ DLIST_REMOVE(id->lpContainerList, element);
+ return MAPI_E_SUCCESS;
+ }
+ element = element->next;
+ }
+ return MAPI_E_NOT_FOUND;
+}
Added: trunk/openchange/libmapi/mapi_id_array.h
===================================================================
--- trunk/openchange/libmapi/mapi_id_array.h (rev 0)
+++ trunk/openchange/libmapi/mapi_id_array.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,34 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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 __MAPI_ID_ARRAY_H
+#define __MAPI_ID_ARRAY_H
+
+typedef struct mapi_container_list {
+ struct mapi_container_list *prev;
+ struct mapi_container_list *next;
+ mapi_id_t id;
+} mapi_container_list_t;
+
+typedef struct mapi_id_array {
+ uint16_t count;
+ mapi_container_list_t *lpContainerList;
+} mapi_id_array_t;
+
+#endif /* __MAPI_ID_ARRAY_H */
Added: trunk/openchange/libmapi/mapi_nameid.c
===================================================================
--- trunk/openchange/libmapi/mapi_nameid.c (rev 0)
+++ trunk/openchange/libmapi/mapi_nameid.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,873 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/mapi_nameid.h>
+#include <libmapi/mapi_nameid_private.h>
+#include <libmapi/proto_private.h>
+
+
+/**
+ \file mapi_nameid.c
+
+ \brief mapi_nameid convenience API
+*/
+
+
+/**
+ \details Create a new mapi_nameid structure
+
+ \param mem_ctx memory context to use for allocation
+
+ \returns a pointer to an allocated mapi_nameid structure on
+ success, otherwise NULL
+
+ \sa GetIDsFromNames
+*/
+_PUBLIC_ struct mapi_nameid *mapi_nameid_new(TALLOC_CTX *mem_ctx)
+{
+ struct mapi_nameid *mapi_nameid = NULL;
+
+ /* Sanity check */
+ if (!mem_ctx) return NULL;
+
+ mapi_nameid = talloc_zero(mem_ctx, struct mapi_nameid);
+ if (!mapi_nameid) return NULL;
+
+ mapi_nameid->nameid = NULL;
+ mapi_nameid->entries = NULL;
+ mapi_nameid->count = 0;
+
+ return mapi_nameid;
+}
+
+
+/**
+ \details Add a mapi_nameid entry given its OOM and OLEGUID
+ (MNID_ID|MNID_STRING)
+
+ \param mapi_nameid the structure where results are stored
+ \param OOM the Outlook Object Model matching string
+ \param OLEGUID the property set this entry belongs to
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+ - MAPI_E_NOT_FOUND: the entry intended to be added was not found
+
+ \sa mapi_nameid_new
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_OOM_add(struct mapi_nameid *mapi_nameid,
+ const char *OOM,
+ const char *OLEGUID)
+{
+ uint32_t i;
+ uint16_t count;
+
+ /* Sanity check */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!OOM, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!OLEGUID, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; mapi_nameid_tags[i].OLEGUID; i++) {
+ if (mapi_nameid_tags[i].OOM &&
+ !strcmp(OOM, mapi_nameid_tags[i].OOM) &&
+ !strcmp(OLEGUID, mapi_nameid_tags[i].OLEGUID)) {
+ mapi_nameid->nameid = talloc_realloc(mapi_nameid,
+ mapi_nameid->nameid, struct MAPINAMEID,
+ mapi_nameid->count + 1);
+ mapi_nameid->entries = talloc_realloc(mapi_nameid,
+ mapi_nameid->entries, struct mapi_nameid_tags,
+ mapi_nameid->count + 1);
+ count = mapi_nameid->count;
+
+ mapi_nameid->entries[count] = mapi_nameid_tags[i];
+
+ mapi_nameid->nameid[count].ulKind = mapi_nameid_tags[i].ulKind;
+ GUID_from_string(mapi_nameid_tags[i].OLEGUID,
+ &(mapi_nameid->nameid[count].lpguid));
+ switch (mapi_nameid_tags[i].ulKind) {
+ case MNID_ID:
+ mapi_nameid->nameid[count].kind.lid = mapi_nameid_tags[i].lid;
+ 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;
+ break;
+ }
+ mapi_nameid->count++;
+ return MAPI_E_SUCCESS;
+ }
+ }
+
+ return MAPI_E_NOT_FOUND;
+}
+
+
+/**
+ \details Add a mapi_nameid entry given its lid and OLEGUID
+ (MNID_ID)
+
+ \param mapi_nameid the structure where results are stored
+ \param lid the light ID of the name property (used by MNID_ID named
+ props only)
+ \param OLEGUID the property set this entry belongs to
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+ - MAPI_E_NOT_FOUND: the entry intended to be added was not found
+
+ \sa mapi_nameid_new
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_lid_add(struct mapi_nameid *mapi_nameid,
+ uint16_t lid, const char *OLEGUID)
+{
+ uint32_t i;
+ uint16_t count;
+
+ /* Sanity check */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!lid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!OLEGUID, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; mapi_nameid_tags[i].OLEGUID; i++) {
+ if ((lid == mapi_nameid_tags[i].lid) &&
+ !strcmp(OLEGUID, mapi_nameid_tags[i].OLEGUID)) {
+ mapi_nameid->nameid = talloc_realloc(mapi_nameid,
+ mapi_nameid->nameid, struct MAPINAMEID,
+ mapi_nameid->count + 1);
+ mapi_nameid->entries = talloc_realloc(mapi_nameid,
+ mapi_nameid->entries, struct mapi_nameid_tags,
+ mapi_nameid->count + 1);
+ count = mapi_nameid->count;
+
+ mapi_nameid->entries[count] = mapi_nameid_tags[i];
+
+ mapi_nameid->nameid[count].ulKind = mapi_nameid_tags[i].ulKind;
+ GUID_from_string(mapi_nameid_tags[i].OLEGUID,
+ &(mapi_nameid->nameid[count].lpguid));
+ switch (mapi_nameid_tags[i].ulKind) {
+ case MNID_ID:
+ mapi_nameid->nameid[count].kind.lid = mapi_nameid_tags[i].lid;
+ 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;
+ break;
+ }
+ mapi_nameid->count++;
+ return MAPI_E_SUCCESS;
+ }
+ }
+
+ return MAPI_E_NOT_FOUND;
+}
+
+
+/**
+ \details Add a mapi_nameid entry given its Name and OLEGUID
+ (MNID_STRING)
+
+ \param mapi_nameid the structure where results are stored
+ \param Name the property name (used by MNID_STRING named
+ props only)
+ \param OLEGUID the property set this entry belongs to
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+ - MAPI_E_NOT_FOUND: the entry intended to be added was not found
+
+ \sa mapi_nameid_new
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_string_add(struct mapi_nameid *mapi_nameid,
+ const char *Name,
+ const char *OLEGUID)
+{
+ uint32_t i;
+ uint16_t count;
+
+ /* Sanity check */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!Name, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!OLEGUID, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; mapi_nameid_tags[i].OLEGUID; i++) {
+ if (mapi_nameid_tags[i].Name &&
+ !strcmp(Name, mapi_nameid_tags[i].Name) &&
+ !strcmp(OLEGUID, mapi_nameid_tags[i].OLEGUID)) {
+ mapi_nameid->nameid = talloc_realloc(mapi_nameid,
+ mapi_nameid->nameid, struct MAPINAMEID,
+ mapi_nameid->count + 1);
+ mapi_nameid->entries = talloc_realloc(mapi_nameid,
+ mapi_nameid->entries, struct mapi_nameid_tags,
+ mapi_nameid->count + 1);
+ count = mapi_nameid->count;
+
+ mapi_nameid->entries[count] = mapi_nameid_tags[i];
+
+ mapi_nameid->nameid[count].ulKind = mapi_nameid_tags[i].ulKind;
+ GUID_from_string(mapi_nameid_tags[i].OLEGUID,
+ &(mapi_nameid->nameid[count].lpguid));
+ switch (mapi_nameid_tags[i].ulKind) {
+ case MNID_ID:
+ mapi_nameid->nameid[count].kind.lid = mapi_nameid_tags[i].lid;
+ 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;
+ break;
+ }
+ mapi_nameid->count++;
+ return MAPI_E_SUCCESS;
+ }
+ }
+
+ return MAPI_E_NOT_FOUND;
+}
+
+/**
+ \details Register and add a custom MNID_ID named property given its
+ lid, proptype and OLEGUID.
+
+ \param mapi_nameid the structure where results are stored
+ \param lid the light ID of the name property (used by MNID_ID named
+ props only)
+ \param propType the named property type
+ \param OLEGUID the property set this entry belongs to
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: one of the parameter was no set properly
+
+ \sa mapi_nameid_new, mapi_nameid_lid_add
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_custom_lid_add(struct mapi_nameid *mapi_nameid,
+ uint16_t lid, uint16_t propType,
+ const char *OLEGUID)
+{
+ uint16_t count;
+
+ /* Sanity check */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!lid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!propType, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!OLEGUID, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mapi_nameid->nameid = talloc_realloc(mapi_nameid,
+ mapi_nameid->nameid, struct MAPINAMEID,
+ mapi_nameid->count + 1);
+ mapi_nameid->entries = talloc_realloc(mapi_nameid,
+ mapi_nameid->entries, struct mapi_nameid_tags,
+ mapi_nameid->count + 1);
+
+ count = mapi_nameid->count;
+ mapi_nameid->entries[count].lid = lid;
+ mapi_nameid->entries[count].propType = propType;
+ mapi_nameid->entries[count].ulKind = MNID_ID;
+ mapi_nameid->entries[count].OLEGUID = OLEGUID;
+
+ mapi_nameid->nameid[count].ulKind = MNID_ID;
+ GUID_from_string(OLEGUID, &(mapi_nameid->nameid[count].lpguid));
+ mapi_nameid->nameid[count].kind.lid = lid;
+
+ mapi_nameid->count++;
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Register and add a custom MNID_STRING named property given
+ its string, proptype and OLEGUID.
+
+ \param mapi_nameid the structure where results are stored
+ \param Name the property name (used by MNID_STRING named props only)
+ \param propType the named property type
+ \param OLEGUID the property set this entry belongs to
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: one of the parameter was not set properly.
+
+ \sa mapi_nameid_new, mapi_nameid_string_add
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_custom_string_add(struct mapi_nameid *mapi_nameid,
+ const char *Name, uint16_t propType,
+ const char *OLEGUID)
+{
+ uint16_t count;
+
+ /* Sanity check */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!Name, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!propType, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!OLEGUID, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mapi_nameid->nameid = talloc_realloc(mapi_nameid,
+ mapi_nameid->nameid, struct MAPINAMEID,
+ mapi_nameid->count + 1);
+ mapi_nameid->entries = talloc_realloc(mapi_nameid,
+ mapi_nameid->entries, struct mapi_nameid_tags,
+ mapi_nameid->count + 1);
+ count = mapi_nameid->count;
+ mapi_nameid->entries[count].Name = Name;
+ mapi_nameid->entries[count].propType = propType;
+ mapi_nameid->entries[count].ulKind = MNID_STRING;
+ mapi_nameid->entries[count].OLEGUID = OLEGUID;
+
+ 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->count++;
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Add a mapi_nameid entry given its canonical property tag
+
+ \param mapi_nameid the structure where results are stored
+ \param proptag the canonical property tag we are searching
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZE: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+ - MAPI_E_NOT_FOUND: the entry intended to be added was not found
+
+ \sa mapi_nameid_new
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_canonical_add(struct mapi_nameid *mapi_nameid,
+ uint32_t proptag)
+{
+ uint32_t i;
+ uint16_t count;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!proptag, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; mapi_nameid_tags[i].OLEGUID; i++) {
+ if (mapi_nameid_tags[i].proptag == proptag) {
+ mapi_nameid->nameid = talloc_realloc(mapi_nameid,
+ mapi_nameid->nameid, struct MAPINAMEID,
+ mapi_nameid->count + 1);
+ mapi_nameid->entries = talloc_realloc(mapi_nameid,
+ mapi_nameid->entries, struct mapi_nameid_tags,
+ mapi_nameid->count + 1);
+ count = mapi_nameid->count;
+
+ mapi_nameid->entries[count] = mapi_nameid_tags[i];
+
+ mapi_nameid->nameid[count].ulKind = mapi_nameid_tags[i].ulKind;
+ GUID_from_string(mapi_nameid_tags[i].OLEGUID,
+ &(mapi_nameid->nameid[count].lpguid));
+ switch (mapi_nameid_tags[i].ulKind) {
+ case MNID_ID:
+ mapi_nameid->nameid[count].kind.lid = mapi_nameid_tags[i].lid;
+ 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;
+ break;
+ }
+ mapi_nameid->count++;
+ return MAPI_E_SUCCESS;
+ }
+ }
+
+ return MAPI_E_NOT_FOUND;
+}
+
+
+/**
+ \details Search for a given OOM,OLEGUID couple and return the
+ associated propType.
+
+ \param OOM The Outlook Object Model
+ \param OLEGUID the named property GUID for this entry
+ \param propType pointer on returned named property type
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: one of the parameter was not set properly.
+ - MAPI_E_NOT_FOUND: no named property found
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_OOM_lookup(const char *OOM, const char *OLEGUID,
+ uint16_t *propType)
+{
+ uint32_t i;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!OOM, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!OLEGUID, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; mapi_nameid_tags[i].OLEGUID; i++) {
+ if (mapi_nameid_tags[i].OOM &&
+ !strcmp(mapi_nameid_tags[i].OOM, OOM) &&
+ !strcmp(mapi_nameid_tags[i].OLEGUID, OLEGUID)) {
+ *propType = mapi_nameid_tags[i].propType;
+ return MAPI_E_SUCCESS;
+ }
+ }
+
+ errno = MAPI_E_NOT_FOUND;
+ return -1;
+}
+
+
+/**
+ \details Search for a given lid,OLEGUID couple and return the
+ associated propType.
+
+ \param lid the named property light ID
+ \param OLEGUID the named property GUID for this entry
+ \param propType pointer on returned named property type
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: one of the parameter was not set properly.
+ - MAPI_E_NOT_FOUND: no named property found
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_lid_lookup(uint16_t lid, const char *OLEGUID,
+ uint16_t *propType)
+{
+ uint32_t i;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!lid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!OLEGUID, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; mapi_nameid_tags[i].OLEGUID; i++) {
+ if (mapi_nameid_tags[i].lid == lid &&
+ !strcmp(mapi_nameid_tags[i].OLEGUID, OLEGUID)) {
+ *propType = mapi_nameid_tags[i].propType;
+ return MAPI_E_SUCCESS;
+ }
+ }
+
+ errno = MAPI_E_NOT_FOUND;
+ return -1;
+}
+
+
+/**
+ \details Search for a given Name,OLEGUID couple and return the
+ associated propType.
+
+ \param Name the named property name
+ \param OLEGUID the named property GUID for this entry
+ \param propType pointer on returned named property type
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: one of the parameter was not set properly.
+ - MAPI_E_NOT_FOUND: no named property found
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_string_lookup(const char *Name,
+ const char *OLEGUID,
+ uint16_t *propType)
+{
+ uint32_t i;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!Name, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!OLEGUID, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; mapi_nameid_tags[i].OLEGUID; i++) {
+ if (mapi_nameid_tags[i].Name &&
+ !strcmp(mapi_nameid_tags[i].Name, Name) &&
+ !strcmp(mapi_nameid_tags[i].OLEGUID, OLEGUID)) {
+ *propType = mapi_nameid_tags[i].propType;
+ return MAPI_E_SUCCESS;
+ }
+ }
+
+ errno = MAPI_E_NOT_FOUND;
+ return -1;
+}
+
+
+/**
+ \details set SPropTagArray ulPropTag property types from
+ mapi_nameid returned by GetIDsFromNames()
+
+ \param mapi_nameid the structure where results are stored
+ \param SPropTagArray the array of property tags returned by
+ previous call to GetIDsFromNames()
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+
+ \sa GetIDsFromNames
+*/
+_PUBLIC_ enum MAPISTATUS mapi_nameid_SPropTagArray(struct mapi_nameid *mapi_nameid,
+ struct SPropTagArray *SPropTagArray)
+{
+ uint32_t i;
+
+ /* sanity check */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; i < mapi_nameid->count; i++) {
+ if (mapi_nameid->entries[i].propType) {
+ SPropTagArray->aulPropTag[i] = (SPropTagArray->aulPropTag[i] & 0xFFFF0000) |
+ mapi_nameid->entries[i].propType;
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Replace named property tags in SPropTagArray with the
+ property ID Exchange expects and stored in SPropTagArray2.
+
+ \param mapi_nameid the structure where results are stored
+ \param SPropTagArray the array of property tags with original
+ property tags
+ \param SPropTagArray2 the array of named property tags resolved
+ with GetIDsFromNames
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+
+ \sa GetIDsFromNames
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_map_SPropTagArray(struct mapi_nameid *mapi_nameid,
+ struct SPropTagArray *SPropTagArray,
+ struct SPropTagArray *SPropTagArray2)
+{
+ uint32_t i;
+ uint32_t j;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SPropTagArray2, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; i < SPropTagArray->cValues; i++) {
+ for (j = 0; j < mapi_nameid->count; j++) {
+ if (mapi_nameid->entries[j].proptag == SPropTagArray->aulPropTag[i]) {
+ SPropTagArray->aulPropTag[i] = (SPropTagArray2->aulPropTag[j] & 0xFFFF0000) |
+ mapi_nameid->entries[j].propType;
+ mapi_nameid->entries[j].position = i;
+ }
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Restore the original SPropTagArray array with the property
+ tags saved in the mapi_nameid structure.
+
+ \param mapi_nameid the structure where results are stored
+ \param SPropTagArray the array of property tags with original
+ property tags
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+
+ \sa GetIDsFromNames
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_unmap_SPropTagArray(struct mapi_nameid *mapi_nameid,
+ struct SPropTagArray *SPropTagArray)
+{
+ uint32_t i;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; i < mapi_nameid->count; i++) {
+ if (mapi_nameid->entries[i].position <= SPropTagArray->cValues) {
+ SPropTagArray->aulPropTag[mapi_nameid->entries[i].position] = mapi_nameid->entries[i].proptag;
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Replace named property tags in the SPropValue array with
+ the property ID Exchange expects and stored in SPropTagArray.
+
+ \param mapi_nameid the structure where results are stored
+ \param lpProps pointer on a SPropValue structure with property tags
+ and values
+ \param PropCount count of lpProps elements
+ \param SPropTagArray the array of named property tags resolved
+ with GetIDsFromNames
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+
+ \sa GetIDsFromNames
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_map_SPropValue(struct mapi_nameid *mapi_nameid,
+ struct SPropValue *lpProps,
+ uint32_t PropCount,
+ struct SPropTagArray *SPropTagArray)
+{
+ uint32_t i;
+ uint32_t j;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!lpProps, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!PropCount, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; i < PropCount; i++) {
+ for (j = 0; j < mapi_nameid->count; j++) {
+ if (mapi_nameid->entries[j].proptag == lpProps[i].ulPropTag) {
+ lpProps[i].ulPropTag = (SPropTagArray->aulPropTag[j] & 0xFFFF0000) |
+ mapi_nameid->entries[j].propType;
+ mapi_nameid->entries[j].position = i;
+ }
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Restore the original SPropValue array with the property
+ tags saved in the mapi_nameid structure.
+
+ \param mapi_nameid the structure where results are stored
+ \param lpProps the array of SPropValue structures with original
+ property tags
+ \param PropCount count of lpProps elements
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+
+ \sa GetIDsFromNames
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_unmap_SPropValue(struct mapi_nameid *mapi_nameid,
+ struct SPropValue *lpProps,
+ uint32_t PropCount)
+{
+ uint32_t i;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!lpProps, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!PropCount, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; i < mapi_nameid->count; i++) {
+ if (mapi_nameid->entries[i].position <= PropCount) {
+ lpProps[mapi_nameid->entries[i].position].ulPropTag = mapi_nameid->entries[i].proptag;
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Loop over SPropTagArray and look for canonical named
+ property tags we can add to the nameid structure.
+
+ \param nameid the structure where results are stored
+ \param SPropTagArray the array of property tags where to look for
+ canonical named property tags.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+ - MAPI_E_NOT_FOUND: no named property found
+
+ \sa GetIDsFromNames
+
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_lookup_SPropTagArray(struct mapi_nameid *nameid,
+ struct SPropTagArray *SPropTagArray)
+{
+ enum MAPISTATUS retval;
+ uint32_t i;
+ uint16_t proptype;
+ bool status = false;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!nameid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; i < SPropTagArray->cValues; i++) {
+ proptype = (SPropTagArray->aulPropTag[i] & 0xFFFF0000) >> 16;
+ if (((proptype >= 0x8000) && (proptype <= 0x8FFF)) ||
+ ((proptype >= 0xa000) && (proptype <= 0xaFFF))) {
+ retval = mapi_nameid_canonical_add(nameid, SPropTagArray->aulPropTag[i]);
+ if (retval == MAPI_E_SUCCESS) {
+ status = true;
+ }
+ }
+ }
+
+ return (status == true) ? MAPI_E_SUCCESS : MAPI_E_NOT_FOUND;
+}
+
+
+/**
+ \details Loop over lpProps and look for canonical named
+ property tags we can add to the nameid structure.
+
+ \param mapi_nameid the structure where results are stored
+ \param lpProps pointer on a SPropValue structure with the property
+ tags where to look for canonical named property tags
+ \param PropCount count of lpProps elemense
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+ - MAPI_E_NOT_FOUND: no named property found
+
+ \sa GetIDsFromNames
+
+ */
+_PUBLIC_ enum MAPISTATUS mapi_nameid_lookup_SPropValue(struct mapi_nameid *mapi_nameid,
+ struct SPropValue *lpProps,
+ unsigned long PropCount)
+{
+ enum MAPISTATUS retval;
+ uint32_t i;
+ uint16_t proptype;
+ bool status = false;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!lpProps, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (i = 0; i < PropCount; i++) {
+ proptype = (lpProps[i].ulPropTag & 0xFFFF0000) >> 16;
+ if (((proptype >= 0x8000) && (proptype <= 0x8FFF)) ||
+ ((proptype >= 0xa000) && (proptype <= 0xaFFF))) {
+ retval = mapi_nameid_canonical_add(mapi_nameid, lpProps[i].ulPropTag);
+ if (retval == MAPI_E_SUCCESS) {
+ status = true;
+ }
+ }
+ }
+
+ return (status == true) ? MAPI_E_SUCCESS : MAPI_E_NOT_FOUND;
+}
+
+
+/**
+ \details Lookup named properties (MNID_STRING) and return their
+ mapped proptags
+
+ This convenient function calls GetIDsFromNames() and returns
+ property tags with their real property type.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_INVALID_PARAMETER: one of the parameters was not set
+ properly
+
+ \sa GetIDsFromNames, mapi_nameid_SPropTagArray
+*/
+_PUBLIC_ enum MAPISTATUS mapi_nameid_GetIDsFromNames(struct mapi_nameid *mapi_nameid,
+ mapi_object_t *obj,
+ struct SPropTagArray *SPropTagArray)
+{
+ enum MAPISTATUS retval;
+ uint32_t i;
+
+ /* sanity check */
+ OPENCHANGE_RETVAL_IF(!mapi_nameid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
+
+ retval = GetIDsFromNames(obj, mapi_nameid->count, mapi_nameid->nameid, 0,
+ &SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, GetLastError(), NULL);
+
+ for (i = 0; i < SPropTagArray->cValues; i++) {
+ SPropTagArray->aulPropTag[i] = (SPropTagArray->aulPropTag[i] & 0xFFFF0000) |
+ mapi_nameid->entries[i].propType;
+ }
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/mapi_notification.h
===================================================================
--- trunk/openchange/libmapi/mapi_notification.h (rev 0)
+++ trunk/openchange/libmapi/mapi_notification.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,49 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 __MAPI_NOTIFICATION_H__
+#define __MAPI_NOTIFICATION_H__
+
+/* notification which takes:
+ * - ulEvenType = type of notification
+ * - void * = notification data
+ * - void * = private data pointer
+*/
+typedef int (*mapi_notify_callback_t)(uint16_t, void *, void *);
+
+struct notifications {
+ uint32_t ulConnection; /* connection number */
+ uint32_t NotificationFlags; /* events mask associated */
+ mapi_id_t parentID; /* parent EntryID == FID here */
+ mapi_notify_callback_t callback; /* callback to run when */
+ struct mapi_object obj_notif; /* notification object */
+ struct notifications *prev;
+ struct notifications *next;
+};
+
+struct mapi_notify_ctx {
+ struct NOTIFKEY key; /* unique identifier */
+ int fd; /* UDP socket file descriptor */
+ struct sockaddr *addr;
+ struct notifications *notifications;
+};
+
+#define DFLT_NOTIF_PORT 2500
+
+#endif /*!__MAPI_NOTIFICATION_H__ */
Added: trunk/openchange/libmapi/mapi_object.c
===================================================================
--- trunk/openchange/libmapi/mapi_object.c (rev 0)
+++ trunk/openchange/libmapi/mapi_object.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,367 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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/proto_private.h>
+#include <libmapi/defs_private.h>
+
+/**
+ \file mapi_object.c
+
+ \brief mapi_object_t support functions
+*/
+
+
+/* FIXME: mapi_object functions should return error codes */
+
+
+/**
+ keep intern to this file
+*/
+#define INVALID_HANDLE_VALUE 0xffffffff
+
+
+/**
+ \details Reset a MAPI object structure
+
+ \param obj pointer on the MAPI object to reset
+ */
+static void mapi_object_reset(mapi_object_t *obj)
+{
+ obj->handle = INVALID_HANDLE_VALUE;
+ obj->id = 0;
+ obj->session = NULL;
+ obj->private_data = NULL;
+}
+
+
+/**
+ \details Initialize MAPI object
+
+ This function is required to be called before any
+ manipulation of this MAPI object.
+
+ \param obj the object to initialize
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
+
+ \sa mapi_object_release
+*/
+_PUBLIC_ enum MAPISTATUS mapi_object_init(mapi_object_t *obj)
+{
+ mapi_object_reset(obj);
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Release MAPI object
+
+ This function is required to be called when this MAPI object
+ is no longer required.
+
+ \param obj pointer on the MAPI object to release
+
+ \sa mapi_object_initialize, Release
+*/
+_PUBLIC_ void mapi_object_release(mapi_object_t *obj)
+{
+ enum MAPISTATUS retval;
+
+ if (!obj) return;
+ if (obj->handle == INVALID_HANDLE_VALUE) return;
+
+ retval = Release(obj);
+ if (retval == MAPI_E_SUCCESS) {
+ if (obj->private_data) {
+ talloc_free(obj->private_data);
+ }
+ mapi_object_reset(obj);
+ }
+}
+
+
+/**
+ \details Check if the supplied object has a valid handle
+
+ \param obj pointer on the MAPI object to test
+
+ \return 0 on success, otherwise 1
+ */
+int mapi_object_is_invalid(mapi_object_t *obj)
+{
+ if (mapi_object_get_handle(obj) == INVALID_HANDLE_VALUE) {
+ return 1;
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Copy MAPI object
+
+ This function copies mapi_object data from source to destination.
+
+ \param dst pointer on the destination MAPI object
+ \param src pointer on the source MAPI object
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_INITIALIZED
+
+ */
+_PUBLIC_ enum MAPISTATUS mapi_object_copy(mapi_object_t *dst, mapi_object_t *src)
+{
+ mapi_object_reset(dst);
+
+ OPENCHANGE_RETVAL_IF(!dst || !src, MAPI_E_NOT_INITIALIZED, NULL);
+
+ dst->id = src->id;
+ dst->handle = src->handle;
+ dst->private_data = src->private_data;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve the session associated to the MAPI object
+
+ \param obj the object to get the session for
+
+ \return pointer on a MAPI session on success, otherwise NULL
+ */
+_PUBLIC_ struct mapi_session *mapi_object_get_session(mapi_object_t *obj)
+{
+ if (!obj) return NULL;
+ if (!obj->session) return NULL;
+
+ return obj->session;
+}
+
+
+/**
+ \details Set the session for a given MAPI object
+
+ \param obj pointer on the object to set the session for
+ \param session pointer on the MAPI session to associate to the MAPI
+ object
+ */
+_PUBLIC_ void mapi_object_set_session(mapi_object_t *obj,
+ struct mapi_session *session)
+{
+ if (obj) {
+ obj->session = session;
+ }
+}
+
+
+/**
+ \details Retrieve an object ID for a given MAPI object
+
+ \param obj pointer on the MAPI object to get the ID for
+
+ \return the object ID, or -1 if the object does not exist
+*/
+_PUBLIC_ mapi_id_t mapi_object_get_id(mapi_object_t *obj)
+{
+ return (!obj) ? -1 : obj->id;
+}
+
+
+/**
+ \details Set the id for a given MAPI object
+
+ \param obj pointer on the MAPI object to set the session for
+ \param id Identifier to set to the object obj
+ */
+void mapi_object_set_id(mapi_object_t *obj, mapi_id_t id)
+{
+ obj->id = id;
+}
+
+
+/**
+ \details Retrieve the handle associated to a MAPI object
+
+ \param obj pointer on the MAPI object to retrieve the handle from
+
+ \return a valid MAPI object handle on success, otherwise -1.
+ */
+mapi_handle_t mapi_object_get_handle(mapi_object_t *obj)
+{
+ return (!obj) ? -1 : obj->handle;
+}
+
+
+/**
+ \details Associate a handle to a MAPI object
+
+ \param obj pointer on the MAPI object on which handle has to be set
+ \param handle the MAPI handle value
+ */
+void mapi_object_set_handle(mapi_object_t *obj, mapi_handle_t handle)
+{
+ obj->handle = handle;
+}
+
+
+/**
+ \details Dump a MAPI object (for debugging)
+
+ \param obj pointer on the MAPI object to dump out
+*/
+_PUBLIC_ void mapi_object_debug(mapi_object_t *obj)
+{
+ DEBUG(0, ("mapi_object {\n"));
+ DEBUG(0, (" .handle == 0x%x\n", obj->handle));
+ DEBUG(0, (" .id == 0x%"PRIx64"\n", obj->id));
+ DEBUG(0, ("};\n"));
+}
+
+
+/**
+ \details Initialize MAPI object private data to store a MAPI object
+ table
+
+ \param mem_ctx pointer on the memory context
+ \param obj_table pointer on the MAPI object
+ */
+void mapi_object_table_init(TALLOC_CTX *mem_ctx, mapi_object_t *obj_table)
+{
+ mapi_object_table_t *table = NULL;
+
+ if (obj_table->private_data == NULL) {
+ obj_table->private_data = talloc_zero((TALLOC_CTX *)mem_ctx, mapi_object_table_t);
+ }
+
+ table = (mapi_object_table_t *) obj_table->private_data;
+
+ if (table->bookmark == NULL) {
+ table->bookmark = talloc_zero((TALLOC_CTX *)table, mapi_object_bookmark_t);
+ }
+
+
+ table->proptags.aulPropTag = 0;
+ table->proptags.cValues = 0;
+ /* start bookmark index after BOOKMARK_END */
+ table->bk_last = 3;
+}
+
+
+/**
+ \details Fetch a bookmark within a MAPI object table
+
+ \param obj_table pointer on the MAPI object table
+ \param bkPosition the bookmark position to find
+ \param bin pointer on the Sbinary_short the function fills
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+ */
+enum MAPISTATUS mapi_object_bookmark_find(mapi_object_t *obj_table, uint32_t bkPosition,
+ struct SBinary_short *bin)
+{
+ mapi_object_table_t *table;
+ mapi_object_bookmark_t *bookmark;
+
+ table = (mapi_object_table_t *)obj_table->private_data;
+ bookmark = table->bookmark;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!table, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!bookmark, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(bkPosition > table->bk_last, MAPI_E_INVALID_BOOKMARK, NULL);
+
+ while (bookmark) {
+ if (bookmark->index == bkPosition) {
+ bin->cb = bookmark->bin.cb;
+ bin->lpb = bookmark->bin.lpb;
+ return MAPI_E_SUCCESS;
+ }
+ bookmark = bookmark->next;
+ }
+ return MAPI_E_INVALID_BOOKMARK;
+}
+
+
+/**
+ \details Retrieve the number of bookmarks stored in a MAPI object table
+
+ \param obj_table pointer to the MAPI object table
+ \param count pointer to the number of bookmarks to return
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+ */
+_PUBLIC_ enum MAPISTATUS mapi_object_bookmark_get_count(mapi_object_t *obj_table,
+ uint32_t *count)
+{
+ mapi_object_table_t *table;
+
+ table = (mapi_object_table_t *)obj_table->private_data;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!table, MAPI_E_NOT_INITIALIZED, NULL);
+
+ *count = table->bk_last - 3;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Dump bookmarks associated to a MAPI object table
+
+ \param obj_table pointer on the MAPI object table
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+ */
+_PUBLIC_ enum MAPISTATUS mapi_object_bookmark_debug(mapi_object_t *obj_table)
+{
+ mapi_object_table_t *table;
+ mapi_object_bookmark_t *bookmark;
+
+ table = (mapi_object_table_t *)obj_table->private_data;
+ bookmark = table->bookmark;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!table, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!bookmark, MAPI_E_NOT_INITIALIZED, NULL);
+
+ while (bookmark) {
+ DEBUG(0, ("mapi_object_bookmark {\n"));
+ DEBUG(0, (".index == %u\n", bookmark->index));
+ dump_data(0, bookmark->bin.lpb, bookmark->bin.cb);
+ DEBUG(0, ("};\n"));
+
+ bookmark = bookmark->next;
+ }
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/mapi_object.h
===================================================================
--- trunk/openchange/libmapi/mapi_object.h (rev 0)
+++ trunk/openchange/libmapi/mapi_object.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,117 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007.
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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 __MAPI_OBJECT_H
+#define __MAPI_OBJECT_H
+
+
+#include <gen_ndr/exchange.h>
+
+
+/* forward declarations
+ */
+struct mapi_session;
+
+/* generic mapi object definition
+ */
+
+typedef uint64_t mapi_id_t;
+typedef uint32_t mapi_handle_t;
+
+typedef struct mapi_object {
+ uint64_t id;
+ mapi_handle_t handle;
+ struct mapi_session *session;
+ void *private_data;
+} mapi_object_t;
+
+
+/*
+ * Interface objects
+ */
+
+
+/**
+ * IMsgStore object
+ */
+typedef struct mapi_obj_store
+{
+ /* Mailbox */
+ uint64_t fid_mailbox_root;
+ uint64_t fid_deferred_actions;
+ uint64_t fid_spooler_queue;
+ uint64_t fid_top_information_store;
+ uint64_t fid_inbox;
+ uint64_t fid_outbox;
+ uint64_t fid_sent_items;
+ uint64_t fid_deleted_items;
+ uint64_t fid_common_views;
+ uint64_t fid_schedule;
+ uint64_t fid_search;
+ uint64_t fid_views;
+ uint64_t fid_shortcuts;
+ /* Public Folders */
+ uint64_t fid_pf_public_root;
+ uint64_t fid_pf_ipm_subtree;
+ uint64_t fid_pf_non_ipm_subtree;
+ uint64_t fid_pf_EFormsRegistryRoot;
+ uint64_t fid_pf_FreeBusyRoot;
+ uint64_t fid_pf_OfflineAB;
+ uint64_t fid_pf_EFormsRegistry;
+ uint64_t fid_pf_LocalSiteFreeBusy;
+ uint64_t fid_pf_LocalSiteOfflineAB;
+ uint64_t fid_pf_NNTPArticle;
+ /* cached data */
+ bool cached_mailbox_fid;
+ uint64_t fid_calendar;
+ uint64_t fid_contact;
+ uint64_t fid_journal;
+ uint64_t fid_note;
+ uint64_t fid_task;
+ uint64_t fid_drafts;
+} mapi_object_store_t;
+
+
+/**
+ * IMAPITable object
+ */
+
+typedef struct mapi_obj_bookmark {
+ uint32_t index;
+ struct SBinary_short bin;
+ struct mapi_obj_bookmark *prev;
+ struct mapi_obj_bookmark *next;
+} mapi_object_bookmark_t;
+
+
+typedef struct mapi_obj_table {
+ uint32_t bk_last;
+ mapi_object_bookmark_t *bookmark;
+ struct SPropTagArray proptags;
+} mapi_object_table_t;
+
+
+typedef struct mapi_obj_message {
+ uint32_t cValues;
+ struct SPropTagArray SPropTagArray;
+ struct SRowSet SRowSet;
+} mapi_object_message_t;
+
+#endif /*!__MAPI_OBJECT_H */
Added: trunk/openchange/libmapi/mapi_profile.h
===================================================================
--- trunk/openchange/libmapi/mapi_profile.h (rev 0)
+++ trunk/openchange/libmapi/mapi_profile.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,58 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007.
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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 __MAPI_PROFILE_H
+#define __MAPI_PROFILE_H
+
+
+#include <talloc.h>
+
+
+/* forward decls */
+struct cli_credentials;
+struct ldb_context;
+
+
+/* mapi profile
+ */
+struct mapi_profile
+{
+ struct cli_credentials *credentials;
+ char *profname;
+ const char *org;
+ const char *ou;
+ const char *username;
+ const char *password;
+ const char *mailbox;
+ const char *workstation;
+ const char *homemdb;
+ const char *domain;
+ const char *realm;
+ const char *server;
+ uint32_t codepage;
+ uint32_t language;
+ uint32_t method;
+};
+
+typedef int (*mapi_profile_callback_t)(struct SRowSet *, const void *);
+
+#define OC_PROFILE_NOPASSWORD 1
+
+#endif /* ! __MAPI_PROFILE_H__ */
Added: trunk/openchange/libmapi/mapi_provider.h
===================================================================
--- trunk/openchange/libmapi/mapi_provider.h (rev 0)
+++ trunk/openchange/libmapi/mapi_provider.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,58 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007.
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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 __MAPI_PROVIDER_H
+#define __MAPI_PROVIDER_H
+
+
+/* forward decls */
+struct mapi_object;
+struct mapi_profile;
+struct mapi_notify_ctx;
+
+enum PROVIDER_ID {
+ PROVIDER_ID_EMSMDB = 0x1,
+ PROVIDER_ID_NSPI = 0x2,
+ PROVIDER_ID_UNKNOWN
+};
+
+struct mapi_provider {
+ enum PROVIDER_ID id;
+ void *ctx;
+};
+
+struct mapi_objects {
+ struct mapi_object *object;
+ struct mapi_objects *prev;
+ struct mapi_objects *next;
+};
+
+struct mapi_session {
+ struct mapi_provider *emsmdb;
+ struct mapi_provider *nspi;
+ struct mapi_profile *profile;
+ struct mapi_notify_ctx *notify_ctx;
+ struct mapi_objects *objects;
+
+ struct mapi_session *next;
+ struct mapi_session *prev;
+};
+
+#endif /* !__MAPI_PROVIDER_H */
Added: trunk/openchange/libmapi/mapidefs.h
===================================================================
--- trunk/openchange/libmapi/mapidefs.h (rev 0)
+++ trunk/openchange/libmapi/mapidefs.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,292 @@
+/*
+ OpenChange MAPI implementation.
+ MAPI definitions
+
+ Copyright (C) Julien Kerihuel 2005 - 2007.
+
+ 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 __MAPIDEFS_H__
+#define __MAPIDEFS_H__
+
+#define PROP_TAG(type, id) (((id << 16))| (type))
+#define MV_FLAG 0x1000
+
+/* UNICODE flags */
+#define MAPI_UNICODE 0x80000000
+
+/* Property types */
+#define PT_UNSPECIFIED 0x0
+#define PT_NULL 0x1
+#define PT_I2 0x2
+#define PT_SHORT 0x2
+#define PT_LONG 0x3
+#define PT_FLOAT 0x4
+#define PT_DOUBLE 0x5
+#define PT_CURRENCY 0x6
+#define PT_APPTIME 0x7
+#define PT_ERROR 0xa
+#define PT_BOOLEAN 0xb
+#define PT_OBJECT 0xd
+#define PT_I8 0x14
+#define PT_STRING8 0x1e
+#define PT_UNICODE 0x1f
+#define PT_SYSTIME 0x40
+#define PT_CLSID 0x48
+#define PT_SVREID 0xFB
+#define PT_SRESTRICT 0xFD
+#define PT_BINARY 0x102
+
+/* Multi valued property types */
+#define PT_MV_SHORT (MV_FLAG | PT_SHORT)
+#define PT_MV_LONG (MV_FLAG | PT_LONG)
+#define PT_MV_FLOAT (MV_FLAG | PT_FLOAT)
+#define PT_MV_DOUBLE (MV_FLAG | PT_DOUBLE)
+#define PT_MV_CURRENCY (MV_FLAG | PT_CURRENCY)
+#define PT_MV_APPTIME (MV_FLAG | PT_APPTIME)
+#define PT_MV_I8 (MV_FLAG | PT_I8)
+#define PT_MV_STRING8 (MV_FLAG | PT_STRING8)
+#define PT_MV_UNICODE (MV_FLAG | PT_UNICODE)
+#define PT_MV_SYSTIME (MV_FLAG | PT_SYSTIME)
+#define PT_MV_CLSID (MV_FLAG | PT_CLSID)
+#define PT_MV_BINARY (MV_FLAG | PT_BINARY)
+
+/* Restriction types */
+#define RES_AND 0
+#define RES_OR 1
+#define RES_NOT 2
+#define RES_CONTENT 3
+#define RES_PROPERTY 4
+#define RES_COMPAREPROPS 5
+#define RES_BITMASK 6
+#define RES_SIZE 7
+#define RES_EXIST 8
+#define RES_SUBRESTRICTION 9
+#define RES_COMMENT 10
+
+/* Resolve types */
+#define MAPI_UNRESOLVED 0x0
+#define MAPI_AMBIGUOUS 0x1
+#define MAPI_RESOLVED 0x2
+
+/* Object Type */
+#define MAPI_STORE 0x1 /* Message Store */
+#define MAPI_ADDRBOOK 0x2 /* Address Book */
+#define MAPI_FOLDER 0x3 /* Folder */
+#define MAPI_ABCONT 0x4 /* Address Book Container */
+#define MAPI_MESSAGE 0x5 /* Message */
+#define MAPI_MAILUSER 0x6 /* Individual Recipient */
+#define MAPI_ATTACH 0x7 /* Attachment */
+#define MAPI_DISTLIST 0x8 /* Distribution List Recipient */
+#define MAPI_PROFSECT 0x9 /* Profile Section */
+#define MAPI_STATUS 0xA /* Status Object */
+#define MAPI_SESSION 0xB /* Session */
+#define MAPI_FORMINFO 0xC /* Form Information */
+
+/* Display Type */
+#define DT_MAILUSER 0x0
+#define DT_DISTLIST 0x1
+#define DT_FORUM 0x2
+#define DT_AGENT 0x3
+#define DT_ORGANIZATION 0x4
+#define DT_PRIVATE_DISTLIST 0x5
+#define DT_REMOTE_MAILUSER 0x6
+#define DT_CONTAINER 0x100
+#define DT_TEMPLATE 0x101
+#define DT_ADDRESS_TEMPLATE 0x102
+#define DT_SEARCH 0x200
+
+/* Attachment method */
+#define NO_ATTACHMENT 0
+#define ATTACH_BY_VALUE 1
+#define ATTACH_BY_REFERENCE 2
+#define ATTACH_BY_REF_RESOLVE 3
+#define ATTACH_BY_REF_ONLY 4
+#define ATTACH_EMBEDDED_MSG 5
+#define ATTACH_OLE 6
+
+/* Creation flags */
+#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 */
+
+/* OpenMessage flags */
+#define MAPI_MODIFY 0x1
+/* see MAPI_CREATE above */
+
+
+/* GetGALTable flags */
+#define TABLE_START 0x0
+#define TABLE_CUR 0x1
+
+/*
+ * ENTRYID flags
+ */
+
+/* definition for abFlags[0] */
+#define MAPI_SHORTTERM 0x80
+#define MAPI_NOTRECIP 0x40
+#define MAPI_THISSESSION 0x20
+#define MAPI_NOW 0x10
+#define MAPI_NOTRESERVED 0x08
+
+/* definition for abFlags[1] */
+#define MAPI_COMPOUND 0x80
+
+/*
+ * Priority
+ */
+
+#define PRIORITY_LOW -1
+#define PRIORITY_NORMAL 0
+#define PRIORITY_HIGH 1
+
+/*
+ * Importance
+ */
+
+#define IMPORTANCE_LOW 0
+#define IMPORTANCE_NORMAL 1
+#define IMPORTANCE_HIGH 2
+
+/*
+ * Color
+ */
+
+#define olBlue 0
+#define olGreen 1
+#define olPink 2
+#define olYellow 3
+#define olWhite 4
+
+
+/*
+ * Appointment flags with PR_APPOINTMENT_BUSY_STATUS
+ */
+
+#define BUSY_STATUS_FREE 0
+#define BUSY_STATUS_TENTATIVE 1
+#define BUSY_STATUS_BUSY 2
+#define BUSY_STATUS_OUTOFOFFICE 3
+
+/*
+ * Appointment meeting status
+ */
+#define MEETING_STATUS_NONMEETING 0
+#define MEETING_STATUS_MEETING 1
+
+/*
+ * Task status
+ */
+
+#define olTaskNotStarted 0
+#define olTaskInProgress 1
+#define olTaskComplete 2
+#define olTaskWaiting 3
+#define olTaskDeferred 4
+
+/*
+ * Task OwnerShip
+ */
+#define olNewTask 0
+#define olDelegatedTask 1
+#define olOwnTask 2
+
+/*
+ * PR_MESSAGE_EDITOR_FORMAT type
+ */
+#define EDITOR_FORMAT_PLAINTEXT 1
+#define EDITOR_FORMAT_HTML 2
+#define EDITOR_FORMAT_RTF 3
+
+#define olEditorText 1
+#define olEditorHTML 2
+#define olEditorRTF 3
+#define olEditorWord 4
+
+/*
+ * Default folders
+ */
+#define olFolderTopInformationStore 1
+#define olFolderDeletedItems 3
+#define olFolderOutbox 4
+#define olFolderSentMail 5
+#define olFolderInbox 6
+#define olFolderCommonView 8
+#define olFolderCalendar 9
+#define olFolderContacts 10
+#define olFolderJournal 11
+#define olFolderNotes 12
+#define olFolderTasks 13
+#define olFolderDrafts 16
+#define olPublicFoldersAllPublicFolders 18
+#define olFolderConflicts 19
+#define olFolderSyncIssues 20
+#define olFolderLocalFailures 21
+#define olFolderServerFailures 22
+#define olFolderJunk 23
+#define olFolderFinder 24
+#define olFolderPublicRoot 25
+#define olFolderPublicIPMSubtree 26
+#define olFolderPublicNonIPMSubtree 27
+#define olFolderPublicEFormsRoot 28
+#define olFolderPublicFreeBusyRoot 29
+#define olFolderPublicOfflineAB 30
+#define olFolderPublicEFormsRegistry 31
+#define olFolderPublicLocalFreeBusy 32
+#define olFolderPublicLocalOfflineAB 33
+#define olFolderPublicNNTPArticle 34
+
+/*
+ * IPF container class
+ */
+
+#define IPF_APPOINTMENT "IPF.Appointment"
+#define IPF_CONTACT "IPF.Contact"
+#define IPF_JOURNAL "IPF.Journal"
+#define IPF_NOTE "IPF.Note"
+#define IPF_STICKYNOTE "IPF.StickyNote"
+#define IPF_TASK "IPF.Task"
+#define IPF_POST "IPF.Post"
+
+/*
+ * Common OLEGUID - see MS-OXPROPS, Section 1.3.2
+ */
+
+#define PSETID_Appointment "00062002-0000-0000-c000-000000000046"
+#define PSETID_Task "00062003-0000-0000-c000-000000000046"
+#define PSETID_Address "00062004-0000-0000-c000-000000000046"
+#define PSETID_Common "00062008-0000-0000-c000-000000000046"
+#define PSETID_Note "0006200e-0000-0000-c000-000000000046"
+#define PSETID_Log "0006200a-0000-0000-c000-000000000046"
+#define PSETID_Sharing "00062040-0000-0000-c000-000000000046"
+#define PSETID_PostRss "00062041-0000-0000-c000-000000000046"
+#define PSETID_UnifiedMessaging "4442858e-a9e3-4e80-b900-317a210cc15b"
+#define PSETID_Meeting "6ed8da90-450b-101b-98da-00aa003f1305"
+#define PSETID_AirSync "71035549-0739-4dcb-9163-00f0580dbbdf"
+#define PSETID_Attachment "96357f7f-59e1-47d0-99a7-46515c183b54"
+#define PS_PUBLIC_STRINGS "00020329-0000-0000-c000-000000000046"
+#define PS_INTERNET_HEADERS "00020386-0000-0000-c000-000000000046"
+#define PS_MAPI "00020328-0000-0000-c000-000000000046"
+
+/* FreeBusy strings for Exchange 2003 and below */
+#define FREEBUSY_FOLDER "EX:/o=%s/ou=%s"
+#define FREEBUSY_USER "USER-/CN=RECIPIENTS/CN=%s"
+
+#endif /*!__MAPIDEFS_H__ */
Added: trunk/openchange/libmapi/mapidump.c
===================================================================
--- trunk/openchange/libmapi/mapidump.c (rev 0)
+++ trunk/openchange/libmapi/mapidump.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,767 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/mapidump.h>
+#include <libmapi/proto_private.h>
+#include <libmapi/defs_private.h>
+#include <time.h>
+
+/**
+ \file mapidump.c
+
+ \brief Functions for displaying various data structures, mainly for debugging
+ */
+
+_PUBLIC_ void mapidump_SPropValue(struct SPropValue lpProp, const char *sep)
+{
+ const char *proptag;
+ const void *data;
+ TALLOC_CTX *mem_ctx = NULL;
+ const struct StringArray_r *StringArray_r = NULL;
+ uint32_t i;
+
+ proptag = get_proptag_name(lpProp.ulPropTag);
+ if (!proptag) {
+ mem_ctx = talloc_named(NULL, 0, "mapidump_SPropValue");
+ proptag = talloc_asprintf(mem_ctx, "0x%.8x", lpProp.ulPropTag);
+ }
+
+
+ switch(lpProp.ulPropTag & 0xFFFF) {
+ case PT_BOOLEAN:
+ data = get_SPropValue_data(&lpProp);
+ printf("%s%s: 0x%x\n", sep?sep:"", proptag, (*(const uint8_t *)data));
+ break;
+ case PT_I8:
+ data = get_SPropValue_data(&lpProp);
+ printf("%s%s: %.16"PRIx64"\n", sep?sep:"", proptag, (*(const uint64_t *)data));
+ break;
+ 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");
+ break;
+ case PT_SYSTIME:
+ mapidump_date_SPropValue(lpProp, proptag);
+ break;
+ case PT_ERROR:
+ data = get_SPropValue_data(&lpProp);
+ printf("%s%s: 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));
+ break;
+ 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);
+ break;
+ case PT_MV_STRING8:
+ StringArray_r = (const struct StringArray_r *) get_SPropValue_data(&lpProp);
+ printf("%s%s: ", sep?sep:"", proptag);
+ for (i = 0; i < StringArray_r->cValues - 1; i++) {
+ printf("%s, ", StringArray_r->lppszA[i]);
+ }
+ printf("%s\n", StringArray_r->lppszA[i]);
+ break;
+ default:
+ break;
+ }
+
+ if (mem_ctx) {
+ talloc_free(mem_ctx);
+ }
+
+}
+
+_PUBLIC_ void mapidump_SPropTagArray(struct SPropTagArray *SPropTagArray)
+{
+ uint32_t count;
+ const char *proptag;
+
+ if (!SPropTagArray) return;
+ if (!SPropTagArray->cValues) return;
+
+ for (count = 0; count != SPropTagArray->cValues; count++) {
+ proptag = get_proptag_name(SPropTagArray->aulPropTag[count]);
+ if (proptag) {
+ printf("%s\n", proptag);
+ } else {
+ printf("0x%.8x\n", SPropTagArray->aulPropTag[count]);
+ }
+ }
+}
+
+_PUBLIC_ void mapidump_SRowSet(struct SRowSet *SRowSet, const char *sep)
+{
+ uint32_t i;
+
+ /* Sanity checks */
+ if (!SRowSet) return;
+ if (!SRowSet->cRows) return;
+
+ for (i = 0; i < SRowSet->cRows; i++) {
+ mapidump_SRow(&(SRowSet->aRow[i]), sep);
+ }
+}
+
+_PUBLIC_ void mapidump_SRow(struct SRow *aRow, const char *sep)
+{
+ uint32_t i;
+
+ for (i = 0; i < aRow->cValues; i++) {
+ mapidump_SPropValue(aRow->lpProps[i], sep);
+ }
+}
+
+
+_PUBLIC_ void mapidump_PAB_entry(struct SRow *aRow)
+{
+ const char *addrtype;
+ const char *name;
+ const char *email;
+ const char *account;
+
+ addrtype = (const char *)find_SPropValue_data(aRow, PR_ADDRTYPE_UNICODE);
+ name = (const char *)find_SPropValue_data(aRow, PR_DISPLAY_NAME_UNICODE);
+ email = (const char *)find_SPropValue_data(aRow, PR_EMAIL_ADDRESS_UNICODE);
+ account = (const char *)find_SPropValue_data(aRow, PR_ACCOUNT_UNICODE);
+
+ printf("[%s] %s:\n\tName: %-25s\n\tEmail: %-25s\n",
+ addrtype, account, name, email);
+ fflush(0);
+}
+
+
+_PUBLIC_ void mapidump_Recipients(const char **usernames, struct SRowSet *rowset, struct SPropTagArray *flaglist)
+{
+ uint32_t i;
+ uint32_t j;
+
+ for (i = 0, j= 0; i < flaglist->cValues; i++) {
+ switch (flaglist->aulPropTag[i]) {
+ case MAPI_UNRESOLVED:
+ printf("\tUNRESOLVED (%s)\n", usernames[i]);
+ break;
+ case MAPI_AMBIGUOUS:
+ printf("\tAMBIGUOUS (%s)\n", usernames[i]);
+ break;
+ case MAPI_RESOLVED:
+ printf("\tRESOLVED (%s)\n", usernames[i]);
+ mapidump_SRow(&rowset->aRow[j], "\t\t[+] ");
+ j++;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+_PUBLIC_ void mapidump_date(struct mapi_SPropValue_array *properties, uint32_t mapitag, const char *label)
+{
+ TALLOC_CTX *mem_ctx;
+ NTTIME time;
+ const struct FILETIME *filetime;
+ const char *date;
+
+ mem_ctx = talloc_named(NULL, 0, "mapidump_date");
+
+ filetime = (const struct FILETIME *) find_mapi_SPropValue_data(properties, mapitag);
+ if (filetime) {
+ time = filetime->dwHighDateTime;
+ time = time << 32;
+ time |= filetime->dwLowDateTime;
+ date = nt_time_string(mem_ctx, time);
+ printf("\t%-15s: %s\n", label, date);
+ fflush(0);
+ }
+
+ talloc_free(mem_ctx);
+}
+
+
+_PUBLIC_ void mapidump_date_SPropValue(struct SPropValue lpProp, const char *label)
+{
+ TALLOC_CTX *mem_ctx;
+ NTTIME time;
+ const struct FILETIME *filetime;
+ const char *date;
+
+ mem_ctx = talloc_named(NULL, 0, "mapidump_date_SPropValue");
+
+ filetime = (const struct FILETIME *) get_SPropValue_data(&lpProp);
+ if (filetime) {
+ time = filetime->dwHighDateTime;
+ time = time << 32;
+ time |= filetime->dwLowDateTime;
+ date = nt_time_string(mem_ctx, time);
+ printf("\t%s: %s\n", label, date);
+ fflush(0);
+ }
+
+ talloc_free(mem_ctx);
+}
+
+/**
+ \details This function dumps the properties relating to a message to standard output
+
+ The expected way to obtain the properties array is to use OpenMessage() to obtain the
+ message object, then to use GetPropsAll() to obtain all the properties.
+
+ \param properties array of message properties
+ \param id identification to display for the message (can be NULL)
+
+ \sa mapidump_appointment, mapidump_contact, mapidump_task, mapidump_note
+*/
+_PUBLIC_ void mapidump_message(struct mapi_SPropValue_array *properties, const char *id)
+{
+ const char *msgid;
+ const char *from;
+ const char *to;
+ const char *cc;
+ const char *bcc;
+ const char *subject;
+ const char *body;
+ const char *codepage;
+ const struct SBinary_short *html = NULL;
+ const uint8_t *has_attach;
+ const uint32_t *cp;
+ ssize_t len;
+
+ msgid = (const char *)find_mapi_SPropValue_data(properties, PR_INTERNET_MESSAGE_ID);
+ subject = (const char *) find_mapi_SPropValue_data(properties, PR_CONVERSATION_TOPIC);
+ body = (const char *) find_mapi_SPropValue_data(properties, PR_BODY);
+ if (!body) {
+ body = (const char *) find_mapi_SPropValue_data(properties, PR_BODY_UNICODE);
+ if (!body) {
+ html = (const struct SBinary_short *) find_mapi_SPropValue_data(properties, PR_HTML);
+ }
+ }
+ from = (const char *) find_mapi_SPropValue_data(properties, PR_SENT_REPRESENTING_NAME);
+ to = (const char *) find_mapi_SPropValue_data(properties, PR_DISPLAY_TO);
+ cc = (const char *) find_mapi_SPropValue_data(properties, PR_DISPLAY_CC);
+ bcc = (const char *) find_mapi_SPropValue_data(properties, PR_DISPLAY_BCC);
+
+ has_attach = (const uint8_t *)find_mapi_SPropValue_data(properties, PR_HASATTACH);
+
+ cp = (const uint32_t *)find_mapi_SPropValue_data(properties, PR_MESSAGE_CODEPAGE);
+ switch (cp ? *cp : 0) {
+ case CP_USASCII:
+ codepage = "CP_USASCII";
+ break;
+ case CP_UNICODE:
+ codepage = "CP_UNICODE";
+ break;
+ case CP_JAUTODETECT:
+ codepage = "CP_JAUTODETECT";
+ break;
+ case CP_KAUTODETECT:
+ codepage = "CP_KAUTODETECT";
+ break;
+ case CP_ISO2022JPESC:
+ codepage = "CP_ISO2022JPESC";
+ break;
+ case CP_ISO2022JPSIO:
+ codepage = "CP_ISO2022JPSIO";
+ break;
+ default:
+ codepage = "";
+ break;
+ }
+
+ printf("+-------------------------------------+\n");
+ printf("message id: %s %s\n", msgid ? msgid : "", id?id:"");
+ printf("subject: %s\n", subject ? subject : "");
+ printf("From: %s\n", from ? from : "");
+ printf("To: %s\n", to ? to : "");
+ printf("Cc: %s\n", cc ? cc : "");
+ printf("Bcc: %s\n", bcc ? bcc : "");
+ if (has_attach) {
+ printf("Attachment: %s\n", *has_attach ? "True" : "False");
+ }
+ printf("Codepage: %s\n", codepage);
+ printf("Body:\n");
+ fflush(0);
+ if (body) {
+ printf("%s\n", body ? body : "");
+ } else if (html) {
+ len = write(1, html->lpb, html->cb);
+ len = write(1, "\n", 1);
+ fflush(0);
+ }
+}
+
+/**
+ \details This function dumps the properties relating to an appointment to standard output
+
+ The expected way to obtain the properties array is to use OpenMessage() to obtain the
+ appointment object, then to use GetPropsAll() to obtain all the properties.
+
+ \param properties array of appointment properties
+ \param id identification to display for the appointment (can be NULL)
+
+ \sa mapidump_message, mapidump_contact, mapidump_task, mapidump_note
+*/
+_PUBLIC_ void mapidump_appointment(struct mapi_SPropValue_array *properties, const char *id)
+{
+ const struct mapi_SLPSTRArray *contacts = NULL;
+ const char *subject = NULL;
+ const char *location= NULL;
+ const char *timezone = NULL;
+ const uint32_t *status;
+ const uint8_t *priv = NULL;
+ uint32_t i;
+
+ contacts = (const struct mapi_SLPSTRArray *)find_mapi_SPropValue_data(properties, PidLidContacts);
+ subject = (const char *)find_mapi_SPropValue_data(properties, PR_CONVERSATION_TOPIC);
+ timezone = (const char *)find_mapi_SPropValue_data(properties, PidLidTimeZoneDescription);
+ location = (const char *)find_mapi_SPropValue_data(properties, PidLidLocation);
+ status = (const uint32_t *)find_mapi_SPropValue_data(properties, PidLidBusyStatus);
+ priv = (const uint8_t *)find_mapi_SPropValue_data(properties, PidLidPrivate);
+
+ printf("|== %s ==| %s\n", subject?subject:"", id?id:"");
+ fflush(0);
+
+ if (location) {
+ printf("\tLocation: %s\n", location);
+ fflush(0);
+ }
+
+ mapidump_date(properties, PR_START_DATE, "Start time");
+ mapidump_date(properties, PR_END_DATE, "End time");
+
+ if (timezone) {
+ printf("\tTimezone: %s\n", timezone);
+ fflush(0);
+ }
+
+ printf("\tPrivate: %s\n", (priv && (*priv == true)) ? "True" : "False");
+ fflush(0);
+
+ if (status) {
+ printf("\tStatus: %s\n", get_task_status(*status));
+ fflush(0);
+ }
+
+ if (contacts) {
+ printf("\tContacts:\n");
+ fflush(0);
+ for (i = 0; i < contacts->cValues; i++) {
+ printf("\t\tContact: %s\n", contacts->strings[i].lppszA);
+ fflush(0);
+ }
+ }
+}
+
+/**
+ \details This function dumps the properties relating to a contact (address book entry)
+ to standard output
+
+ The expected way to obtain the properties array is to use OpenMessage() to obtain the
+ contact object, then to use GetPropsAll() to obtain all the properties.
+
+ \param properties array of contact properties
+ \param id identification to display for the contact (can be NULL)
+
+ \sa mapidump_message, mapidump_appointment, mapidump_task, mapidump_note
+*/
+_PUBLIC_ void mapidump_contact(struct mapi_SPropValue_array *properties, const char *id)
+{
+ const char *card_name =NULL;
+ const char *topic =NULL;
+ const char *full_name = NULL;
+ const char *given_name = NULL;
+ const char *surname = NULL;
+ const char *company = NULL;
+ const char *email = NULL;
+ const char *title = NULL;
+ const char *office_phone = NULL;
+ const char *home_phone = NULL;
+ const char *mobile_phone = NULL;
+ const char *postal_address = NULL;
+ const char *street_address = NULL;
+ const char *locality = NULL;
+ const char *state = NULL;
+ const char *country = NULL;
+ const char *department = NULL;
+ const char *business_fax = NULL;
+ const char *business_home_page = NULL;
+
+ card_name = (const char *)find_mapi_SPropValue_data(properties, PidLidFileUnder);
+ topic = (const char *)find_mapi_SPropValue_data(properties, PR_CONVERSATION_TOPIC);
+ company = (const char *)find_mapi_SPropValue_data(properties, PR_COMPANY_NAME);
+ title = (const char *)find_mapi_SPropValue_data(properties, PR_TITLE);
+ full_name = (const char *)find_mapi_SPropValue_data(properties, PR_DISPLAY_NAME);
+ given_name = (const char *)find_mapi_SPropValue_data(properties, PR_GIVEN_NAME);
+ surname = (const char *)find_mapi_SPropValue_data(properties, PR_SURNAME);
+ department = (const char *)find_mapi_SPropValue_data(properties, PR_DEPARTMENT_NAME);
+ email = (const char *)find_mapi_SPropValue_data(properties, PidLidEmail1OriginalDisplayName);
+ office_phone = (const char *)find_mapi_SPropValue_data(properties, PR_OFFICE_TELEPHONE_NUMBER);
+ home_phone = (const char *)find_mapi_SPropValue_data(properties, PR_HOME_TELEPHONE_NUMBER);
+ mobile_phone = (const char *)find_mapi_SPropValue_data(properties, PR_MOBILE_TELEPHONE_NUMBER);
+ business_fax = (const char *)find_mapi_SPropValue_data(properties, PR_BUSINESS_FAX_NUMBER);
+ business_home_page = (const char *)find_mapi_SPropValue_data(properties, PR_BUSINESS_HOME_PAGE);
+ postal_address = (const char*)find_mapi_SPropValue_data(properties, PR_POSTAL_ADDRESS);
+ street_address = (const char*)find_mapi_SPropValue_data(properties, PR_STREET_ADDRESS);
+ locality = (const char*)find_mapi_SPropValue_data(properties, PR_LOCALITY);
+ state = (const char*)find_mapi_SPropValue_data(properties, PR_STATE_OR_PROVINCE);
+ country = (const char*)find_mapi_SPropValue_data(properties, PR_COUNTRY);
+
+ if (card_name)
+ printf("|== %s ==| %s\n", card_name, id?id:"");
+ else if (topic)
+ printf("|== %s ==| %s\n", topic, id?id:"");
+ else
+ printf("|== <Unknown> ==| %s\n", id?id:"");
+ fflush(0);
+ if (topic) printf("Topic: %s\n", topic);
+ fflush(0);
+ if (full_name)
+ printf("Full Name: %s\n", full_name);
+ else if (given_name && surname)
+ printf("Full Name: %s %s\n", given_name, surname); // initials? l10n?
+ fflush(0);
+ if (title) printf("Job Title: %s\n", title);
+ fflush(0);
+ if (department) printf("Department: %s\n", department);
+ fflush(0);
+ if (company) printf("Company: %s\n", company);
+ fflush(0);
+ if (email) printf("E-mail: %s\n", email);
+ fflush(0);
+ if (office_phone) printf("Office phone number: %s\n", office_phone);
+ fflush(0);
+ if (home_phone) printf("Work phone number: %s\n", home_phone);
+ fflush(0);
+ if (mobile_phone) printf("Mobile phone number: %s\n", mobile_phone);
+ fflush(0);
+ if (business_fax) printf("Business fax number: %s\n", business_fax);
+ fflush(0);
+ if (business_home_page) printf("Business home page: %s\n", business_home_page);
+ fflush(0);
+ if (postal_address) printf("Postal address: %s\n", postal_address);
+ fflush(0);
+ if (street_address) printf("Street address: %s\n", street_address);
+ fflush(0);
+ if (locality) printf("Locality: %s\n", locality);
+ fflush(0);
+ if (state) printf("State / Province: %s\n", state);
+ fflush(0);
+ if (country) printf("Country: %s\n", country);
+ fflush(0);
+
+ printf("\n");
+}
+
+_PUBLIC_ const char *get_task_status(uint32_t status)
+{
+ switch (status) {
+ case olTaskNotStarted:
+ return ("Not Started");
+ case olTaskInProgress:
+ return ("In Progress");
+ case olTaskComplete:
+ return ("Completed");
+ case olTaskWaiting:
+ return ("Waiting on someone else");
+ case olTaskDeferred:
+ return ("Deferred");
+ }
+
+ return NULL;
+}
+
+_PUBLIC_ const char *get_importance(uint32_t importance)
+{
+ switch (importance) {
+ case IMPORTANCE_LOW:
+ return ("Low");
+ case IMPORTANCE_NORMAL:
+ return ("Normal");
+ case IMPORTANCE_HIGH:
+ return ("High");
+ }
+ return NULL;
+}
+
+/**
+ \details This function dumps the properties relating to a task (to-do list entry)
+ to standard output
+
+ The expected way to obtain the properties array is to use OpenMessage() to obtain the
+ task object, then to use GetPropsAll() to obtain all the properties.
+
+ \param properties array of task properties
+ \param id identification to display for the task (can be NULL)
+
+ \sa mapidump_message, mapidump_appointment, mapidump_contact, mapidump_note
+*/
+_PUBLIC_ void mapidump_task(struct mapi_SPropValue_array *properties, const char *id)
+{
+ const struct mapi_SLPSTRArray *contacts = NULL;
+ const char *subject = NULL;
+ const char *body = NULL;
+ const double *complete = 0;
+ const uint32_t *status;
+ const uint32_t *importance;
+ const uint8_t *private;
+ uint32_t i;
+
+ contacts = (const struct mapi_SLPSTRArray *)find_mapi_SPropValue_data(properties, PidLidContacts);
+ subject = (const char *)find_mapi_SPropValue_data(properties, PR_CONVERSATION_TOPIC);
+ body = (const char *)find_mapi_SPropValue_data(properties, PR_BODY);
+ complete = (const double *)find_mapi_SPropValue_data(properties, PidLidPercentComplete);
+ status = (const uint32_t *)find_mapi_SPropValue_data(properties, PidLidTaskStatus);
+ importance = (const uint32_t *)find_mapi_SPropValue_data(properties, PR_IMPORTANCE);
+ private = (const uint8_t *)find_mapi_SPropValue_data(properties, PidLidPrivate);
+
+ printf("|== %s ==| %s\n", subject?subject:"", id?id:"");
+ fflush(0);
+
+ printf("\tBody: %s\n", body?body:"none");
+ fflush(0);
+
+ if (complete) {
+ printf("\tComplete: %u %c\n", (uint32_t)(*complete * 100), '%');
+ fflush(0);
+ }
+
+ if (status) {
+ printf("\tStatus: %s\n", get_task_status(*status));
+ fflush(0);
+ if (*status == olTaskComplete) {
+ mapidump_date(properties, PidLidTaskDateCompleted, "Date Completed");
+ }
+ }
+
+ if (importance) {
+ printf("\tImportance: %s\n", get_importance(*importance));
+ fflush(0);
+ }
+
+ mapidump_date(properties, PidLidTaskDueDate,"Due Date");
+ mapidump_date(properties, PidLidTaskStartDate, "Start Date");
+
+ if (private) {
+ printf("\tPrivate: %s\n", (*private == true)?"True":"False");
+ fflush(0);
+ } else {
+ printf("\tPrivate: false\n");
+ fflush(0);
+ }
+
+ if (contacts) {
+ for (i = 0; i < contacts->cValues; i++) {
+ printf("\tContact: %s\n", contacts->strings[i].lppszA);
+ fflush(0);
+ }
+ }
+}
+
+/**
+ \details This function dumps the properties relating to a note to standard output
+
+ The expected way to obtain the properties array is to use OpenMessage() to obtain the
+ note object, then to use GetPropsAll() to obtain all the properties.
+
+ \param properties array of note properties
+ \param id identification to display for the note (can be NULL)
+
+ \sa mapidump_message, mapidump_appointment, mapidump_contact, mapidump_task
+*/
+_PUBLIC_ void mapidump_note(struct mapi_SPropValue_array *properties, const char *id)
+{
+ const char *subject = NULL;
+ const char *body = NULL;
+
+ subject = (const char *)find_mapi_SPropValue_data(properties, PR_CONVERSATION_TOPIC);
+ body = (const char *)find_mapi_SPropValue_data(properties, PR_BODY);
+
+ printf("|== %s ==| %s\n", subject?subject:"", id?id:"");
+ fflush(0);
+
+ mapidump_date(properties, PR_CLIENT_SUBMIT_TIME, "Submit Time");
+
+ if (body) {
+ printf("Content:\n");
+ printf("%s\n", body);
+ fflush(0);
+ } else {
+ body = (const char *)find_mapi_SPropValue_data(properties, PR_BODY_HTML);
+ if (body) {
+ printf("Content HTML:\n");
+ printf("%s\n", body);
+ fflush(0);
+ }
+ }
+}
+
+_PUBLIC_ void mapidump_msgflags(uint32_t MsgFlags, const char *sep)
+{
+ uint32_t i;
+
+ for (i = 0; mdump_msgflags[i].flag; i++) {
+ if (MsgFlags & mdump_msgflags[i].flag) {
+ printf("%s\t%s (0x%x)\n", sep?sep:"",
+ mdump_msgflags[i].value, mdump_msgflags[i].flag);
+ fflush(0);
+ }
+ }
+
+}
+
+
+_PUBLIC_ void mapidump_newmail(struct NewMailNotification *newmail, const char *sep)
+{
+ printf("%sParent Entry ID: 0x%"PRIx64"\n", sep?sep:"", newmail->FID);
+ fflush(0);
+ printf("%sMessage Entry ID: 0x%"PRIx64"\n", sep?sep:"", newmail->MID);
+ fflush(0);
+ printf("%sMessage flags:\n", sep?sep:"");
+ fflush(0);
+ mapidump_msgflags(newmail->MessageFlags, sep);
+ if (newmail->UnicodeFlag == 0x0) {
+ printf("%sMessage Class: %s\n", sep?sep:"", newmail->MessageClass.lpszA);
+ } else {
+ printf("%sMessage Class: %s\n", sep?sep:"", newmail->MessageClass.lpszW);
+ }
+ fflush(0);
+}
+
+
+_PUBLIC_ const char *mapidump_freebusy_month(uint32_t month, uint32_t year)
+{
+ uint32_t realmonth;
+
+ realmonth = month - (year * 16);
+
+ switch (realmonth) {
+ case 0x1:
+ return "January";
+ case 0x2:
+ return "February";
+ case 0x3:
+ return "March";
+ case 0x4:
+ return "April";
+ case 0x5:
+ return "May";
+ case 0x6:
+ return "June";
+ case 0x7:
+ return "July";
+ case 0x8:
+ return "August";
+ case 0x9:
+ return "September";
+ case 0xa:
+ return "October";
+ case 0xb:
+ return "November";
+ case 0xc:
+ return "December";
+ }
+ return NULL;
+}
+
+
+_PUBLIC_ uint32_t mapidump_freebusy_year(uint32_t month, uint32_t year)
+{
+ uint32_t realmonth;
+
+ realmonth = month - (year * 16);
+ while (realmonth > 0xc) {
+ year++;
+ realmonth = month - (year * 16);
+ }
+
+ return year;
+}
+
+
+_PUBLIC_ void mapidump_freebusy_date(uint32_t t, const char *sep)
+{
+ TALLOC_CTX *mem_ctx;
+ NTTIME time;
+ const char *date;
+
+ mem_ctx = talloc_named(NULL, 0, "mapidump_freebusy_date");
+
+ time = t;
+ time *= 60;
+ time *= 10000000;
+
+ date = nt_time_string(mem_ctx, time);
+ DEBUG(0, ("%s %-30s\n", sep, date));
+ talloc_free((char *)date);
+ talloc_free(mem_ctx);
+}
+
+
+_PUBLIC_ void mapidump_freebusy_event(struct Binary_r *bin, uint32_t month, uint32_t year, const char *sep)
+{
+ uint16_t event_start;
+ uint16_t event_end;
+ uint32_t i;
+ uint32_t hour;
+ uint32_t hours;
+ uint32_t day;
+ const char *month_name;
+ uint32_t last;
+ uint32_t minutes;
+
+ if (!bin) return;
+ /* bin.cb must be a multiple of 4 */
+ if (bin->cb % 4) return;
+
+ year = mapidump_freebusy_year(month, year);
+ month_name = mapidump_freebusy_month(month, year);
+ if (!month_name) return;
+
+ for (i = 0; i < bin->cb; i+= 4) {
+ event_start = (bin->lpb[i + 1] << 8) | bin->lpb[i];
+ event_end = (bin->lpb[i + 3] << 8) | bin->lpb[i + 2];
+
+ for (hour = 0; hour < 24; hour++) {
+ if (!((event_start - (60 * hour)) % 1440)) {
+ day = ((event_start - (60 * hour)) / 1440) + 1;
+ last = event_end - event_start;
+#if defined (__FreeBSD__)
+ DEBUG(0, ("%s %u %s %u at %u hours and lasts ", sep ? sep : "", day, month_name, year, hour));
+#else
+ DEBUG(0, ("%s %u %s %u at %u hours and lasts ", sep ? sep : "", day, month_name, year, hour + daylight));
+#endif
+ if (last < 60) {
+ DEBUG(0, ("%u minutes\n", last));
+ } else {
+ hours = last / 60;
+ minutes = last - hours * 60;
+ if (minutes > 0) {
+ DEBUG(0, ("%u hours and %u minutes\n", hours, minutes));
+ } else {
+ DEBUG(0, ("%u hours\n", hours));
+ }
+ }
+ }
+ }
+
+ }
+}
Added: trunk/openchange/libmapi/mapidump.h
===================================================================
--- trunk/openchange/libmapi/mapidump.h (rev 0)
+++ trunk/openchange/libmapi/mapidump.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,42 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 __MAPIDUMP_H__
+#define __MAPIDUMP_H__
+
+struct mdump_msgflags {
+ uint16_t flag;
+ const char *value;
+};
+
+struct mdump_msgflags mdump_msgflags[] = {
+ {0x1, "MSGFLAG_READ"},
+ {0x2, "MSGFLAG_UNMODIFIED"},
+ {0x4, "MSGFLAG_SUBMIT"},
+ {0x8, "MSGFLAG_UNSENT"},
+ {0x10, "MSGFLAG_HASATTACH"},
+ {0x20, "MSGFLAG_FROMME"},
+ {0x40, "MSGFLAG_ASSOCIATED"},
+ {0x80, "MSGFLAG_RESEND"},
+ {0x100, "MSGFLAG_RN_PENDING"},
+ {0x200, "MSGFLAG_NRN_PENDING"},
+ {0, NULL}
+};
+
+#endif /* __MAPIDUMP_H__ */
Added: trunk/openchange/libmapi/nspi.c
===================================================================
--- trunk/openchange/libmapi/nspi.c (rev 0)
+++ trunk/openchange/libmapi/nspi.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1152 @@
+/*
+ OpenChange NSPI implementation.
+
+ Copyright (C) Julien Kerihuel 2005 - 2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange_c.h>
+#include <param.h>
+#include <credentials.h>
+
+
+/**
+ \file nspi.c
+
+ \brief Name Service Provider (NSPI) stack functions
+ */
+
+
+/**
+ \details Initialize the STAT structure and set common STAT parameters
+
+ \param mem_ctx pointer to the memory context
+ \param CodePage the CodePage value to set in the STAT structure
+ \param TemplateLocale the Locale for the STAT TemplateLocale parameter
+ \param SortLocale the Locale for the STAT SortLocal parameter
+ */
+static struct STAT *nspi_set_STAT(TALLOC_CTX *mem_ctx,
+ uint32_t CodePage,
+ uint32_t TemplateLocale,
+ uint32_t SortLocale)
+{
+ struct STAT *pStat;
+
+ /* Sanity Checks */
+ if (!CodePage || !TemplateLocale || !SortLocale) {
+ return NULL;
+ }
+
+ pStat = talloc_zero(mem_ctx, struct STAT);
+ pStat->SortType = SortTypeDisplayName;
+ pStat->CodePage = CodePage;
+ pStat->TemplateLocale = TemplateLocale;
+ pStat->SortLocale = SortLocale;
+
+ return pStat;
+}
+
+
+/**
+ \details Initiates a session between a client and the NSPI server.
+
+ \param mem_ctx pointer to the memory context
+ \param p pointer to the DCERPC pipe
+ \param cred pointer to the user credentials
+ \param codepage the code to set in the STAT structure
+ \param language the language to set in the STAT structure
+ \param method the method to set in the STAT structure
+
+ \return Allocated pointer to a nspi_context structure on success,
+ otherwise NULL
+ */
+_PUBLIC_ struct nspi_context *nspi_bind(TALLOC_CTX *mem_ctx,
+ struct dcerpc_pipe *p,
+ struct cli_credentials *cred,
+ uint32_t codepage,
+ uint32_t language,
+ uint32_t method)
+{
+ struct NspiBind r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ struct nspi_context *ret;
+ struct GUID guid;
+
+ /* Sanity checks */
+ if (!p) return NULL;
+ if (!cred) return NULL;
+
+ ret = talloc(mem_ctx, struct nspi_context);
+ ret->rpc_connection = p;
+ ret->mem_ctx = mem_ctx;
+ ret->cred = cred;
+ ret->version = 0;
+
+ /* Sanity Checks */
+ if (!(ret->pStat = nspi_set_STAT(mem_ctx, codepage, language, method))) {
+ talloc_free(ret);
+ return NULL;
+ }
+
+ r.in.dwFlags = 0;
+
+ r.in.pStat = ret->pStat;
+ r.in.pStat->ContainerID = 0x0;
+
+ r.in.mapiuid = talloc(mem_ctx, struct GUID);
+ memset(r.in.mapiuid, 0, sizeof(struct GUID));
+
+ r.out.mapiuid = &guid;
+
+ r.in.mapiuid = talloc(mem_ctx, struct GUID);
+ memset(r.in.mapiuid, 0, sizeof(struct GUID));
+
+ r.out.handle = &ret->handle;
+
+
+ status = dcerpc_NspiBind(p, mem_ctx, &r);
+ retval = r.out.result;
+ if ((!NT_STATUS_IS_OK(status)) || (retval != MAPI_E_SUCCESS)) {
+ talloc_free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+
+/**
+ \details Destructor for the NSPI context. Call the NspiUnbind
+ function.
+
+ \param data generic pointer to data with mapi_provider information
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+ */
+
+int nspi_disconnect_dtor(void *data)
+{
+ enum MAPISTATUS retval;
+ struct mapi_provider *provider = (struct mapi_provider *) data;
+
+ retval = nspi_unbind(provider->ctx);
+ return retval;
+}
+
+
+/**
+ \details Destroys the context handle
+
+ \param nspi_ctx pointer to the NSPI connection context
+
+ \return return 1 on success or 2 if the input context is NULL
+ */
+_PUBLIC_ enum MAPISTATUS nspi_unbind(struct nspi_context *nspi_ctx)
+{
+ struct NspiUnbind r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ r.in.handle = r.out.handle = &nspi_ctx->handle;
+ r.in.Reserved = 0;
+
+ status = dcerpc_NspiUnbind(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF((retval != 1) && !MAPI_STATUS_IS_OK(NT_STATUS_V(status)), retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Updates the STAT block representing position in a table to
+ reflect positioning changes requested by the client.
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param plDelta pointer to an unsigned long indicating movement
+ within the address book container specified by the input parameter
+ pStat.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_UpdateStat(struct nspi_context *nspi_ctx,
+ uint32_t *plDelta)
+{
+ struct NspiUpdateStat r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!plDelta, MAPI_E_INVALID_PARAMETER, NULL);
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.Reserved = 0x0;
+
+ r.in.pStat = nspi_ctx->pStat;
+ r.in.plDelta = plDelta;
+
+ r.out.pStat = nspi_ctx->pStat;
+ r.out.plDelta = r.in.plDelta;
+
+ status = dcerpc_NspiUpdateStat(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns a number of Rows from a specified table.
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param pPropTags pointer to the list of proptags that the client
+ requires to be returned for each row.
+ \param MIds pointer to a list of values representing an Explicit
+ table
+ \param count the number of rows requested
+ \param ppRows pointer on pointer to the the rows returned by the
+ server
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_QueryRows(struct nspi_context *nspi_ctx,
+ struct SPropTagArray *pPropTags,
+ struct SPropTagArray *MIds,
+ uint32_t count,
+ struct SRowSet **ppRows)
+{
+ TALLOC_CTX *mem_ctx;
+ struct NspiQueryRows r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ struct STAT *pStat;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "nspi_QueryRows");
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.dwFlags = 0x0;
+ r.in.pStat = nspi_ctx->pStat;
+
+ if (MIds && MIds->cValues) {
+ r.in.dwETableCount = MIds->cValues;
+ r.in.lpETable = MIds->aulPropTag;
+ /* We set CurrentRec to the first entry */
+ r.in.pStat->CurrentRec = MIds->aulPropTag[0];
+ } else {
+ r.in.dwETableCount = 0;
+ r.in.lpETable = NULL;
+ }
+
+ r.in.Count = count;
+ r.in.pPropTags = pPropTags;
+
+ pStat = talloc(mem_ctx, struct STAT);
+ r.out.pStat = pStat;
+
+ r.out.ppRows = ppRows;
+
+ status = dcerpc_NspiQueryRows(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, mem_ctx);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ nspi_ctx->pStat->CurrentRec = r.out.pStat->CurrentRec;
+ nspi_ctx->pStat->Delta = r.out.pStat->Delta;
+ nspi_ctx->pStat->NumPos = r.out.pStat->NumPos;
+ nspi_ctx->pStat->TotalRecs = r.out.pStat->TotalRecs;
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+
+}
+
+
+/**
+ \details Searches for and sets the logical position in a specific
+ table to the first entry greater than or equal to a specified
+ value. Optionally, it might also return information about rows in
+ the table.
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param SortType the table sort order to use
+ \param pTarget SPropValue struct holding the value being sought
+ \param pPropTags pointer to an array of property tags of columns
+ that the client wants to be returned for each row returned.
+ \param pMIds pointer to a list of Mid that comprise a restricted
+ address book container
+ \param pRows pointer to pointer to a SRowSet structure holding the
+ rows returned by the server
+
+ SortType can take the following values:
+ -# SortTypeDisplayName
+ -# SortTypePhoneticDisplayName
+
+ If pTarget property tag is not set accordingly to SortType, the
+ function returns MAPI_E_INVALID_PARAMETER. Possible values are:
+ -# SortType set to SortTypeDisplayName and pTarget property tag set
+ to PR_DISPLAY_NAME or PR_DISPLAY_UNICODE
+ -# SortType set to SortTypePhoneticDisplayName and pTarget property
+ tag set to PR_EMS_AB_PHONETIC_DISPLAY_NAME or
+ PR_EMS_AB_PHONETIC_DISPLAY_NAME_UNICODE
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_SeekEntries(struct nspi_context *nspi_ctx,
+ enum TableSortOrders SortType,
+ struct SPropValue *pTarget,
+ struct SPropTagArray *pPropTags,
+ struct SPropTagArray *pMIds,
+ struct SRowSet **pRows)
+{
+ struct NspiSeekEntries r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ struct STAT *pStat;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!pTarget, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!pRows, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(((SortType != SortTypeDisplayName)
+ && (SortType != SortTypePhoneticDisplayName)),
+ MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Sanity Checks on SortType and pTarget combination */
+ OPENCHANGE_RETVAL_IF(((SortType == SortTypeDisplayName) &&
+ (pTarget->ulPropTag != PR_DISPLAY_NAME) &&
+ (pTarget->ulPropTag != PR_DISPLAY_NAME_UNICODE)),
+ MAPI_E_INVALID_PARAMETER, NULL);
+
+ OPENCHANGE_RETVAL_IF(((SortType == SortTypePhoneticDisplayName) &&
+ (pTarget->ulPropTag != PR_EMS_AB_PHONETIC_DISPLAY_NAME) &&
+ (pTarget->ulPropTag != PR_EMS_AB_PHONETIC_DISPLAY_NAME_UNICODE)),
+ MAPI_E_INVALID_PARAMETER, NULL);
+
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.Reserved = 0x0;
+ r.in.pStat = nspi_ctx->pStat;
+ r.in.pStat->SortType = SortType;
+ r.in.pTarget = pTarget;
+
+ if (pMIds && pMIds->cValues) {
+ r.in.lpETable = pMIds;
+ } else {
+ r.in.lpETable = NULL;
+ }
+
+ r.in.pPropTags = pPropTags;
+
+ r.out.pRows = pRows;
+
+ pStat = talloc(nspi_ctx->mem_ctx, struct STAT);
+ r.out.pStat = pStat;
+
+ status = dcerpc_NspiSeekEntries(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, pStat);
+ OPENCHANGE_RETVAL_IF(retval, retval, pStat);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns an explicit table.
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param pPropTags pointer to an array of property tags of columns
+ \param Filter pointer to the Restriction to apply to the table
+ \param ppRows pointer to pointer to a SRowSet structure holding the
+ rows returned by the server
+ \param ppOutMIds pointer to pointer to a list of MId that comprise
+ a restricted address book container
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+ */
+_PUBLIC_ enum MAPISTATUS nspi_GetMatches(struct nspi_context *nspi_ctx,
+ struct SPropTagArray *pPropTags,
+ struct Restriction_r *Filter,
+ struct SRowSet **ppRows,
+ struct SPropTagArray **ppOutMIds)
+{
+ TALLOC_CTX *mem_ctx;
+ struct NspiGetMatches r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ struct STAT *pStat;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!ppRows, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ppOutMIds, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "nspi_GetMatches");
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.Reserved = 0;
+
+ r.in.pStat = nspi_ctx->pStat;
+ r.in.pStat->ContainerID = 0x0;
+ r.in.pStat->CurrentRec = 0x0;
+ r.in.pStat->Delta = 0x0;
+ r.in.pStat->NumPos = 0x0;
+ r.in.pStat->TotalRecs = 0x0;
+
+ r.in.pReserved = NULL;
+ r.in.Reserved2 = 0;
+ r.in.Filter = Filter;
+ r.in.lpPropName = NULL;
+ r.in.ulRequested = 5000;
+ r.in.pPropTags = pPropTags;
+
+ pStat = talloc(mem_ctx, struct STAT);
+ r.out.pStat = pStat;
+ r.out.ppOutMIds = ppOutMIds;
+ r.out.ppRows = ppRows;
+
+ status = dcerpc_NspiGetMatches(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_NOT_FOUND, mem_ctx);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Applies a sort order to the objects in a restricted
+ address book container
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param SortType the table sort order to use
+ \param pInMIds pointer on a list of MIds that comprise a
+ restricted addess book container
+ \param ppMIds pointer on pointer to the returned list of MIds that
+ comprise a restricted addess book container.
+
+ SortType can take the following values:
+ -# SortTypeDisplayName
+ -# SortTypePhoneticDisplayName
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_ResortRestriction(struct nspi_context *nspi_ctx,
+ enum TableSortOrders SortType,
+ struct SPropTagArray *pInMIds,
+ struct SPropTagArray **ppMIds)
+{
+ TALLOC_CTX *mem_ctx;
+ struct NspiResortRestriction r;
+ enum MAPISTATUS retval;
+ NTSTATUS status;
+ struct SPropTagArray *ppInMIds = NULL;
+ struct STAT *pStat = NULL;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!pInMIds, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ppMIds, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Sanity check on SortType */
+ OPENCHANGE_RETVAL_IF(((SortType != SortTypeDisplayName) && (SortType != SortTypePhoneticDisplayName)),
+ MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "nspi_ResortRestriction");
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.Reserved = 0;
+ r.in.pStat = nspi_ctx->pStat;
+ r.in.pStat->SortType = SortType;
+ r.in.pInMIds = pInMIds;
+ r.in.ppMIds = &ppInMIds;
+
+ pStat = talloc_zero(mem_ctx, struct STAT);
+ r.out.pStat = pStat;
+ r.out.ppMIds = ppMIds;
+
+ status = dcerpc_NspiResortRestriction(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Maps a set of DN to a set of MId
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param pNames pointer to a StringsArray_r structure with the DN to
+ map
+ \param ppMIds pointer on pointer to the returned list of MIds
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_DNToMId(struct nspi_context *nspi_ctx,
+ struct StringsArray_r *pNames,
+ struct SPropTagArray **ppMIds)
+{
+ struct NspiDNToMId r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!pNames, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!pNames->Count, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ppMIds, MAPI_E_INVALID_PARAMETER, NULL);
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.Reserved = 0;
+ r.in.pNames = pNames;
+
+ r.out.ppMIds = ppMIds;
+
+ status = dcerpc_NspiDNToMId(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL)
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns a list of all the properties that have values on
+ the specified object
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param WantObject boolean value defining whether we want the server
+ to include properties with the type set to PT_OBJECT
+ \param dwMId the MId of the specified object
+ \param ppPropTags pointer on pointer to the list of property tags
+ associated to the object.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+ */
+_PUBLIC_ enum MAPISTATUS nspi_GetPropList(struct nspi_context *nspi_ctx,
+ bool WantObject,
+ uint32_t dwMId,
+ struct SPropTagArray **ppPropTags)
+{
+ struct NspiGetPropList r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!ppPropTags, MAPI_E_INVALID_PARAMETER, NULL);
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.dwFlags = (WantObject == true) ? 0x0 : fSkipObjects;
+ r.in.dwMId = dwMId;
+ r.in.CodePage = nspi_ctx->pStat->CodePage;
+
+ r.out.ppPropTags = ppPropTags;
+
+ status = dcerpc_NspiGetPropList(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+
+/**
+ \details Returns an address book row containing a set of the
+ properties and values that exists on an object
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param pPropTags pointer to the list of property tags that the
+ client wants to be returned
+ \param MId pointer to the MId of the record
+ \param SRowSet pointer on pointer to the row returned by the server
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_GetProps(struct nspi_context *nspi_ctx,
+ struct SPropTagArray *pPropTags,
+ struct SPropTagArray *MId,
+ struct SRowSet **SRowSet)
+
+{
+ struct NspiGetProps r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ struct SRow *ppRows;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!MId, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!MId->cValues, MAPI_E_INVALID_PARAMETER, NULL);
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.dwFlags = 0;
+
+ r.in.pStat = nspi_ctx->pStat;
+ r.in.pStat->CurrentRec = MId->aulPropTag[0];
+ r.in.pStat->Delta = 0x0;
+ r.in.pStat->NumPos = 0x0;
+ r.in.pStat->TotalRecs = 0x0;
+
+ r.in.pPropTags = pPropTags;
+
+ ppRows = talloc(nspi_ctx->mem_ctx, struct SRow);
+ r.out.ppRows = &ppRows;
+
+ status = dcerpc_NspiGetProps(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL)
+
+ SRowSet[0]->cRows = 1;
+ SRowSet[0]->aRow = talloc(nspi_ctx->mem_ctx, struct SRow);
+ SRowSet[0]->aRow->ulAdrEntryPad = ppRows->ulAdrEntryPad;
+ SRowSet[0]->aRow->cValues = ppRows->cValues;
+ SRowSet[0]->aRow->lpProps = ppRows->lpProps;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Compares the position in an address book container of two
+ objects identified by MId and returns the value of the comparison
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param MId1 the first MId to compare
+ \param MId2 the second MId to compare
+ \param plResult pointer to the value of the comparison
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+ */
+_PUBLIC_ enum MAPISTATUS nspi_CompareMIds(struct nspi_context *nspi_ctx,
+ uint32_t MId1, uint32_t MId2,
+ uint32_t *plResult)
+{
+ struct NspiCompareMIds r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!plResult, MAPI_E_INVALID_PARAMETER, NULL);
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.Reserved = 0x0;
+ r.in.pStat = nspi_ctx->pStat;
+ r.in.MId1 = MId1;
+ r.in.MId2 = MId2;
+
+ r.out.plResult = plResult;
+
+ status = dcerpc_NspiCompareMIds(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Modify the properties of an object in the address book
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param MId the MId of the address book object
+ \param pPropTags pointer to the list of properties to be modified
+ on the object
+ \param pRow Contains an address book row
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_ModProps(struct nspi_context *nspi_ctx,
+ uint32_t MId,
+ struct SPropTagArray *pPropTags,
+ struct SRow *pRow)
+{
+ struct NspiModProps r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!pPropTags, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!pRow, MAPI_E_INVALID_PARAMETER, NULL);
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.Reserved = 0x0;
+ r.in.pStat = nspi_ctx->pStat;
+
+ if (MId) {
+ r.in.pStat->CurrentRec = MId;
+ }
+
+ r.in.pPropTags = pPropTags;
+ r.in.pRow = pRow;
+
+ status = dcerpc_NspiModProps(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+
+/**
+ \details Returns the rows of a special table to the client. The
+ special table can be a Hierarchy Table or an Address Creation Table
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param Type bitmap of flags defining the type of the special table
+ \param ppRows pointer on pointer to the rows returned by the server
+
+ Possible values for Type:
+ -# NspiAddressCreationTemplates to access an Address Creation Table
+ -# NspiUnicodeStrings for strings to be returned in Unicode
+
+ If NspiAddressCreationTemplates is not set, then
+ NspiGetSpecialTable will automatically fetch the Hierarchy Table.
+
+ If NspiAddressCreationTemplates is set, then NspiUnicodeStrings is
+ ignored.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+ */
+_PUBLIC_ enum MAPISTATUS nspi_GetSpecialTable(struct nspi_context *nspi_ctx,
+ uint32_t Type,
+ struct SRowSet **ppRows)
+{
+ struct NspiGetSpecialTable r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(((Type != 0x0) && (Type != 0x2) && (Type != 0x4)),
+ MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ppRows, MAPI_E_INVALID_PARAMETER, NULL);
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.dwFlags = Type;
+
+ r.in.pStat = nspi_ctx->pStat;
+ r.in.lpVersion = &nspi_ctx->version;
+
+ r.out.lpVersion = &nspi_ctx->version;
+ r.out.ppRows = ppRows;
+
+ status = dcerpc_NspiGetSpecialTable(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns information about template objects in the address
+ book.
+
+ \param nspi_ctx pointer to the NSPI memory context
+ \param dwFlags set of bit flags
+ \param ulType specifies the display type of the template
+ \param pDN the DN of the template requested
+ \param ppData pointer on pointer to the data requested
+
+ Possible values for dwFlags:
+ -# TI_TEMPLATE to return the template
+ -# TI_SCRIPT to return the script associated to the template
+ -# TI_EMT to return the e-mail type associated to the template
+ -# TI_HELPFILE_NAME to return the help file associated to the
+ template
+ -# TI_HELPFILE_CONTENTS to return the contents of the help file
+ associated to the template
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+ */
+_PUBLIC_ enum MAPISTATUS nspi_GetTemplateInfo(struct nspi_context *nspi_ctx,
+ uint32_t dwFlags,
+ uint32_t ulType,
+ char *pDN,
+ struct SRow **ppData)
+{
+ struct NspiGetTemplateInfo r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!ppData, MAPI_E_INVALID_PARAMETER, NULL);
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.dwFlags = dwFlags;
+ r.in.ulType = ulType;
+ r.in.pDN = pDN;
+ r.in.dwCodePage = nspi_ctx->pStat->CodePage;
+ r.in.dwLocaleID = nspi_ctx->pStat->TemplateLocale;
+
+ r.out.ppData = ppData;
+
+ status = dcerpc_NspiGetTemplateInfo(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Modifies the values of a specific property of a specific
+ row in the address book. This function only applies only to rows
+ that support the PT_OBJECT Property Type.
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param Delete boolean value defining whether the server must remove
+ all values specified by the input parameter lpEntryIDs from the
+ property specified by ulPropTag
+ \param ulPropTag property tag of the property the client wishes to
+ modify
+ \param MId the MId of the address book object
+ \param lpEntryIds array of BinaryArray_r structures intended to be
+ modified or deleted
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_ModLinkAtt(struct nspi_context *nspi_ctx,
+ bool Delete,
+ uint32_t ulPropTag,
+ uint32_t MId,
+ struct BinaryArray_r *lpEntryIds)
+{
+ struct NspiModLinkAtt r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(((ulPropTag & 0xFFFF) != PT_OBJECT), MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!lpEntryIds, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!lpEntryIds->cValues, MAPI_E_INVALID_PARAMETER, NULL)
+
+ r.in.handle = &nspi_ctx->handle;
+ /* FIXME: need to find fDelete value first */
+ r.in.dwFlags = (Delete == true) ? 0x1 : 0x0;
+ r.in.ulPropTag = ulPropTag;
+ r.in.MId = MId;
+ r.in.lpEntryIds = lpEntryIds;
+
+ status = dcerpc_NspiModLinkAtt(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns a list of all the properties the NSPI server is
+ aware off.
+
+ \param nspi_ctx pointer to the NSPI connection context
+ \param WantUnicode whether we want UNICODE properties or not
+ \param ppColumns pointer on pointer to a property tag array
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+ */
+_PUBLIC_ enum MAPISTATUS nspi_QueryColumns(struct nspi_context *nspi_ctx,
+ bool WantUnicode,
+ struct SPropTagArray **ppColumns)
+{
+ struct NspiQueryColumns r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!ppColumns, MAPI_E_INVALID_PARAMETER, NULL);
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.Reserved = 0x0;
+ r.in.dwFlags = (WantUnicode == true) ? NspiUnicodeProptypes : 0x0;
+
+ r.out.ppColumns = ppColumns;
+
+ status = dcerpc_NspiQueryColumns(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Returns a list of property names for a set of proptags
+
+ \param nspi_ctx pointer on the NSPI connection text
+ \param lpGuid the property set about which the client is requesting
+ information
+ \param pPropTags pointer to the proptags list
+ \param ppReturnedPropTags pointer on pointer to the list of
+ all the proptags in the property set specified in lpGuid
+ \param ppNames pointer on pointer to the list of property names
+ returned by the server
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_GetNamesFromIDs(struct nspi_context *nspi_ctx,
+ struct FlatUID_r *lpGuid,
+ struct SPropTagArray *pPropTags,
+ struct SPropTagArray **ppReturnedPropTags,
+ struct PropertyNameSet_r **ppNames)
+{
+ struct NspiGetNamesFromIDs r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!ppReturnedPropTags, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ppNames, MAPI_E_INVALID_PARAMETER, NULL);
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.Reserved = 0x0;
+ r.in.lpGuid = lpGuid;
+ r.in.pPropTags = pPropTags;
+
+ r.out.ppReturnedPropTags = ppReturnedPropTags;
+ r.out.ppNames = ppNames;
+
+ status = dcerpc_NspiGetNamesFromIDs(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve the Property IDs associated with property names
+ from the NSPI server.
+
+ \param nspi_ctx pointer on the NSPI connection context
+ \param VerifyNames boolean value defining whether the NSPI server
+ must verify that all client specified names are recognized by the
+ server
+ \param cNames count of PropertyName_r entries
+ \param ppNames pointer to a PropertyName_r structure with the list of
+ property tags supplied by the client
+ \param ppPropTags pointer on pointer to the list of proptags
+ returned by the server
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_GetIDsFromNames(struct nspi_context *nspi_ctx,
+ bool VerifyNames,
+ uint32_t cNames,
+ struct PropertyName_r *ppNames,
+ struct SPropTagArray **ppPropTags)
+{
+ TALLOC_CTX *mem_ctx;
+ struct NspiGetIDsFromNames r;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t i;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!ppNames, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ppPropTags, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "nspi_GetIDsFromNames");
+
+ r.in.handle = &nspi_ctx->handle;
+ r.in.Reserved = 0;
+ r.in.dwFlags = (VerifyNames == true) ? 0x2 : 0x0;
+ r.in.cPropNames = cNames;
+
+ r.in.ppNames = talloc_array(mem_ctx, struct PropertyName_r *, cNames);
+ for (i = 0; i < cNames; i++) {
+ r.in.ppNames[i] = &ppNames[i];
+ }
+
+ r.out.ppPropTags = ppPropTags;
+
+ status = dcerpc_NspiGetIDsFromNames(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, mem_ctx);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Takes a set of string values in an 8-bit character set and
+ performs ANR on those strings
+
+ \param nspi_ctx pointer on the NSPI connection context
+ \param usernames pointer on pointer to the list of values we want
+ to perform ANR on
+ \param pPropTags pointer on the property tags list we want for each
+ row returned
+ \param pppRows pointer on pointer on pointer to the rows returned
+ by the server
+ \param pppMIds pointer on pointer on pointer to the MIds matching
+ the array of strings
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_ResolveNames(struct nspi_context *nspi_ctx,
+ const char **usernames,
+ struct SPropTagArray *pPropTags,
+ struct SRowSet ***pppRows,
+ struct SPropTagArray ***pppMIds)
+{
+ TALLOC_CTX *mem_ctx;
+ struct NspiResolveNames r;
+ struct StringsArray_r *paStr;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t count;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!usernames, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!pppRows, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!pppMIds, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (count = 0; usernames[count]; count++);
+ OPENCHANGE_RETVAL_IF(!count, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "nspi_ResolveNames");
+
+ r.in.handle = &nspi_ctx->handle;
+
+ r.in.pStat = nspi_ctx->pStat;
+ r.in.Reserved = 0;
+ r.in.pPropTags = pPropTags;
+
+ paStr = talloc(mem_ctx, struct StringsArray_r);
+ paStr->Count = count;
+ paStr->Strings = usernames;
+ r.in.paStr = paStr;
+
+ r.out.ppMIds = *pppMIds;
+ r.out.ppRows = *pppRows;
+
+ status = dcerpc_NspiResolveNames(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, mem_ctx);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Takes a set of string values in the Unicode character set
+ and performs ANR on those strings
+
+ \param nspi_ctx pointer on the NSPI connection context
+ \param usernames pointer on pointer to the list of values we want
+ to perform ANR on
+ \param pPropTags pointer on the property tags list we want for each
+ row returned
+ \param pppRows pointer on pointer on pointer to the rows returned
+ by the server
+ \param pppMIds pointer on pointer on pointer to the MIds matching
+ the array of strings
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS nspi_ResolveNamesW(struct nspi_context *nspi_ctx,
+ const char **usernames,
+ struct SPropTagArray *pPropTags,
+ struct SRowSet ***pppRows,
+ struct SPropTagArray ***pppMIds)
+{
+ TALLOC_CTX *mem_ctx;
+ struct NspiResolveNamesW r;
+ struct WStringsArray_r *paWStr;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t count;
+
+ OPENCHANGE_RETVAL_IF(!nspi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!usernames, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!pppRows, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!pppMIds, MAPI_E_INVALID_PARAMETER, NULL);
+
+ for (count = 0; usernames[count]; count++);
+ OPENCHANGE_RETVAL_IF(!count, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "mapi_ResolveNamesW");
+
+ r.in.handle = &nspi_ctx->handle;
+
+ r.in.pStat = nspi_ctx->pStat;
+ r.in.Reserved = 0;
+ r.in.pPropTags = pPropTags;
+
+ paWStr = talloc(mem_ctx, struct WStringsArray_r);
+ paWStr->Count = count;
+ paWStr->Strings = usernames;
+ r.in.paWStr = paWStr;
+
+ r.out.ppMIds = *pppMIds;
+ r.out.ppRows = *pppRows;
+
+ status = dcerpc_NspiResolveNamesW(nspi_ctx->rpc_connection, nspi_ctx->mem_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, mem_ctx);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/nspi.h
===================================================================
--- trunk/openchange/libmapi/nspi.h (rev 0)
+++ trunk/openchange/libmapi/nspi.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,43 @@
+/*
+ OpenChange NSPI implementation.
+
+ Copyright (C) Julien Kerihuel 2005.
+
+ 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 __NSPI_H__
+#define __NSPI_H__
+
+struct nspi_context {
+ struct dcerpc_pipe *rpc_connection;
+ struct policy_handle handle;
+ TALLOC_CTX *mem_ctx;
+ struct cli_credentials *cred;
+ struct STAT *pStat;
+ struct mapi_profile *profile;
+ struct SRowSet *rowSet;
+ char *org;
+ char *org_unit;
+ char *servername;
+ uint32_t version;
+};
+
+#define ORG "/o="
+#define ORG_UNIT "/ou="
+#define SERVER_DN "/o=%s/ou=%s/cn=Configuration/cn=Servers/cn=%s"
+#define SERVERNAME "/cn=Servers/cn="
+#define RECIPIENT_DN "/o=%s/ou=%s/cn=Recipients/cn=%s"
+
+#endif /* __NSPI_H__ */
Added: trunk/openchange/libmapi/property.c
===================================================================
--- trunk/openchange/libmapi/property.c (rev 0)
+++ trunk/openchange/libmapi/property.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,847 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2005 - 2008.
+ Copyright (C) Gregory Schiro 2006
+
+ 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/proto_private.h>
+#include <libmapi/mapitags.h>
+#include <gen_ndr/ndr_property.h>
+#include <param.h>
+
+/**
+ \file property.c
+
+ \brief Functions for manipulating MAPI properties
+ */
+
+_PUBLIC_ struct SPropTagArray *set_SPropTagArray(TALLOC_CTX *mem_ctx,
+ uint32_t PropCount, ...)
+{
+ struct SPropTagArray *SPropTagArray;
+ va_list ap;
+ uint32_t i;
+ uint32_t *aulPropTag;
+
+ aulPropTag = talloc_array(mem_ctx, uint32_t, PropCount);
+
+ va_start(ap, PropCount);
+ for (i = 0; i < PropCount; i++) {
+ aulPropTag[i] = va_arg(ap, int);
+ }
+ va_end(ap);
+
+ SPropTagArray = talloc(mem_ctx, struct SPropTagArray);
+ SPropTagArray->aulPropTag = aulPropTag;
+ SPropTagArray->cValues = PropCount;
+ return SPropTagArray;
+}
+
+/**
+ \details Add a property tag to an existing properties array
+
+ \param mem_ctx talloc memory context to use for allocation
+ \param SPropTagArray existing properties array to add to
+ \param aulPropTag the property tag to add
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error.
+
+ \note Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+ - MAPI_E_INVALID_PARAMETER: SPropTagArray parameter is not correctly set
+*/
+_PUBLIC_ enum MAPISTATUS SPropTagArray_add(TALLOC_CTX *mem_ctx,
+ struct SPropTagArray *SPropTagArray,
+ uint32_t aulPropTag)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!mem_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!SPropTagArray->cValues, MAPI_E_INVALID_PARAMETER, NULL);
+
+ SPropTagArray->cValues += 1;
+ SPropTagArray->aulPropTag = talloc_realloc(mem_ctx, SPropTagArray->aulPropTag,
+ uint32_t, SPropTagArray->cValues + 1);
+ SPropTagArray->aulPropTag[SPropTagArray->cValues - 1] = aulPropTag;
+ SPropTagArray->aulPropTag[SPropTagArray->cValues] = 0;
+
+ return MAPI_E_SUCCESS;
+}
+
+_PUBLIC_ const void *get_SPropValue(struct SPropValue *lpProps,
+ uint32_t ulPropTag)
+{
+ uint32_t i;
+
+ for (i = 0; lpProps[i].ulPropTag; i++) {
+ if (ulPropTag == lpProps[i].ulPropTag) {
+ return get_SPropValue_data(&lpProps[i]);
+ }
+ }
+ return NULL;
+}
+
+_PUBLIC_ struct SPropValue *get_SPropValue_SRowSet(struct SRowSet *RowSet,
+ uint32_t ulPropTag)
+{
+ uint32_t i;
+ uint32_t j;
+
+ /* Sanity Checks */
+ if (!RowSet) return NULL;
+
+ for (i = 0; i != RowSet->cRows; i++) {
+ for (j = 0; j < RowSet->aRow[i].cValues; j++) {
+ if (ulPropTag == RowSet->aRow[i].lpProps[j].ulPropTag) {
+ return (&RowSet->aRow[i].lpProps[j]);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+_PUBLIC_ const void *get_SPropValue_SRowSet_data(struct SRowSet *RowSet,
+ uint32_t ulPropTag)
+{
+ struct SPropValue *lpProp;
+
+ lpProp = get_SPropValue_SRowSet(RowSet, ulPropTag);
+ return get_SPropValue(lpProp, ulPropTag);
+}
+
+_PUBLIC_ enum MAPISTATUS set_default_error_SPropValue_SRow(struct SRow *aRow, uint32_t ulPropTag, void *data)
+{
+ uint32_t i;
+
+ for (i = 0; i < aRow->cValues; i++) {
+ if ((ulPropTag & 0xFFFF0000) == (aRow->lpProps[i].ulPropTag & 0xFFFF0000) &&
+ (aRow->lpProps[i].ulPropTag & 0xFFFF) == 0xA) {
+ set_SPropValue_proptag(&(aRow->lpProps[i]), ulPropTag, data);
+ return MAPI_E_SUCCESS;
+ }
+ }
+ return MAPI_E_NOT_FOUND;
+}
+
+_PUBLIC_ struct SPropValue *get_SPropValue_SRow(struct SRow *aRow,
+ uint32_t ulPropTag)
+{
+ uint32_t i;
+
+ for (i = 0; i < aRow->cValues; i++) {
+ if (ulPropTag == aRow->lpProps[i].ulPropTag) {
+ return (&aRow->lpProps[i]);
+ }
+ }
+
+ return NULL;
+}
+
+_PUBLIC_ const void *get_SPropValue_SRow_data(struct SRow *aRow,
+ uint32_t ulPropTag)
+{
+ struct SPropValue *lpProp;
+
+ lpProp = get_SPropValue_SRow(aRow, ulPropTag);
+ return get_SPropValue(lpProp, ulPropTag);
+}
+
+/*
+ Create a MAPITAGS array from a SRow entry
+ */
+
+enum MAPITAGS *get_MAPITAGS_SRow(TALLOC_CTX *mem_ctx, struct SRow *aRow)
+{
+ enum MAPITAGS *mapitags;
+ uint32_t count, idx;
+
+ mapitags = talloc_array(mem_ctx, enum MAPITAGS, aRow->cValues + 1);
+
+ for (count = 0, idx=0; count < aRow->cValues; count++) {
+ if ((aRow->lpProps[count].ulPropTag & 0xFFFF) != PT_ERROR) {
+ mapitags[idx] = aRow->lpProps[count].ulPropTag;
+ idx++;
+ }
+ }
+ mapitags[idx] = 0;
+ return mapitags;
+}
+
+/*
+ Remove MAPITAGS entries from a MAPITAGS array
+*/
+
+uint32_t MAPITAGS_delete_entries(enum MAPITAGS *mapitags, uint32_t final_count, uint32_t PropCount, ...)
+{
+ va_list ap;
+ uint32_t i,j;
+ uint32_t aulPropTag;
+ uint32_t count = 0;
+
+ va_start(ap, PropCount);
+ for (i = 0; i != PropCount; i++) {
+ aulPropTag = va_arg(ap, uint32_t);
+ for (count = 0; mapitags[count]; count++) {
+ if (aulPropTag == (uint32_t)mapitags[count]) {
+ final_count -= 1;
+ for (j = count; mapitags[j]; j++) {
+ mapitags[j] = (mapitags[j+1]) ? mapitags[j+1] : 0;
+ }
+ }
+ }
+ }
+ va_end(ap);
+
+ return final_count;
+}
+
+_PUBLIC_ const void *find_SPropValue_data(struct SRow *aRow, uint32_t mapitag)
+{
+ uint32_t i;
+
+ for (i = 0; i < aRow->cValues; i++) {
+ if (aRow->lpProps[i].ulPropTag == mapitag) {
+ return get_SPropValue_data(&(aRow->lpProps[i]));
+ }
+ }
+ return NULL;
+}
+
+_PUBLIC_ const void *find_mapi_SPropValue_data(
+ struct mapi_SPropValue_array *properties, uint32_t mapitag)
+{
+ uint32_t i;
+
+ for (i = 0; i < properties->cValues; i++) {
+ if (properties->lpProps[i].ulPropTag == mapitag) {
+ return get_mapi_SPropValue_data(&properties->lpProps[i]);
+ }
+ }
+ return NULL;
+}
+
+_PUBLIC_ const void *get_mapi_SPropValue_data(struct mapi_SPropValue *lpProp)
+{
+ if (lpProp->ulPropTag == 0) {
+ return NULL;
+ }
+ switch(lpProp->ulPropTag & 0xFFFF) {
+ case PT_BOOLEAN:
+ return (const void *)(uint8_t *)&lpProp->value.b;
+ case PT_I2: /* Equivalent to PT_SHORT */
+ return (const void *)(uint16_t *)&lpProp->value.i;
+ case PT_LONG: /* Equivalent to PT_I4 */
+ return (const void *)&lpProp->value.l;
+ case PT_DOUBLE:
+ return (const void *)&lpProp->value.dbl;
+ case PT_I8:
+ return (const void *)&lpProp->value.d;
+ case PT_SYSTIME:
+ return (const void *)(struct FILETIME *)&lpProp->value.ft;
+ case PT_ERROR:
+ return (const void *)&lpProp->value.err;
+ case PT_STRING8:
+ return (const void *)lpProp->value.lpszA;
+ case PT_UNICODE:
+ return (const void *)lpProp->value.lpszW;
+ case PT_BINARY:
+ return (const void *)(struct SBinary_short *)&lpProp->value.bin;
+ case PT_MV_LONG:
+ return (const void *)(struct mapi_MV_LONG_STRUCT *)&lpProp->value.MVl;
+ case PT_MV_STRING8:
+ return (const void *)(struct mapi_SLPSTRArray *)&lpProp->value.MVszA;
+ case PT_MV_BINARY:
+ return (const void *)(struct mapi_SBinaryArray *)&lpProp->value.MVbin;
+ default:
+ return NULL;
+ }
+}
+
+_PUBLIC_ const void *get_SPropValue_data(struct SPropValue *lpProps)
+{
+ if (lpProps->ulPropTag == 0) {
+ return NULL;
+ }
+
+ switch(lpProps->ulPropTag & 0xFFFF) {
+ case PT_SHORT:
+ return (const void *)&lpProps->value.i;
+ case PT_BOOLEAN:
+ return (const void *)&lpProps->value.b;
+ case PT_I8:
+ return (const void *)&lpProps->value.d;
+ case PT_STRING8:
+ return (const void *)lpProps->value.lpszA;
+ case PT_UNICODE:
+ return (const void *)lpProps->value.lpszW;
+ case PT_SYSTIME:
+ return (const void *)(struct FILETIME *)&lpProps->value.ft;
+ case PT_ERROR:
+ return (const void *)&lpProps->value.err;
+ case PT_LONG:
+ return (const void *)&lpProps->value.l;
+ case PT_DOUBLE:
+ return (const void *)&lpProps->value.dbl;
+ case PT_CLSID:
+ return (const void *)lpProps->value.lpguid;
+ case PT_BINARY:
+ return (const void *)&lpProps->value.bin;
+ case PT_MV_SHORT:
+ return (const void *)(struct ShortArray_r *)&lpProps->value.MVi;
+ case PT_MV_LONG:
+ return (const void *)(struct LongArray_r *)&lpProps->value.MVl;
+ case PT_MV_STRING8:
+ return (const void *)(struct StringArray_r *)&lpProps->value.MVszA;
+ case PT_MV_UNICODE:
+ return (const void *)(struct WStringArray_r *)&lpProps->value.MVszW;
+ case PT_MV_BINARY:
+ return (const void *)(struct BinaryArray_r *)&lpProps->value.MVbin;
+ case PT_MV_SYSTIME:
+ return (const void *)(struct DateTimeArray_r *)&lpProps->value.MVft;
+ case PT_NULL:
+ return (const void *)&lpProps->value.null;
+ default:
+ return NULL;
+ }
+}
+
+_PUBLIC_ bool set_SPropValue_proptag(struct SPropValue *lpProps, uint32_t aulPropTag, const void *data)
+{
+ lpProps->ulPropTag = aulPropTag;
+ lpProps->dwAlignPad = 0x0;
+
+ return (set_SPropValue(lpProps, data));
+}
+
+_PUBLIC_ struct SPropValue *add_SPropValue(TALLOC_CTX *mem_ctx, struct SPropValue *lpProps, uint32_t *cValues, uint32_t aulPropTag, const void * data)
+{
+ lpProps = talloc_realloc(mem_ctx, lpProps, struct SPropValue, *cValues + 2);
+
+ set_SPropValue_proptag(&lpProps[*cValues], aulPropTag, data);
+ *cValues = *cValues + 1;
+
+ return lpProps;
+}
+/*
+ TODO: should this be public?
+*/
+_PUBLIC_ bool set_SPropValue(struct SPropValue *lpProps, const void *data)
+{
+ if (data == NULL) {
+ lpProps->value.err = MAPI_E_NOT_FOUND;
+ return false;
+ }
+ switch (lpProps->ulPropTag & 0xFFFF) {
+ case PT_SHORT:
+ lpProps->value.i = *((const uint16_t *)data);
+ break;
+ case PT_LONG:
+ lpProps->value.l = *((const uint32_t *)data);
+ break;
+ case PT_I8:
+ lpProps->value.d = *((const uint64_t *)data);
+ break;
+ case PT_BOOLEAN:
+ lpProps->value.b = *((const uint8_t *)data);
+ break;
+ case PT_STRING8:
+ lpProps->value.lpszA = (const char *) data;
+ break;
+ case PT_BINARY:
+ lpProps->value.bin = *((const struct Binary_r *)data);
+ break;
+ case PT_UNICODE:
+ lpProps->value.lpszW = (const char *) data;
+ break;
+ case PT_CLSID:
+ lpProps->value.lpguid = (struct FlatUID_r *) data;
+ break;
+ case PT_SYSTIME:
+ lpProps->value.ft = *((const struct FILETIME *) data);
+ break;
+ case PT_ERROR:
+ lpProps->value.err = *((const uint32_t *)data);
+ break;
+ case PT_MV_SHORT:
+ lpProps->value.MVi = *((const struct ShortArray_r *)data);
+ break;
+ case PT_MV_LONG:
+ lpProps->value.MVl = *((const struct LongArray_r *)data);
+ break;
+ case PT_MV_STRING8:
+ lpProps->value.MVszA = *((const struct StringArray_r *)data);
+ break;
+ case PT_MV_BINARY:
+ lpProps->value.MVbin = *((const struct BinaryArray_r *)data);
+ break;
+ case PT_MV_CLSID:
+ lpProps->value.MVguid = *((const struct FlatUIDArray_r *)data);
+ break;
+ case PT_MV_UNICODE:
+ lpProps->value.MVszW = *((const struct WStringArray_r *)data);
+ break;
+ case PT_MV_SYSTIME:
+ lpProps->value.MVft = *((const struct DateTimeArray_r *)data);
+ break;
+ case PT_NULL:
+ lpProps->value.null = *((const uint32_t *)data);
+ break;
+ case PT_OBJECT:
+ lpProps->value.object = *((const uint32_t *)data);
+ break;
+ default:
+ lpProps->value.err = MAPI_E_NOT_FOUND;
+
+ return false;
+ }
+
+ return true;
+}
+
+_PUBLIC_ uint32_t get_mapi_property_size(struct mapi_SPropValue *lpProp)
+{
+ switch(lpProp->ulPropTag & 0xFFFF) {
+ case PT_BOOLEAN:
+ return sizeof (uint8_t);
+ case PT_I2:
+ return sizeof (uint16_t);
+ case PT_LONG:
+ case PT_ERROR:
+ return sizeof (uint32_t);
+ case PT_DOUBLE:
+ case PT_I8:
+ return sizeof (uint64_t);
+ case PT_STRING8:
+ return strlen(lpProp->value.lpszA) + 1;
+ case PT_UNICODE:
+ return strlen(lpProp->value.lpszW) * 2 + 2;
+ case PT_SYSTIME:
+ return sizeof (struct FILETIME);
+ case PT_BINARY:
+ return (lpProp->value.bin.cb + sizeof(uint16_t));
+ }
+ return 0;
+}
+
+/*
+ convenient function which cast a SPropValue structure in a mapi_SPropValue one and return the associated size
+*/
+
+_PUBLIC_ uint32_t cast_mapi_SPropValue(struct mapi_SPropValue *mapi_sprop, struct SPropValue *sprop)
+{
+ mapi_sprop->ulPropTag = sprop->ulPropTag;
+
+ switch(sprop->ulPropTag & 0xFFFF) {
+ case PT_BOOLEAN:
+ mapi_sprop->value.b = sprop->value.b;
+ return sizeof(uint8_t);
+ case PT_I2:
+ mapi_sprop->value.i = sprop->value.i;
+ return sizeof(uint16_t);
+ case PT_LONG:
+ mapi_sprop->value.l = sprop->value.l;
+ return sizeof(uint32_t);
+ case PT_DOUBLE:
+ mapi_sprop->value.dbl = sprop->value.dbl;
+ return sizeof(uint64_t);
+ case PT_STRING8:
+ mapi_sprop->value.lpszA = sprop->value.lpszA;
+ if (!mapi_sprop->value.lpszA) return 0;
+ return (strlen(sprop->value.lpszA) + 1);
+ case PT_UNICODE:
+ mapi_sprop->value.lpszW = sprop->value.lpszW;
+ if (!mapi_sprop->value.lpszW) return 0;
+ return (strlen(sprop->value.lpszW) * 2 + 2);
+ case PT_SYSTIME:
+ mapi_sprop->value.ft.dwLowDateTime = sprop->value.ft.dwLowDateTime;
+ mapi_sprop->value.ft.dwHighDateTime = sprop->value.ft.dwHighDateTime;
+ return (sizeof (struct FILETIME));
+ case PT_BINARY:
+ mapi_sprop->value.bin.cb = sprop->value.bin.cb;
+ mapi_sprop->value.bin.lpb = sprop->value.bin.lpb;
+ return (mapi_sprop->value.bin.cb + sizeof(uint16_t));
+ case PT_MV_STRING8:
+ {
+ uint32_t i;
+ uint32_t size = 0;
+
+ mapi_sprop->value.MVszA.cValues = sprop->value.MVszA.cValues;
+ size += 4;
+
+ mapi_sprop->value.MVszA.strings = talloc_array(global_mapi_ctx->mem_ctx, struct mapi_LPSTR, mapi_sprop->value.MVszA.cValues);
+ for (i = 0; i < mapi_sprop->value.MVszA.cValues; i++) {
+ mapi_sprop->value.MVszA.strings[i].lppszA = sprop->value.MVszA.lppszA[i];
+ size += strlen(mapi_sprop->value.MVszA.strings[i].lppszA) + 1;
+ }
+ return size;
+ }
+ }
+ return 0;
+
+}
+
+/*
+ *
+ */
+_PUBLIC_ uint32_t cast_SPropValue(struct mapi_SPropValue *mapi_sprop, struct SPropValue *sprop)
+{
+ sprop->ulPropTag = mapi_sprop->ulPropTag;
+
+ switch(sprop->ulPropTag & 0xFFFF) {
+ case PT_BOOLEAN:
+ sprop->value.b = mapi_sprop->value.b;
+ return sizeof(uint8_t);
+ case PT_I2:
+ sprop->value.i = mapi_sprop->value.i;
+ return sizeof(uint16_t);
+ case PT_LONG:
+ sprop->value.l = mapi_sprop->value.l;
+ return sizeof(uint32_t);
+ case PT_DOUBLE:
+ sprop->value.dbl = mapi_sprop->value.dbl;
+ return sizeof(uint64_t);
+ case PT_STRING8:
+ sprop->value.lpszA = mapi_sprop->value.lpszA;
+ if (!mapi_sprop->value.lpszA) return 0;
+ return (strlen(sprop->value.lpszA) + 1);
+ case PT_UNICODE:
+ sprop->value.lpszW = mapi_sprop->value.lpszW;
+ if (!sprop->value.lpszW) return 0;
+ return (strlen(mapi_sprop->value.lpszW) * 2 + 2);
+ case PT_SYSTIME:
+ sprop->value.ft.dwLowDateTime = mapi_sprop->value.ft.dwLowDateTime;
+ sprop->value.ft.dwHighDateTime = mapi_sprop->value.ft.dwHighDateTime;
+ return (sizeof (struct FILETIME));
+ case PT_BINARY:
+ sprop->value.bin.cb = mapi_sprop->value.bin.cb;
+ sprop->value.bin.lpb = mapi_sprop->value.bin.lpb;
+ return (sprop->value.bin.cb + sizeof(uint16_t));
+
+ case PT_MV_STRING8:
+ {
+ uint32_t i;
+ uint32_t size = 0;
+
+ sprop->value.MVszA.cValues = mapi_sprop->value.MVszA.cValues;
+ size += 4;
+
+ sprop->value.MVszA.lppszA = talloc_array(global_mapi_ctx->mem_ctx, const char *, sprop->value.MVszA.cValues);
+ for (i = 0; i < sprop->value.MVszA.cValues; i++) {
+ sprop->value.MVszA.lppszA[i] = mapi_sprop->value.MVszA.strings[i].lppszA;
+ size += strlen(sprop->value.MVszA.lppszA[i]) + 1;
+ }
+ return size;
+ }
+ }
+ return 0;
+}
+
+
+/**
+ \details add a SPropValue structure to a SRow array
+
+ \param aRow pointer to the SRow array where SPropBalue should be
+ appended
+ \param SPropValue reference to the SPropValue structure to add to
+ aRow
+
+ \return MAPI_E_SUCCESS on success, otherwise
+ MAPI_E_INVALID_PARAMETER.
+ */
+_PUBLIC_ enum MAPISTATUS SRow_addprop(struct SRow *aRow, struct SPropValue SPropValue)
+{
+ TALLOC_CTX *mem_ctx;
+ uint32_t cValues;
+ struct SPropValue lpProp;
+ uint32_t i;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!aRow, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = (TALLOC_CTX *) aRow;
+
+ /* If the property tag already exist, overwrite its value */
+ for (i = 0; i < aRow->cValues; i++) {
+ if (aRow->lpProps[i].ulPropTag == SPropValue.ulPropTag) {
+ aRow->lpProps[i] = SPropValue;
+ return MAPI_E_SUCCESS;
+ }
+ }
+
+ cValues = aRow->cValues + 1;
+ aRow->lpProps = talloc_realloc(mem_ctx, aRow->lpProps, struct SPropValue, cValues);
+ lpProp = aRow->lpProps[cValues-1];
+ lpProp.ulPropTag = SPropValue.ulPropTag;
+ lpProp.dwAlignPad = 0;
+ set_SPropValue(&(lpProp), get_SPropValue_data(&SPropValue));
+ aRow->cValues = cValues;
+ aRow->lpProps[cValues - 1] = lpProp;
+
+ return MAPI_E_SUCCESS;
+}
+
+_PUBLIC_ uint32_t SRowSet_propcpy(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, struct SPropValue SPropValue)
+{
+ uint32_t rows;
+ uint32_t cValues;
+ struct SPropValue lpProp;
+
+ for (rows = 0; rows < SRowSet->cRows; rows++) {
+ cValues = SRowSet->aRow[rows].cValues + 1;
+ SRowSet->aRow[rows].lpProps = talloc_realloc(mem_ctx, SRowSet->aRow[rows].lpProps, struct SPropValue, cValues);
+ lpProp = SRowSet->aRow[rows].lpProps[cValues-1];
+ lpProp.ulPropTag = SPropValue.ulPropTag;
+ lpProp.dwAlignPad = 0;
+ set_SPropValue(&(lpProp), (void *)&SPropValue.value);
+ SRowSet->aRow[rows].cValues = cValues;
+ SRowSet->aRow[rows].lpProps[cValues - 1] = lpProp;
+ }
+ return 0;
+}
+
+_PUBLIC_ void mapi_SPropValue_array_named(mapi_object_t *obj,
+ struct mapi_SPropValue_array *props)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct MAPINAMEID *nameid;
+ uint32_t propID;
+ uint16_t count;
+ uint32_t i;
+
+ mem_ctx = talloc_named(NULL, 0, "mapi_SPropValue_array_named");
+
+ for (i = 0; i < props->cValues; i++) {
+ if ((props->lpProps[i].ulPropTag & 0xFFFF0000) > 0x80000000) {
+ propID = props->lpProps[i].ulPropTag;
+ propID = (propID & 0xFFFF0000) | PT_NULL;
+ nameid = talloc_zero(mem_ctx, struct MAPINAMEID);
+ retval = GetNamesFromIDs(obj, propID, &count, &nameid);
+ if (retval != MAPI_E_SUCCESS) goto end;
+
+ if (count) {
+ /* Display property given its propID */
+ switch (nameid->ulKind) {
+ case MNID_ID:
+ props->lpProps[i].ulPropTag = (nameid->kind.lid << 16) |
+ (props->lpProps[i].ulPropTag & 0x0000FFFF);
+ break;
+ case MNID_STRING:
+ /* MNID_STRING named properties don't have propIDs */
+ break;
+ }
+ }
+ talloc_free(nameid);
+ }
+ }
+end:
+ talloc_free(mem_ctx);
+}
+
+_PUBLIC_ enum MAPISTATUS get_mapi_SPropValue_array_date_timeval(struct timeval *t,
+ struct mapi_SPropValue_array *properties,
+ uint32_t mapitag)
+{
+ const struct FILETIME *filetime;
+ NTTIME time;
+
+ filetime = (const struct FILETIME *) find_mapi_SPropValue_data(properties, mapitag);
+ if (!filetime) {
+ t = NULL;
+ return MAPI_E_NOT_FOUND;
+ }
+
+ time = filetime->dwHighDateTime;
+ time = time << 32;
+ time |= filetime->dwLowDateTime;
+ nttime_to_timeval(t, time);
+
+ return MAPI_E_SUCCESS;
+}
+
+_PUBLIC_ enum MAPISTATUS get_mapi_SPropValue_date_timeval(struct timeval *t,
+ struct SPropValue lpProp)
+{
+ const struct FILETIME *filetime;
+ NTTIME time;
+
+ filetime = (const struct FILETIME *) get_SPropValue_data(&lpProp);
+ if (!filetime) {
+ t = NULL;
+ return MAPI_E_NOT_FOUND;
+ }
+
+ time = filetime->dwHighDateTime;
+ time = time << 32;
+ time |= filetime->dwLowDateTime;
+ nttime_to_timeval(t, time);
+
+ return MAPI_E_SUCCESS;
+}
+
+_PUBLIC_ bool set_SPropValue_proptag_date_timeval(struct SPropValue *lpProps, uint32_t aulPropTag, const struct timeval *t)
+{
+ struct FILETIME filetime;
+ NTTIME time;
+
+ time = timeval_to_nttime(t);
+
+ filetime.dwLowDateTime = (time << 32) >> 32;
+ filetime.dwHighDateTime = time >> 32;
+
+ return set_SPropValue_proptag(lpProps, aulPropTag, &filetime);
+}
+
+
+/**
+ \details Retrieve a RecurrencePattern structure from a binary blob
+
+ \param mem_ctx pointer to the memory context
+ \param bin pointer to the Binary_r structure with non-mapped
+ reccurrence data
+
+ \return Allocated RecurrencePattern structure on success,
+ otherwise NULL
+
+ \note Developers must free the allocated RecurrencePattern when
+ finished.
+ */
+_PUBLIC_ struct RecurrencePattern *get_RecurrencePattern(TALLOC_CTX *mem_ctx,
+ struct Binary_r *bin)
+{
+ struct RecurrencePattern *RecurrencePattern = NULL;
+ struct ndr_pull *ndr;
+ enum ndr_err_code ndr_err_code;
+
+ /* Sanity checks */
+ if (!bin) return NULL;
+ if (!bin->cb) return NULL;
+ if (!bin->lpb) return NULL;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_pull);
+ ndr->offset = 0;
+ ndr->data = bin->lpb;
+ ndr->data_size = bin->cb;
+
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ ndr->iconv_convenience = smb_iconv_convenience_init(mem_ctx, "CP850", "UTF8", true);
+ RecurrencePattern = talloc_zero(mem_ctx, struct RecurrencePattern);
+ ndr_err_code = ndr_pull_RecurrencePattern(ndr, NDR_SCALARS, RecurrencePattern);
+
+ talloc_free(ndr);
+
+ if (ndr_err_code != NDR_ERR_SUCCESS) {
+ talloc_free(RecurrencePattern);
+ return NULL;
+ }
+
+ return RecurrencePattern;
+}
+
+
+/**
+ \details Retrieve a TimeZoneStruct structure from a binary blob
+
+ \param mem_ctx pointer to the memory context
+ \param bin pointer to the Binary_r structure with raw
+ TimeZoneStruct data
+
+ \return Allocated TimeZoneStruct structure on success, otherwise
+ NULL
+
+ \note Developers must free the allocated TimeZoneStruct when
+ finished.
+ */
+_PUBLIC_ struct TimeZoneStruct *get_TimeZoneStruct(TALLOC_CTX *mem_ctx,
+ struct Binary_r *bin)
+{
+ struct TimeZoneStruct *TimeZoneStruct = NULL;
+ struct ndr_pull *ndr;
+ enum ndr_err_code ndr_err_code;
+
+ /* Sanity checks */
+ if (!bin) return NULL;
+ if (!bin->cb) return NULL;
+ if (!bin->lpb) return NULL;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_pull);
+ ndr->offset = 0;
+ ndr->data = bin->lpb;
+ ndr->data_size = bin->cb;
+
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ ndr->iconv_convenience = smb_iconv_convenience_init(mem_ctx, "CP850", "UTF8", true);
+ TimeZoneStruct = talloc_zero(mem_ctx, struct TimeZoneStruct);
+ ndr_err_code = ndr_pull_TimeZoneStruct(ndr, NDR_SCALARS, TimeZoneStruct);
+
+ talloc_free(ndr);
+
+ if (ndr_err_code != NDR_ERR_SUCCESS) {
+ talloc_free(TimeZoneStruct);
+ return NULL;
+ }
+
+ return TimeZoneStruct;
+}
+
+
+/**
+ \details Retrieve a GlobalObjectId structure from a binary blob
+
+ \param mem_ctx pointer to the memory context
+ \param bin pointer to the Binary_r structure with raw
+ GlobalObjectId data
+
+ \return Allocated GlobalObjectId structure on success, otherwise
+ NULL
+
+ \note Developers must free the allocated GlobalObjectId when
+ finished.
+ */
+_PUBLIC_ struct GlobalObjectId *get_GlobalObjectId(TALLOC_CTX *mem_ctx,
+ struct Binary_r *bin)
+{
+ struct GlobalObjectId *GlobalObjectId = NULL;
+ struct ndr_pull *ndr;
+ enum ndr_err_code ndr_err_code;
+
+ /* Sanity checks */
+ if (!bin) return NULL;
+ if (!bin->cb) return NULL;
+ if (!bin->lpb) return NULL;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_pull);
+ ndr->offset = 0;
+ ndr->data = bin->lpb;
+ ndr->data_size = bin->cb;
+
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ ndr->iconv_convenience = smb_iconv_convenience_init(mem_ctx, "CP850", "UTF8", true);
+ GlobalObjectId = talloc_zero(mem_ctx, struct GlobalObjectId);
+ ndr_err_code = ndr_pull_GlobalObjectId(ndr, NDR_SCALARS, GlobalObjectId);
+
+ talloc_free(ndr);
+
+ if (ndr_err_code != NDR_ERR_SUCCESS) {
+ talloc_free(GlobalObjectId);
+ return NULL;
+ }
+
+ return GlobalObjectId;
+}
Added: trunk/openchange/libmapi/simple_mapi.c
===================================================================
--- trunk/openchange/libmapi/simple_mapi.c (rev 0)
+++ trunk/openchange/libmapi/simple_mapi.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,862 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+
+/**
+ \file simple_mapi.c
+
+ \brief Convenience functions.
+*/
+
+
+/**
+ \details Retrieve the folder id for the specified default folder in
+ a public folder store
+
+ \param obj_store the store to search
+ \param id the type of folder to search for
+ \param folder the resulting folder reference
+
+ The following types of folders are supported:
+ - olFolderPublicRoot - the parent (directly or indirectly) for the folders below
+ - olFolderPublicIPMSubtree - Interpersonal Messages (IPM) folders
+ - olFolderPublicNonIPMSubtree - Non-interpersonal message folders
+ - olFolderPublicEFormsRoot - EForms Registry Root Folder
+ - olFolderPublicFreeBusyRoot - Free/busy root folder
+ - olFolderPublicOfflineAB - Offline address book root folder
+ - olFolderPublicEFormsRegistry - EForms Registry for the users locale
+ - olFolderPublicLocalFreeBusy - Site local free/busy folders
+ - olFolderPublicLocalOfflineAB - Site local Offline address book
+ - olFolderPublicNNTPArticle - NNTP article index folder
+
+ \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
+ indicating the error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
+ - MAPI_E_INVALID_PARAMETER: obj_store is undefined
+ - MAPI_E_NOT_FOUND: The specified folder could not be found or is
+ not yet supported.
+
+ \sa MAPIInitialize, OpenPublicFolder, GetLastError
+ */
+_PUBLIC_ enum MAPISTATUS GetDefaultPublicFolder(mapi_object_t *obj_store,
+ uint64_t *folder,
+ const uint32_t id)
+{
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+
+ switch (id) {
+ case olFolderPublicRoot:
+ *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_public_root;
+ break;
+ case olFolderPublicIPMSubtree:
+ *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_ipm_subtree;
+ break;
+ case olFolderPublicNonIPMSubtree:
+ *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_non_ipm_subtree;
+ break;
+ case olFolderPublicEFormsRoot:
+ *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_EFormsRegistryRoot;
+ break;
+ case olFolderPublicFreeBusyRoot:
+ *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_FreeBusyRoot;
+ break;
+ case olFolderPublicOfflineAB:
+ *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_OfflineAB;
+ break;
+ case olFolderPublicEFormsRegistry:
+ *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_EFormsRegistry;
+ break;
+ case olFolderPublicLocalFreeBusy:
+ *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_LocalSiteFreeBusy;
+ break;
+ case olFolderPublicLocalOfflineAB:
+ *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_LocalSiteOfflineAB;
+ break;
+ case olFolderPublicNNTPArticle:
+ *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_NNTPArticle;
+ break;
+ default:
+ OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, NULL);
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+static enum MAPISTATUS CacheDefaultFolders(mapi_object_t *obj_store)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_store_t *store;
+ mapi_object_t obj_inbox;
+ mapi_id_t id_inbox;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SRow aRow;
+ struct SPropValue *lpProps;
+ uint32_t count;
+ const struct Binary_r *entryid;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+
+ store = (mapi_object_store_t *)obj_store->private_data;
+ OPENCHANGE_RETVAL_IF(!store, MAPI_E_NOT_INITIALIZED, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetDefaultFolder");
+
+ mapi_object_init(&obj_inbox);
+ retval = GetReceiveFolder(obj_store, &id_inbox, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = OpenFolder(obj_store, id_inbox, &obj_inbox);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
+ PR_IPM_APPOINTMENT_ENTRYID,
+ PR_IPM_CONTACT_ENTRYID,
+ PR_IPM_JOURNAL_ENTRYID,
+ PR_IPM_NOTE_ENTRYID,
+ PR_IPM_TASK_ENTRYID,
+ PR_IPM_DRAFTS_ENTRYID);
+
+ retval = GetProps(&obj_inbox, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ aRow.cValues = count;
+ aRow.lpProps = lpProps;
+
+ /* set cached calendar FID */
+ entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_APPOINTMENT_ENTRYID);
+ OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
+ retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_calendar);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* set cached contact FID */
+ entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_CONTACT_ENTRYID);
+ OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
+ retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_contact);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* set cached journal FID */
+ entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_JOURNAL_ENTRYID);
+ OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
+ retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_journal);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* set cached note FID */
+ entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_NOTE_ENTRYID);
+ OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
+ retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_note);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* set cached task FID */
+ entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_TASK_ENTRYID);
+ OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
+ retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_task);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* set cached drafts FID */
+ entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_DRAFTS_ENTRYID);
+ OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
+ retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_drafts);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ store->cached_mailbox_fid = true;
+
+ mapi_object_release(&obj_inbox);
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieves the folder id for the specified default folder
+ in a mailbox store
+
+ \param obj_store the store to search
+ \param id the type of folder to search for
+ \param folder the resulting folder reference
+
+ The following types of folders are supported:
+ - olFolderTopInformationStore
+ - olFolderDeletedItems
+ - olFolderOutbox
+ - olFolderSentMail
+ - olFolderInbox
+ - olFolderCommonView
+ - olFolderCalendar
+ - olFolderContacts
+ - olFolderJournal
+ - olFolderNotes
+ - olFolderTasks
+ - olFolderDrafts
+ - olFolderReminders
+ - olFolderFinder
+
+ Note that this function will cache FID values for common accessed
+ folders such as calendar, contact, journal, note, task and drafts
+ until the store object got released.
+
+ \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
+ indicating the error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
+ - MAPI_E_INVALID_PARAMETER: obj_store is undefined
+ - MAPI_E_NOT_FOUND: The specified folder could not be found or is
+ not yet supported.
+
+ \sa MAPIInitialize, OpenMsgStore, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS GetDefaultFolder(mapi_object_t *obj_store,
+ uint64_t *folder,
+ const uint32_t id)
+{
+ enum MAPISTATUS retval;
+ mapi_object_store_t *store;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+
+ store = (mapi_object_store_t *)obj_store->private_data;
+ OPENCHANGE_RETVAL_IF(!store, MAPI_E_NOT_INITIALIZED, NULL);
+
+ if ((id > 6) && (store->cached_mailbox_fid == false)) {
+ retval = CacheDefaultFolders(obj_store);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+ }
+
+ switch (id) {
+ case olFolderTopInformationStore:
+ *folder = store->fid_top_information_store;
+ return MAPI_E_SUCCESS;
+ case olFolderDeletedItems:
+ *folder = store->fid_deleted_items;
+ return MAPI_E_SUCCESS;
+ case olFolderOutbox:
+ *folder = store->fid_outbox;
+ return MAPI_E_SUCCESS;
+ case olFolderSentMail:
+ *folder = store->fid_sent_items;
+ return MAPI_E_SUCCESS;
+ case olFolderInbox:
+ *folder = store->fid_inbox;
+ return MAPI_E_SUCCESS;
+ case olFolderCommonView:
+ *folder = store->fid_common_views;
+ return MAPI_E_SUCCESS;
+ case olFolderCalendar:
+ *folder = store->fid_calendar;
+ return MAPI_E_SUCCESS;
+ case olFolderContacts:
+ *folder = store->fid_contact;
+ return MAPI_E_SUCCESS;
+ case olFolderJournal:
+ *folder = store->fid_journal;
+ return MAPI_E_SUCCESS;
+ case olFolderNotes:
+ *folder = store->fid_note;
+ return MAPI_E_SUCCESS;
+ case olFolderTasks:
+ *folder = store->fid_task;
+ return MAPI_E_SUCCESS;
+ case olFolderDrafts:
+ *folder = store->fid_drafts;
+ return MAPI_E_SUCCESS;
+ case olFolderFinder:
+ *folder = store->fid_search;
+ return MAPI_E_SUCCESS;
+ default:
+ *folder = 0;
+ OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, 0);
+ }
+}
+
+
+/**
+ \details Check if a given folder identifier matches with a
+ system/default one and optionally returns the olFolder type
+
+ \param obj_store pointer to the store object
+ \param fid reference to the folder identifier to check
+ \param olFolder pointer to the returned olFolder
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool IsMailboxFolder(mapi_object_t *obj_store,
+ uint64_t fid,
+ uint32_t *olFolder)
+{
+ enum MAPISTATUS retval;
+ mapi_object_store_t *store;
+ uint32_t olFolderNum;
+ bool ret = true;
+
+ if (!obj_store) return false;
+ store = (mapi_object_store_t *) obj_store->private_data;
+ if (!store) return false;
+
+ if (store->cached_mailbox_fid == false) {
+ retval = CacheDefaultFolders(obj_store);
+ if (retval) return false;
+ }
+
+ if(fid == store->fid_top_information_store) {
+ olFolderNum = olFolderTopInformationStore;
+ } else if (fid == store->fid_deleted_items) {
+ olFolderNum = olFolderDeletedItems;
+ } else if (fid == store->fid_outbox) {
+ olFolderNum = olFolderOutbox;
+ } else if (fid == store->fid_sent_items) {
+ olFolderNum = olFolderSentMail;
+ } else if (fid == store->fid_inbox) {
+ olFolderNum = olFolderInbox;
+ } else if (fid == store->fid_common_views) {
+ olFolderNum = olFolderCommonView;
+ } else if (fid == store->fid_calendar) {
+ olFolderNum = olFolderCalendar;
+ } else if (fid == store->fid_contact) {
+ olFolderNum = olFolderContacts;
+ } else if (fid == store->fid_journal) {
+ olFolderNum = olFolderJournal;
+ } else if (fid == store->fid_note) {
+ olFolderNum = olFolderNotes;
+ } else if (fid == store->fid_task) {
+ olFolderNum = olFolderTasks;
+ } else if (fid == store->fid_drafts) {
+ olFolderNum = olFolderDrafts;
+ } else if (fid == store->fid_search) {
+ olFolderNum = olFolderFinder;
+ } else {
+ olFolderNum = -1;
+ ret = false;
+ }
+
+ if (olFolder) *olFolder = olFolderNum;
+ return ret;
+}
+
+/**
+ \details Retrieves the total and unread number of items for a
+ specified folder.
+
+ \param obj_folder the folder to get item counts for
+ \param unread the number of items in the folder (result)
+ \param total the number of items in the folder, including unread
+ items (result)
+
+ \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
+ indicating the error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
+ - MAPI_E_INVALID_PARAMETER: obj_folder is undefined
+ - MAPI_E_NOT_FOUND: The specified folder could not be found or is
+ not yet supported.
+
+ \sa MAPIInitialize, OpenFolder, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS GetFolderItemsCount(mapi_object_t *obj_folder,
+ uint32_t *unread,
+ uint32_t *total)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProps;
+ uint32_t count;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!unread, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!total, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "GetFolderItemsCount");
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x2,
+ PR_CONTENT_UNREAD,
+ PR_CONTENT_COUNT);
+
+ retval = GetProps(obj_folder, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ *unread = lpProps[0].value.l;
+ *total = lpProps[1].value.l;
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Adds permissions for a user on a given folder
+
+ \param obj_folder the folder we add permission for
+ \param username the Exchange username we add permissions for
+ \param role the permission mask value
+
+ The following permissions and rights are supported:
+ - RightsNone
+ - RightsReadItems
+ - RightsCreateItems
+ - RightsEditOwn
+ - RightsDeleteOwn
+ - RightsEditAll
+ - RightsDeleteAll
+ - RightsCreateSubfolders
+ - RightsFolderOwner
+ - RightsFolderContact
+ - RoleNone
+ - RoleReviewer
+ - RoleContributor
+ - RoleNoneditingAuthor
+ - RoleAuthor
+ - RoleEditor
+ - RolePublishAuthor
+ - RolePublishEditor
+ - RightsAll
+ - RoleOwner
+
+ \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
+ indicating the error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
+ - MAPI_E_INVALID_PARAMETER: username is NULL
+
+ \sa ResolveNames, ModifyTable
+ */
+_PUBLIC_ enum MAPISTATUS AddUserPermission(mapi_object_t *obj_folder, const char *username, enum ACLRIGHTS role)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct SPropTagArray *SPropTagArray;
+ const char *names[2];
+ struct SRowSet *rows = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ struct mapi_SRowList rowList;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!username, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "AddUserPermission");
+
+ /* query Address book */
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 2, PR_ENTRYID, PR_DISPLAY_NAME);
+ names[0] = username;
+ names[1] = NULL;
+ retval = ResolveNames(mapi_object_get_session(obj_folder), (const char **)names,
+ SPropTagArray, &rows, &flaglist, 0);
+ MAPIFreeBuffer(SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Check if the username was found */
+ OPENCHANGE_RETVAL_IF((flaglist->aulPropTag[0] != MAPI_RESOLVED), MAPI_E_NOT_FOUND, mem_ctx);
+
+ rowList.cEntries = 1;
+ rowList.aEntries = talloc_array(mem_ctx, struct mapi_SRow, 1);
+ rowList.aEntries[0].ulRowFlags = ROW_ADD;
+ rowList.aEntries[0].lpProps.cValues = 2;
+ rowList.aEntries[0].lpProps.lpProps = talloc_array(mem_ctx, struct mapi_SPropValue, 2);
+ cast_mapi_SPropValue(&rowList.aEntries[0].lpProps.lpProps[0], &rows->aRow[0].lpProps[0]);
+ rowList.aEntries[0].lpProps.lpProps[1].ulPropTag = PR_MEMBER_RIGHTS;
+ rowList.aEntries[0].lpProps.lpProps[1].value.l = role;
+
+ retval = ModifyTable(obj_folder, &rowList);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Modify permissions for a user on a given folder
+
+ \param obj_folder the folder we add permission for
+ \param username the Exchange username we modify permissions for
+ \param role the permission mask value (see AddUserPermission)
+
+ \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
+ indicating the error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
+ - MAPI_E_INVALID_PARAMETER: username is NULL
+ - MAPI_E_NOT_FOUND: couldn't find or change permissions for the
+ given user
+
+ \sa AddUserPermission, ResolveNames, GetTable, ModifyTable
+ */
+_PUBLIC_ enum MAPISTATUS ModifyUserPermission(mapi_object_t *obj_folder, const char *username, enum ACLRIGHTS role)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct SPropTagArray *SPropTagArray;
+ const char *names[2];
+ const char *user = NULL;
+ struct SRowSet *rows = NULL;
+ struct SRowSet rowset;
+ struct SPropTagArray *flaglist = NULL;
+ struct mapi_SRowList rowList;
+ struct SPropValue *lpProp;
+ mapi_object_t obj_table;
+ uint32_t Numerator;
+ uint32_t Denominator;
+ bool found = false;
+ uint32_t i = 0;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!username, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "ModifyUserPermission");
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 2, PR_ENTRYID, PR_DISPLAY_NAME);
+ names[0] = username;
+ names[1] = NULL;
+ retval = ResolveNames(mapi_object_get_session(obj_folder), (const char **)names,
+ SPropTagArray, &rows, &flaglist, 0);
+ MAPIFreeBuffer(SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ if (flaglist->aulPropTag[0] == MAPI_RESOLVED) {
+ user = find_SPropValue_data(&(rows->aRow[0]), PR_DISPLAY_NAME);
+ } else {
+ /* Special case: Not a AD user account but Default or
+ * Anonymous. Since names are language specific, we
+ * can't use strcmp
+ */
+ user = username;
+ }
+
+ mapi_object_init(&obj_table);
+ retval = GetTable(obj_folder, &obj_table);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 4,
+ PR_ENTRYID,
+ PR_MEMBER_RIGHTS,
+ PR_MEMBER_ID,
+ PR_MEMBER_NAME);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = QueryPosition(&obj_table, &Numerator, &Denominator);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = QueryRows(&obj_table, Denominator, TBL_ADVANCE, &rowset);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ for (i = 0; i < rowset.cRows; i++) {
+ lpProp = get_SPropValue_SRow(&rowset.aRow[i], PR_MEMBER_NAME);
+ if (lpProp && lpProp->value.lpszA) {
+ if (!strcmp(lpProp->value.lpszA, user)) {
+ rowList.cEntries = 1;
+ rowList.aEntries = talloc_array(mem_ctx, struct mapi_SRow, 1);
+ rowList.aEntries[0].ulRowFlags = ROW_MODIFY;
+ rowList.aEntries[0].lpProps.cValues = 2;
+ rowList.aEntries[0].lpProps.lpProps = talloc_array(mem_ctx, struct mapi_SPropValue, 2);
+ lpProp = get_SPropValue_SRow(&(rowset.aRow[i]), PR_MEMBER_ID);
+ rowList.aEntries[0].lpProps.lpProps[0].ulPropTag = PR_MEMBER_ID;
+ rowList.aEntries[0].lpProps.lpProps[0].value.d = lpProp->value.d;
+ rowList.aEntries[0].lpProps.lpProps[1].ulPropTag = PR_MEMBER_RIGHTS;
+ rowList.aEntries[0].lpProps.lpProps[1].value.l = role;
+
+ retval = ModifyTable(obj_folder, &rowList);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ mapi_object_release(&obj_table);
+ talloc_free(mem_ctx);
+
+ OPENCHANGE_RETVAL_IF((found == true), MAPI_E_NOT_FOUND, 0);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Remove permissions for a user on a given folder
+
+ \param obj_folder the folder we add permission for
+ \param username the Exchange username we remove permissions for
+
+ \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
+ indicating the error.
+
+ \note Developers may also call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
+ - MAPI_E_INVALID_PARAMETER: username or obj_folder are NULL
+ - MAPI_E_NOT_FOUND: couldn't find or remove permissions for the
+ given user
+
+ \sa ResolveNames, GetTable, ModifyTable
+ */
+_PUBLIC_ enum MAPISTATUS RemoveUserPermission(mapi_object_t *obj_folder, const char *username)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct SPropTagArray *SPropTagArray;
+ const char *names[2];
+ const char *user = NULL;
+ struct SRowSet *rows = NULL;
+ struct SRowSet rowset;
+ struct SPropTagArray *flaglist = NULL;
+ struct mapi_SRowList rowList;
+ struct SPropValue *lpProp;
+ mapi_object_t obj_table;
+ uint32_t Numerator;
+ uint32_t Denominator;
+ bool found = false;
+ uint32_t i = 0;
+
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!username, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "RemoveUserPermission");
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 2, PR_ENTRYID, PR_DISPLAY_NAME);
+ names[0] = username;
+ names[1] = NULL;
+ retval = ResolveNames(mapi_object_get_session(obj_folder), (const char **)names,
+ SPropTagArray, &rows, &flaglist, 0);
+ MAPIFreeBuffer(SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Check if the username was found */
+ OPENCHANGE_RETVAL_IF((flaglist->aulPropTag[0] != MAPI_RESOLVED), MAPI_E_NOT_FOUND, mem_ctx);
+
+ user = find_SPropValue_data(&(rows->aRow[0]), PR_DISPLAY_NAME);
+
+ mapi_object_init(&obj_table);
+ retval = GetTable(obj_folder, &obj_table);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 4,
+ PR_ENTRYID,
+ PR_MEMBER_RIGHTS,
+ PR_MEMBER_ID,
+ PR_MEMBER_NAME);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = QueryPosition(&obj_table, &Numerator, &Denominator);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = QueryRows(&obj_table, Denominator, TBL_ADVANCE, &rowset);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ for (i = 0; i < rowset.cRows; i++) {
+ lpProp = get_SPropValue_SRow(&rowset.aRow[i], PR_MEMBER_NAME);
+ if (lpProp && lpProp->value.lpszA) {
+ if (!strcmp(lpProp->value.lpszA, user)) {
+ rowList.cEntries = 1;
+ rowList.aEntries = talloc_array(mem_ctx, struct mapi_SRow, 1);
+ rowList.aEntries[0].ulRowFlags = ROW_REMOVE;
+ rowList.aEntries[0].lpProps.cValues = 1;
+ rowList.aEntries[0].lpProps.lpProps = talloc_array(mem_ctx, struct mapi_SPropValue, 1);
+ lpProp = get_SPropValue_SRow(&(rowset.aRow[i]), PR_MEMBER_ID);
+ rowList.aEntries[0].lpProps.lpProps[0].ulPropTag = PR_MEMBER_ID;
+ rowList.aEntries[0].lpProps.lpProps[0].value.d = lpProp->value.d;
+
+ retval = ModifyTable(obj_folder, &rowList);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ mapi_object_release(&obj_table);
+ talloc_free(mem_ctx);
+
+ OPENCHANGE_RETVAL_IF((found == true), MAPI_E_NOT_FOUND, 0);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Implement the BestBody algorithm and return the best body
+ content type for a given message.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND. If
+ MAPI_E_NOT_FOUND is returned then format is set to 0x0
+ (undefined). If MAPI_E_SUCCESS is returned, then format can have
+ one of the following values:
+ - olEditorText: format is plain text
+ - olEditorHTML: format is HTML
+ - olEditorRTF: format is RTF
+
+ \param obj_message the message we find the best body for
+ \param format the format - see above.
+ */
+_PUBLIC_ enum MAPISTATUS GetBestBody(mapi_object_t *obj_message, uint8_t *format)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SPropValue *lpProps;
+ struct SRow aRow;
+ uint32_t count;
+ uint8_t RtfInSync;
+ uint32_t PlainStatus;
+ uint32_t RtfStatus;
+ uint32_t HtmlStatus;
+ const uint32_t *err_code;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!format, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Step 1. Retrieve properties needed by the BestBody algorithm */
+ SPropTagArray = set_SPropTagArray(global_mapi_ctx->mem_ctx, 0x4,
+ PR_BODY,
+ PR_RTF_COMPRESSED,
+ PR_HTML,
+ PR_RTF_IN_SYNC);
+ retval = GetProps(obj_message, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) {
+ *format = 0;
+ OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, 0);
+ }
+
+ aRow.ulAdrEntryPad = 0;
+ aRow.cValues = count;
+ aRow.lpProps = lpProps;
+
+ /* Step 2. Retrieve properties values and map errors */
+ RtfInSync = *(const uint8_t *)find_SPropValue_data(&aRow, PR_RTF_IN_SYNC);
+
+ err_code = (const uint32_t *)find_SPropValue_data(&aRow, PR_BODY_ERROR);
+ PlainStatus = (err_code) ? *err_code : 0;
+
+ err_code = (const uint32_t *)find_SPropValue_data(&aRow, PR_RTF_COMPRESSED_ERROR);
+ RtfStatus = (err_code) ? *err_code : 0;
+
+ err_code = (const uint32_t *)find_SPropValue_data(&aRow, PR_BODY_HTML_ERROR);
+ HtmlStatus = (err_code) ? *err_code : 0;
+
+ /* Step 3. Determine the body format (9 possible cases) */
+
+ /* case 1 */
+ if ((PlainStatus == MAPI_E_NOT_FOUND) && (RtfStatus == MAPI_E_NOT_FOUND) &&
+ (HtmlStatus == MAPI_E_NOT_FOUND)) {
+ *format = 0;
+ OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, 0);
+ }
+
+ /* case 2 */
+ if (((PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY) || (PlainStatus == 0)) &&
+ (RtfStatus == MAPI_E_NOT_FOUND) && (HtmlStatus == MAPI_E_NOT_FOUND)) {
+ *format = olEditorText;
+ return MAPI_E_SUCCESS;
+ }
+
+ /* case 3 */
+ if ((PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
+ (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
+ (HtmlStatus == MAPI_E_NOT_FOUND)) {
+ *format = olEditorRTF;
+ return MAPI_E_SUCCESS;
+ }
+
+ /* case 4 */
+ if ((PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
+ (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
+ (HtmlStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
+ (RtfInSync == 1)) {
+ *format = olEditorRTF;
+ return MAPI_E_SUCCESS;
+ }
+
+ /* case 5 */
+ if ((PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
+ (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
+ (HtmlStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
+ (RtfInSync == 0)) {
+ *format = olEditorHTML;
+ return MAPI_E_SUCCESS;
+ }
+
+ /* case 6 */
+ if (((RtfStatus == 0) || (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
+ ((HtmlStatus == 0) || (HtmlStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
+ (RtfInSync == 1)) {
+ *format = olEditorRTF;
+ return MAPI_E_SUCCESS;
+ }
+
+ /* case 7 */
+ if (((RtfStatus == 0) || (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
+ ((HtmlStatus == 0) || (HtmlStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
+ (RtfInSync == 0)) {
+ *format = olEditorHTML;
+ return MAPI_E_SUCCESS;
+ }
+
+ /* case 8 */
+ if (((PlainStatus == 0) || (PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
+ ((RtfStatus == 0) || (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
+ (RtfInSync == 1)) {
+ *format = olEditorRTF;
+ return MAPI_E_SUCCESS;
+ }
+
+ /* case 9 */
+ if (((PlainStatus == 0) || (PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
+ ((RtfStatus == 0) || (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
+ (RtfInSync == 0)) {
+ *format = olEditorText;
+ return MAPI_E_SUCCESS;
+ }
+
+ OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, 0);
+}
Added: trunk/openchange/libmapi/socket/interface.c
===================================================================
--- trunk/openchange/libmapi/socket/interface.c (rev 0)
+++ trunk/openchange/libmapi/socket/interface.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,323 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ multiple interface handling
+
+ Copyright (C) Andrew Tridgell 1992-2005
+
+ 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/proto_private.h>
+#include <param.h>
+
+#define ALLONES ((uint32_t)0xFFFFFFFF)
+/*
+ address construction based on a patch from fred at datalync.com
+*/
+#define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
+#define MKNETADDR(_IP, _NM) (_IP & _NM)
+
+/****************************************************************************
+Try and find an interface that matches an ip. If we cannot, return NULL
+ **************************************************************************/
+static struct interface *iface_find(struct interface *interfaces,
+ struct in_addr ip, bool CheckMask)
+{
+ struct interface *i;
+ if (is_zero_ip_v4(ip)) return interfaces;
+
+ for (i=interfaces;i;i=i->next)
+ if (CheckMask) {
+ if (same_net_v4(i->ip,ip,i->nmask)) return i;
+ } else if (i->ip.s_addr == ip.s_addr) return i;
+
+ return NULL;
+}
+
+
+/****************************************************************************
+add an interface to the linked list of interfaces
+****************************************************************************/
+static void add_interface(TALLOC_CTX *mem_ctx, struct in_addr ip, struct in_addr nmask, struct interface **interfaces)
+{
+ struct interface *iface;
+ struct in_addr bcast;
+
+ if (iface_find(*interfaces, ip, false)) {
+ DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
+ return;
+ }
+
+ iface = talloc(*interfaces == NULL ? mem_ctx : *interfaces, struct interface);
+ if (iface == NULL)
+ return;
+
+ ZERO_STRUCTPN(iface);
+
+ iface->ip = ip;
+ iface->nmask = nmask;
+ bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
+
+ /* keep string versions too, to avoid people tripping over the implied
+ static in inet_ntoa() */
+ iface->ip_s = talloc_strdup(iface, inet_ntoa(iface->ip));
+ iface->nmask_s = talloc_strdup(iface, inet_ntoa(iface->nmask));
+
+ if (nmask.s_addr != ~0) {
+ iface->bcast_s = talloc_strdup(iface, inet_ntoa(bcast));
+ }
+
+ DLIST_ADD_END(*interfaces, iface, struct interface *);
+
+ DEBUG(2,("added interface ip=%s nmask=%s\n", iface->ip_s, iface->nmask_s));
+}
+
+
+
+/**
+interpret a single element from a interfaces= config line
+
+This handles the following different forms:
+
+1) wildcard interface name
+2) DNS name
+3) IP/masklen
+4) ip/mask
+5) bcast/mask
+**/
+static void interpret_interface(TALLOC_CTX *mem_ctx,
+ const char *token,
+ struct iface_struct *probed_ifaces,
+ int total_probed,
+ struct interface **local_interfaces)
+{
+ struct in_addr ip, nmask;
+ char *p;
+ char *address;
+ int i, added=0;
+
+ ip.s_addr = 0;
+ nmask.s_addr = 0;
+
+ /* first check if it is an interface name */
+ for (i=0;i<total_probed;i++) {
+ if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
+ add_interface(mem_ctx, probed_ifaces[i].ip,
+ probed_ifaces[i].netmask,
+ local_interfaces);
+ added = 1;
+ }
+ }
+ if (added) return;
+
+ /* maybe it is a DNS name */
+ p = strchr_m(token,'/');
+ if (!p) {
+ /* don't try to do dns lookups on wildcard names */
+ if (strpbrk(token, "*?") != NULL) {
+ return;
+ }
+ ip.s_addr = interpret_addr2(token).s_addr;
+ for (i=0;i<total_probed;i++) {
+ if (ip.s_addr == probed_ifaces[i].ip.s_addr) {
+ add_interface(mem_ctx, probed_ifaces[i].ip,
+ probed_ifaces[i].netmask,
+ local_interfaces);
+ return;
+ }
+ }
+ DEBUG(2,("can't determine netmask for %s\n", token));
+ return;
+ }
+
+ address = talloc_strdup(mem_ctx, token);
+ p = strchr_m(address,'/');
+
+ /* parse it into an IP address/netmasklength pair */
+ *p++ = 0;
+
+ ip.s_addr = interpret_addr2(address).s_addr;
+
+ if (strlen(p) > 2) {
+ nmask.s_addr = interpret_addr2(p).s_addr;
+ } else {
+ nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
+ }
+
+ /* maybe the first component was a broadcast address */
+ if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
+ ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
+ for (i=0;i<total_probed;i++) {
+ if (same_net_v4(ip, probed_ifaces[i].ip, nmask)) {
+ add_interface(mem_ctx, probed_ifaces[i].ip, nmask,
+ local_interfaces);
+ talloc_free(address);
+ return;
+ }
+ }
+ DEBUG(2,("Can't determine ip for broadcast address %s\n", address));
+ talloc_free(address);
+ return;
+ }
+
+ add_interface(mem_ctx, ip, nmask, local_interfaces);
+ talloc_free(address);
+}
+
+
+/**
+load the list of network interfaces
+**/
+void load_interfaces(TALLOC_CTX *mem_ctx, const char **interfaces, struct interface **local_interfaces)
+{
+ const char **ptr = interfaces;
+ int i;
+ struct iface_struct ifaces[MAX_INTERFACES];
+ struct in_addr loopback_ip;
+ int total_probed;
+
+ *local_interfaces = NULL;
+
+ loopback_ip = interpret_addr2("127.0.0.1");
+
+ /* probe the kernel for interfaces */
+ total_probed = get_interfaces(ifaces, MAX_INTERFACES);
+
+ /* if we don't have a interfaces line then use all interfaces
+ except loopback */
+ if (!ptr || !*ptr || !**ptr) {
+ if (total_probed <= 0) {
+ DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
+ }
+ for (i=0;i<total_probed;i++) {
+ if (ifaces[i].ip.s_addr != loopback_ip.s_addr) {
+ add_interface(mem_ctx, ifaces[i].ip,
+ ifaces[i].netmask, local_interfaces);
+ }
+ }
+ }
+
+ while (ptr && *ptr) {
+ interpret_interface(mem_ctx, *ptr, ifaces, total_probed, local_interfaces);
+ ptr++;
+ }
+
+ if (!*local_interfaces) {
+ DEBUG(0,("WARNING: no network interfaces found\n"));
+ }
+}
+
+/**
+ how many interfaces do we have
+ **/
+int iface_count(struct interface *ifaces)
+{
+ int ret = 0;
+ struct interface *i;
+
+ for (i=ifaces;i;i=i->next)
+ ret++;
+ return ret;
+}
+
+/**
+ return IP of the Nth interface
+ **/
+const char *iface_n_ip(struct interface *ifaces, int n)
+{
+ struct interface *i;
+
+ for (i=ifaces;i && n;i=i->next)
+ n--;
+
+ if (i) {
+ return i->ip_s;
+ }
+ return NULL;
+}
+
+/**
+ return bcast of the Nth interface
+ **/
+const char *iface_n_bcast(struct interface *ifaces, int n)
+{
+ struct interface *i;
+
+ for (i=ifaces;i && n;i=i->next)
+ n--;
+
+ if (i) {
+ return i->bcast_s;
+ }
+ return NULL;
+}
+
+/**
+ return netmask of the Nth interface
+ **/
+const char *iface_n_netmask(struct interface *ifaces, int n)
+{
+ struct interface *i;
+
+ for (i=ifaces;i && n;i=i->next)
+ n--;
+
+ if (i) {
+ return i->nmask_s;
+ }
+ return NULL;
+}
+
+/**
+ return the local IP address that best matches a destination IP, or
+ our first interface if none match
+*/
+const char *iface_best_ip(struct interface *ifaces, const char *dest)
+{
+ struct interface *iface;
+ struct in_addr ip;
+
+ ip.s_addr = interpret_addr(dest);
+ iface = iface_find(ifaces, ip, true);
+ if (iface) {
+ return iface->ip_s;
+ }
+ return iface_n_ip(ifaces, 0);
+}
+
+/**
+ return true if an IP is one one of our local networks
+*/
+bool iface_is_local(struct interface *ifaces, const char *dest)
+{
+ struct in_addr ip;
+
+ ip.s_addr = interpret_addr(dest);
+ if (iface_find(ifaces, ip, true)) {
+ return true;
+ }
+ return false;
+}
+
+/**
+ return true if a IP matches a IP/netmask pair
+*/
+bool iface_same_net(const char *ip1, const char *ip2, const char *netmask)
+{
+ return same_net_v4(interpret_addr2(ip1),
+ interpret_addr2(ip2),
+ interpret_addr2(netmask));
+}
Added: trunk/openchange/libmapi/socket/netif.c
===================================================================
--- trunk/openchange/libmapi/socket/netif.c (rev 0)
+++ trunk/openchange/libmapi/socket/netif.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,151 @@
+/*
+ Unix SMB/CIFS implementation.
+ return a list of network interfaces
+ Copyright (C) Andrew Tridgell 1998
+
+ 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/>.
+*/
+
+
+/* working out the interfaces for a OS is an incredibly non-portable
+ thing. We have several possible implementations below, and autoconf
+ tries each of them to see what works
+
+ Note that this file does _not_ include includes.h. That is so this code
+ can be called directly from the autoconf tests. That also means
+ this code cannot use any of the normal Samba debug stuff or defines.
+ This is standalone code.
+
+*/
+
+#include <libmapi/libmapi.h>
+
+#ifdef __COMPAR_FN_T
+#define QSORT_CAST (__compar_fn_t)
+#endif
+
+#ifndef QSORT_CAST
+#define QSORT_CAST (int (*)(const void *, const void *))
+#endif
+
+/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
+ V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2.
+
+ It probably also works on any BSD style system. */
+
+/****************************************************************************
+ get the netmask address for a local interface
+****************************************************************************/
+static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
+{
+ struct ifconf ifc;
+ struct ifreq *ifr=NULL;
+ struct in_addr ipaddr;
+ struct in_addr nmask;
+ struct sockaddr *sockaddr;
+ struct sockaddr_in *sockaddr_in;
+ char *iname;
+ char buff[8192];
+ int fd, i, n;
+ int total = 0;
+
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
+ return -1;
+ }
+
+ ifc.ifc_len = sizeof(buff);
+ ifc.ifc_buf = buff;
+
+ if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
+ close(fd);
+ return -1;
+ }
+
+ ifr = ifc.ifc_req;
+
+ n = ifc.ifc_len / sizeof(struct ifreq);
+
+ /* Loop through interfaces, looking for given IP address */
+ for (i=n-1;i>=0 && total < max_interfaces;i--) {
+ if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != 0) {
+ continue;
+ }
+
+ iname = ifr[i].ifr_name;
+ sockaddr = (struct sockaddr *) &ifr[i].ifr_addr;
+ sockaddr_in = (struct sockaddr_in *) sockaddr;
+ ipaddr = sockaddr_in->sin_addr;
+
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) {
+ continue;
+ }
+
+ if (!(ifr[i].ifr_flags & IFF_UP)) {
+ continue;
+ }
+
+ if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != 0) {
+ continue;
+ }
+
+ nmask = sockaddr_in->sin_addr;
+
+ strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1);
+ ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
+ ifaces[total].ip = ipaddr;
+ ifaces[total].netmask = nmask;
+ total++;
+ }
+
+ close(fd);
+
+ return total;
+}
+
+static int iface_comp(struct iface_struct *i1, struct iface_struct *i2)
+{
+ int r;
+ r = strcmp(i1->name, i2->name);
+ if (r) return r;
+ r = ntohl(i1->ip.s_addr) - ntohl(i2->ip.s_addr);
+ if (r) return r;
+ r = ntohl(i1->netmask.s_addr) - ntohl(i2->netmask.s_addr);
+ return r;
+}
+
+/* this wrapper is used to remove duplicates from the interface list generated
+ above */
+_PUBLIC_ int get_interfaces(struct iface_struct *ifaces, int max_interfaces)
+{
+ int total, i, j;
+
+ total = _get_interfaces(ifaces, max_interfaces);
+ if (total <= 0) return total;
+
+ /* now we need to remove duplicates */
+ qsort(ifaces, total, sizeof(ifaces[0]), QSORT_CAST iface_comp);
+
+ for (i=1;i<total;) {
+ if (iface_comp(&ifaces[i-1], &ifaces[i]) == 0) {
+ for (j=i-1;j<total-1;j++) {
+ ifaces[j] = ifaces[j+1];
+ }
+ total--;
+ } else {
+ i++;
+ }
+ }
+
+ return total;
+}
Added: trunk/openchange/libmapi/socket/netif.h
===================================================================
--- trunk/openchange/libmapi/socket/netif.h (rev 0)
+++ trunk/openchange/libmapi/socket/netif.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,38 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ structures for socke/netif.c and socket/interface.c
+
+ Copyright (C) Andrew Tridgell 2004
+
+ 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/>.
+*/
+
+/** used for network interfaces */
+struct interface {
+ struct interface *next, *prev;
+ struct in_addr ip;
+ struct in_addr nmask;
+ const char *ip_s;
+ const char *bcast_s;
+ const char *nmask_s;
+};
+
+struct iface_struct {
+ char name[16];
+ struct in_addr ip;
+ struct in_addr netmask;
+};
+
+#define MAX_INTERFACES 128
Added: trunk/openchange/libmapi/tests/locale.c
===================================================================
--- trunk/openchange/libmapi/tests/locale.c (rev 0)
+++ trunk/openchange/libmapi/tests/locale.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,103 @@
+/*
+ OpenChange MAPI implementation.
+ Codepages handled by Microsoft Exchange Server
+
+ Copyright (C) Julien Kerihuel 2005.
+
+ 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 <talloc.h>
+#include <popt.h>
+#include <util.h>
+
+/* command line options */
+static struct {
+ bool locale_id;
+ bool language_group;
+ bool group;
+} options;
+
+/*
+ print locales information given a locale_id
+*/
+
+static void process_one(const char *name)
+{
+ uint32_t value = 0;
+
+ if (options.group) {
+ printf("Language groups:\n");
+ print_group();
+ }
+
+ else if (options.locale_id) {
+ value = (uint32_t)strtol(name, NULL, 16);
+ if (print_locale(value) == False) {
+ DEBUG(0, ("Unknown locale id in the locale database (%s)\n", name));
+ }
+
+ }
+ else if (options.language_group) {
+ if ((value = strtol(name, NULL, 10)) == 0) {
+ if ((value = lang2nb(name)) == -1) {
+ DEBUG(0, ("Invalid language group provided (%s)\n", name));
+ exit (1);
+ }
+ }
+ DEBUG(3, ("value = %d\n", value));
+ print_groupmember(value);
+ }
+}
+
+int main(int argc, const char *argv[])
+{
+ poptContext pc;
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "locale_id", 'L', POPT_ARG_VAL, &options.locale_id,
+ 'L', "Display locale information for a given locale id", "LOCALE ID" },
+
+ { "language_group", 'G', POPT_ARG_VAL, &options.language_group,
+ 'G', "Display all languages for the specified language group", "LANGUAGE_GROUP" },
+
+ {"list_groups", 'l', POPT_ARG_NONE, &options.group,
+ True, "List existing language groups"},
+
+ { 0, 0, 0, 0 }
+ };
+
+ pc = poptGetContext("locale", argc, (const char **)argv, long_options,
+ POPT_CONTEXT_KEEP_FIRST);
+
+ while ((poptGetNextOpt(pc) != -1)) /* noop */;
+
+ /* swallow argv[0] */
+ poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintUsage(pc, stderr, 0);
+ exit (1);
+ }
+
+ while (poptPeekArg(pc)) {
+ const char *name = poptGetArg(pc);
+
+ process_one(name);
+ }
+
+ poptFreeContext(pc);
+
+ return 0;
+}
Added: trunk/openchange/libmapi/tests/locale_codepage.c
===================================================================
--- trunk/openchange/libmapi/tests/locale_codepage.c (rev 0)
+++ trunk/openchange/libmapi/tests/locale_codepage.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,107 @@
+/*
+ OpenChange MAPI implementation.
+ Codepages handled by Microsoft Exchange Server
+
+ Copyright (C) Julien Kerihuel 2005.
+
+ 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/proto_private.h>
+#include <samba/popt.h>
+
+/* command line options */
+static struct {
+ uint32_t locale_id;
+ char *language_group;
+ bool group;
+ uint32_t codepage;
+ char *language_info;
+} options;
+
+/*
+ print locales information given a locale_id
+*/
+
+static void process_one(const char *name)
+{
+ if (options.group) {
+ printf("Language groups:\n");
+ lcid_print_group();
+ }
+
+ if (options.locale_id) {
+ if (lcid_print_locale(options.locale_id) == false) {
+ DEBUG(0, ("Unknown locale id in the locale database (%s)\n", name));
+ }
+
+ }
+ if (options.language_group) {
+ if (lcid_print_groupmember(lcid_lang2nb(options.language_group)) == false) {
+ DEBUG(0, ("(%s)\n", name));
+ exit (1);
+ }
+ }
+
+ if (options.codepage) {
+ if (print_codepage_infos(options.codepage) == false) {
+ DEBUG(0, ("Invalid codepage (%s)\n", name));
+ exit (1);
+ }
+ }
+ if (options.language_info) {
+ printf("######### BEGIN: (copy and paste into smb.conf) #########\n");
+ if (lcid_get_locales(options.language_info) == false) {
+ DEBUG(0, ("Invalid language (%s)\n", name));
+ exit (1);
+ }
+ printf("######### END: (copy and paste into smb.conf) #########\n");
+ }
+}
+
+int main(int argc, const char *argv[])
+{
+ poptContext pc;
+ int opt;
+ enum{OPT_LOCALID=1,OPT_LANGROUPS,OPT_GROUPS,OPT_CP,OPT_LANGINFO};
+ struct poptOption popt_options[] = {
+ POPT_AUTOHELP
+ { "locale_id", 'L', POPT_ARG_STRING, &options.locale_id, OPT_LOCALID, "Display locale information for a given locale id", "LOCALE ID" },
+ { "language_group", 'G', POPT_ARG_STRING, &options.language_group,OPT_LANGROUPS, "Display all languages for the specified language group", "LANGUAGE_GROUP" },
+ {"list_groups", 'l', POPT_ARG_NONE, &options.group, OPT_GROUPS, "List existing language groups", NULL},
+ {"codepage", 'c', POPT_ARG_INT, &options.codepage, OPT_CP, "Check if CODEPAGE exists and display related information\n", "CODEPAGE"},
+ {"language_info", 'i', POPT_ARG_STRING, &options.language_info, OPT_LANGINFO, "Copy and Paste information into your smb.conf file\n", "LANGUAGE"},
+ POPT_TABLEEND
+ };
+
+ pc = poptGetContext(argv[0], argc, argv, popt_options,
+ POPT_CONTEXT_KEEP_FIRST);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_GROUPS:
+ process_one(NULL);
+ break;
+ case OPT_LOCALID:
+ case OPT_LANGROUPS:
+ case OPT_CP:
+ case OPT_LANGINFO:
+ process_one(poptGetOptArg(pc));
+ break;
+ }
+ }
+
+ return 0;
+}
Added: trunk/openchange/libmapi/utf8_convert.l
===================================================================
--- trunk/openchange/libmapi/utf8_convert.l (rev 0)
+++ trunk/openchange/libmapi/utf8_convert.l 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,379 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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/>.
+ */
+%option nounput
+%option noinput
+
+%{
+#include <stdlib.h>
+#include <string.h>
+
+int yylex(void);
+
+/*
+ * Prototypes
+ */
+
+int yyget_lineno(void);
+FILE *yyget_in(void);
+FILE *yyget_out(void);
+int yyget_leng(void);
+char *yyget_text(void);
+void yyset_lineno(int);
+void yyset_in (FILE *);
+void yyset_out (FILE *);
+int yyget_debug(void);
+void yyset_debug(int);
+int yylex_destroy(void);
+
+int yyreplace_utf8(char *);
+int yyparse_utf8(char *, char *);
+
+char *newbuf;
+int newbuf_idx;
+
+#define U00A1 "\xc2\xa1" /* ¡ */
+#define U00A2 "\xc2\xa2" /* ¢ */
+#define U00A3 "\xc2\xa3" /* £ */
+#define U00A4 "\xc2\xa4" /* ¤ */
+#define U00A5 "\xc2\xa5" /* ¥ */
+#define U00A6 "\xc2\xa6" /* ¦ */
+#define U00A7 "\xc2\xa7" /* § */
+#define U00A8 "\xc2\xa8" /* ¨ */
+#define U00A9 "\xc2\xa9" /* © */
+#define U00AA "\xc2\xaa" /* ª */
+#define U00AB "\xc2\xab" /* « */
+#define U00AC "\xc2\xac" /* ¬ */
+#define U00AD "\xc2\xad" /* Â */
+#define U00AE "\xc2\xae" /* ® */
+#define U00AF "\xc2\xaf" /* ¯ */
+#define U00B0 "\xc2\xb0" /* ° */
+#define U00B1 "\xc2\xb1" /* ± */
+#define U00B2 "\xc2\xb2" /* ² */
+#define U00B3 "\xc2\xb3" /* ³ */
+#define U00B4 "\xc2\xb4" /* ´ */
+#define U00B5 "\xc2\xb5" /* µ */
+#define U00B6 "\xc2\xb6" /* ¶ */
+#define U00B7 "\xc2\xb7" /* · */
+#define U00B8 "\xc2\xb8" /* ¸ */
+#define U00B9 "\xc2\xb9" /* ¹ */
+#define U00BA "\xc2\xba" /* º */
+#define U00BB "\xc2\xbb" /* » */
+#define U00BC "\xc2\xbc" /* ¼ */
+#define U00BD "\xc2\xbd" /* ½ */
+#define U00BE "\xc2\xbe" /* ¾ */
+#define U00BF "\xc2\xbf" /* ¿ */
+#define U00C0 "\xc3\x80" /* Ã */
+#define U00C1 "\xc3\x81" /* Ã */
+#define U00C2 "\xc3\x82" /* Ã */
+#define U00C3 "\xc3\x83" /* Ã */
+#define U00C4 "\xc3\x84" /* Ã */
+#define U00C5 "\xc3\x85" /* Ã
*/
+#define U00C6 "\xc3\x86" /* Ã */
+#define U00C7 "\xc3\x87" /* Ã */
+#define U00C8 "\xc3\x88" /* Ã */
+#define U00C9 "\xc3\x89" /* Ã */
+#define U00CA "\xc3\x8a" /* Ã */
+#define U00CB "\xc3\x8b" /* Ã */
+#define U00CC "\xc3\x8c" /* Ã */
+#define U00CD "\xc3\x8d" /* Ã */
+#define U00CE "\xc3\x8e" /* Ã */
+#define U00CF "\xc3\x8f" /* Ã */
+#define U00D0 "\xc3\x90" /* Ã */
+#define U00D1 "\xc3\x91" /* Ã */
+#define U00D2 "\xc3\x92" /* Ã */
+#define U00D3 "\xc3\x93" /* Ã */
+#define U00D4 "\xc3\x94" /* Ã */
+#define U00D5 "\xc3\x95" /* Ã */
+#define U00D6 "\xc3\x96" /* Ã */
+#define U00D7 "\xc3\x97" /* Ã */
+#define U00D8 "\xc3\x98" /* Ã */
+#define U00D9 "\xc3\x99" /* Ã */
+#define U00DA "\xc3\x9a" /* Ã */
+#define U00DB "\xc3\x9b" /* Ã */
+#define U00DC "\xc3\x9c" /* Ã */
+#define U00DD "\xc3\x9d" /* Ã */
+#define U00DE "\xc3\x9e" /* Ã */
+#define U00DF "\xc3\x9f" /* Ã */
+#define U00E0 "\xc3\xa0" /* Ã */
+#define U00E1 "\xc3\xa1" /* á */
+#define U00E2 "\xc3\xa2" /* â */
+#define U00E3 "\xc3\xa3" /* ã */
+#define U00E4 "\xc3\xa4" /* ä */
+#define U00E5 "\xc3\xa5" /* å */
+#define U00E6 "\xc3\xa6" /* æ */
+#define U00E7 "\xc3\xa7" /* ç */
+#define U00E8 "\xc3\xa8" /* è */
+#define U00E9 "\xc3\xa9" /* é */
+#define U00EA "\xc3\xaa" /* ê */
+#define U00EB "\xc3\xab" /* ë */
+#define U00EC "\xc3\xac" /* ì */
+#define U00ED "\xc3\xad" /* Ã */
+#define U00EE "\xc3\xae" /* î */
+#define U00EF "\xc3\xaf" /* ï */
+#define U00F0 "\xc3\xb0" /* ð */
+#define U00F1 "\xc3\xb1" /* ñ */
+#define U00F2 "\xc3\xb2" /* ò */
+#define U00F3 "\xc3\xb3" /* ó */
+#define U00F4 "\xc3\xb4" /* ô */
+#define U00F5 "\xc3\xb5" /* õ */
+#define U00F6 "\xc3\xb6" /* ö */
+#define U00F7 "\xc3\xb7" /* ÷ */
+#define U00F8 "\xc3\xb8" /* ø */
+#define U00F9 "\xc3\xb9" /* ù */
+#define U00FA "\xc3\xba" /* ú */
+#define U00FB "\xc3\xbb" /* û */
+#define U00FC "\xc3\xbc" /* ü */
+#define U00FD "\xc3\xbd" /* ý */
+#define U00FE "\xc3\xbe" /* þ */
+#define U00FF "\xc3\xbf" /* ÿ */
+
+%}
+
+chars [0-9A-za-z\_\'\.\"/\+\-=\{\}:]
+numbers ([0-9])+
+delim [" "\n\t\s]
+whitespace {delim}+
+words {chars}+
+
+WIN_U00A1 "\xc3\xad"
+WIN_U00A2 "\xc3\xb3"
+WIN_U00A3 "\xc3\xba"
+WIN_U00A4 "\xc3\xb1"
+WIN_U00A5 "\xc3\x91"
+WIN_U00A6 "\xc2\xaa"
+WIN_U00A7 "\xc2\xba"
+WIN_U00A8 "\xc2\xbf"
+WIN_U00A9 "\xc2\xae"
+WIN_U00AA "\xc2\xac"
+WIN_U00AB "\xc2\xbd"
+WIN_U00AC "\xc2\xbc"
+WIN_U00AD "\xc2\xa1"
+WIN_U00AE "\xc2\xab"
+WIN_U00AF "\xc2\xbb"
+WIN_U00B0 "\xe2\x96\x91"
+WIN_U00B1 "\xe2\x96\x92"
+WIN_U00B2 "\xe2\x96\x93"
+WIN_U00B3 "\xe2\x94\x82"
+WIN_U00B4 "\xe2\x94\xa4"
+WIN_U00B5 "\xc3\x81"
+WIN_U00B6 "\xc3\x82"
+WIN_U00B7 "\xc3\x80"
+WIN_U00B8 "\xc2\xa9"
+WIN_U00B9 "\xe2\x95\xa3"
+WIN_U00BA "\xe2\x95\x91"
+WIN_U00BB "\xe2\x95\x97"
+WIN_U00BC "\xe2\x95\x9d"
+WIN_U00BD "\xc2\xa2"
+WIN_U00BE "\xc2\xa5"
+WIN_U00BF "\xe2\x94\x90"
+WIN_U00C0 "\xe2\x94\x94"
+WIN_U00C1 "\xe2\x94\xb4"
+WIN_U00C2 "\xe2\x94\xac"
+WIN_U00C3 "\xe2\x94\x9c"
+WIN_U00C4 "\xe2\x94\x80"
+WIN_U00C5 "\xe2\x94\xbc"
+WIN_U00C6 "\xc3\xa3"
+WIN_U00C7 "\xc3\x83"
+WIN_U00C8 "\xe2\x95\x9a"
+WIN_U00C9 "\xe2\x95\x94"
+WIN_U00CA "\xe2\x95\xa9"
+WIN_U00CB "\xe2\x95\xa6"
+WIN_U00CC "\xe2\x95\xa0"
+WIN_U00CD "\xe2\x95\x90"
+WIN_U00CE "\xe2\x95\xac"
+WIN_U00CF "\xc2\xa4"
+WIN_U00D0 "\xc3\xb0"
+WIN_U00D1 "\xc3\x90"
+WIN_U00D2 "\xc3\x8a"
+WIN_U00D3 "\xc3\x8b"
+WIN_U00D4 "\xc3\x88"
+WIN_U00D5 "\xc4\xb1"
+WIN_U00D6 "\xc3\x8d"
+WIN_U00D7 "\xc3\x8e"
+WIN_U00D8 "\xc3\x8f"
+WIN_U00D9 "\xe2\x94\x98"
+WIN_U00DA "\xe2\x94\x8c"
+WIN_U00DB "\xe2\x96\x88"
+WIN_U00DC "\xe2\x96\x84"
+WIN_U00DD "\xc2\xa6"
+WIN_U00DE "\xc3\x8c"
+WIN_U00DF "\xe2\x96\x80"
+WIN_U00E0 "\xc3\x93"
+WIN_U00E1 "\xc3\x9f"
+WIN_U00E2 "\xc3\x94"
+WIN_U00E3 "\xc3\x92"
+WIN_U00E4 "\xc3\xb5"
+WIN_U00E5 "\xc3\x95"
+WIN_U00E6 "\xc2\xb5"
+WIN_U00E7 "\xc3\xbe"
+WIN_U00E8 "\xc3\x9e"
+WIN_U00E9 "\xc3\x9a"
+WIN_U00EA "\xc3\x9b"
+WIN_U00EB "\xc3\x99"
+WIN_U00EC "\xc3\xbd"
+WIN_U00ED "\xc3\x9d"
+WIN_U00EE "\xc2\xaf"
+WIN_U00EF "\xc2\xb4"
+WIN_U00F0 "\xc2\xad"
+WIN_U00F1 "\xc2\xb1"
+WIN_U00F2 "\xe2\x80\x97"
+WIN_U00F3 "\xc2\xbe"
+WIN_U00F4 "\xc2\xb6"
+WIN_U00F5 "\xc2\xa7"
+WIN_U00F6 "\xc3\xb7"
+WIN_U00F7 "\xc2\xb8"
+WIN_U00F8 "\xc2\xb0"
+WIN_U00F9 "\xc2\xa8"
+WIN_U00FA "\xc2\xb7"
+WIN_U00FB "\xc2\xb9"
+WIN_U00FC "\xc2\xb3"
+WIN_U00FD "\xc2\xb2"
+WIN_U00FE "\xe2\x96\xa0"
+WIN_U00FF "\xc2\xa0"
+
+
+%%
+{words} { yyreplace_utf8(yytext); }
+{delim} { yyreplace_utf8(yytext); }
+{whitespace} { yyreplace_utf8(yytext); }
+{WIN_U00A1} { yyreplace_utf8(U00A1);}
+{WIN_U00A2} { yyreplace_utf8(U00A2);}
+{WIN_U00A3} { yyreplace_utf8(U00A3);}
+{WIN_U00A4} { yyreplace_utf8(U00A4);}
+{WIN_U00A5} { yyreplace_utf8(U00A5);}
+{WIN_U00A6} { yyreplace_utf8(U00A6);}
+{WIN_U00A7} { yyreplace_utf8(U00A7);}
+{WIN_U00A8} { yyreplace_utf8(U00A8);}
+{WIN_U00A9} { yyreplace_utf8(U00A9);}
+{WIN_U00AA} { yyreplace_utf8(U00AA);}
+{WIN_U00AB} { yyreplace_utf8(U00AB);}
+{WIN_U00AC} { yyreplace_utf8(U00AC);}
+{WIN_U00AD} { yyreplace_utf8(U00AD);}
+{WIN_U00AE} { yyreplace_utf8(U00AE);}
+{WIN_U00AF} { yyreplace_utf8(U00AF);}
+{WIN_U00B0} { yyreplace_utf8(U00B0);}
+{WIN_U00B1} { yyreplace_utf8(U00B1);}
+{WIN_U00B2} { yyreplace_utf8(U00B2);}
+{WIN_U00B3} { yyreplace_utf8(U00B3);}
+{WIN_U00B4} { yyreplace_utf8(U00B4);}
+{WIN_U00B5} { yyreplace_utf8(U00B5);}
+{WIN_U00B6} { yyreplace_utf8(U00B6);}
+{WIN_U00B7} { yyreplace_utf8(U00B7);}
+{WIN_U00B8} { yyreplace_utf8(U00B8);}
+{WIN_U00B9} { yyreplace_utf8(U00B9);}
+{WIN_U00BA} { yyreplace_utf8(U00BA);}
+{WIN_U00BB} { yyreplace_utf8(U00BB);}
+{WIN_U00BC} { yyreplace_utf8(U00BC);}
+{WIN_U00BD} { yyreplace_utf8(U00BD);}
+{WIN_U00BE} { yyreplace_utf8(U00BE);}
+{WIN_U00BF} { yyreplace_utf8(U00BF);}
+{WIN_U00C0} { yyreplace_utf8(U00C0);}
+{WIN_U00C1} { yyreplace_utf8(U00C1);}
+{WIN_U00C2} { yyreplace_utf8(U00C2);}
+{WIN_U00C3} { yyreplace_utf8(U00C3);}
+{WIN_U00C4} { yyreplace_utf8(U00C4);}
+{WIN_U00C5} { yyreplace_utf8(U00C5);}
+{WIN_U00C6} { yyreplace_utf8(U00C6);}
+{WIN_U00C7} { yyreplace_utf8(U00C7);}
+{WIN_U00C8} { yyreplace_utf8(U00C8);}
+{WIN_U00C9} { yyreplace_utf8(U00C9);}
+{WIN_U00CA} { yyreplace_utf8(U00CA);}
+{WIN_U00CB} { yyreplace_utf8(U00CB);}
+{WIN_U00CC} { yyreplace_utf8(U00CC);}
+{WIN_U00CD} { yyreplace_utf8(U00CD);}
+{WIN_U00CE} { yyreplace_utf8(U00CE);}
+{WIN_U00CF} { yyreplace_utf8(U00CF);}
+{WIN_U00D0} { yyreplace_utf8(U00D0);}
+{WIN_U00D1} { yyreplace_utf8(U00D1);}
+{WIN_U00D2} { yyreplace_utf8(U00D2);}
+{WIN_U00D3} { yyreplace_utf8(U00D3);}
+{WIN_U00D4} { yyreplace_utf8(U00D4);}
+{WIN_U00D5} { yyreplace_utf8(U00D5);}
+{WIN_U00D6} { yyreplace_utf8(U00D6);}
+{WIN_U00D7} { yyreplace_utf8(U00D7);}
+{WIN_U00D8} { yyreplace_utf8(U00D8);}
+{WIN_U00D9} { yyreplace_utf8(U00D9);}
+{WIN_U00DA} { yyreplace_utf8(U00DA);}
+{WIN_U00DB} { yyreplace_utf8(U00DB);}
+{WIN_U00DC} { yyreplace_utf8(U00DC);}
+{WIN_U00DD} { yyreplace_utf8(U00DD);}
+{WIN_U00DE} { yyreplace_utf8(U00DE);}
+{WIN_U00DF} { yyreplace_utf8(U00DF);}
+{WIN_U00E0} { yyreplace_utf8(U00E0);}
+{WIN_U00E1} { yyreplace_utf8(U00E1);}
+{WIN_U00E2} { yyreplace_utf8(U00E2);}
+{WIN_U00E3} { yyreplace_utf8(U00E3);}
+{WIN_U00E4} { yyreplace_utf8(U00E4);}
+{WIN_U00E5} { yyreplace_utf8(U00E5);}
+{WIN_U00E6} { yyreplace_utf8(U00E6);}
+{WIN_U00E7} { yyreplace_utf8(U00E7);}
+{WIN_U00E8} { yyreplace_utf8(U00E8);}
+{WIN_U00E9} { yyreplace_utf8(U00E9);}
+{WIN_U00EA} { yyreplace_utf8(U00EA);}
+{WIN_U00EB} { yyreplace_utf8(U00EB);}
+{WIN_U00EC} { yyreplace_utf8(U00EC);}
+{WIN_U00ED} { yyreplace_utf8(U00ED);}
+{WIN_U00EE} { yyreplace_utf8(U00EE);}
+{WIN_U00EF} { yyreplace_utf8(U00EF);}
+{WIN_U00F0} { yyreplace_utf8(U00F0);}
+{WIN_U00F1} { yyreplace_utf8(U00F1);}
+{WIN_U00F2} { yyreplace_utf8(U00F2);}
+{WIN_U00F3} { yyreplace_utf8(U00F3);}
+{WIN_U00F4} { yyreplace_utf8(U00F4);}
+{WIN_U00F5} { yyreplace_utf8(U00F5);}
+{WIN_U00F6} { yyreplace_utf8(U00F6);}
+{WIN_U00F7} { yyreplace_utf8(U00F7);}
+{WIN_U00F8} { yyreplace_utf8(U00F8);}
+{WIN_U00F9} { yyreplace_utf8(U00F9);}
+{WIN_U00FA} { yyreplace_utf8(U00FA);}
+{WIN_U00FB} { yyreplace_utf8(U00FB);}
+{WIN_U00FC} { yyreplace_utf8(U00FC);}
+{WIN_U00FD} { yyreplace_utf8(U00FD);}
+{WIN_U00FE} { yyreplace_utf8(U00FE);}
+{WIN_U00FF} { yyreplace_utf8(U00FF);}
+
+%%
+
+#ifndef yywrap
+int
+yywrap(void)
+{
+ return 1;
+}
+#endif
+
+int
+yyreplace_utf8(char *str)
+{
+ memcpy(&newbuf[newbuf_idx], str, strlen(str));
+ newbuf_idx += strlen(str);
+ return 0;
+}
+
+int
+yyparse_utf8(char *mybuf, char *str)
+{
+ newbuf = mybuf;
+ newbuf_idx = 0;
+ yy_scan_string(str);
+ yylex();
+ newbuf[newbuf_idx] = 0;
+ libmapi_utf8_convert_lex_destroy();
+ return 0;
+}
Added: trunk/openchange/libmapi/util/codepage.c
===================================================================
--- trunk/openchange/libmapi/util/codepage.c (rev 0)
+++ trunk/openchange/libmapi/util/codepage.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,228 @@
+/*
+ OpenChange MAPI implementation.
+ Codepages handled by Microsoft Exchange Server
+
+ Copyright (C) Julien Kerihuel 2005.
+
+ 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/proto_private.h>
+
+#define CP_VAL "codepage"
+#define CP_NAME "codepage name"
+#define CP_DESC "codepage description"
+
+struct codepages
+{
+ const char *cp_name;
+ uint32_t cpid;
+ const char *cp_desc;
+};
+
+static struct codepages codepages[] =
+{
+ { "cpANSI", 0x0, "ANSI code page" },
+ { "cpOEM", 0x1, "OEM code page" },
+ { "cpMAC", 0x2, "Macintosh code page." },
+ { "cpebcdiccpus", 0x25, "IBM EBCDIC - U.S./Canada, IBM EBCDIC (US-Canada), Charset Label:ebcdic-cp-us" },
+ { "cpIBM437", 0x1B5, "OEM - United States, OEM United States, Charset Label:IBM437, Aliases:437, cp437, csPC8, CodePage437" },
+ { "cpIBMEBCDICInternational", 0x1F4, "IBM EBCDIC - International" },
+ { "cpASMO708", 0x2C4, "Arabic - ASMO 708, Arabic (ASMO 708), Charset Label:ASMO-708" },
+ { "cpArabicASMO449BCONV4", 0x2C5, "Arabic - ASMO 449+, BCON V4" },
+ { "cpArabicTransparentArabic", 0x2C6, "Arabic - Transparent Arabic" },
+ { "cpDOS720", 0x2D0, "Arabic - Transparent ASMO, Arabic (DOS), Charset Label:DOS-720" },
+ { "cpibm737", 0x2E1, "OEM - Greek (formerly 437G), Greek (DOS), Charset Label:ibm737" },
+ { "cpibm775", 0x307, "OEM - Baltic, Baltic (DOS), Charset Label:ibm775, Aliases:CP500" },
+ { "cpibm850", 0x352, "OEM - Multilingual Latin I, Western European (DOS), Charset Label:ibm850" },
+ { "cpibm852", 0x354, "OEM - Latin II, Central European (DOS), Charset Label:ibm852, Aliases:cp852" },
+ { "cpOEMCyrillicprimarilyRussian", 0x357, "OEM - Cyrillic (primarily Russian)" },
+ { "cpibm857", 0x359, "OEM - Turkish, Turkish (DOS), Charset Label:ibm857" },
+ { "cpOEMMultlingualLatinIEurosymbol", 0x35A, "OEM - Multlingual Latin I + Euro symbol" },
+ { "cpOEMPortuguese", 0x35C, "OEM - Portuguese" },
+ { "cpibm861", 0x35D, "OEM - Icelandic, Icelandic (DOS), Charset Label:ibm861" },
+ { "cpDOS862", 0x35E, "OEM - Hebrew, Hebrew (DOS), Charset Label:DOS-862" },
+ { "cpOEMCanadianFrench", 0x35F, "OEM - Canadian-French, " },
+ { "cpOEMArabic", 0x360, "OEM - Arabic, " },
+ { "cpOEMNordic", 0x361, "OEM - Nordic, " },
+ { "cpcp866", 0x362, "OEM - Russian, Cyrillic (DOS), Charset Label:cp866, Aliases:ibm866" },
+ { "cpibm869", 0x365, "OEM - Modern Greek, Greek, Modern (DOS), Charset Label:ibm869" },
+ { "cpCP870", 0x366, "IBM EBCDIC - Multilingual/ROECE (Latin-2), IBM EBCDIC (Multilingual Latin-2), Charset Label:CP870" },
+ { "cpwindows874", 0x36A, "ANSI/OEM - Thai (same as 28605, ISO 8859-15), Thai (Windows), Charset Label:windows-874, Aliases:DOS-874, iso-8859-11, TIS-620" },
+ { "cpxEBCDICGreekModern", 0x36B, "IBM EBCDIC - Modern Greek, IBM EBCDIC (Greek Modern), Charset Label:x-EBCDIC-GreekModern" },
+ { "cpshiftjis", 0x3A4, "ANSI/OEM - Japanese, Shift-JIS, Japanese (Shift-JIS), Charset Label:shift_jis, Aliases:csShiftJIS, csWindows31J, ms_Kanji, shift-jis, x-ms-cp932, x-sjis" },
+ { "cpgb2312", 0x3A8, "ANSI/OEM - Simplified Chinese (PRC, Singapore), Chinese Simplified (GB2312), Charset Label:gb2312, Aliases:chinese, CN-GB, csGB2312, csGB231280, csISO58GB231280, GB_2312-80, GB231280, GB2312-80, GBK, iso-ir-58" },
+ { "cpksc56011987", 0x3B5, "ANSI/OEM - Korean (Unified Hangeul Code), Korean, Charset Label:ks_c_5601-1987, Aliases:csKSC56011987, euc-kr, iso-ir-149, korean, ks_c_5601, ks_c_5601_1987, ks_c_5601-1989, KSC_5601, KSC5601" },
+ { "cpbig5", 0x3B6, "ANSI/OEM - Traditional Chinese (Taiwan; Hong Kong SAR, PRC), Chinese Traditional (Big5), Charset Label:big5, Aliases:cn-big5, csbig5, x-x-big5" },
+ { "cpCP1026", 0x402, "IBM EBCDIC - Turkish (Latin-5), IBM EBCDIC (Turkish Latin-5), Charset Label:CP1026" },
+ { "cpIBMEBCDICLatin1OpenSystem", 0x417, "IBM EBCDIC - Latin 1/Open System, " },
+ { "cpxebcdiccpuseuro", 0x474, "IBM EBCDIC - U.S./Canada (037 + Euro symbol), IBM EBCDIC (US-Canada-Euro), Charset Label:x-ebcdic-cp-us-euro" },
+ { "cpxebcdicgermanyeuro", 0x475, "IBM EBCDIC - Germany (20273 + Euro symbol), IBM EBCDIC (Germany-Euro), Charset Label:x-ebcdic-germany-euro" },
+ { "cpxebcdicdenmarknorwayeuro", 0x476, "IBM EBCDIC - Denmark/Norway (20277 + Euro symbol), IBM EBCDIC (Denmark-Norway-Euro), Charset Label:x-ebcdic-denmarknorway-euro" },
+ { "cpxebcdicfinlandswedeneuro", 0x477, "IBM EBCDIC - Finland/Sweden (20278 + Euro symbol), IBM EBCDIC (Finland-Sweden-Euro), Charset Label:x-ebcdic-finlandsweden-euro, Aliases:X-EBCDIC-France" },
+ { "cpxebcdicitalyeuro", 0x478, "IBM EBCDIC - Italy (20280 + Euro symbol), IBM EBCDIC (Italy-Euro), Charset Label:x-ebcdic-italy-euro" },
+ { "cpxebcdicspaineuro", 0x479, "IBM EBCDIC - Latin America/Spain (20284 + Euro symbol), IBM EBCDIC (Spain-Euro), Charset Label:x-ebcdic-spain-euro" },
+ { "cpxebcdicukeuro", 0x47A, "IBM EBCDIC - United Kingdom (20285 + Euro symbol), IBM EBCDIC (UK-Euro), Charset Label:x-ebcdic-uk-euro" },
+ { "cpxebcdicfranceeuro", 0x47B, "IBM EBCDIC - France (20297 + Euro symbol), IBM EBCDIC (France-Euro), Charset Label:x-ebcdic-france-euro" },
+ { "cpxebcdicinternationaleuro", 0x47C, "IBM EBCDIC - International (500 + Euro symbol), IBM EBCDIC (International-Euro), Charset Label:x-ebcdic-international-euro" },
+ { "cpxebcdicicelandiceuro", 0x47D, "IBM EBCDIC - Icelandic (20871 + Euro symbol), IBM EBCDIC (Icelandic-Euro), Charset Label:x-ebcdic-icelandic-euro" },
+ { "cpunicode", 0x4B0, "Unicode UCS-2 Little-Endian (BMP of ISO 10646), Unicode, Charset Label:unicode, Aliases:utf-16" },
+ { "cpunicodeFFFE", 0x4B1, "Unicode UCS-2 Big-Endian, Unicode (Big-Endian), Charset Label:unicodeFFFE" },
+ { "cpwindows1250", 0x4E2, "ANSI - Central European, Central European (Windows), Charset Label:windows-1250, Aliases:x-cp1250" },
+ { "cpwindows1251", 0x4E3, "ANSI - Cyrillic, Cyrillic (Windows), Charset Label:windows-1251, Aliases:x-cp1251" },
+ { "cpWindows1252", 0x4E4, "ANSI - Latin I, Western European (Windows), Charset Label:Windows-1252, Aliases:ANSI_X3.4-1968, ANSI_X3.4-1986, ascii, cp367, cp819, csASCII, IBM367, ibm819, ISO_646.irv:1991, iso_8859-1, iso_8859-1:1987, ISO646-US, iso8859-1, iso-8859-1, iso-ir-100, i..." },
+ { "cpwindows1253", 0x4E5, "ANSI - Greek, Greek (Windows), Charset Label:windows-1253" },
+ { "cpwindows1254", 0x4E6, "ANSI - Turkish, Turkish (Windows), Charset Label:windows-1254, Aliases:ISO_8859-9, ISO_8859-9:1989, iso-8859-9, iso-ir-148, latin5" },
+ { "cpwindows1255", 0x4E7, "ANSI - Hebrew, Hebrew (Windows), Charset Label:windows-1255, Aliases:ISO_8859-8-I, ISO-8859-8, visual" },
+ { "cpwindows1256", 0x4E8, "ANSI - Arabic, Arabic (Windows), Charset Label:windows-1256, Aliases:cp1256" },
+ { "cpwindows1257", 0x4E9, "ANSI - Baltic, Baltic (Windows), Charset Label:windows-1257" },
+ { "cpwindows1258", 0x4EA, "ANSI/OEM - Vietnamese, Vietnamese (Windows), Charset Label:windows-1258" },
+ { "cpJohab", 0x551, "Korean (Johab), Korean (Johab), Charset Label:Johab" },
+ { "cpmacintosh", 0x2710, "MAC - Roman, Western European (Mac), Charset Label:macintosh" },
+ { "cpxmacjapanese", 0x2711, "MAC - Japanese, Japanese (Mac), Charset Label:x-mac-japanese" },
+ { "cpxmacchinesetrad", 0x2712, "MAC - Traditional Chinese (Big5), Chinese Traditional (Mac), Charset Label:x-mac-chinesetrad" },
+ { "cpxmackorean", 0x2713, "MAC - Korean, Korean (Mac), Charset Label:x-mac-korean" },
+ { "cpxmacarabic", 0x2714, "MAC - Arabic, Arabic (Mac), Charset Label:x-mac-arabic" },
+ { "cpxmachebrew", 0x2715, "MAC - Hebrew, Hebrew (Mac), Charset Label:x-mac-hebrew" },
+ { "cpxmacgreek", 0x2716, "MAC - Greek I, Greek (Mac), Charset Label:x-mac-greek" },
+ { "cpxmaccyrillic", 0x2717, "MAC - Cyrillic, Cyrillic (Mac), Charset Label:x-mac-cyrillic" },
+ { "cpxmacchinesesimp", 0x2718, "MAC - Simplified Chinese (GB 2312), Chinese Simplified (Mac), Charset Label:x-mac-chinesesimp" },
+ { "cpMACRomania", 0x271A, "MAC - Romania, " },
+ { "cpMACUkraine", 0x2721, "MAC - Ukraine, " },
+ { "cpMACThai", 0x2725, "MAC - Thai, " },
+ { "cpxmacce", 0x272D, "MAC - Latin II, Central European (Mac), Charset Label:x-mac-ce" },
+ { "cpxmacicelandic", 0x275F, "MAC - Icelandic, Icelandic (Mac), Charset Label:x-mac-icelandic" },
+ { "cpxmacturkish", 0x2761, "MAC - Turkish, Turkish (Mac), Charset Label:x-mac-turkish" },
+ { "cpMACCroatia", 0x2762, "MAC - Croatia, " },
+ { "cpUnicodeUCS4LittleEndian", 0x2EE0, "Unicode UCS-4 Little-Endian, " },
+ { "cpUnicodeUCS4BigEndian", 0x2EE1, "Unicode UCS-4 Big-Endian, " },
+ { "cpxChineseCNS", 0x4E20, "CNS - Taiwan, Chinese Traditional (CNS), Charset Label:x-Chinese-CNS" },
+ { "cpTCATaiwan", 0x4E21, "TCA - Taiwan, " },
+ { "cpxChineseEten", 0x4E22, "Eten - Taiwan, Chinese Traditional (Eten), Charset Label:x-Chinese-Eten" },
+ { "cpIBM5550Taiwan", 0x4E23, "IBM5550 - Taiwan, " },
+ { "cpTeleTextTaiwan", 0x4E24, "TeleText - Taiwan, " },
+ { "cpWangTaiwan", 0x4E25, "Wang - Taiwan, " },
+ { "cpxIA5", 0x4E89, "IA5 IRV International Alphabet No. 5 (7-bit), Western European (IA5), Charset Label:x-IA5" },
+ { "cpxIA5German", 0x4E8A, "IA5 German (7-bit), German (IA5), Charset Label:x-IA5-German" },
+ { "cpxIA5Swedish", 0x4E8B, "IA5 Swedish (7-bit), Swedish (IA5), Charset Label:x-IA5-Swedish" },
+ { "cpxIA5Norwegian", 0x4E8C, "IA5 Norwegian (7-bit), Norwegian (IA5), Charset Label:x-IA5-Norwegian" },
+ { "cpusascii", 0x4E9F, "US-ASCII (7-bit), US-ASCII, Charset Label:us-ascii, Aliases:ANSI_X3.4-1968, ANSI_X3.4-1986, ascii, cp367, csASCII, IBM367, ISO_646.irv:1991, ISO646-US, iso-ir-6us" },
+ { "cpT61", 0x4F25, "T.61, " },
+ { "cpISO6937NonSpacingAccent", 0x4F2D, "ISO 6937 Non-Spacing Accent, " },
+ { "cpxEBCDICGermany", 0x4F31, "IBM EBCDIC - Germany, IBM EBCDIC (Germany), Charset Label:x-EBCDIC-Germany" },
+ { "cpxEBCDICDenmarkNorway", 0x4F35, "IBM EBCDIC - Denmark/Norway, IBM EBCDIC (Denmark-Norway), Charset Label:x-EBCDIC-DenmarkNorway" },
+ { "cpxEBCDICFinlandSweden", 0x4F36, "IBM EBCDIC - Finland/Sweden, IBM EBCDIC (Finland-Sweden), Charset Label:x-EBCDIC-FinlandSweden" },
+ { "cpxEBCDICItaly", 0x4F38, "IBM EBCDIC - Italy, IBM EBCDIC (Italy), Charset Label:x-EBCDIC-Italy" },
+ { "cpXEBCDICSpain", 0x4F3C, "IBM EBCDIC - Latin America/Spain, IBM EBCDIC (Spain), Charset Label:X-EBCDIC-Spain" },
+ { "cpxEBCDICUK", 0x4F3D, "IBM EBCDIC - United Kingdom, IBM EBCDIC (UK), Charset Label:x-EBCDIC-UK" },
+ { "cpxEBCDICJapaneseKatakana", 0x4F42, "IBM EBCDIC - Japanese Katakana Extended, IBM EBCDIC (Japanese katakana), Charset Label:x-EBCDIC-JapaneseKatakana" },
+ { "cpIBMEBCDICFrance", 0x4F49, "IBM EBCDIC - France, " },
+ { "cpxEBCDICArabic", 0x4FC4, "IBM EBCDIC - Arabic, IBM EBCDIC (Arabic), Charset Label:x-EBCDIC-Arabic" },
+ { "cpxEBCDICGreek", 0x4FC7, "IBM EBCDIC - Greek, IBM EBCDIC (Greek), Charset Label:x-EBCDIC-Greek" },
+ { "cpxEBCDICHebrew", 0x4FC8, "IBM EBCDIC - Hebrew, IBM EBCDIC (Hebrew), Charset Label:x-EBCDIC-Hebrew" },
+ { "cpxEBCDICKoreanExtended", 0x5161, "IBM EBCDIC - Korean Extended, IBM EBCDIC (Korean Extended), Charset Label:x-EBCDIC-KoreanExtended" },
+ { "cpxEBCDICThai", 0x5166, "IBM EBCDIC - Thai, IBM EBCDIC (Thai), Charset Label:x-EBCDIC-Thai" },
+ { "cpkoi8r", 0x5182, "Russian - KOI8-R, Cyrillic (KOI8-R), Charset Label:koi8-r, Aliases:csKOI8R, koi, koi8, koi8r" },
+ { "cpxEBCDICIcelandic", 0x5187, "IBM EBCDIC - Icelandic, IBM EBCDIC (Icelandic), Charset Label:x-EBCDIC-Icelandic" },
+ { "cpxEBCDICCyrillicRussian", 0x5190, "IBM EBCDIC - Cyrillic (Russian), IBM EBCDIC (Cyrillic Russian), Charset Label:x-EBCDIC-CyrillicRussian" },
+ { "cpxEBCDICTurkish", 0x51A9, "IBM EBCDIC - Turkish, IBM EBCDIC (Turkish), Charset Label:x-EBCDIC-Turkish" },
+ { "cpIBMEBCDICLatin1OpenSystem1047Eurosymbol", 0x51BC, "IBM EBCDIC - Latin-1/Open System (1047 + Euro symbol), " },
+ { "cpJISX0208199001211990", 0x51C4, "JIS X 0208-1990 & 0121-1990, " },
+ { "cpSimplifiedChineseGB2312", 0x51C8, "Simplified Chinese (GB2312), " },
+ { "cpxEBCDICCyrillicSerbianBulgarian", 0x5221, "IBM EBCDIC - Cyrillic (Serbian, Bulgarian), IBM EBCDIC (Cyrillic Serbian-Bulgarian), Charset Label:x-EBCDIC-CyrillicSerbianBulgarian" },
+ { "cpExtendedAlphaLowercase", 0x5223, "Extended Alpha Lowercase, " },
+ { "cpkoi8u", 0x556A, "Ukrainian (KOI8-U), Cyrillic (KOI8-U), Charset Label:koi8-u, Aliases:koi8-ru" },
+ { "cpiso88591", 0x6FAF, "ISO 8859-1 Latin I, Western European (ISO), Charset Label:iso-8859-1, Aliases:cp819, csISO, Latin1, ibm819, iso_8859-1, iso_8859-1:1987, iso8859-1, iso-ir-100, l1, latin1" },
+ { "cpiso88592", 0x6FB0, "ISO 8859-2 Central Europe, Central European (ISO), Charset Label:iso-8859-2, Aliases:csISOLatin2, iso_8859-2, iso_8859-2:1987, iso8859-2, iso-ir-101, l2, latin2" },
+ { "cpiso88593", 0x6FB1, "ISO 8859-3 Latin 3, Latin 3 (ISO), Charset Label:iso-8859-3, Aliases:csISO, Latin3, ISO_8859-3, ISO_8859-3:1988, iso-ir-109, l3, latin3" },
+ { "cpiso88594", 0x6FB2, "ISO 8859-4 Baltic, Baltic (ISO), Charset Label:iso-8859-4, Aliases:csISOLatin4, ISO_8859-4, ISO_8859-4:1988, iso-ir-110, l4, latin4" },
+ { "cpiso88595", 0x6FB3, "ISO 8859-5 Cyrillic, Cyrillic (ISO), Charset Label:iso-8859-5, Aliases:csISOLatin5, csISOLatinCyrillic, cyrillic, ISO_8859-5, ISO_8859-5:1988, iso-ir-144, l5" },
+ { "cpiso88596", 0x6FB4, "ISO 8859-6 Arabic, Arabic (ISO), Charset Label:iso-8859-6, Aliases:arabic, csISOLatinArabic, ECMA-114, ISO_8859-6, ISO_8859-6:1987, iso-ir-127" },
+ { "cpiso88597", 0x6FB5, "ISO 8859-7 Greek, Greek (ISO), Charset Label:iso-8859-7, Aliases:csISOLatinGreek, ECMA-118, ELOT_928, greek, greek8, ISO_8859-7, ISO_8859-7:1987, iso-ir-126" },
+ { "cpiso88598", 0x6FB6, "ISO 8859-8 Hebrew, Hebrew (ISO-Visual), Charset Label:iso-8859-8, Aliases:csISOLatinHebrew, hebrew, ISO_8859-8, ISO_8859-8:1988, ISO-8859-8, iso-ir-138, visual" },
+ { "cpiso88599", 0x6FB7, "ISO 8859-9 Latin 5, Turkish (ISO), Charset Label:iso-8859-9, Aliases:csISO, Latin5, ISO_8859-9, ISO_8859-9:1989, iso-ir-148, l5, latin5" },
+ { "cpiso885915", 0x6FBD, "ISO 8859-15 Latin 9, Latin 9 (ISO), Charset Label:iso-8859-15, Aliases:csISO, Latin9, ISO_8859-15, l9, latin9" },
+ { "cpxEuropa", 0x7149, "Europa 3, Europa, Charset Label:x-Europa" },
+ { "cpiso88598i", 0x96C6, "ISO 8859-8 Hebrew, Hebrew (ISO-Logical), Charset Label:iso-8859-8-i, Aliases:logical" },
+ { "cpiso2022jp", 0xC42C, "ISO 2022 Japanese with no halfwidth Katakana, Japanese (JIS), Charset Label:iso-2022-jp" },
+ { "cpcsISO2022JP", 0xC42D, "ISO 2022 Japanese with halfwidth Katakana, Japanese (JIS-Allow 1 byte Kana), Charset Label:csISO2022JP, Aliases:_iso-2022-jp" },
+ { "cpiso2022jp1", 0xC42E, "ISO 2022 Japanese JIS X 0201-1989, Japanese (JIS-Allow 1 byte Kana - SO/SI), Charset Label:iso-2022-jp-1, Aliases:_iso-2022-jp$SIO" },
+ { "cpiso2022kr", 0xC431, "ISO 2022 Korean, Korean (ISO), Charset Label:iso-2022-kr, Aliases:csISO2022KR" },
+ { "cpISO2022SimplifiedChinese", 0xC433, "ISO 2022 Simplified Chinese, " },
+ { "cpISO2022TraditionalChinese", 0xC435, "ISO 2022 Traditional Chinese, " },
+ { "cpxEBCDICJapaneseAndKana", 0xC6F2, "Japanese (Katakana) Extended, IBM EBCDIC (Japanese and Japanese Katakana), Charset Label:x-EBCDIC-JapaneseAndKana" },
+ { "cpxEBCDICJapaneseAndUSCanada", 0xC6F3, "US/Canada and Japanese, IBM EBCDIC (Japanese and US-Canada), Charset Label:x-EBCDIC-JapaneseAndUSCanada" },
+ { "cpxEBCDICKoreanAndKoreanExtended", 0xC6F5, "Korean Extended and Korean, IBM EBCDIC (Korean and Korean Extended), Charset Label:x-EBCDIC-KoreanAndKoreanExtended" },
+ { "cpxEBCDICSimplifiedChinese", 0xC6F7, "Simplified Chinese Extended and Simplified Chinese, IBM EBCDIC (Simplified Chinese), Charset Label:x-EBCDIC-SimplifiedChinese" },
+ { "cpSimplifiedChinese", 0xC6F8, "Simplified Chinese, " },
+ { "cpxEBCDICTraditionalChinese", 0xC6F9, "US/Canada and Traditional Chinese, IBM EBCDIC (Traditional Chinese), Charset Label:x-EBCDIC-TraditionalChinese" },
+ { "cpxEBCDICJapaneseAndJapaneseLatin", 0xC6FB, "Japanese (Latin) Extended and Japanese, IBM EBCDIC (Japanese and Japanese-Latin), Charset Label:x-EBCDIC-JapaneseAndJapaneseLatin" },
+ { "cpeucjp", 0xCADC, "EUC - Japanese, Japanese (EUC), Charset Label:euc-jp, Aliases:csEUCPkdFmtJapanese, Extended_UNIX_Code_Packed_Format_for_Japanese, x-euc, x-euc-jp" },
+ { "cpEUCCN", 0xCAE0, "EUC - Simplified Chinese, Chinese Simplified (EUC), Charset Label:EUC-CN, Aliases:x-euc-cn" },
+ { "cpeuckr", 0xCAED, "EUC - Korean, Korean (EUC), Charset Label:euc-kr, Aliases:csEUCKR" },
+ { "cpEUCTraditionalChinese", 0xCAEE, "EUC - Traditional Chinese, " },
+ { "cphzgb2312", 0xCEC8, "HZ-GB2312 Simplified Chinese, Chinese Simplified (HZ), Charset Label:hz-gb-2312" },
+ { "cpWindowsXPGB18030SimplifiedChinese4Byte", 0xD698, "Windows XP: GB18030 Simplified Chinese (4 Byte), " },
+ { "cpxisciide", 0xDEAA, "ISCII Devanagari, ISCII Devanagari, Charset Label:x-iscii-de" },
+ { "cpxisciibe", 0xDEAB, "ISCII Bengali, ISCII Bengali, Charset Label:x-iscii-be" },
+ { "cpxisciita", 0xDEAC, "ISCII Tamil, ISCII Tamil, Charset Label:x-iscii-ta" },
+ { "cpxisciite", 0xDEAD, "ISCII Telugu, ISCII Telugu, Charset Label:x-iscii-te" },
+ { "cpxisciias", 0xDEAE, "ISCII Assamese, ISCII Assamese, Charset Label:x-iscii-as" },
+ { "cpxisciior", 0xDEAF, "ISCII Oriya, ISCII Oriya, Charset Label:x-iscii-or" },
+ { "cpxisciika", 0xDEB0, "ISCII Kannada, ISCII Kannada, Charset Label:x-iscii-ka" },
+ { "cpxisciima", 0xDEB1, "ISCII Malayalam, ISCII Malayalam, Charset Label:x-iscii-ma" },
+ { "cpxisciigu", 0xDEB2, "ISCII Gujarati, ISCII Gujarathi, Charset Label:x-iscii-gu" },
+ { "cpxisciipa", 0xDEB3, "ISCII Punjabi, ISCII Panjabi, Charset Label:x-iscii-pa" },
+ { "cputf7", 0xFDE8, "Unicode UTF-7, Unicode (UTF-7), Charset Label:utf-7, Aliases:csUnicode11UTF7, unicode-1-1-utf-7, x-unicode-2-0-utf-7" },
+ { "cputf8", 0xFDE9, "Unicode UTF-8, Unicode (UTF-8), Charset Label:utf-8, Aliases:unicode-1-1-utf-8, unicode-2-0-utf-8, x-unicode-2-0-utf-8" },
+ {NULL, 0, NULL}
+};
+
+/*
+ Check for a valid codepage
+*/
+
+_PUBLIC_ bool valid_codepage(uint32_t cpid)
+{
+ uint32_t idx = 0;
+
+ while (codepages[idx].cp_name) {
+ if (codepages[idx].cpid == cpid) {
+ return true;
+ }
+ idx++;
+ }
+ return false;
+}
+
+bool print_codepage_infos(uint32_t cpid)
+{
+ uint32_t idx = 0;
+
+ if (valid_codepage(cpid) == false) {
+ return false;
+ }
+
+ while (codepages[idx].cp_name) {
+ if (codepages[idx].cpid == cpid) {
+ printf("\t%-25s: 0x%x\n", CP_VAL, cpid);
+ printf("\t%-25s: %s\n", CP_NAME, codepages[idx].cp_name);
+ printf("\t%-25s: %s\n", CP_DESC, codepages[idx].cp_desc);
+ return true;
+ }
+ idx++;
+ }
+ return false;
+}
Added: trunk/openchange/libmapi/util/lcid.c
===================================================================
--- trunk/openchange/libmapi/util/lcid.c (rev 0)
+++ trunk/openchange/libmapi/util/lcid.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,460 @@
+/*
+ OpenChange MAPI implementation.
+ Codepages handled by Microsoft Exchange Server
+
+ Copyright (C) Julien Kerihuel 2005.
+
+ 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/proto_private.h>
+
+#define CP_WESTERN_EUROPE_AND_US 1 /* 1 (Western Europe & US) */
+#define CP_CENTRAL_EUROPE 2 /* 2 (Central Europe) */
+#define CP_BALTIC 3 /* 3 (Baltic) */
+#define CP_GREEK 4 /* 4 (Greek) */
+#define CP_CYRILLIC 5 /* 5 (Cyrillic) */
+#define CP_TURKIC 6 /* 6 (Turkic) */
+#define CP_JAPENESE 7 /* 7 (Japanese) */
+#define CP_KOREAN 8 /* 8 (Korean) */
+#define CP_TRADITIONAL_CHINESE 9 /* 9 (Traditional Chinese) */
+#define CP_SIMPLIFIED_CHINESE 10 /* 10 (Simplified Chinese) */
+#define CP_THAI 11 /* 11 (Thai) */
+#define CP_HEBREW 12 /* 12 (Hebrew) */
+#define CP_ARABIC 13 /* 13 (Arabic) */
+#define CP_VIETNAMESE 14 /* 14 (Vietnamese) */
+#define CP_INDIC 15 /* 15 (Indic) */
+#define CP_GEORGIAN 16 /* 16 (Georgian) */
+#define CP_ARMENIAN 17 /* 17 (Armenian) */
+
+#define LANG_GROUP "language group"
+#define LOCALE_ID "locale id"
+#define INPUT_COMBINATIONS "input combinations"
+
+static const char *language_group[] =
+{
+ "CP_NONEXISTENT",
+ "CP_WESTERN_EUROPE_AND_US",
+ "CP_CENTRAL_EUROPE",
+ "CP_BALTIC",
+ "CP_GREEK",
+ "CP_CYRILLIC",
+ "CP_TURKIC",
+ "CP_JAPANESE",
+ "CP_KOREAN",
+ "CP_TRADITIONAL_CHINESE",
+ "CP_SIMPLIFIED_CHINESE",
+ "CP_THAI",
+ "CP_HEBREW",
+ "CP_ARABIC",
+ "CP_VIETNAMESE",
+ "CP_INDIC",
+ "CP_GEORGIAN",
+ "CP_ARMENIAN",
+ NULL
+};
+
+struct combination {
+ uint32_t lcid;
+ uint32_t input_locale;
+};
+
+struct locale_struct {
+ const char *locale_str;
+ uint32_t lcid;
+ const char *lang_tag; /* RFC4646 language tag */
+ int language_group;
+ struct combination combination[6];
+};
+
+/*
+Missing entries from this table (compared to MS-LCID v20081024:
+ - everything from 0x0001 to 0x0091
+ - 0x0417 =-> rm-CH
+ - 0x0428 =-> tg-Cyrl-TJ
+ - 0x042E =-> wen-DE
+ - 0x0430 to 0x0435 (*-ZA)
+ - 0x043A =-> mt-MT
+ - 0x043B =-> se-NO
+ - 0x0440 =-> ky-KG
+ - 0x0442 =-> tk-TM
+ - 0x0445 =-> bn-IN
+ - 0x0446 =-> pa-IN
+ - 0x0447 =-> gu-IN
+ - 0x0448 =-> or-IN
+ - 0x044A =-> te-IN
+ - 0x044B =-> kn-IN
+ - 0x044C =-> ml-IN
+ - 0x044D =-> as-IN
+ - 0x0450 =-> mn-MN
+ - 0x0451 =-> bo-CN
+ - 0x0452 =-> cy-GB
+ - 0x0453 =-> km-KH
+ - 0x0454 =-> lo-LA
+ - 0x0455 =-> my-MM
+ - 0x0456 =-> gl-ES
+ - everything between 0x0458 and 0x048D
+ - 0x0818 =-> ro-MO
+ - 0x0819 =-> ru-MO
+ - 0x0820 =-> ur-IN
+ - 0x082E =-> dsb-DE
+ - 0x083B =-> se-SE
+ - 0x083C =-> ga-IE
+ - 0x0845 =-> bn-BD
+ - 0x0846 =-> pa-PK
+ - 0x0850 =-> mn-Mong-CN
+ - 0x0851 =-> bo-BT
+ - 0x0859 =-> sd-PK
+ - 0x085D =-> iu-Latn-CA
+ - 0x085F =-> tzm-Latn-DZ
+ - 0x0861 =-> ne-IN
+ - 0x086B =-> quz-EC
+ - 0x0873 =-> ti-ET
+ - 0x0C3B =-> se-FI
+ - 0x0C5F =-> tmz-MA
+ - 0x0C6B =-> quz-PE
+ - 0x101A =-> hr-BA
+ - 0x103B =-> smj-NO
+ - 0x141A =-> bs-Latn-BA
+ - 0x143B =-> smj-SE
+ - 0x181A =-> sr-Latn-BA
+ - 0x183B =-> sma-NO
+ - 0x1C0C =-> fr-West Indies
+ - 0x1C1A =-> sr-Cyrl-BA
+ - 0x1C3B =-> sma-SE
+ - 0x200C =-> fr-RE
+ - 0x201A =-> bs-Cyrl->BA
+ - 0x203b =-> sms-FI
+ - 0x240c =-> fr-CG
+ - 0x243B =-> smn-FI
+ - 0x280C =-> fr-SN
+ - 0x2C0C =-> fr-CM
+ - 0x300C =-> fr-CI
+ - 0x340C =-> fr-ML
+ - 0x3809 =-> en-ID
+ - 0x380C =-> fr-MA
+ - 0x3C09 =-> en-HK
+ - 0x3C0C =-> fr-HT
+ - 0x4009 =-> en-IN
+ - 0x4409 =-> en-MY
+ - 0x4809 =-> en-SG
+ - everything from 0x540a to 0x7c68 (and after)
+*/
+static const struct locale_struct locales[] =
+{
+ { "Afrikaans", 0x436, "af-ZA", CP_WESTERN_EUROPE_AND_US, { {0x436, 0x409}, {0x409, 0x409}, {0, 0} } },
+ { "Albanian", 0x41c, "sq-AL", CP_CENTRAL_EUROPE, { {0x41c, 0x41c}, {0x409, 0x409}, {0, 0} } },
+ { "Arabic_Saudi_Arabia", 0x401, "ar-SA", CP_ARABIC, { {0x409, 0x409}, {0x401, 0x401}, {0, 0} } },
+ { "Arabic_Iraq", 0x801, "ar-IQ", CP_ARABIC, { {0x409, 0x409}, {0x801, 0x401}, {0, 0} } },
+ { "Arabic_Egypt", 0xc01, "ar-EG", CP_ARABIC, { {0x409, 0x409}, {0xc01, 0x401}, {0, 0} } },
+ { "Arabic_Libya ", 0x1001, "ar-LY", CP_ARABIC, { {0x40c, 0x40c}, {0x1001, 0x20401}, {0, 0} } },
+ { "Arabic_Algeria", 0x1401, "ar-DZ", CP_ARABIC, { {0x40c, 0x40c}, {0x1401, 0x20401}, {0, 0} } },
+ { "Arabic_Morocco", 0x1801, "ar-MA", CP_ARABIC, { {0x40c, 0x40c}, {0x1801, 0x20401}, {0, 0} } },
+ { "Arabic_Tunisia", 0x1c01, "ar-TN", CP_ARABIC, { {0x40c, 0x40c}, {0x1c01, 0x20401}, {0, 0} } },
+ { "Arabic_Oman", 0x2001, "ar-OM", CP_ARABIC, { {0x409, 0x409}, {0x2001, 0x401}, {0, 0} } },
+ { "Arabic_Yemen", 0x2401, "ar-YE", CP_ARABIC, { {0x409, 0x409}, {0x2401, 0x401}, {0, 0} } },
+ { "Arabic_Syria", 0x2801, "ar-SY", CP_ARABIC, { {0x409,0x409}, {0x2801, 0x401}, {0, 0} } },
+ { "Arabic_Jordan", 0x2c01, "ar-JO", CP_ARABIC, { {0x409, 0x409}, {0x2c01, 0x401}, {0, 0} } },
+ { "Arabic_Lebanon", 0x3001, "ar-LB", CP_ARABIC, { {0x409, 0x409}, {0x3001, 0x401}, {0, 0} } },
+ { "Arabic_Kuwait", 0x3401, "ar-KW", CP_ARABIC, { {0x409, 0x409}, {0x3401, 0x401}, {0, 0} } },
+ { "Arabic_UAE", 0x3801, "ar-AE", CP_ARABIC, { {0x409, 0x409}, {0x3801, 0x401}, {0, 0} } },
+ { "Arabic_Bahrain", 0x3c01, "ar-BH", CP_ARABIC, { {0x409, 0x409}, {0x3c01, 0x401}, {0, 0} } },
+ { "Arabic_Qatar", 0x4001, "ar-QA", CP_ARABIC, { {0x409, 0x409}, {0x4001, 0x401}, {0, 0} } },
+ { "Armenian", 0x42b, "hy-AM", CP_ARMENIAN, { {0x42b, 0x42b}, {0x409, 0x409}, {0x419,0x419}, {0, 0} } },
+ { "Azeri_Latin", 0x42c, "az-Latn-AZ", CP_TURKIC, { {0x42c, 0x42c}, {0x82c, 0x82c}, {0x419, 0x419}, {0, 0} } },
+ { "Azeri_Cyrillic", 0x82c, "az-Cyrl-AZ", CP_CYRILLIC, { {0x82c, 0x82c}, {0x42c, 0x42c}, {0x419, 0x419}, {0, 0} } },
+ { "Basque", 0x42d, "eu-ES", CP_WESTERN_EUROPE_AND_US, { {0x42d, 0x40a}, {0x409, 0x409}, {0, 0} } },
+ { "Belarusian", 0x423, "be-BY", CP_CYRILLIC, { {0x423, 0x423}, {0x409, 0x409}, {0x419, 0x419}, {0, 0} } },
+ { "Bulgarian", 0x402, "bg-BG", CP_CYRILLIC, { {0x402, 0x402}, {0x409, 0x409}, {0, 0} } },
+ { "Catalan", 0x403, "ca-ES", CP_WESTERN_EUROPE_AND_US, { {0x403, 0x40a}, {0x409, 0x409}, {0, 0} } },
+ { "Chinese_Taiwan", 0x404, "zh-TW", CP_TRADITIONAL_CHINESE, { {0x404, 0x404}, {0x404, 0xe0080404}, {0x404, 0xe0010404}, {0, 0} } },
+ { "Chinese_PRC", 0x804, "zh-CN", CP_SIMPLIFIED_CHINESE, { {0x804, 0x804}, {0x804, 0xe00e0804}, {0x804, 0xe0010804}, {0x804, 0xe0030804}, {0x804, 0xe0040804}, {0, 0} } },
+ { "Chinese_Hong_Kong", 0xc04, "zh-HK", CP_TRADITIONAL_CHINESE, { {0x409, 0x409}, {0xc04, 0xe0080404}, {0, 0} } },
+ { "Chinese_Singapore", 0x1004, "zh-SG", CP_SIMPLIFIED_CHINESE, { {0x409, 0x409}, {0x804, 0xe00e0804}, {0x804, 0xe0010804}, {0x804, 0xe0030804}, {0x804, 0xe0040804}, {0, 0} } },
+ { "Chinese_Macau", 0x1404, "zh-MO", CP_TRADITIONAL_CHINESE, { {0x409, 0x409}, {0x804, 0xe00e0804}, {0x404, 0xe0020404}, {0x404, 0xe0080404}, {0, 0} } },
+ { "Croatian", 0x41a, "hr-HR", CP_CENTRAL_EUROPE, { {0x41a, 0x41a}, {0x409, 0x409}, {0, 0} } },
+ { "Czech", 0x405, "cz-CZ", CP_CENTRAL_EUROPE, { {0x405, 0x405}, {0x409, 0x409}, {0, 0} } },
+ { "Danish", 0x406, "da-DK", CP_WESTERN_EUROPE_AND_US, { {0x406, 0x406}, {0x409, 0x409}, {0, 0} } },
+ { "Dutch_Standard", 0x413, "nl-NL", CP_WESTERN_EUROPE_AND_US, { {0x409, 0x20409}, {0x413, 0x413}, {0x409, 0x409}, {0, 0} } },
+ { "Dutch_Belgian", 0x813, "nl-BE", CP_WESTERN_EUROPE_AND_US, { {0x813, 0x813}, {0x409, 0x409}, {0, 0} } },
+ { "English_United_States", 0x409, "en-US", CP_WESTERN_EUROPE_AND_US, { {0x409, 0x409}, {0, 0} } },
+ { "English_United_Kingdom", 0x809, "en-GB", CP_WESTERN_EUROPE_AND_US, { {0x809, 0x809}, {0, 0} } },
+ { "English_Australia", 0xc09, "en-AU", CP_WESTERN_EUROPE_AND_US, { {0xc09, 0x409}, {0, 0} } },
+ { "English_Canada", 0x1009, "en-CA", CP_WESTERN_EUROPE_AND_US, { {0x1009, 0x409}, {0x1009, 0x11009}, {0x1009, 0x1009}, {0, 0} } },
+ { "English_New_Zealand", 0x1409, "en-NZ", CP_WESTERN_EUROPE_AND_US, { {0x1409, 0x409}, {0, 0} } },
+ { "English_Ireland", 0x1809, "en-IE", CP_WESTERN_EUROPE_AND_US, { {0x1809, 0x1809}, {0x1809, 0x11809}, {0, 0} } },
+ { "English_South_Africa", 0x1c09, "en-ZA", CP_WESTERN_EUROPE_AND_US, { {0x1c09, 0x409}, {0, 0} } },
+ { "English_Jamaica", 0x2009, "en-JM", CP_WESTERN_EUROPE_AND_US, { {0x2009, 0x409}, {0, 0} } },
+ { "English_Caribbean", 0x2409, "en-CB", CP_WESTERN_EUROPE_AND_US, { {0x2409, 0x409}, {0, 0} } },
+ { "English_Belize", 0x2809, "en-BZ", CP_WESTERN_EUROPE_AND_US, { {0x2809, 0x409}, {0, 0} } },
+ { "English_Trinidad", 0x2c09, "en-TT", CP_WESTERN_EUROPE_AND_US, { {0x2c09, 0x409}, {0, 0} } },
+ { "English_Zimbabwe", 0x3009, "en-ZW", CP_WESTERN_EUROPE_AND_US, { {0x3009, 0x409}, {0, 0} } },
+ { "English_Philippines", 0x3409, "en-PH", CP_WESTERN_EUROPE_AND_US, { {0x3409, 0x409}, {0, 0} } },
+ { "Estonian", 0x425, "et-EE", CP_BALTIC, { {0x425, 0x425}, {0, 0} } },
+ { "Faeroese", 0x438, "fo-FO", CP_WESTERN_EUROPE_AND_US, { {0x438, 0x406}, {0x409, 0x409}, {0, 0} } },
+ { "Farsi", 0x429, "fa-IR", CP_ARABIC, { {0x409, 0x409}, {0x429, 0x429}, {0x429, 0x401}, {0, 0} } },
+ { "Finnish", 0x40b, "fi-FI", CP_WESTERN_EUROPE_AND_US, { {0x40b, 0x40b}, {0x409, 0x409}, {0, 0} } },
+ { "French_Standard", 0x40c, "fr-FR", CP_WESTERN_EUROPE_AND_US, { {0x40c, 0x40c}, {0x409, 0x409}, {0, 0} } },
+ { "French_Belgian", 0x80c, "fr-BE", CP_WESTERN_EUROPE_AND_US, { {0x80c, 0x80c}, {0x409, 0x409}, {0, 0} } },
+ { "French_Canadian", 0xc0c, "fr-CA", CP_WESTERN_EUROPE_AND_US, { {0xc0c, 0x11009}, {0x409, 0x409}, {0, 0} } },
+ { "French_Swiss", 0x100c, "fr-CH", CP_WESTERN_EUROPE_AND_US, { {0x100c, 0x100c}, {0x409, 0x409}, {0, 0} } },
+ { "French_Luxembourg", 0x140c, "fr-LU", CP_WESTERN_EUROPE_AND_US, { {0x140c, 0x40c}, {0x409, 0x409}, {0, 0} } },
+ { "French_Monaco", 0x180c, "fr-MC", CP_WESTERN_EUROPE_AND_US, { {0x180c, 0x40c}, {0x409, 0x409}, {0, 0} } },
+ { "Georgian", 0x437, "ka-GE", CP_GEORGIAN, { {0x437, 0x437}, {0x409, 0x409}, {0x419, 0x419}, {0, 0} } },
+ { "German_Standard", 0x407, "de-DE", CP_WESTERN_EUROPE_AND_US, { {0x407, 0x407}, {0x409, 0x409}, {0, 0} } },
+ { "German_Swiss", 0x807, "de-CH", CP_WESTERN_EUROPE_AND_US, { {0x807, 0x807}, {0x409, 0x409}, {0, 0} } },
+ { "German_Austria", 0xc07, "de-AT", CP_WESTERN_EUROPE_AND_US, { {0xc07, 0x407}, {0x409, 0x409}, {0, 0} } },
+ { "German_Luxembourg", 0x1007, "de-LU", CP_WESTERN_EUROPE_AND_US, { {0x1007, 0x407}, {0x409, 0x409}, {0, 0} } },
+ { "German_Liechtenstein", 0x1407, "de-LI", CP_WESTERN_EUROPE_AND_US, { {0x1407, 0x407}, {0x409, 0x409}, {0, 0} } },
+ { "Greek", 0x408, "el-GR", CP_GREEK, { {0x409, 0x409}, {0x408, 0x408}, {0, 0} } },
+ { "Hebrew", 0x40d, "he-IL", CP_HEBREW, { {0x409, 0x409}, {0x40d, 0x40d}, {0, 0} } },
+ { "Hindi", 0x439, "hi-IN", CP_INDIC, { {0x409, 0x409}, {0x439, 0x10439}, {0x439, 0x439}, {0, 0} } },
+ { "Hungarian", 0x40e, "hu-HU", CP_CENTRAL_EUROPE, { {0x40e, 0x40e}, {0x409, 0x409}, {0, 0} } },
+ { "Icelandic", 0x40f, "is-IS", CP_WESTERN_EUROPE_AND_US, { {0x40f, 0x40f}, {0x409, 0x409}, {0, 0} } },
+ { "Indonesian", 0x421, "id-ID", CP_WESTERN_EUROPE_AND_US, { {0x421, 0x409}, {0x409, 0x409}, {0, 0} } },
+ { "Italian_Standard", 0x410, "it-IT", CP_WESTERN_EUROPE_AND_US, { {0x410, 0x410}, {0x409, 0x409}, {0, 0} } },
+ { "Italian_Swiss", 0x810, "it-CH", CP_WESTERN_EUROPE_AND_US, { {0x810, 0x410}, {0x409, 0x409}, {0, 0} } },
+ { "Japanese", 0x411, "ja-JP", CP_JAPENESE, { {0x411, 0xe0010411}, {0, 0} } },
+ { "Kazakh", 0x43f, "kk-KZ", CP_CYRILLIC, { {0x43f, 0x43f}, {0x409, 0x409}, {0x419, 0x419}, {0, 0} } },
+ { "Konkani", 0x457, "kok-IN", CP_INDIC, { {0x409, 0x409}, {0x457, 0x439}, {0, 0} } },
+ { "Korean", 0x412, "ko-KR", CP_KOREAN, { {0x412, 0xe0010412}, {0, 0} } },
+ { "Latvian", 0x426, "lv-LV", CP_BALTIC, { {0x426, 0x10426}, {0, 0} } },
+ { "Lithuanian", 0x427, "lt-LT", CP_BALTIC, { {0x427, 0x10427}, {0, 0} } },
+ { "Macedonian", 0x42f, "mk-MK", CP_CYRILLIC, { {0x42f, 0x42f}, {0x409, 0x409}, {0, 0} } },
+ { "Malay_Malaysia", 0x43e, "ms-MY", CP_WESTERN_EUROPE_AND_US, { {0x409, 0x409}, {0, 0} } },
+ { "Malay_Brunei_Darussalam", 0x83e, "ms-BN", CP_WESTERN_EUROPE_AND_US, { {0x409, 0x409}, {0, 0} } },
+ { "Marathi", 0x44e, "mr-IN", CP_INDIC, { {0x409, 0x409}, {0x44e, 0x44e}, {0x44e, 0x439}, {0, 0} } },
+ { "Norwegian_Bokmal", 0x414, "nb-NO", CP_WESTERN_EUROPE_AND_US, { {0x414, 0x414}, {0x409, 0x409}, {0, 0} } },
+ { "Norwegian_Nynorsk", 0x814, "nn-NO", CP_WESTERN_EUROPE_AND_US, { {0x814, 0x414}, {0x409, 0x409}, {0, 0} } },
+ { "Polish", 0x415, "pl-PL", CP_CENTRAL_EUROPE, { {0x415, 0x10415}, {0x415, 0x415}, {0x409, 0x409}, {0, 0} } },
+ { "Portuguese_Brazilian", 0x416, "pt-BR", CP_WESTERN_EUROPE_AND_US, { {0x416, 0x416}, {0x409, 0x409}, {0, 0} } },
+ { "Portuguese_Standard", 0x816, "pt-PT", CP_WESTERN_EUROPE_AND_US, { {0x816, 0x816}, {0x409, 0x409}, {0, 0} } },
+ { "Romanian", 0x418, "ro-RM", CP_CENTRAL_EUROPE, { {0x418, 0x418}, {0x409, 0x409}, {0, 0} } },
+ { "Russian", 0x419, "ru-RU", CP_CYRILLIC, { {0x419, 0x419}, {0x409, 0x409}, {0, 0} } },
+ { "Sanskrit", 0x44f, "sa-IN", CP_INDIC, { {0x409, 0x409}, {0x44f, 0x439}, {0, 0} } },
+ { "Serbian_Latin", 0x81a, "sr-Latn-CS", CP_CENTRAL_EUROPE, { {0x81a, 0x81a}, {0x409, 0x409}, {0, 0} } },
+ { "Serbian_Cyrillic", 0xc1a, "sr-Cyrl-CS", CP_CYRILLIC, { {0xc1a, 0xc1a}, {0x409, 0x409}, {0, 0} } },
+ { "Slovak", 0x41b, "sk-SK", CP_CENTRAL_EUROPE, { {0x41b, 0x41b}, {0x409, 0x409}, {0, 0}, {0, 0} } },
+ { "Slovenian", 0x424, "sl-SI", CP_CENTRAL_EUROPE, { {0x424, 0x424}, {0x409, 0x409}, {0, 0}, {0, 0} } },
+ { "Spanish_Traditional_Sort", 0x40a, "es-ES_tradnl", CP_WESTERN_EUROPE_AND_US, { {0x40a, 0x40a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Mexican", 0x80a, "es-MX", CP_WESTERN_EUROPE_AND_US, { {0x80a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Modern_Sort", 0xc0a, "es-ES", CP_WESTERN_EUROPE_AND_US, { {0xc0a, 0x40a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Guatemala", 0x100a, "es-GT", CP_WESTERN_EUROPE_AND_US, { {0x100a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Costa_Rica", 0x140a, "es-CR", CP_WESTERN_EUROPE_AND_US, { {0x140a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Panama", 0x180a, "es-PA", CP_WESTERN_EUROPE_AND_US, { {0x180a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Dominican_Republic", 0x1c0a, "es-DO", CP_WESTERN_EUROPE_AND_US, { {0x1c0a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Venezuela", 0x200a, "es-VE", CP_WESTERN_EUROPE_AND_US, { {0x200a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Colombia", 0x240a, "es-CO", CP_WESTERN_EUROPE_AND_US, { {0x240a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Peru", 0x280a, "es-PE", CP_WESTERN_EUROPE_AND_US, { {0x280a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Argentina", 0x2c0a, "es-AR", CP_WESTERN_EUROPE_AND_US, { {0x2c0a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Ecuador", 0x300a, "es-EC", CP_WESTERN_EUROPE_AND_US, { {0x300a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Chile", 0x340a, "es-CL", CP_WESTERN_EUROPE_AND_US, { {0x340a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Uruguay", 0x380a, "es-UY",CP_WESTERN_EUROPE_AND_US, { {0x380a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Paraguay", 0x3c0a, "es-PY", CP_WESTERN_EUROPE_AND_US, { {0x3c0a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Bolivia", 0x400a, "es-BO", CP_WESTERN_EUROPE_AND_US, { {0x400a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_El_Salvador", 0x440a, "es-SV", CP_WESTERN_EUROPE_AND_US, { {0x440a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Honduras", 0x480a, "es-HN", CP_WESTERN_EUROPE_AND_US, { {0x480a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Nicaragua", 0x4c0a, "es-NI", CP_WESTERN_EUROPE_AND_US, { {0x4c0a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Spanish_Puerto_Rico", 0x500a, "es-PR", CP_WESTERN_EUROPE_AND_US, { {0x500a, 0x80a}, {0x409, 0x409}, {0, 0} } },
+ { "Swahili", 0x441, "sw-KE", CP_WESTERN_EUROPE_AND_US, { {0x409, 0x409}, {0, 0} } },
+ { "Swedish", 0x41d, "sv-SE", CP_WESTERN_EUROPE_AND_US, { {0x41d, 0x41d}, {0x409, 0x409}, {0, 0} } },
+ { "Swedish_Finland", 0x81d, "sv-FI", CP_WESTERN_EUROPE_AND_US, { {0x81d, 0x41d}, {0x409, 0x409}, {0, 0} } },
+ { "Tamil", 0x449, "ta-IN", CP_INDIC, { {0x409, 0x409}, {0x449, 0x449}, {0, 0} } },
+ { "Tatar", 0x444, "tt-RU", CP_CYRILLIC, { {0x444, 0x444}, {0x409, 0x409}, {0x419, 0x419}, {0, 0} } },
+ { "Thai", 0x41e, "th-TH", CP_THAI, { {0x409, 0x409}, {0x41e, 0x41e}, {0, 0} } },
+ { "Turkish", 0x41f, "tr-TR", CP_TURKIC, { {0x41f, 0x41f}, {0x409, 0x41f}, {0, 0} } },
+ { "Ukrainian", 0x422, "uk-UA", CP_CYRILLIC, { {0x422, 0x422}, {0x409, 0x409}, {0, 0} } },
+ { "Urdu", 0x420, "ur-PK", CP_ARABIC, { {0x420, 0x401}, {0x409, 0x409}, {0, 0} } },
+ { "Uzbek_Latin", 0x443, "uz-Latn-UZ", CP_TURKIC, { {0x443, 0x409}, {0x843, 0x843}, {0x419, 0x419}, {0, 0} } },
+ { "Uzbek_Cyrillic", 0x843, "uz-Cyrl-UZ", CP_CYRILLIC, { {0x843, 0x843}, {0x443, 0x409}, {0x419, 0x419}, {0, 0} } },
+ { "Vietnamese", 0x42a, "vi-VN", CP_VIETNAMESE, { {0x409, 0x409}, {0x42a, 0x42a}, {0, 0} } },
+ { NULL, 0, NULL, 0, { { 0, 0 } } }
+};
+
+/*
+ Print locale_id information for a given Language
+*/
+
+_PUBLIC_ bool lcid_get_locales(const char *lang)
+{
+ int idx = 0;
+
+ if (!lang) {
+ return false;
+ }
+
+ while (locales[idx].locale_str != NULL) {
+ if (!strcmp(lang, locales[idx].locale_str)) {
+ DEBUG(0, ("locale:language = 0x%x\n", locales[idx].lcid));
+ /* Fix me */
+ DEBUG(0, ("locale:method = 0x%x\n", locales[idx].combination[1].lcid));
+ return true;
+ }
+ idx++;
+ }
+ return false;
+}
+
+/*
+ Check if the locale provided exists
+*/
+
+_PUBLIC_ bool lcid_valid_locale(uint32_t locale)
+{
+ int idx = 0;
+
+ while (locales[idx].locale_str != NULL) {
+ if (locales[idx].lcid == locale)
+ return true;
+ idx++;
+ }
+ return false;
+}
+
+/*
+ Find the short language code for a given language code
+*/
+
+_PUBLIC_ const char *lcid_langcode2langtag(uint32_t langcode)
+{
+ int idx = 0;
+
+ while (locales[idx].locale_str != NULL) {
+ if (locales[idx].lcid == langcode)
+ return locales[idx].lang_tag;
+ idx++;
+ }
+ return NULL;
+}
+
+/*
+ Print locale information for a given locale id
+ */
+
+_PUBLIC_ bool lcid_print_locale(uint32_t locale)
+{
+ int idx = 0;
+ int i = 0;
+
+ while (locales[idx].locale_str != NULL) {
+ if (locales[idx].lcid == locale) {
+ printf("%s:\n", locales[idx].locale_str);
+ printf("\t%-25s: %s\n", LANG_GROUP, language_group[locales[idx].language_group]);
+ printf("\t%-25s: 0x%x\n", LOCALE_ID, locales[idx].lcid);
+ printf("\t%-25s:\n", INPUT_COMBINATIONS);
+ for (i = 0; locales[idx].combination[i].lcid != 0; i++) {
+ printf("\t\t\t\t 0x%x:0x%x\n",
+ locales[idx].combination[i].lcid,
+ locales[idx].combination[i].input_locale);
+ }
+ return true;
+ }
+ idx++;
+ }
+ return false;
+}
+
+/*
+ Print all languages
+*/
+_PUBLIC_ void lcid_print_languages(void)
+{
+ int idx = 0;
+
+ while (locales[idx].locale_str != NULL) {
+ printf("\t%s\n", locales[idx].locale_str);
+ idx++;
+ }
+}
+
+/*
+ Convert language name (as a string) to an integer language code
+ */
+
+_PUBLIC_ uint32_t lcid_lang2lcid(const char *name)
+{
+ int idx = 0;
+
+ if (!name) {
+ return 0xFFFFFFFF;
+ }
+
+ while (locales[idx].locale_str != NULL) {
+ if (strncasecmp(locales[idx].locale_str, name, strlen(name)) == 0) {
+ // we found a match
+ return locales[idx].lcid;
+ }
+ idx++;
+ }
+ return 0xFFFFFFFF;
+}
+
+/*
+ Print language groups
+ */
+
+_PUBLIC_ void lcid_print_group(void)
+{
+ int idx = 1;
+
+ while (language_group[idx]) {
+ printf("\t\t%s\n", language_group[idx]);
+ idx++;
+ }
+}
+
+/*
+ Print languages associated to a single language group
+ */
+
+_PUBLIC_ bool lcid_print_groupmember(int group)
+{
+ uint32_t idx = 0;
+
+ if (group == -1) {
+ DEBUG(0, ("Invalid language group "));
+ return false;
+ }
+
+ DEBUG(0, ("%s:\n", language_group[group]));
+
+ for (idx = 0; locales[idx].locale_str != NULL; idx++) {
+ if (locales[idx].language_group == group) {
+ printf("\t\t\t%s\n", locales[idx].locale_str);
+ }
+ }
+ return true;
+}
+
+/*
+ Convert language group from string to integer
+ */
+
+_PUBLIC_ int lcid_lang2nb(const char *name)
+{
+ int idx = 0;
+
+ if (!name) {
+ return -1;
+ }
+
+ while (language_group[idx]) {
+ if (!strcmp(language_group[idx], name)) {
+ return idx++;
+ }
+ idx++;
+ }
+ return -1;
+}
Added: trunk/openchange/libmapi/utils.c
===================================================================
--- trunk/openchange/libmapi/utils.c (rev 0)
+++ trunk/openchange/libmapi/utils.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,156 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Julien Kerihuel 2005 - 2006.
+
+ 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/proto_private.h>
+#include <gen_ndr/ndr_exchange.h>
+
+/*
+ Constructs a PR_ENTRYID value for recipients.
+ */
+
+/*
+ FIXME:
+ nor 0x00 0x00 0x00 0x00 at the beginning
+ neither 0x2f at the end should be listed
+*/
+static const uint8_t MAPI_LOCAL_UID[] = {
+ 0xdc, 0xa7, 0x40, 0xc8, 0xc0, 0x42, 0x10, 0x1a,
+ 0xb4, 0xb9, 0x08, 0x00, 0x2b, 0x2f, 0xe1, 0x82
+};
+
+static const uint8_t MAPI_LOCAL_UID_END[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x2f
+};
+
+_PUBLIC_ char *guid_delete_dash(TALLOC_CTX *mem_ctx, const char *recipient_id)
+{
+ char *guid;
+ uint32_t count,i;
+
+ if (!recipient_id) {
+ return NULL;
+ }
+
+ for (count=0,i=0;i!=strlen(recipient_id);i++) {
+ if (recipient_id[i] != '-') count++;
+ }
+
+ guid = talloc_zero_size(mem_ctx, count+1);
+ for (count=0,i = 0;i!=strlen(recipient_id);i++) {
+ if (recipient_id[i] != '-') {
+ guid[count] = recipient_id[i];
+ count++;
+ }
+ }
+
+ return guid;
+}
+
+_PUBLIC_ struct Binary_r *generate_recipient_entryid(TALLOC_CTX *mem_ctx, const char *recipient_id)
+{
+ struct Binary_r *entryid;
+ uint32_t off;
+ char *guid = (char *) NULL;
+
+ entryid = talloc(mem_ctx, struct Binary_r);
+ entryid->cb = sizeof (uint32_t) + sizeof (MAPI_LOCAL_UID) + sizeof (MAPI_LOCAL_UID_END) + 1;
+
+ if (recipient_id) {
+ guid = guid_delete_dash(mem_ctx, recipient_id);
+ entryid->cb += strlen(guid);
+ }
+
+ entryid->lpb = talloc_zero_size(mem_ctx, entryid->cb);
+ off = 4;
+ memcpy(entryid->lpb + off, MAPI_LOCAL_UID, sizeof (MAPI_LOCAL_UID));
+ off += sizeof (MAPI_LOCAL_UID);
+
+ memcpy(entryid->lpb + off, MAPI_LOCAL_UID_END, sizeof (MAPI_LOCAL_UID_END));
+ off += sizeof (MAPI_LOCAL_UID_END);
+
+ if (recipient_id) {
+ strcpy((char *)entryid->lpb + off, guid);
+ off += strlen(recipient_id);
+ }
+
+ return entryid;
+}
+
+/**
+ * convert utf8 windows string into classic utf8
+ * NOTE: windows utf8 encoding is equal or larger to classic utf8
+ * we should anyway find a better way to allocate the output buf
+ */
+
+int yyparse_utf8(char *, const char *);
+
+_PUBLIC_ char *windows_to_utf8(TALLOC_CTX *mem_ctx, const char *input)
+{
+ char *tmp = NULL;
+ char *output;
+
+ if (!input) return NULL;
+
+ tmp = malloc(strlen(input) + 1);
+ yyparse_utf8(tmp, input);
+ output = talloc_strdup(mem_ctx, tmp);
+ free(tmp);
+
+ return output;
+}
+
+
+/**
+ \details Create a FID from an EntryID
+
+ \param cb count of lpb bytes
+ \param lpb pointer on an array of bytes
+ \param parent_fid the parent folder identifier
+ \param pointer on the returned fid
+
+ \return MAPI_E_SUCCESS on success, otherwise
+ MAPI_E_INVALID_PARAMETER
+ */
+_PUBLIC_ enum MAPISTATUS GetFIDFromEntryID(uint16_t cb,
+ uint8_t *lpb,
+ uint64_t parent_fid,
+ uint64_t *fid)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!lpb, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!fid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(cb < 8, MAPI_E_INVALID_PARAMETER, NULL);
+
+ *fid = 0;
+ *fid += ((uint64_t)lpb[cb - 3] << 56);
+ *fid += ((uint64_t)lpb[cb - 4] << 48);
+ *fid += ((uint64_t)lpb[cb - 5] << 40);
+ *fid += ((uint64_t)lpb[cb - 6] << 32);
+ *fid += ((uint64_t)lpb[cb - 7] << 24);
+ *fid += ((uint64_t)lpb[cb - 8] << 16);
+ /* WARNING: for some unknown reason the latest byte of folder
+ ID may change (0x1 or 0x4 values identified so far).
+ However this byte sounds the same than the parent folder
+ one */
+ *fid += (parent_fid & 0xFF);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapi/x500.c
===================================================================
--- trunk/openchange/libmapi/x500.c (rev 0)
+++ trunk/openchange/libmapi/x500.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,80 @@
+/*
+ OpenChange NSPI implementation.
+
+ Copyright (C) Julien Kerihuel 2005 - 2006.
+
+ 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>
+
+
+/**
+ \details Extract a DN element from a given DN
+
+ \param mem_ctx pointer to the memory context
+ \param dn pointer to a valid DN
+ \param element pointer to the substring where extraction should start
+
+ \return pointer to an allocated substring on success, otherwise NULL
+ */
+_PUBLIC_ char *x500_get_dn_element(TALLOC_CTX *mem_ctx, const char *dn, const char *element)
+{
+ char *pdn, *p, *str;
+ char *tmp_dn;
+
+ if ((dn == NULL) || (dn[0] == '\0') || !element) return NULL;
+
+ tmp_dn = talloc_strdup(mem_ctx, dn);
+ pdn = strcasestr((const char *)tmp_dn, element);
+ if (pdn == NULL) {
+ talloc_free(tmp_dn);
+ return NULL;
+ }
+
+ pdn += strlen(element);
+ p = pdn;
+
+ if ((p = strchr(pdn, '/')) != NULL) {
+ p[0] = '\0';
+ }
+
+ str = talloc_strdup(mem_ctx, pdn);
+
+ talloc_free(tmp_dn);
+ return str;
+}
+
+/**
+ * Retrieve the servername from a string
+ * We should definitively find a better way to handle this
+ */
+
+_PUBLIC_ char *x500_get_servername(const char *dn)
+{
+ char *pdn;
+ char *servername;
+
+ if (!dn) {
+ return NULL;
+ }
+
+ pdn = strcasestr(dn, SERVERNAME);
+ if (pdn == NULL) return NULL;
+
+ pdn += strlen(SERVERNAME);
+ servername = strsep(&pdn, "/");
+
+ return (servername);
+}
Added: trunk/openchange/libmapi++/Doxyfile.in
===================================================================
--- trunk/openchange/libmapi++/Doxyfile.in (rev 0)
+++ trunk/openchange/libmapi++/Doxyfile.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1257 @@
+# Doxyfile 1.5.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = MAPI C++ Client Library Bindings
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = apidocs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = libmapi++
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.h *.doxy
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = libmapi++/tests libmapi++/examples
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = doc/doxygen/pictures/
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html/libmapi++
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER = doc/doxygen/header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = doc/doxygen/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET = doc/doxygen/apidocs.css
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = _PUBLIC_
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen will always
+# show the root nodes and its direct children regardless of this setting.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
Added: trunk/openchange/libmapi++/attachment.h
===================================================================
--- trunk/openchange/libmapi++/attachment.h (rev 0)
+++ trunk/openchange/libmapi++/attachment.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,157 @@
+/*
+ libmapi C++ Wrapper
+ Attachment Class
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 LIBMAPIPP__ATTACHMENT_H__
+#define LIBMAPIPP__ATTACHMENT_H__
+
+#include <iostream> //for debugging
+#include <string>
+
+#include <libmapi++/clibmapi.h>
+#include <libmapi++/message.h>
+
+namespace libmapipp
+{
+class object;
+
+/**
+ * \brief This class represents a message %attachment
+ *
+ * A message can contain both text content, and also have attached
+ * (embedded) files and messages. This class represents the attachments
+ * for one messaage.
+ *
+ * You may not need to create the attachments yourself, since you can
+ * create a container with all the attachments using message::fetch_attachments().
+ */
+class attachment : public object {
+ public:
+ /** \brief Constructor
+ *
+ * \param mapi_message the message that this attachment belongs to.
+ * \param attach_num Attachment Number.
+ */
+ attachment(message& mapi_message, const uint32_t attach_num) throw(mapi_exception)
+ : object(mapi_message.get_session(), "attachment"), m_attach_num(attach_num), m_bin_data(NULL), m_data_size(0), m_filename("")
+ {
+ if (OpenAttach(&mapi_message.data(), attach_num, &m_object) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "attachment::attachment : OpenAttach");
+
+ property_container properties = get_property_container();
+ properties << PR_ATTACH_FILENAME << PR_ATTACH_LONG_FILENAME << PR_ATTACH_SIZE << PR_ATTACH_DATA_BIN << PR_ATTACH_METHOD;
+ properties.fetch();
+
+ const char* filename = static_cast<const char*>(properties[PR_ATTACH_LONG_FILENAME]);
+ if (!filename) {
+ filename = static_cast<const char*>(properties[PR_ATTACH_FILENAME]);
+ }
+
+ if (filename) {
+ m_filename = filename;
+ }
+
+ m_data_size = *(static_cast<const uint32_t*>(properties[PR_ATTACH_SIZE]));
+
+ const Binary_r* attachment_data = static_cast<const Binary_r*>(properties[PR_ATTACH_DATA_BIN]);
+
+ // Don't load PR_ATTACH_DATA_BIN if it's embedded in message.
+ // NOTE: Use RopOpenEmbeddedMessage when it is implemented.
+ const uint32_t attach_method = *static_cast<const uint32_t*>(properties[PR_ATTACH_METHOD]);
+ if (attach_method != ATTACH_BY_VALUE)
+ return;
+
+ // Get Binary Data.
+ if (attachment_data) {
+ m_data_size = attachment_data->cb;
+ m_bin_data = new uint8_t[m_data_size];
+ memcpy(m_bin_data, attachment_data->lpb, attachment_data->cb);
+ } else {
+ mapi_object_t obj_stream;
+ mapi_object_init(&obj_stream);
+ if (OpenStream(&m_object, PR_ATTACH_DATA_BIN, 0, &obj_stream) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "attachment::attachment : OpenStream");
+
+ if (GetStreamSize(&obj_stream, &m_data_size) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "attachment::attachment : GetStreamSize");
+
+ m_bin_data = new uint8_t[m_data_size];
+
+ uint32_t pos = 0;
+ uint16_t bytes_read = 0;
+ do {
+ if (ReadStream(&obj_stream, m_bin_data+pos, 1024, &bytes_read) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "attachment::attachment : ReadStream");
+
+ pos += bytes_read;
+
+ } while (bytes_read && pos < m_data_size);
+
+ mapi_object_release(&obj_stream);
+ }
+
+ }
+
+ /**
+ * \brief The %attachment number
+ */
+ uint32_t get_num() const { return m_attach_num; }
+
+ /**
+ * \brief the contents of the %attachment
+ *
+ * \note the length of the array is given by get_data_size()
+ */
+ const uint8_t* get_data() const { return m_bin_data; }
+
+ /**
+ * \brief the size of the %attachment
+ *
+ * \return the size of the %attachment in bytes
+ */
+ uint32_t get_data_size() const { return m_data_size; }
+
+ /**
+ * \brief the filename of the %attachment
+ *
+ * \note not all attachments have file names
+ *
+ * \return string containing the file name of the %attachment, if any
+ */
+ std::string get_filename() const { return m_filename; }
+
+ /**
+ * Destructor
+ */
+ virtual ~attachment() throw()
+ {
+ if (m_bin_data) delete m_bin_data;
+ }
+
+ private:
+ uint32_t m_attach_num;
+ uint8_t* m_bin_data; // (same as unsigned char* ?)
+ uint32_t m_data_size;
+ std::string m_filename;
+};
+
+} // namespace libmapipp
+
+#endif //!LIBMAPIPP__ATTACHMENT_H__
Added: trunk/openchange/libmapi++/clibmapi.h
===================================================================
--- trunk/openchange/libmapi++/clibmapi.h (rev 0)
+++ trunk/openchange/libmapi++/clibmapi.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,27 @@
+/*
+ libmapi C++ Wrapper
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 __CLIBMAPI_H
+#define __CLIBMAPI_H
+
+extern "C" {
+#include <libmapi/libmapi.h>
+}
+
+#endif /* ! __CLIBMAPI_H */
Added: trunk/openchange/libmapi++/examples/foldertree.cpp
===================================================================
--- trunk/openchange/libmapi++/examples/foldertree.cpp (rev 0)
+++ trunk/openchange/libmapi++/examples/foldertree.cpp 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,80 @@
+/*
+ libmapi C++ Wrapper
+
+ Sample folder tree list application
+
+ Copyright (C) Brad Hards <bradh at frogmouth.net> 2008.
+
+ 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 <exception>
+#include <string>
+
+#include <libmapi++/libmapi++.h>
+
+int main ()
+{
+ try {
+ // Initialize MAPI Session
+ libmapipp::session mapi_session;
+ // You could log in with a non-default profile here
+ mapi_session.login();
+
+ // Get the private (user) folders message store
+ libmapipp::message_store &msg_store = mapi_session.get_message_store();
+
+ // Get a property of the top level message store
+ libmapipp::property_container msg_store_props = msg_store.get_property_container();
+ msg_store_props << PR_DISPLAY_NAME; // you could use other properties here
+ msg_store_props.fetch();
+
+ // Display the property. You can also use a property_container_iterator
+ // to work through the properties, but in this case there is only one.
+ std::cout << "Message store display name: "
+ << (const char*)msg_store_props[PR_DISPLAY_NAME]
+ << std::endl;
+
+ // Fetch the folder list.
+ // We start off by fetching the top level folder
+ mapi_id_t top_folder_id = msg_store.get_default_folder(olFolderTopInformationStore);
+ libmapipp::folder top_folder(msg_store, top_folder_id);
+ // Now get the child folders of the top level folder. These are returned as
+ // a std::vector of pointers to folders
+ libmapipp::folder::hierarchy_container_type child_folders = top_folder.fetch_hierarchy();
+ // Display the name, total item count and unread item count for each folder
+ for (unsigned int i = 0; i < child_folders.size(); ++i) {
+ libmapipp::property_container child_props = child_folders[i]->get_property_container();
+ child_props << PR_DISPLAY_NAME << PR_CONTENT_COUNT << PR_CONTENT_UNREAD;
+ child_props.fetch();
+ std::cout << "|-----> " << (const char*)child_props[PR_DISPLAY_NAME]
+ << " (" << (*(int*)child_props[PR_CONTENT_COUNT]) << " items, "
+ << (*(int*)child_props[PR_CONTENT_UNREAD]) << " unread)"
+ << std::endl;
+ }
+
+ }
+ catch (libmapipp::mapi_exception e) // Catch any MAPI exceptions
+ {
+ std::cout << "MAPI Exception in main: " << e.what()
+ << std::endl;
+ }
+ catch (std::runtime_error e) // Catch any other runtime exceptions
+ {
+ std::cout << "std::runtime_error exception in main: "
+ << e.what() << std::endl;
+ }
+
+ return 0;
+}
Added: trunk/openchange/libmapi++/examples/messages.cpp
===================================================================
--- trunk/openchange/libmapi++/examples/messages.cpp (rev 0)
+++ trunk/openchange/libmapi++/examples/messages.cpp 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,72 @@
+/*
+ libmapi C++ Wrapper
+
+ Sample folder message application
+
+ Copyright (C) Brad Hards <bradh at frogmouth.net> 2008.
+
+ 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 <exception>
+#include <string>
+
+#include <libmapi++/libmapi++.h>
+
+int main ()
+{
+ try {
+ // Initialize MAPI Session
+ libmapipp::session mapi_session;
+ // You could log in with a non-default profile here
+ mapi_session.login();
+
+ // Get the private (user) folders message store
+ libmapipp::message_store &msg_store = mapi_session.get_message_store();
+
+ // We start off by fetching the inbox
+ mapi_id_t inbox_id = msg_store.get_default_folder(olFolderInbox);
+ libmapipp::folder inbox_folder(msg_store, inbox_id);
+ // Now get the messages in this folder These are returned as
+ // a std::vector of pointers to messages
+ libmapipp::folder::message_container_type messages = inbox_folder.fetch_messages();
+ std::cout << "Inbox contains " << messages.size() << " messages" << std::endl;
+
+ // Work through each message
+ for (unsigned int i = 0; i < messages.size(); ++i) {
+ // Get the properties we are interested in
+ libmapipp::property_container msg_props = messages[i]->get_property_container();
+ // We get the "to" addressee, and the subject
+ // You can get a lot of other properties here (e.g. sender, body, etc).
+ msg_props << PR_DISPLAY_TO << PR_CONVERSATION_TOPIC;
+ msg_props.fetch();
+ // Display those properties
+ std::cout << "|-----> " << (const char*)msg_props[PR_DISPLAY_TO]
+ << "\t\t| " << (const char*)msg_props[PR_CONVERSATION_TOPIC]
+ << std::endl;
+ }
+ }
+ catch (libmapipp::mapi_exception e) // Catch any MAPI exceptions
+ {
+ std::cout << "MAPI Exception in main: " << e.what()
+ << std::endl;
+ }
+ catch (std::runtime_error e) // Catch any other runtime exceptions
+ {
+ std::cout << "std::runtime_error exception in main: "
+ << e.what() << std::endl;
+ }
+
+ return 0;
+}
Added: trunk/openchange/libmapi++/folder.h
===================================================================
--- trunk/openchange/libmapi++/folder.h (rev 0)
+++ trunk/openchange/libmapi++/folder.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,208 @@
+/*
+ libmapi C++ Wrapper
+ Folder Class
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 LIBMAPIPP__FOLDER_H__
+#define LIBMAPIPP__FOLDER_H__
+
+#include <iostream> //for debugging
+#include <vector>
+#include <boost/shared_ptr.hpp>
+
+#include <libmapi++/clibmapi.h>
+#include <libmapi++/mapi_exception.h>
+#include <libmapi++/object.h>
+#include <libmapi++/message.h>
+
+namespace libmapipp
+{
+
+/**
+ * This class represents a %folder or container within Exchange
+ */
+class folder : public object {
+ public:
+ /**
+ * Pointer to a message
+ */
+ typedef boost::shared_ptr<message> message_shared_ptr;
+
+ typedef std::vector<message_shared_ptr > message_container_type;
+
+ /**
+ * Pointer to a %folder
+ */
+ typedef boost::shared_ptr<folder> folder_shared_ptr;
+
+ /**
+ * Hierarchy folders
+ *
+ * This is a vector (list) of child folders for a given %folder
+ */
+ typedef std::vector<folder_shared_ptr> hierarchy_container_type;
+
+ /**
+ * \brief Constructor
+ *
+ * \param parent_folder The parent of this %folder.
+ * \param folder_id This folder's id.
+ */
+ folder(object& parent_folder, const mapi_id_t folder_id) throw(mapi_exception)
+ : object(parent_folder.get_session(), "folder"), m_id(folder_id)
+ {
+ if (OpenFolder(&parent_folder.data(), folder_id, &m_object) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "folder::folder : OpenFolder");
+ }
+
+ /**
+ * \brief Obtain %folder id
+ *
+ * \return This folder's id.
+ */
+ mapi_id_t get_id() const { return m_id; }
+
+ /**
+ * \brief Delete a message that belongs to this %folder
+ *
+ * \param message_id The id of the message to delete.
+ */
+ void delete_message(mapi_id_t message_id) throw (mapi_exception)
+ {
+ if (DeleteMessage(&m_object, &message_id, 1) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "folder::delete_message : DeleteMessage");
+ }
+
+ /**
+ * \brief Fetch all messages in this %folder
+ *
+ * \return A container of message shared pointers.
+ */
+ message_container_type fetch_messages() throw(mapi_exception)
+ {
+ uint32_t contents_table_row_count = 0;
+ mapi_object_t contents_table;
+
+ mapi_object_init(&contents_table);
+ if (GetContentsTable(&m_object, &contents_table, 0, &contents_table_row_count) != MAPI_E_SUCCESS) {
+ mapi_object_release(&contents_table);
+ throw mapi_exception(GetLastError(), "folder::fetch_messages : GetContentsTable");
+ }
+
+ SPropTagArray* property_tag_array = set_SPropTagArray(m_session.get_memory_ctx(), 0x2, PR_FID,
+ PR_MID);
+
+ if (SetColumns(&contents_table, property_tag_array) != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(property_tag_array);
+ mapi_object_release(&contents_table);
+ throw mapi_exception(GetLastError(), "folder::fetch_messages : SetColumns");
+ }
+
+ MAPIFreeBuffer(property_tag_array);
+
+ uint32_t rows_to_read = contents_table_row_count;
+ SRowSet row_set;
+
+ message_container_type message_container;
+ message_container.reserve(contents_table_row_count);
+
+ while( (QueryRows(&contents_table, rows_to_read, TBL_ADVANCE, &row_set) == MAPI_E_SUCCESS) && row_set.cRows) {
+ rows_to_read -= row_set.cRows;
+ for (unsigned int i = 0; i < row_set.cRows; ++i) {
+ try {
+ message_container.push_back(message_shared_ptr(new message(m_session,
+ m_id,
+ row_set.aRow[i].lpProps[1].value.d)));
+ }
+ catch(mapi_exception e) {
+ mapi_object_release(&contents_table);
+ throw;
+ }
+ }
+ }
+
+ mapi_object_release(&contents_table);
+
+ return message_container;
+ }
+
+ /**
+ * \brief Fetch all subfolders within this %folder
+ *
+ * \return A container of %folder shared pointers.
+ */
+ hierarchy_container_type fetch_hierarchy() throw(mapi_exception)
+ {
+ mapi_object_t hierarchy_table;
+ uint32_t hierarchy_table_row_count = 0;
+
+ mapi_object_init(&hierarchy_table);
+ if (GetHierarchyTable(&m_object, &hierarchy_table, 0, &hierarchy_table_row_count) != MAPI_E_SUCCESS) {
+ mapi_object_release(&hierarchy_table);
+ throw mapi_exception(GetLastError(), "folder::fetch_hierarchy : GetHierarchyTable");
+ }
+
+ SPropTagArray* property_tag_array = set_SPropTagArray(m_session.get_memory_ctx(), 0x1, PR_FID);
+
+ if (SetColumns(&hierarchy_table, property_tag_array)) {
+ MAPIFreeBuffer(property_tag_array);
+ mapi_object_release(&hierarchy_table);
+ throw mapi_exception(GetLastError(), "folder::fetch_hierarchy : SetColumns");
+ }
+
+ MAPIFreeBuffer(property_tag_array);
+
+ uint32_t rows_to_read = hierarchy_table_row_count;
+ SRowSet row_set;
+
+ hierarchy_container_type hierarchy_container;
+ hierarchy_container.reserve(hierarchy_table_row_count);
+
+ while( (QueryRows(&hierarchy_table, rows_to_read, TBL_ADVANCE, &row_set) == MAPI_E_SUCCESS) && row_set.cRows) {
+ rows_to_read -= row_set.cRows;
+ for (unsigned int i = 0; i < row_set.cRows; ++i) {
+ try {
+ hierarchy_container.push_back(folder_shared_ptr(new folder(*this,
+ row_set.aRow[i].lpProps[0].value.d)));
+ }
+ catch(mapi_exception e) {
+ mapi_object_release(&hierarchy_table);
+ throw;
+ }
+ }
+ }
+
+ mapi_object_release(&hierarchy_table);
+
+ return hierarchy_container;
+ }
+
+ /**
+ * Destructor
+ */
+ virtual ~folder() throw()
+ {
+ }
+
+ private:
+ mapi_id_t m_id;
+};
+
+} // namespace libmapipp
+
+#endif //!LIBMAPIPP__FOLDER_H__
Added: trunk/openchange/libmapi++/impl/message.ipp
===================================================================
--- trunk/openchange/libmapi++/impl/message.ipp (rev 0)
+++ trunk/openchange/libmapi++/impl/message.ipp 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,64 @@
+/*
+ libmapi C++ Wrapper
+ Message class implementation
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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++/attachment.h>
+
+namespace libmapipp {
+
+message::attachment_container_type message::fetch_attachments()
+{
+ mapi_object_t attachment_table;
+
+ mapi_object_init(&attachment_table);
+ if (GetAttachmentTable(&m_object, &attachment_table) != MAPI_E_SUCCESS) {
+ mapi_object_release(&attachment_table);
+ throw mapi_exception(GetLastError(), "message::fetch_attachments : GetAttachmentTable");
+ }
+
+ SPropTagArray* property_tag_array = set_SPropTagArray(m_session.get_memory_ctx(), 0x1, PR_ATTACH_NUM);
+
+ if (SetColumns(&attachment_table, property_tag_array) != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(property_tag_array);
+ mapi_object_release(&attachment_table);
+ throw mapi_exception(GetLastError(), "message::fetch_attachments : SetColumns");
+ }
+
+ MAPIFreeBuffer(property_tag_array);
+
+ SRowSet row_set;
+ attachment_container_type attachment_container;
+
+ while( (QueryRows(&attachment_table, 0x32, TBL_ADVANCE, &row_set) == MAPI_E_SUCCESS) && row_set.cRows) {
+ for (unsigned int i = 0; i < row_set.cRows; ++i) {
+ try {
+ attachment_container.push_back(attachment_shared_ptr(new attachment(*this, row_set.aRow[i].lpProps[0].value.l)));
+ }
+ catch(mapi_exception e) {
+ mapi_object_release(&attachment_table);
+ throw;
+ }
+ }
+ }
+ mapi_object_release(&attachment_table);
+
+ return attachment_container;
+}
+
+} // namespace libmapipp
Added: trunk/openchange/libmapi++/impl/object.ipp
===================================================================
--- trunk/openchange/libmapi++/impl/object.ipp (rev 0)
+++ trunk/openchange/libmapi++/impl/object.ipp 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,32 @@
+/*
+ libmapi C++ Wrapper
+ Object Class implementation.
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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++/session.h>
+#include <libmapi++/property_container.h>
+
+namespace libmapipp {
+
+inline property_container object::get_property_container()
+{
+ return property_container(m_session.get_memory_ctx(), m_object);
+}
+
+} // namespace libmapipp
+
Added: trunk/openchange/libmapi++/impl/session.ipp
===================================================================
--- trunk/openchange/libmapi++/impl/session.ipp (rev 0)
+++ trunk/openchange/libmapi++/impl/session.ipp 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,98 @@
+/*
+ libmapi C++ Wrapper
+ Session Class implementation.
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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++/message_store.h>
+#include <libmapi++/profile.h>
+
+namespace libmapipp {
+
+inline std::string session::get_default_profile_path()
+{
+ const char* profile_path = getenv("HOME");
+ std::string retval = "";
+ if (profile_path) {
+ retval = profile_path;
+ retval += "/.openchange/profiles.ldb";
+ }
+
+ return retval;
+}
+
+session::session(const std::string& profiledb, bool debug) throw(std::runtime_error, mapi_exception)
+: m_session(NULL), m_memory_ctx(talloc_named(NULL, 0, "libmapi++")), m_message_store(new message_store(*this))
+{
+ mapi_exception::fill_status_map();
+
+ std::string profile_path;
+
+ // If profile is not provided, attempt to get it from default location
+ // (~/.openchange/profiles.ldb)
+ if (profiledb == "") {
+ profile_path = get_default_profile_path();
+ if (profile_path == "") {
+ talloc_free(m_memory_ctx);
+ delete m_message_store;
+ throw std::runtime_error("libmapipp::session(): Failed to get $HOME env variable");
+ }
+ } else {
+ profile_path = profiledb;
+ }
+
+ if (MAPIInitialize(profile_path.c_str()) != MAPI_E_SUCCESS) {
+ talloc_free(m_memory_ctx);
+ delete m_message_store;
+ throw mapi_exception(GetLastError(), "session::session : MAPIInitialize");
+ }
+
+ if (debug) global_mapi_ctx->dumpdata = true;
+}
+
+void session::login(const std::string& profile_name, const std::string& password) throw (mapi_exception)
+{
+ m_profile_name = profile_name;
+ if (m_profile_name == "") { // if profile is not set, try to get default profile
+ try {
+ m_profile_name = profile::get_default_profile();
+ } catch(mapi_exception e) {
+ uninitialize();
+ throw;
+ }
+ }
+
+ if (MapiLogonEx(&m_session, m_profile_name.c_str(), (password != "") ? password.c_str() : 0 ) != MAPI_E_SUCCESS) {
+ uninitialize();
+ throw mapi_exception(GetLastError(), "session::session : MapiLogonEx");
+ }
+
+ try {
+ m_message_store->open(m_session);
+ } catch (mapi_exception e) {
+ throw;
+ }
+}
+
+inline void session::uninitialize() throw()
+{
+ talloc_free(m_memory_ctx);
+ MAPIUninitialize();
+ delete m_message_store;
+}
+
+} // namespace libmapipp
Added: trunk/openchange/libmapi++/libmapi++-example.doxy
===================================================================
--- trunk/openchange/libmapi++/libmapi++-example.doxy (rev 0)
+++ trunk/openchange/libmapi++/libmapi++-example.doxy 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,51 @@
+/** \example test.cpp
+
+An example that shows reading mail.
+
+*/
+
+/** \example attach_test.cpp
+
+An example that shows reading of attachments.
+
+*/
+
+/** \example foldertree.cpp
+
+This example lists the top level folders in the message store,
+with output like:
+\code
+Message store display name: Mailbox - Test User1
+|-----> Calendar (0 items, 0 unread)
+|-----> Contacts (0 items, 0 unread)
+|-----> Deleted Items (0 items, 0 unread)
+|-----> Drafts (0 items, 0 unread)
+|-----> Inbox (26 items, 24 unread)
+|-----> Journal (0 items, 0 unread)
+|-----> Notes (0 items, 0 unread)
+|-----> Outbox (9 items, 0 unread)
+|-----> Sent Items (0 items, 0 unread)
+|-----> Tasks (0 items, 0 unread)
+\endcode
+
+The example shows how to create a session, get the message_store, get
+properties of the message store, and then gets the list of child folders and
+some associated folder properties.
+
+*/
+
+/** \example messages.cpp
+
+This example displays information about the messages in the inbox, with
+output like:
+\code
+Inbox contains 2 messages
+|-----> Test User1 | Working Remotely with Windows Small Business Server
+|-----> Test User1 | Welcome to Windows Small Business Server 2003
+\endcode
+
+The example shows how to create a session, get the message_store, and open
+the inbox folder. It then determines how many messages are in the inbox folder,
+and retrieves and prints the intended addressee and the message subject.
+
+*/
Added: trunk/openchange/libmapi++/libmapi++-mainpage.doxy
===================================================================
--- trunk/openchange/libmapi++/libmapi++-mainpage.doxy (rev 0)
+++ trunk/openchange/libmapi++/libmapi++-mainpage.doxy 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,116 @@
+/**
+\mainpage libmapi++
+
+<h2>libmapi++ - C++ Bindings for OpenChange Clients</h2>
+
+libmapi++ provides C++ bindings for OpenChange client libraries (<a href="../libmapi/index.html">libmapi</a>).
+It is intended to provide a higher level abstraction of the OpenChange client libraries for C++ users who
+would prefer to work with an object-oriented API.
+
+<h2>Using libmapi++</h2>
+
+\note libmapi++ classes live in the libmapipp namespace.
+
+When using libmapi++, you start by creating a session, and logging in to the server.
+\code
+// Initialize MAPI Session
+libmapipp::session mapi_session;
+
+// login() can use an optional profile_name, and an optional password
+mapi_session.login();
+\endcode
+
+The session can then access the message store, which is the tree of private folders associated
+with a single user (containing various folders, such as the Inbox, Sent Mail, Calendar, Journal
+and so on).
+
+The message store is associated with the session, so you don't create it yourself. Instead,
+you obtain it using the session object's get_message_store() method.
+\code
+// Take a reference to the message store
+libmapipp::message_store &msg_store = mapi_session.get_message_store();
+\endcode
+\note It has to be a reference, not a copy / assignment.
+
+Most objects in libmapi++ (and any kind of MAPI library) can be considered to have properties
+that belong to them, and subordinate (child) objects. For example, the name of the message
+store is a property of the message store, but the various folders in the message store (or equally,
+the messages in a folder, or the attachments to a message) are part of a hierachy.
+
+To get access to the properties of an object, you obtain the property_container associated
+with the object, set the properties you want to access, call fetch(), and then read off the
+various properties.
+\code
+// Get a property of the top level message store
+libmapipp::property_container msg_store_props = msg_store.get_property_container();
+msg_store_props << PR_DISPLAY_NAME; // you could use other properties here
+msg_store_props.fetch();
+std::cout << "Message store display name: "
+ << (const char*)msg_store_props[PR_DISPLAY_NAME]
+ << std::endl;
+\endcode
+
+Note that the operator[] is essentially a lookup operator. If you'd prefer to use an
+iterator, look at libmapipp::property_container_iterator.
+
+As noted above, the objects in libmapi++ can be considered as a hierachy. To get the
+child elements for an object, you use the hierachy table for that element. For example,
+to get the various folders in the private information store, you could use code like this:
+\code
+// We start off by fetching the top level folder
+mapi_id_t top_folder_id = msg_store.get_default_folder(olFolderTopInformationStore);
+libmapipp::folder top_folder(msg_store, top_folder_id);
+// Now get the child folders of the top level folder. These are returned as
+// a std::vector of pointers to folders
+libmapipp::folder::hierarchy_container_type child_folders = top_folder.fetch_hierarchy();
+
+// Display the name, total item count and unread item count for each folder
+for (unsigned int i = 0; i < child_folders.size(); ++i) {
+ libmapipp::property_container child_props = child_folders[i]->get_property_container();
+ child_props << PR_DISPLAY_NAME << PR_CONTENT_COUNT << PR_CONTENT_UNREAD;
+ child_props.fetch();
+ std::cout << "|-----> " << (const char*)child_props[PR_DISPLAY_NAME]
+ << " (" << (*(int*)child_props[PR_CONTENT_COUNT]) << " items, "
+ << (*(int*)child_props[PR_CONTENT_UNREAD]) << " unread)"
+ << std::endl;
+}
+\endcode
+
+As an alternative to working through the folder tree hierachy, you can also open
+folders directly. In the example below, we open the Inbox. The API documentation
+for message_store::get_default_folder() provides a list of other folder IDs that
+you may find useful.
+\code
+mapi_id_t inbox_id = msg_store.get_default_folder(olFolderInbox);
+libmapipp::folder inbox_folder(msg_store, inbox_id);
+\endcode
+
+You can then get each message in the folder:
+\code
+// These are returned as a std::vector of pointers to messages
+libmapipp::folder::message_container_type messages = inbox_folder.fetch_messages();
+std::cout << "Inbox contains " << messages.size() << " messages" << std::endl;
+\endcode
+
+You can then get the various properties of each message in the same way as was
+used for the folder properties - you get the associated property_container, set
+the required properties, and call fetch() before reading off the required
+properties:
+\code
+// Work through each message
+for (unsigned int i = 0; i < messages.size(); ++i) {
+ // Get the properties we are interested in
+ libmapipp::property_container msg_props = messages[i]->get_property_container();
+ // We get the "to" addressee, and the subject
+ msg_props << PR_DISPLAY_TO << PR_CONVERSATION_TOPIC;
+ msg_props.fetch();
+ // Display those properties
+ std::cout << "|-----> " << (const char*)msg_props[PR_DISPLAY_TO]
+ << "\t\t| " << (const char*)msg_props[PR_CONVERSATION_TOPIC]
+ << std::endl;
+}
+\endcode
+
+\todo Explain attachments.
+
+*/
Added: trunk/openchange/libmapi++/libmapi++.h
===================================================================
--- trunk/openchange/libmapi++/libmapi++.h (rev 0)
+++ trunk/openchange/libmapi++/libmapi++.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,34 @@
+/*
+ libmapi C++ Wrapper
+ MAPI Exception Class
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 __LIBMAPIPP_H
+#define __LIBMAPIPP_H
+
+#include <libmapi++/clibmapi.h>
+#include <libmapi++/session.h>
+#include <libmapi++/message_store.h>
+#include <libmapi++/mapi_exception.h>
+#include <libmapi++/folder.h>
+#include <libmapi++/message.h>
+#include <libmapi++/attachment.h>
+#include <libmapi++/property_container.h>
+#include <libmapi++/profile.h>
+
+#endif /* ! __LIBMAPIPP_H */
Added: trunk/openchange/libmapi++/mapi_exception.h
===================================================================
--- trunk/openchange/libmapi++/mapi_exception.h (rev 0)
+++ trunk/openchange/libmapi++/mapi_exception.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,148 @@
+/*
+ libmapi C++ Wrapper
+ MAPI Exception Class
+
+ Copyright (C) Alan Alvarez 2007.
+
+ 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 LIBMAPIPP__MAPI_EXCEPTION_H__
+#define LIBMAPIPP__MAPI_EXCEPTION_H__
+
+#include <exception>
+#include <map>
+#include <iostream>
+#include <string>
+
+#include <libmapi++/clibmapi.h>
+
+#define STATUS_TABLE_INSERT(status) sm_status_map.insert(status_map::value_type(status, #status));
+
+namespace libmapipp {
+
+class mapi_exception : public std::exception
+{
+ public:
+
+ mapi_exception(enum MAPISTATUS status, const std::string& origin = "") : std::exception(), m_status(status), m_origin(origin)
+ {
+ }
+
+ virtual const char* what() const throw()
+ {
+ status_map::iterator iter = sm_status_map.find(m_status);
+
+ std::string ret_string = m_origin;
+ ret_string += ": ";
+ ret_string += (iter != sm_status_map.end()) ? iter->second : "Unknown MAPISTATUS value";
+
+ return ret_string.c_str();
+ }
+ enum MAPISTATUS get_status() const { return m_status; }
+
+ virtual ~mapi_exception() throw() {}
+
+ private:
+ enum MAPISTATUS m_status;
+ std::string m_origin;
+ friend class session;
+
+ typedef std::map<enum MAPISTATUS, const char*> status_map;
+ static status_map sm_status_map;
+
+ static void fill_status_map()
+ {
+ static bool filled = false;
+
+ if (!filled) {
+ STATUS_TABLE_INSERT(MAPI_E_SUCCESS);
+ STATUS_TABLE_INSERT(MAPI_E_CALL_FAILED);
+ STATUS_TABLE_INSERT(MAPI_E_NO_SUPPORT);
+ STATUS_TABLE_INSERT(MAPI_E_BAD_CHARWIDTH);
+ STATUS_TABLE_INSERT(MAPI_E_STRING_TOO_LONG);
+ STATUS_TABLE_INSERT(MAPI_E_UNKNOWN_FLAGS);
+ STATUS_TABLE_INSERT(MAPI_E_INVALID_ENTRYID);
+ STATUS_TABLE_INSERT(MAPI_E_INVALID_OBJECT);
+ STATUS_TABLE_INSERT(MAPI_E_OBJECT_CHANGED);
+ STATUS_TABLE_INSERT(MAPI_E_OBJECT_DELETED);
+ STATUS_TABLE_INSERT(MAPI_E_BUSY);
+ STATUS_TABLE_INSERT(MAPI_E_NOT_ENOUGH_DISK);
+ STATUS_TABLE_INSERT(MAPI_E_NOT_ENOUGH_RESOURCES);
+ STATUS_TABLE_INSERT(MAPI_E_NOT_FOUND);
+ STATUS_TABLE_INSERT(MAPI_E_VERSION);
+ STATUS_TABLE_INSERT(MAPI_E_LOGON_FAILED);
+ STATUS_TABLE_INSERT(MAPI_E_SESSION_LIMIT);
+ STATUS_TABLE_INSERT(MAPI_E_USER_CANCEL);
+ STATUS_TABLE_INSERT(MAPI_E_UNABLE_TO_ABORT);
+ STATUS_TABLE_INSERT(MAPI_E_NETWORK_ERROR);
+ STATUS_TABLE_INSERT(MAPI_E_DISK_ERROR);
+ STATUS_TABLE_INSERT(MAPI_E_TOO_COMPLEX);
+ STATUS_TABLE_INSERT(MAPI_E_BAD_COLUMN);
+ STATUS_TABLE_INSERT(MAPI_E_EXTENDED_ERROR);
+ STATUS_TABLE_INSERT(MAPI_E_COMPUTED);
+ STATUS_TABLE_INSERT(MAPI_E_CORRUPT_DATA);
+ STATUS_TABLE_INSERT(MAPI_E_UNCONFIGURED);
+ STATUS_TABLE_INSERT(MAPI_E_FAILONEPROVIDER);
+ STATUS_TABLE_INSERT(MAPI_E_UNKNOWN_CPID);
+ STATUS_TABLE_INSERT(MAPI_E_UNKNOWN_LCID);
+ STATUS_TABLE_INSERT(MAPI_E_PASSWORD_CHANGE_REQUIRED);
+ STATUS_TABLE_INSERT(MAPI_E_PASSWORD_EXPIRED);
+ STATUS_TABLE_INSERT(MAPI_E_INVALID_WORKSTATION_ACCOUNT);
+ STATUS_TABLE_INSERT(MAPI_E_INVALID_ACCESS_TIME);
+ STATUS_TABLE_INSERT(MAPI_E_ACCOUNT_DISABLED);
+ STATUS_TABLE_INSERT(MAPI_E_END_OF_SESSION);
+ STATUS_TABLE_INSERT(MAPI_E_UNKNOWN_ENTRYID);
+ STATUS_TABLE_INSERT(MAPI_E_MISSING_REQUIRED_COLUMN);
+ STATUS_TABLE_INSERT(MAPI_E_BAD_VALUE);
+ STATUS_TABLE_INSERT(MAPI_E_INVALID_TYPE);
+ STATUS_TABLE_INSERT(MAPI_E_TYPE_NO_SUPPORT);
+ STATUS_TABLE_INSERT(MAPI_E_UNEXPECTED_TYPE);
+ STATUS_TABLE_INSERT(MAPI_E_TOO_BIG);
+ STATUS_TABLE_INSERT(MAPI_E_DECLINE_COPY);
+ STATUS_TABLE_INSERT(MAPI_E_UNEXPECTED_ID);
+ STATUS_TABLE_INSERT(MAPI_E_UNABLE_TO_COMPLETE);
+ STATUS_TABLE_INSERT(MAPI_E_TIMEOUT);
+ STATUS_TABLE_INSERT(MAPI_E_TABLE_EMPTY);
+ STATUS_TABLE_INSERT(MAPI_E_TABLE_TOO_BIG);
+ STATUS_TABLE_INSERT(MAPI_E_INVALID_BOOKMARK);
+ STATUS_TABLE_INSERT(MAPI_E_WAIT);
+ STATUS_TABLE_INSERT(MAPI_E_CANCEL);
+ STATUS_TABLE_INSERT(MAPI_E_NOT_ME);
+ STATUS_TABLE_INSERT(MAPI_E_CORRUPT_STORE);
+ STATUS_TABLE_INSERT(MAPI_E_NOT_IN_QUEUE);
+ STATUS_TABLE_INSERT(MAPI_E_NO_SUPPRESS);
+ STATUS_TABLE_INSERT(MAPI_E_COLLISION);
+ STATUS_TABLE_INSERT(MAPI_E_NOT_INITIALIZED);
+ STATUS_TABLE_INSERT(MAPI_E_NON_STANDARD);
+ STATUS_TABLE_INSERT(MAPI_E_NO_RECIPIENTS);
+ STATUS_TABLE_INSERT(MAPI_E_SUBMITTED);
+ STATUS_TABLE_INSERT(MAPI_E_HAS_FOLDERS);
+ STATUS_TABLE_INSERT(MAPI_E_HAS_MESAGES);
+ STATUS_TABLE_INSERT(MAPI_E_FOLDER_CYCLE);
+ STATUS_TABLE_INSERT(MAPI_E_AMBIGUOUS_RECIP);
+ STATUS_TABLE_INSERT(MAPI_E_NO_ACCESS);
+ STATUS_TABLE_INSERT(MAPI_E_INVALID_PARAMETER);
+ STATUS_TABLE_INSERT(MAPI_E_RESERVED);
+
+ filled = true;
+ }
+ }
+};
+
+mapi_exception::status_map mapi_exception::sm_status_map = status_map();
+
+} // namespace libmapipp
+
+#endif //!LIBMAPIPP__EXCEPTION_H__
Added: trunk/openchange/libmapi++/message.h
===================================================================
--- trunk/openchange/libmapi++/message.h (rev 0)
+++ trunk/openchange/libmapi++/message.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,96 @@
+/*
+ libmapi C++ Wrapper
+ Message Class
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 LIBMAPIPP__MESSAGE_H__
+#define LIBMAPIPP__MESSAGE_H__
+
+#include <iostream> //for debugging
+#include <vector>
+
+#include <libmapi++/mapi_exception.h>
+#include <libmapi++/session.h>
+#include <libmapi++/clibmapi.h>
+
+namespace libmapipp
+{
+class object;
+class attachment;
+
+/**
+ * \brief This class represents a %message in Exchange.
+ *
+ * It is important to note that a %message is not necessarily an email %message.
+ * It could be a contact, journal or anything else that is not a folder.
+ */
+class message : public object {
+ public:
+ typedef boost::shared_ptr<attachment> attachment_shared_ptr;
+ typedef std::vector<attachment_shared_ptr> attachment_container_type;
+
+ /**
+ * \brief Constructor
+ *
+ * \param mapi_session The session to use to retrieve this %message.
+ * \param folder_id The id of the folder this %message belongs to.
+ * \param message_id The %message id.
+ */
+ message(session& mapi_session, const mapi_id_t folder_id, const mapi_id_t message_id) throw(mapi_exception)
+ : object(mapi_session, "message"), m_folder_id(folder_id), m_id(message_id)
+ {
+ if (OpenMessage(&mapi_session.get_message_store().data(), folder_id, message_id, &m_object, 0) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "message::message : OpenMessage");
+ }
+
+ /**
+ * \brief Fetches all attachments in this %message.
+ *
+ * \return A container of attachment shared pointers.
+ */
+ attachment_container_type fetch_attachments();
+
+ /**
+ * \brief Get this %message's ID.
+ */
+ mapi_id_t get_id() const { return m_id; }
+
+ /**
+ * \brief Get this message's parent folder ID.
+ */
+ mapi_id_t get_folder_id() const { return m_folder_id; }
+
+ /**
+ * Destructor
+ */
+ virtual ~message() throw()
+ {
+ }
+
+ private:
+ mapi_id_t m_folder_id;
+ mapi_id_t m_id;
+
+};
+
+} // namespace libmapipp
+
+#include <libmapi++/impl/message.ipp>
+
+#endif //!LIBMAPIPP__MESSAGE_H__
Added: trunk/openchange/libmapi++/message_store.h
===================================================================
--- trunk/openchange/libmapi++/message_store.h (rev 0)
+++ trunk/openchange/libmapi++/message_store.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,101 @@
+/*
+ libmapi C++ Wrapper
+ Message Store Class
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 LIBMAPIPP__MESSAGE_STORE_H__
+#define LIBMAPIPP__MESSAGE_STORE_H__
+
+#include <stdint.h>
+
+#include <libmapi++/clibmapi.h>
+#include <libmapi++/mapi_exception.h>
+#include <libmapi++/object.h>
+
+namespace libmapipp
+{
+class session;
+
+/**
+ * \brief This class represents the Message Store in Exchange.
+ *
+ * The message_store is the grouping of message folders (which could be the
+ * users private store including mail, calendar, todo list, journal, contacts
+ * and so on) or could be the public store (e.g. shared public folders).
+ *
+ * It is not possible for you, the user, to create a message_store object.
+ * Instead, you should retrieve the message_store associated with a session
+ * using session::get_message_store()
+ */
+class message_store : public object {
+ public:
+ /**
+ * \brief Retrieves the folder id for the specified default folder in the Message Store.
+ *
+ * \param id The type of folder to search for.
+ *
+ * The following types of folders are supported:
+ * - olFolderTopInformationStore
+ * - olFolderDeletedItems
+ * - olFolderOutbox
+ * - olFolderSentMail
+ * - olFolderInbox
+ * - olFolderCalendar
+ * - olFolderContacts
+ * - olFolderJournal
+ * - olFolderNotes
+ * - olFolderTasks
+ * - olFolderDrafts
+ *
+ * If you are trying to enumerate all folders, you should open the
+ * olFolderTopInformationStore, and then get the hierachy container for
+ * that top level folder.
+ *
+ * \return The resulting folder id.
+ */
+ mapi_id_t get_default_folder(const uint32_t id) const throw(mapi_exception)
+ {
+ mapi_id_t folder;
+
+ if (GetDefaultFolder(const_cast<mapi_object_t*>(&m_object), &folder, id) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "message_store::get_default_folder() : GetDefaultFolder");
+
+ return folder;
+ }
+
+
+ private:
+ friend class session;
+ message_store(session& mapi_session) throw() : object(mapi_session, "message_store")
+ {}
+
+ void open(mapi_session *mapi_session) throw(mapi_exception)
+ {
+ if (OpenMsgStore(mapi_session, &m_object) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "message_store::open() : OpenMsgStore");
+ }
+
+ ~message_store() throw()
+ {
+ }
+};
+
+} // namespace libmapipp
+
+#endif //!LIBMAPIPP__MESSAGE_STORE_H__
Added: trunk/openchange/libmapi++/object.h
===================================================================
--- trunk/openchange/libmapi++/object.h (rev 0)
+++ trunk/openchange/libmapi++/object.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,108 @@
+/*
+ libmapi C++ Wrapper
+ Base Object Class
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 LIBMAPIPP__OBJECT_H__
+#define LIBMAPIPP__OBJECT_H__
+
+#include <iostream> //for debugging
+
+#include <stdexcept>
+
+#include <libmapi++/clibmapi.h>
+#include <libmapi++/session.h>
+
+/**
+ * The libmapi++ classes and other definitions are all enclosed in
+ * the libmapipp namespace.
+ */
+namespace libmapipp
+{
+// #define INVALID_HANDLE_VALUE 0xffffffff
+class property_container;
+
+/**
+ * Base Object class
+ *
+ * Most classes such as folder, message and message_store derive from this class.
+ * It is important that objects be passed around as references and that no unnecessary
+ * copies are made as this will call the class destructor which will call
+ * mapi_object_release() and release the handle associated with this object.
+ */
+class object {
+ public:
+ /**
+ * \brief Object Constructor
+ *
+ * \param mapi_session Session this object is to be associated with.
+ * \param object_type The name of the type of object (to be set in a subclass)
+ */
+ object(session& mapi_session, const std::string& object_type = "") throw() : m_session(mapi_session), m_object_type(object_type)
+ {
+ mapi_object_init(&m_object);
+ }
+
+ /**
+ * \brief Obtain a reference to the mapi_object_t associated with this object
+ *
+ * \return A reference to the C struct mapi_object_t associated with this object
+ */
+ virtual mapi_object_t& data() throw() { return m_object; }
+
+ /**
+ * \brief Obtain a property_container to be used with this object.
+ *
+ * \return A property_container to be used with this object.
+ */
+ virtual property_container get_property_container();
+
+ /**
+ * \brief Obtain the session associated with this object.
+ *
+ * \return The session associated with this object
+ */
+ virtual session& get_session() { return m_session; }
+
+ /**
+ * \brief Destructor
+ *
+ * Calls mapi_object_release() which releases the handle associated with this object.
+ */
+ virtual ~object() throw()
+ {
+ // TODO: Check for invalid handle in libmapi 0.7
+ // if (m_object.handle != INVALID_HANDLE_VALUE)
+ mapi_object_release(&m_object);
+
+// std::cout << "destroying object " << m_object_type << std::endl;
+ }
+
+ protected:
+ mapi_object_t m_object;
+ session& m_session;
+
+ private:
+ std::string m_object_type; // for debugging purposes
+};
+
+} // namespace libmapipp
+
+#include <libmapi++/impl/object.ipp>
+
+#endif //!LIBMAPIPP__OBJECT_H__
Added: trunk/openchange/libmapi++/profile.h
===================================================================
--- trunk/openchange/libmapi++/profile.h (rev 0)
+++ trunk/openchange/libmapi++/profile.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,88 @@
+/*
+ libmapi C++ Wrapper
+ Profile Class
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 LIBMAPIPP__PROFILE_H__
+#define LIBMAPIPP__PROFILE_H__
+
+#include <libmapi++/clibmapi.h>
+
+namespace libmapipp {
+
+/**
+ * This class represents a user %profile database
+ *
+ * \todo possibly rename profile class to profile_database?
+ * \todo we should be able to create a profile using libmapi++ classes
+ * \todo we should be able to delete a profile using libmapi++ classes
+ * \todo maybe move some of the session.h documentation on profiles to profile.h?
+ */
+class profile
+{
+ public:
+
+ /**
+ * Make the specified profile the default profile
+ *
+ * \param profname the name of the profile to make default
+ */
+ bool static set_default(const char* profname)
+ {
+ return (SetDefaultProfile(profname) == MAPI_E_SUCCESS);
+ }
+
+ /**
+ * Make the specified profile the default profile
+ *
+ * \param profname the name of the profile to make default
+ */
+ bool static set_default(const std::string& profname)
+ {
+ return set_default(profname.c_str());
+ }
+
+ /**
+ * Get the default profile name
+ *
+ * \return the name of the default profile
+ */
+ std::string static get_default_profile() throw (mapi_exception)
+ {
+ char* profname = NULL;
+ if (GetDefaultProfile(&profname) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "profile::get_default_profile : GetDefaultProfile()");
+
+ return std::string(profname);
+ }
+
+ ~profile()
+ {
+ if (m_profile)
+ ::ShutDown(m_profile);
+ }
+
+
+ private:
+ mapi_profile *m_profile;
+};
+
+} // namespace libmapipp
+
+#endif //!LIBMAPIPP__PROFILE_H__
Added: trunk/openchange/libmapi++/property_container.h
===================================================================
--- trunk/openchange/libmapi++/property_container.h (rev 0)
+++ trunk/openchange/libmapi++/property_container.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,307 @@
+/*
+ libmapi C++ Wrapper
+ Property Tag Container Class
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 LIBMAPIPP__PROPERTY_CONTAINER_H__
+#define LIBMAPIPP__PROPERTY_CONTAINER_H__
+
+#include <stdint.h>
+#include <iostream> // for debugging only.
+
+#include <libmapi++/clibmapi.h>
+#include <libmapi++/mapi_exception.h>
+
+// This is not declared in any of libmapi's headers, but it is defined in libmapi/property.c
+extern "C" {
+extern const void *get_mapi_SPropValue_data(struct mapi_SPropValue *lpProp);
+}
+
+namespace libmapipp
+{
+/// Iterator to use with Property Container
+class property_container_iterator {
+ public:
+ /// Default Constructor. Creates an invalid iterator.
+ property_container_iterator() : m_property_values(NULL), m_mapi_property_values(NULL)
+ {}
+
+ property_container_iterator(SPropValue* property_values) : m_property_values(property_values),
+ m_mapi_property_values(NULL)
+ {}
+
+ property_container_iterator(mapi_SPropValue* mapi_property_values) : m_property_values(NULL),
+ m_mapi_property_values(mapi_property_values)
+ {}
+
+ /** \brief Get Property Tag Type.
+ * \return Type of property this iterator points to or MAPI_PROP_RESERVED if this is an invalid iterator.
+ * Valid Types are:
+ * - PT_BOOLEAN
+ * - PT_I2
+ * - PT_LONG
+ * - PT_DOUBLE
+ * - PT_I8
+ * - PT_SYSTIME
+ * - PT_ERROR
+ * - PT_STRING8
+ * - PT_UNICODE
+ * - PT_BINARY
+ * - PT_CLSID
+ * - PT_ERROR
+ * - PT_MV_SHORT
+ * - PT_MV_LONG
+ * - PT_MV_STRING8
+ * - PT_MV_BINARY
+ * - PT_MV_CLSID
+ * - PT_MV_UNICODE
+ * - PT_MV_SYSTIME
+ * - PT_NULL
+ * - PT_OBJECT
+ */
+ int get_type()
+ {
+ if (m_property_values) {
+ return m_property_values->ulPropTag & 0xffff;
+ } else if (m_mapi_property_values) {
+ return m_mapi_property_values->ulPropTag & 0xffff;
+ } else {
+ return MAPI_PROP_RESERVED;
+ }
+ }
+
+ /**
+ * \brief Get Property Tag of the Property Value this operator points to.
+ *
+ * \return Property Tag of Property this iterator points to or MAPI_PROP_RESERVED if this is an invalid iterator.
+ */
+ int get_tag()
+ {
+ if (m_property_values) {
+ return m_property_values->ulPropTag;
+ } else if (m_mapi_property_values) {
+ return m_mapi_property_values->ulPropTag;
+ } else {
+ return MAPI_PROP_RESERVED;
+ }
+ }
+
+ /// operator++
+ property_container_iterator& operator++() // prefix
+ {
+ if (m_property_values)
+ ++m_property_values;
+ else if (m_mapi_property_values)
+ ++m_mapi_property_values;
+
+ return *this;
+ }
+
+ /// operator++ postfix
+ property_container_iterator operator++(int postfix) // postfix
+ {
+ property_container_iterator retval = *this;
+ if (m_property_values)
+ ++m_property_values;
+ else if (m_mapi_property_values)
+ ++m_mapi_property_values;
+
+ return retval;
+ }
+
+ /// operator==
+ bool operator==(const property_container_iterator& rhs) const
+ {
+ return ( (m_property_values == rhs.m_property_values) && (m_mapi_property_values == rhs.m_mapi_property_values) );
+ }
+
+ /// operator!=
+ bool operator!=(const property_container_iterator& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ /**
+ * \brief operator*
+ *
+ * \return The property value as a void pointer.
+ */
+ const void* operator*()
+ {
+ if (m_property_values)
+ return get_SPropValue_data(m_property_values);
+ else
+ return get_mapi_SPropValue_data(m_mapi_property_values);
+ }
+
+ private:
+ SPropValue* m_property_values;
+ mapi_SPropValue* m_mapi_property_values;
+};
+
+
+/// A container of properties to be used with classes derived from object.
+class property_container {
+
+ public:
+ typedef property_container_iterator iterator;
+ typedef const void* value_type;
+
+ /// Constructor
+ property_container(TALLOC_CTX* memory_ctx, mapi_object_t& mapi_object) :
+ m_memory_ctx(memory_ctx), m_mapi_object(mapi_object), m_fetched(false), m_property_tag_array(NULL), m_cn_vals(0), m_property_values()
+ {
+ }
+
+ /**
+ * \brief Fetches properties with the tags supplied using operator<<
+ *
+ * \return The number of objects that were fetched.
+ */
+ uint32_t fetch()
+ {
+ if (GetProps(&m_mapi_object, m_property_tag_array, &m_property_values, &m_cn_vals) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "property_container::fetch : GetProps");
+
+ MAPIFreeBuffer(m_property_tag_array);
+ m_property_tag_array = NULL;
+
+ m_fetched = true;
+ return m_cn_vals;
+ }
+
+ /// \brief Fetches \b ALL properties of the object associated with this container.
+ void fetch_all()
+ {
+ if (GetPropsAll(&m_mapi_object, &m_property_value_array) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "property_container::fetch_all : GetPropsAll");
+
+ // Free property_tag_array in case user used operator<< by mistake.
+ if (m_property_tag_array) {
+ MAPIFreeBuffer(m_property_tag_array);
+ m_property_tag_array = NULL;
+ }
+
+ m_fetched = true;
+ }
+
+ /// \brief Adds a Property Tag to be fetched by fetch().
+ property_container& operator<<(uint32_t property_tag)
+ {
+ if (!m_property_tag_array) {
+ m_property_tag_array = set_SPropTagArray(m_memory_ctx, 1, property_tag);
+ } else {
+ if (SPropTagArray_add(m_memory_ctx, m_property_tag_array, property_tag) != MAPI_E_SUCCESS)
+ throw mapi_exception(GetLastError(), "property_container::operator<< : SPropTagArray_add");
+ }
+
+ return *this;
+ }
+
+ /**
+ * \brief Finds the property value associated with a property tag
+ *
+ * \param property_tag The Property Tag to be searched for
+ *
+ * \return Property Value as a const void pointer
+ */
+ const void* operator[](uint32_t property_tag)
+ {
+ if (!m_fetched) return NULL;
+
+ if (m_property_values)
+ return find_SPropValue_value(property_tag);
+ else
+ return find_mapi_SPropValue_data(&m_property_value_array, property_tag);
+ }
+
+ enum MAPITAGS get_tag_at(uint32_t pos)
+ {
+ if (m_property_values)
+ return m_property_values[pos].ulPropTag;
+ else
+ return m_property_value_array.lpProps[pos].ulPropTag;
+ }
+
+ iterator begin() const
+ {
+ if (!m_fetched) return iterator();
+
+ if (m_property_values)
+ return iterator(m_property_values);
+ else
+ return iterator(m_property_value_array.lpProps);
+ }
+
+ iterator end() const
+ {
+ if (!m_fetched) return iterator();
+
+ if (m_property_values)
+ return iterator(m_property_values + m_cn_vals);
+ else
+ return iterator(m_property_value_array.lpProps + m_property_value_array.cValues);
+ }
+
+ /// \brief Get number of properties in container.
+ size_t size() const
+ {
+ if (!m_fetched) return 0;
+
+ if (m_property_values)
+ return m_cn_vals;
+ else
+ return m_property_value_array.cValues;
+ }
+
+ /// Destructor
+ ~property_container()
+ {
+ if (m_property_tag_array) MAPIFreeBuffer(m_property_tag_array);
+ }
+
+ private:
+ TALLOC_CTX* m_memory_ctx;
+ mapi_object_t& m_mapi_object;
+
+ bool m_fetched;
+
+ SPropTagArray* m_property_tag_array;
+
+ // Used when calling GetProps (fetch)
+ uint32_t m_cn_vals;
+ SPropValue* m_property_values;
+
+ // Used when calling GetPropsAll (fetch_all)
+ mapi_SPropValue_array m_property_value_array;
+
+ const void* find_SPropValue_value(uint32_t property_tag)
+ {
+ for (uint32_t i = 0; i < m_cn_vals; ++i)
+ {
+ if (m_property_values[i].ulPropTag == property_tag)
+ return get_SPropValue_data(&m_property_values[i]);
+ }
+
+ return NULL;
+ }
+};
+
+} // namespace libmapipp
+
+#endif //!LIBMAPIPP__PROPERTY_CONTAINER_H__
Added: trunk/openchange/libmapi++/session.h
===================================================================
--- trunk/openchange/libmapi++/session.h (rev 0)
+++ trunk/openchange/libmapi++/session.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,146 @@
+/*
+ libmapi C++ Wrapper
+ Session Class
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 LIBMAPIPP__SESSION_H__
+#define LIBMAPIPP__SESSION_H__
+
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <stdexcept>
+
+#include <iostream> // for debugging
+
+#include <libmapi++/clibmapi.h>
+#include <libmapi++/mapi_exception.h>
+
+using std::cout;
+using std::endl;
+
+namespace libmapipp
+{
+class message_store;
+/**
+ * This class represents a MAPI %session with the Exchange Server
+ *
+ * The %session is best thought of as the connection by a single user to a
+ * single server. It is possible to have multiple sessions open at the same
+ * time.
+ *
+ * A key concept in the %session is that of a \em profile, and the %profile
+ * database. The %profile is a pre-established data set that specifies the
+ * server information (e.g. server name / IP address, and Exchange domain)
+ * and client information (e.g. the user name, preferred language, and
+ * optionally the users password). The profiles are stored in a local store
+ * (Samba LDB database) known as the %profile store or %profile database. One
+ * of the profiles in the %profile database can be designated as the default
+ * %profile (which is particularly useful given that most users may only have
+ * one). See the profile class documentation for more information.
+ *
+ * The general concept is that you create a %session %object, log in to the
+ * %session using a selected %profile name, and then work with the message_store
+ * associated with that %session. The message_store is only valid so long
+ * as the session is valid.
+ */
+class session {
+ public:
+ /**
+ * \brief Constructor
+ *
+ * \param profiledb An absolute path specifying the location of the
+ * %profile database. If not specified (or "" is specified) the default
+ * location will be used (~/.openchange.profiles.ldb).
+ *
+ * \param debug Whether to output debug information to stdout
+ */
+ session(const std::string& profiledb = "", const bool debug = false) throw(std::runtime_error, mapi_exception);
+
+ /**
+ * \brief Log-in to the Exchange Server
+ *
+ * \param profile_name The name of the profile to use to login with.
+ * If not specified (or "" is specified), then the default %profile will
+ * be used.
+ *
+ * \param password The password to use to login with. It is possible to
+ * omit this if the password is stored in the %profile database.
+ */
+ void login(const std::string& profile_name = "", const std::string& password = "") throw(mapi_exception);
+
+ /**
+ * \brief The path to the default %profile database
+ *
+ * This method is not normally required to be called by user applications
+ * but might be useful under some circumstances.
+ */
+ static std::string get_default_profile_path();
+
+ /**
+ * \brief The name of the profile that is in use
+ *
+ * Calling this method only makes sense if login() has been called with
+ * this %session object.
+ */
+ std::string get_profile_name() const { return m_profile_name; }
+
+ /**
+ * \brief Obtain a reference to the message_store associated with this %session
+ *
+ * \return The message_store associated with this %session.
+ */
+ message_store& get_message_store() throw() { return *m_message_store; }
+
+ /**
+ * \brief Obtain a talloc memory context for this %session
+ *
+ * This pointer can be used for subsequent memory allocations, and
+ * these will be cleaned up when the %session is terminated.
+ */
+ TALLOC_CTX* get_memory_ctx() throw() { return m_memory_ctx; }
+
+ /**
+ * \brief Uninitialize and clean up the MAPI %session.
+ */
+ ~session()
+ {
+ uninitialize();
+ }
+
+ /**
+ * \brief The underlying mapi_session
+ *
+ * Exposing this is temporary. Maybe be removed when we sort it out
+ */
+ mapi_session* get_mapi_session() throw() { return m_session; }
+
+ private:
+ mapi_session *m_session;
+ TALLOC_CTX *m_memory_ctx;
+ message_store *m_message_store;
+ std::string m_profile_name;
+
+ void uninitialize() throw();
+};
+
+} // namespace libmapipp
+
+#include <libmapi++/impl/session.ipp>
+
+#endif //!LIBMAPIPP__SESSION_H__
Added: trunk/openchange/libmapi++/tests/attach_test.cpp
===================================================================
--- trunk/openchange/libmapi++/tests/attach_test.cpp (rev 0)
+++ trunk/openchange/libmapi++/tests/attach_test.cpp 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,97 @@
+/*
+ libmapi C++ Wrapper
+
+ Sample attachment test application
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 <iostream>
+
+#include <libmapi++/libmapi++.h>
+
+using namespace std;
+using namespace libmapipp;
+
+uint32_t get_attachment_count(message& mapi_message)
+{
+ message::attachment_container_type attachment_container = mapi_message.fetch_attachments();
+ return attachment_container.size();
+}
+
+void print_messages_with_attachments(folder& up_folder)
+{
+ folder::message_container_type messages = up_folder.fetch_messages();
+ for (folder::message_container_type::iterator Iter = messages.begin(); Iter != messages.end(); ++Iter) {
+ uint32_t attachment_count = get_attachment_count(*(*Iter));
+// cout << "Attachment Count: " << attachment_count << endl;
+ if (attachment_count) {
+ cout << "Message (" << (*Iter)->get_id() << ") has " << attachment_count << " attachments." << endl;
+ }
+ }
+}
+
+void print_folder_tree(folder& up_folder, session& mapi_session, unsigned int deep = 0)
+{
+ property_container up_folder_property_container = up_folder.get_property_container();
+ up_folder_property_container << PR_DISPLAY_NAME << PR_CONTENT_COUNT;
+ up_folder_property_container.fetch();
+
+ string display_name = static_cast<const char*>(up_folder_property_container[PR_DISPLAY_NAME]);
+ const uint32_t message_count = *(static_cast<const uint32_t*>(up_folder_property_container[PR_CONTENT_COUNT]));
+
+ for (unsigned int i = 0; i < deep; ++i) {
+ cout << "|----> ";
+ }
+
+ cout << display_name << " (id: " << up_folder.get_id() << ") (messages: " << message_count << ")" << endl;
+
+ print_messages_with_attachments(up_folder);
+
+ // Fetch Top Information Folder Hierarchy (child folders)
+ folder::hierarchy_container_type hierarchy = up_folder.fetch_hierarchy();
+ for (unsigned int i = 0; i < hierarchy.size(); ++i) {
+ print_folder_tree(*hierarchy[i], mapi_session, deep+1);
+ }
+}
+
+
+int main()
+{
+ try {
+ session mapi_session;
+
+ mapi_session.login();
+
+ // Get Default Top Information Store folder ID
+ mapi_id_t top_folder_id = mapi_session.get_message_store().get_default_folder(olFolderTopInformationStore);
+
+ // Open Top Information Folder
+ folder top_folder(mapi_session.get_message_store(), top_folder_id);
+
+ print_folder_tree(top_folder, mapi_session);
+ }
+ catch (mapi_exception e) // Catch any mapi exceptions
+ {
+ cout << "MAPI Exception @ main: " << e.what() << endl;
+ }
+ catch (std::runtime_error e) // Catch runtime exceptions
+ {
+ cout << "std::runtime_error exception @ main: " << e.what() << endl;
+ }
+
+ return 0;
+}
Added: trunk/openchange/libmapi++/tests/test.cpp
===================================================================
--- trunk/openchange/libmapi++/tests/test.cpp (rev 0)
+++ trunk/openchange/libmapi++/tests/test.cpp 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,140 @@
+/*
+ libmapi C++ Wrapper
+
+ Sample test application
+
+ Copyright (C) Alan Alvarez 2008.
+
+ 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 <exception>
+#include <vector>
+#include <string>
+
+#include <libmapi++/libmapi++.h>
+
+using namespace libmapipp;
+using std::string;
+
+// The best way to get a folder message count is to get property PR_FOLDER_CHILD_COUNT.
+// This is only used to test opening all messages.
+unsigned int get_message_count(folder& the_folder, session& mapi_session)
+{
+ folder::message_container_type messages = the_folder.fetch_messages();
+ return messages.size();
+}
+
+void print_folder_tree(folder& up_folder, session& mapi_session, unsigned int deep = 0)
+{
+ property_container up_folder_property_container = up_folder.get_property_container();
+ up_folder_property_container << PR_DISPLAY_NAME << PR_CONTAINER_CLASS;
+ up_folder_property_container.fetch();
+
+ string display_name = static_cast<const char*>(up_folder_property_container[PR_DISPLAY_NAME]);
+ string container_class;
+ if (up_folder_property_container[PR_CONTAINER_CLASS])
+ container_class = static_cast<const char*>(up_folder_property_container[PR_CONTAINER_CLASS]);
+
+ for (unsigned int i = 0; i < deep; ++i) {
+ cout << "|----> ";
+ }
+
+ cout << display_name << " (id: " << up_folder.get_id() << ") (messages: " << get_message_count(up_folder, mapi_session) << ")"
+ << " container class: " << container_class << endl;
+
+ // Fetch Top Information Folder Hierarchy (child folders)
+ folder::hierarchy_container_type hierarchy = up_folder.fetch_hierarchy();
+ for (unsigned int i = 0; i < hierarchy.size(); ++i) {
+ print_folder_tree(*hierarchy[i], mapi_session, deep+1);
+ }
+}
+
+int main ()
+{
+ try {
+ // Initialize MAPI Session
+ session mapi_session;
+
+ mapi_session.login();
+
+ property_container store_properties = mapi_session.get_message_store().get_property_container();
+ store_properties << PR_DISPLAY_NAME;
+ store_properties.fetch();
+ cout << "Mailbox Name: " << static_cast<const char*>(*store_properties.begin()) << endl;
+
+ // Get Default Inbox folder ID.
+ mapi_id_t inbox_id = mapi_session.get_message_store().get_default_folder(olFolderInbox);
+ cout << "inbox_id: " << inbox_id << endl;
+
+ // Open Inbox Folder
+ folder inbox_folder(mapi_session.get_message_store(), inbox_id);
+
+ // Fetch messages in Inbox Folder
+ folder::message_container_type messages = inbox_folder.fetch_messages();
+ cout << "Inbox size: " << messages.size() << endl;
+
+ // Get and Print some information about the first message in the Inbox Folder
+ if (messages.size() > 0) {
+ // Get a property container associated to the first message
+ property_container message_property_container = messages[0]->get_property_container();
+
+ // Add Property Tags to be fetched and then fetch the properties.
+ message_property_container << PR_DISPLAY_TO << PR_CONVERSATION_TOPIC;
+ message_property_container.fetch_all();
+
+ string to;
+ string subject;
+ // Get some property values using property_container::operator[]
+ // to = static_cast<const char*>(message_property_container[PR_DISPLAY_TO]);
+ // subject = static_cast<const char*>(message_property_container[PR_CONVERSATION_TOPIC]);
+ // Print property values
+ // cout << "To: " << to << endl;
+ // cout << "Subject: " << subject << endl;
+
+ for (property_container::iterator Iter = message_property_container.begin(); Iter != message_property_container.end(); Iter++)
+ {
+ if (Iter.get_tag() == PR_DISPLAY_TO)
+ to = (const char*) *Iter;
+ else if (Iter.get_tag() == PR_CONVERSATION_TOPIC)
+ subject = (const char*) *Iter;
+ }
+
+ // Print property values
+ cout << "To: " << to << endl;
+ cout << "Subject: " << subject << endl;
+ }
+
+ // Get Default Top Information Store folder ID
+ mapi_id_t top_folder_id = mapi_session.get_message_store().get_default_folder(olFolderTopInformationStore);
+
+ // Open Top Information Folder
+ folder top_folder(mapi_session.get_message_store(), top_folder_id);
+
+ print_folder_tree(top_folder, mapi_session);
+
+ cout << "finished session" << endl;
+ }
+ catch (mapi_exception e) // Catch any mapi exceptions
+ {
+ cout << "MAPI Exception @ main: " << e.what() << endl;
+ }
+ catch (std::runtime_error e) // Catch runtime exceptions
+ {
+ cout << "std::runtime_error exception @ main: " << e.what() << endl;
+
+ }
+
+ return 0;
+}
Added: trunk/openchange/libmapi.pc.in
===================================================================
--- trunk/openchange/libmapi.pc.in (rev 0)
+++ trunk/openchange/libmapi.pc.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,15 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@prefix@/share
+datadir=@datadir@
+
+Name: MAPI
+Description: MAPI Protocol Implementation
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lmapi
+Libs.private: @LIBS@
+Cflags: -I${includedir}
+Requires: talloc dcerpc ndr ldb
+Requires.private: samba-hostconfig
Added: trunk/openchange/libmapiadmin/Doxyfile.in
===================================================================
--- trunk/openchange/libmapiadmin/Doxyfile.in (rev 0)
+++ trunk/openchange/libmapiadmin/Doxyfile.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1272 @@
+# Doxyfile 1.5.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = libmapiadmin
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = apidocs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = libmapiadmin
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.h *.c *.doxy
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = *_private.h
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = *.yy.c *_private.h
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = doc/doxygen/pictures/
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER = "sed \
+ -e '20,50s/.*\<libmapiadmin\/proto_private.h\>//' \
+ -e '20,50s/.*\<param.h\>//' \
+ -e '20,50s/.*\<time.h\>//' \
+ -e '20,50s/.*\<credentials.h\>//' \
+ -e '20,50s/.*\<samba\/popt.h\>//' \
+ -e '20,50s/.*\<ldberrors.h\>//' \
+ -e '20,50s/.*\<ldb_wrap.h\>//' \
+ -e '20,50s/.*\<ldb_errors.h\>//' \
+ -e '20,50s/.*\<util_ldb.h\>//' \
+ -e '20,50s/.*\<ldap.h\>//' \
+ -e '20,50s/.*\<ldap_ndr.h\>//' \
+ -e '20,50s/.*\<core\/error.h\>//' \
+ -e '20,50s/.*\<gen_ndr\/ndr_samr.h\>//' \
+ -e '20,50s/.*\<gen_ndr\/ndr_samr_c.h\>//' \
+ -e 's/_PUBLIC_//'"
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html/libmapiadmin
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER = doc/doxygen/header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = doc/doxygen/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET = doc/doxygen/apidocs.css
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = _PUBLIC_
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen will always
+# show the root nodes and its direct children regardless of this setting.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
Added: trunk/openchange/libmapiadmin/libmapiadmin-mainpage.doxy
===================================================================
--- trunk/openchange/libmapiadmin/libmapiadmin-mainpage.doxy (rev 0)
+++ trunk/openchange/libmapiadmin/libmapiadmin-mainpage.doxy 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,11 @@
+/**
+\mainpage libmapiadmin
+
+<h2>Client library for OpenChange Administration</h2>
+
+libmapiadmin provides administration client capabilities for
+OpenChange and Exchange servers.
+
+\note As of version 0.8, libmapiadmin is considered alpha quality.
+
+*/
Added: trunk/openchange/libmapiadmin/libmapiadmin.h
===================================================================
--- trunk/openchange/libmapiadmin/libmapiadmin.h (rev 0)
+++ trunk/openchange/libmapiadmin/libmapiadmin.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,114 @@
+/*
+ OpenChange Exchange Administration library.
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 __LIBMAPIADMIN_H__
+#define __LIBMAPIADMIN_H__
+
+#define _GNU_SOURCE 1
+
+struct mapiadmin_ctx;
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+/* Samba4 includes */
+#include <stdint.h>
+#include <talloc.h>
+#include <ldb.h>
+#include <tevent.h>
+
+/* OpenChange includes */
+#include <libmapi/libmapi.h>
+#include <libmapiadmin/proto.h>
+
+#undef _PRINTF_ATTRIBUTE
+#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2)
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+#ifndef MAX
+#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
+#endif
+
+/**
+ \file
+ Structures for MAPI admin functions
+*/
+
+struct test_join {
+ struct dcerpc_pipe *p;
+ struct policy_handle user_handle;
+ struct libnet_JoinDomain *libnet_r;
+ struct dom_sid *dom_sid;
+ const char *dom_netbios_name;
+ const char *dom_dns_name;
+ struct dom_sid *user_sid;
+ struct GUID user_guid;
+ const char *netbios_name;
+};
+
+/**
+ MAPI admin function context
+*/
+struct mapiadmin_ctx
+{
+ struct mapi_session *session;
+ const char *username;
+ const char *password;
+ const char *fullname;
+ const char *description;
+ const char *comment;
+ struct test_join *user_ctx;
+ const char *binding;
+ const char *dc_binding;
+ struct policy_handle *handle;
+};
+
+/*
+ * prototypes from Samba4
+ */
+
+__BEGIN_DECLS
+struct ldb_dn *samdb_search_dn(struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, const char *, ...) _PRINTF_ATTRIBUTE(4,5);
+int samdb_msg_add_string(struct ldb_context *, TALLOC_CTX *,
+ struct ldb_message *, const char *, const char *);
+int samdb_replace(struct ldb_context *, TALLOC_CTX *, struct ldb_message *);
+struct dom_sid *dom_sid_add_rid(TALLOC_CTX *, const struct dom_sid *, uint32_t);
+bool encode_pw_buffer(uint8_t buffer[516], const char *, int);
+void arcfour_crypt_blob(uint8_t *, int, const DATA_BLOB *);
+__END_DECLS
+
+#define DEFAULT_PROFDB_PATH "%s/.openchange/profiles.ldb"
+#define MAPIADMIN_DEBUG_STR "[%s:%d]: %s %s\n", __FUNCTION__, __LINE__
+
+#endif /* __LIBMAPIADMIN_H__ */
Added: trunk/openchange/libmapiadmin/mapiadmin.c
===================================================================
--- trunk/openchange/libmapiadmin/mapiadmin.c (rev 0)
+++ trunk/openchange/libmapiadmin/mapiadmin.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,64 @@
+/*
+ OpenChange Exchange Administration library.
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <libmapiadmin/libmapiadmin.h>
+#include <libmapiadmin/proto_private.h>
+
+/**
+ \file
+ Housekeeping functions for mapiadmin
+*/
+
+/**
+ Create and initialise a mapiadmin_ctx structure
+
+ You should use mapiadmin_release to clean up the mapiadmin_ctx
+ structure when done.
+*/
+_PUBLIC_ struct mapiadmin_ctx *mapiadmin_init(struct mapi_session *session)
+{
+ struct mapiadmin_ctx *mapiadmin_ctx;
+
+ if (!global_mapi_ctx) return NULL;
+ if (!session) return NULL;
+ if (!session->profile) return NULL;
+
+ mapiadmin_ctx = talloc_zero((TALLOC_CTX *)session, struct mapiadmin_ctx);
+
+ mapiadmin_ctx->binding = talloc_asprintf((TALLOC_CTX *)mapiadmin_ctx, "ncacn_np:%s",
+ session->profile->server);
+ mapiadmin_ctx->session = session;
+
+ return mapiadmin_ctx;
+}
+
+/**
+ Clean up a mapiadmin_ctx structure
+
+ The structure is assumed to have been allocated uding mapiadmin_init() or
+ equivalent code.
+*/
+_PUBLIC_ enum MAPISTATUS mapiadmin_release(struct mapiadmin_ctx *mapiadmin_ctx)
+{
+ MAPI_RETVAL_IF(!mapiadmin_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ talloc_free(mapiadmin_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libmapiadmin/mapiadmin_user.c
===================================================================
--- trunk/openchange/libmapiadmin/mapiadmin_user.c (rev 0)
+++ trunk/openchange/libmapiadmin/mapiadmin_user.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,574 @@
+/*
+ OpenChange Exchange Administration library.
+
+ Based on the work by Andrew Tridgell, 2004
+
+ Original source code available in SAMBA_4_0:
+ source/torture/rpc/testjoin.c
+
+ Copyright (C) Julien Kerihuel 2007-2008.
+
+ SAMR related code
+
+ 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 <libmapiadmin/libmapiadmin.h>
+#include <libmapiadmin/proto_private.h>
+
+#include <param.h>
+#include <credentials.h>
+#include <samba/popt.h>
+#include <ldb_errors.h>
+#include <ldb_wrap.h>
+#include <util_ldb.h>
+#include <ldap_ndr.h>
+
+#include <core/error.h>
+#include <gen_ndr/ndr_samr.h>
+#include <gen_ndr/ndr_samr_c.h>
+
+#include <time.h>
+
+/**
+ \file
+ User management functions for mapiadmin
+*/
+
+/**
+ * open connection so SAMR + Join Domain
+ * common code needed when adding or removing users
+ */
+static enum MAPISTATUS mapiadmin_samr_connect(struct mapiadmin_ctx *mapiadmin_ctx,
+ TALLOC_CTX *mem_ctx)
+{
+ NTSTATUS status;
+ struct tevent_context *ev;
+ struct mapi_profile *profile;
+ struct samr_Connect c;
+ struct samr_OpenDomain o;
+ struct samr_LookupDomain l;
+ struct policy_handle handle;
+ struct policy_handle domain_handle;
+ struct lsa_String name;
+
+ MAPI_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!mapiadmin_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!mapiadmin_ctx->session, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile->credentials, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!mapiadmin_ctx->username, MAPI_E_NOT_INITIALIZED, NULL);
+
+ profile = mapiadmin_ctx->session->profile;
+
+ mapiadmin_ctx->user_ctx = talloc_zero(mem_ctx, struct test_join);
+ MAPI_RETVAL_IF(!mapiadmin_ctx->user_ctx, MAPI_E_NOT_ENOUGH_RESOURCES ,NULL);
+
+ DEBUG(3, ("Connecting to SAMR\n"));
+
+ ev = tevent_context_init(mem_ctx);
+
+ status = dcerpc_pipe_connect(mapiadmin_ctx->user_ctx,
+ &mapiadmin_ctx->user_ctx->p,
+ mapiadmin_ctx->dc_binding ?
+ mapiadmin_ctx->dc_binding :
+ mapiadmin_ctx->binding,
+ &ndr_table_samr,
+ profile->credentials, ev, global_mapi_ctx->lp_ctx);
+
+ MAPI_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, NULL);
+
+ profile = mapiadmin_ctx->session->profile;
+
+ c.in.system_name = NULL;
+ c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ c.out.connect_handle = &handle;
+
+ status = dcerpc_samr_Connect(mapiadmin_ctx->user_ctx->p,
+ mapiadmin_ctx->user_ctx, &c);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(mapiadmin_ctx->user_ctx, mapiadmin_ctx->user_ctx->p->last_fault_code);
+ }
+ DEBUG(3, ("samr_Connect failed - %s\n", errstr));
+ return MAPI_E_CALL_FAILED;
+ }
+
+ DEBUG(3, ("Opening domain %s\n", profile->domain));
+
+ name.string = profile->domain;
+ l.in.connect_handle = &handle;
+ l.in.domain_name = &name;
+
+ l.out.sid = talloc(mem_ctx, struct dom_sid2 *);
+ talloc_steal(mapiadmin_ctx->user_ctx, l.out.sid);
+
+ status = dcerpc_samr_LookupDomain(mapiadmin_ctx->user_ctx->p,
+ mapiadmin_ctx->user_ctx, &l);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("LookupDomain failed - %s\n", nt_errstr(status)));
+ return MAPI_E_CALL_FAILED;
+ }
+
+ mapiadmin_ctx->user_ctx->dom_sid = *l.out.sid;
+ mapiadmin_ctx->user_ctx->dom_netbios_name = talloc_strdup(mapiadmin_ctx->user_ctx, profile->domain);
+ if (!mapiadmin_ctx->user_ctx->dom_netbios_name) return MAPI_E_CALL_FAILED;
+
+ o.in.connect_handle = &handle;
+ o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ o.in.sid = *l.out.sid;
+ o.out.domain_handle = &domain_handle;
+
+ status = dcerpc_samr_OpenDomain(mapiadmin_ctx->user_ctx->p, mapiadmin_ctx->user_ctx, &o);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("OpenDomain failed - %s\n", nt_errstr(status)));
+ return MAPI_E_CALL_FAILED;
+ }
+
+ mapiadmin_ctx->handle = talloc_memdup(mem_ctx, &domain_handle, sizeof (struct policy_handle));
+
+ errno = 0;
+ return MAPI_E_SUCCESS;
+}
+
+
+struct tce_async_context {
+ int found;
+};
+
+static int tce_search_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+ struct tce_async_context *actx = talloc_get_type(req->context, struct tce_async_context);
+ int ret;
+
+ switch (ares->type) {
+
+ case LDB_REPLY_ENTRY:
+ if (ldb_msg_find_element(ares->message, "msExchMailboxGuid") != NULL) {
+ DEBUG(3, ("[%s:%d]: msExchMailboxGuid found!\n", __FUNCTION__, __LINE__));
+ actx->found = 1;
+ talloc_free(ares);
+ return ldb_request_done(req, LDB_SUCCESS);
+ }
+ break;
+ case LDB_REPLY_DONE:
+ ret = 0;
+ break;
+ default:
+ DEBUG(3, ("[%s:%d]: unknown Reply Type ignore it\n", __FUNCTION__, __LINE__));
+ talloc_free(ares);
+ return LDB_ERR_OTHER;
+ }
+
+ if (talloc_free(ares) == -1) {
+ DEBUG(3, ("[%s:%d]: talloc_free failed\n", __FUNCTION__, __LINE__));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ return LDB_SUCCESS;
+}
+
+/**
+ * Extend user attributes to be Exchange user
+ */
+_PUBLIC_ enum MAPISTATUS mapiadmin_user_extend(struct mapiadmin_ctx *mapiadmin_ctx)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct tevent_context *ev = NULL;
+ struct mapi_profile *profile;
+ struct ldb_context *remote_ldb;
+ struct ldb_request *req;
+ struct ldb_message *msg;
+ struct ldb_result *res;
+ struct ldb_control **controls;
+ const char *control_strings[2] = { "notification:0", NULL };
+ struct tce_async_context *tce_ctx;
+ const struct dom_sid *dom_sid;
+ char *remote_ldb_url;
+ const char * const dom_attrs[] = { "*", NULL };
+ int ret;
+ uint32_t count;
+ char **values;
+ const char *exch_attrs[7];
+ int i;
+ char *realm = NULL;
+ char *org = NULL;
+ const char *UserAccountControl;
+ struct ldb_dn *account_dn;
+
+ /* Sanity checks */
+ MAPI_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!mapiadmin_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!mapiadmin_ctx->session, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile->credentials, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!mapiadmin_ctx->user_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ profile = mapiadmin_ctx->session->profile;
+ dom_sid = mapiadmin_ctx->user_ctx->user_sid;
+
+ /* initialize memory context */
+ mem_ctx = talloc_named(NULL, 0, "mapiadmin_user_extend");
+
+ /* open LDAP connection */
+ ev = tevent_context_init(talloc_autofree_context());
+ remote_ldb_url = talloc_asprintf(mem_ctx, "ldap://%s", profile->server);
+ MAPI_RETVAL_IF(!remote_ldb_url, MAPI_E_CORRUPT_DATA, mem_ctx);
+ remote_ldb = ldb_wrap_connect(mem_ctx, ev, global_mapi_ctx->lp_ctx, remote_ldb_url,
+ NULL, mapiadmin_ctx->session->profile->credentials, 0, NULL);
+ MAPI_RETVAL_IF(!remote_ldb, MAPI_E_NETWORK_ERROR, mem_ctx);
+
+ /* Search the user_dn */
+ account_dn = samdb_search_dn(remote_ldb, mem_ctx, NULL,
+ "(&(objectSid=%s)(objectClass=user))",
+ ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
+
+ ret = ldb_search(remote_ldb, mem_ctx, &res, account_dn, LDB_SCOPE_SUBTREE, dom_attrs, "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
+ MAPI_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, mem_ctx);
+ MAPI_RETVAL_IF(res->count != 1, MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Prepare a new message for modify */
+ msg = ldb_msg_new(mem_ctx);
+ MAPI_RETVAL_IF(!msg, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ msg->dn = res->msgs[0]->dn;
+
+ /* message: givenName */
+ exch_attrs[0] = talloc_strdup(mem_ctx, mapiadmin_ctx->username);
+ ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "givenName", exch_attrs[0]);
+ MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ /* message: userAccountControl */
+ exch_attrs[1] = talloc_asprintf(mem_ctx, "513");
+ ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "userAccountControl",
+ exch_attrs[1]);
+ MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+ msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
+
+ /* message: mail */
+ retval = GetProfileAttr(profile, "ProxyAddress", &count, &values);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ for (i = 0; i < count; i++) {
+ if (values[i] && !strncasecmp("smtp", values[i], 4)) {
+ realm = strchr(values[i], '@');
+ realm += 1;
+ }
+ }
+ MAPI_RETVAL_IF(!realm, MAPI_E_NOT_FOUND, mem_ctx);
+
+ exch_attrs[2] = talloc_asprintf(mem_ctx, "%s@%s", mapiadmin_ctx->username, realm);
+ ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "mail", exch_attrs[2]);
+ MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ /* message: mailNickname */
+ exch_attrs[3] = talloc_strdup(mem_ctx, mapiadmin_ctx->username);
+ ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "mailNickname", exch_attrs[3]);
+ MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ /* message: mDBUseDefaults */
+ exch_attrs[4] = talloc_asprintf(mem_ctx, "TRUE");
+ ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
+ "mDBUseDefaults", exch_attrs[4]);
+ MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ /* message: legacyExchangeDN */
+ org = talloc_strndup(mem_ctx, profile->mailbox,
+ strlen(profile->mailbox) - strlen(profile->username));
+ exch_attrs[5] = talloc_asprintf(mem_ctx, "%s%s", org, mapiadmin_ctx->username);
+ talloc_free(org);
+ ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
+ "legacyExchangeDN", exch_attrs[5]);
+ MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ /* message: msExchHomeServerName */
+ exch_attrs[6] = talloc_strdup(mem_ctx, profile->homemdb);
+ ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
+ "msExchHomeServerName", exch_attrs[6]);
+ MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ /* Prior we call ldb_modify, set up async ldb request on
+ * msExchMailboxGuid
+ */
+ req = talloc_zero(mem_ctx, struct ldb_request);
+ tce_ctx = talloc_zero(mem_ctx, struct tce_async_context);
+ controls = ldb_parse_control_strings(remote_ldb, mem_ctx, control_strings);
+
+ ret = ldb_build_search_req(&req, remote_ldb, mem_ctx,
+ msg->dn,
+ LDB_SCOPE_BASE,
+ "(objectclass=*)",
+ NULL,
+ controls,
+ (void *)tce_ctx,
+ tce_search_callback,
+ NULL);
+ DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_build_search_req", ldb_strerror(ret)));
+ MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CALL_FAILED, mem_ctx);
+
+ ldb_set_timeout(mem_ctx, req, 60);
+
+ ret = ldb_request(remote_ldb, req);
+ DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_request", ldb_strerror(ret)));
+ MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CALL_FAILED, mem_ctx);
+
+ ret = ldb_modify(remote_ldb, msg);
+ DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_modify", ldb_strerror(ret)));
+ MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CORRUPT_DATA, mem_ctx);
+
+ /* async search */
+ ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+ DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_wait", ldb_strerror(ret)));
+ MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CALL_FAILED, mem_ctx);
+ MAPI_RETVAL_IF(!tce_ctx->found, MAPI_E_CALL_FAILED, mem_ctx);
+
+ /* When successful replace UserAccountControl attr in the user
+ * record
+ */
+ talloc_free(msg);
+ msg = ldb_msg_new(mem_ctx);
+ MAPI_RETVAL_IF(!msg, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+ msg->dn = res->msgs[0]->dn;
+
+ UserAccountControl = talloc_asprintf(mem_ctx, "66048");
+ ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
+ "UserAccountControl", UserAccountControl);
+ MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+
+ ret = samdb_replace(remote_ldb, mem_ctx, msg);
+ DEBUG(3, (MAPIADMIN_DEBUG_STR, "samdb_replace", ldb_strerror(ret)));
+ MAPI_RETVAL_IF((ret != 0), MAPI_E_CORRUPT_DATA, mem_ctx);
+
+ /* reset errno before leaving */
+ errno = 0;
+ talloc_free(mem_ctx);
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * Add a user to Active Directory
+ */
+_PUBLIC_ enum MAPISTATUS mapiadmin_user_add(struct mapiadmin_ctx *mapiadmin_ctx)
+{
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ struct mapi_profile *profile;
+ struct samr_CreateUser2 r;
+ struct samr_GetUserPwInfo pwp;
+ struct samr_SetUserInfo s;
+ union samr_UserInfo u;
+ uint32_t access_granted;
+ uint32_t rid;
+ DATA_BLOB session_key;
+ struct lsa_String name;
+ int policy_min_pw_len = 0;
+
+ mem_ctx = talloc_named(NULL, 0, "mapiadmin_user_add");
+
+ retval = mapiadmin_samr_connect(mapiadmin_ctx, mem_ctx);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ DEBUG(3, ("Creating account %s\n", mapiadmin_ctx->username));
+ profile = mapiadmin_ctx->session->profile;
+
+again:
+ name.string = mapiadmin_ctx->username;
+ r.in.domain_handle = mapiadmin_ctx->handle;
+ r.in.account_name = &name;
+ r.in.acct_flags = ACB_NORMAL;
+ r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ r.out.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
+ r.out.access_granted = &access_granted;
+ r.out.rid = &rid;
+
+ status = dcerpc_samr_CreateUser2(mapiadmin_ctx->user_ctx->p,
+ mapiadmin_ctx->user_ctx, &r);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
+ mapiadmin_user_del(mapiadmin_ctx);
+ if (NT_STATUS_IS_OK(status)) {
+ goto again;
+ } else {
+ MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
+ }
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("CreateUser2 failed - %s\n", nt_errstr(status)));
+ MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
+ }
+
+ mapiadmin_ctx->user_ctx->user_sid = dom_sid_add_rid(mapiadmin_ctx->user_ctx, mapiadmin_ctx->user_ctx->dom_sid, rid);
+
+ pwp.in.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
+ pwp.out.info = talloc_zero(mem_ctx, struct samr_PwInfo);
+
+ status = dcerpc_samr_GetUserPwInfo(mapiadmin_ctx->user_ctx->p, mapiadmin_ctx->user_ctx, &pwp);
+ if (NT_STATUS_IS_OK(status)) {
+ policy_min_pw_len = pwp.out.info->min_password_length;
+ } else {
+ DEBUG(3, ("GetUserPwInfo failed - %s\n", nt_errstr(status)));
+ MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
+ }
+
+ if (!mapiadmin_ctx->password) {
+ mapiadmin_ctx->password = generate_random_str(mapiadmin_ctx->user_ctx, MAX(8, policy_min_pw_len));
+ }
+
+ DEBUG(3, ("Setting account password '%s'\n", mapiadmin_ctx->password));
+
+ ZERO_STRUCT(u);
+ s.in.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
+ s.in.info = &u;
+ s.in.level = 24;
+
+ encode_pw_buffer(u.info24.password.data, mapiadmin_ctx->password, STR_UNICODE);
+ u.info24.password_expired = 0;
+
+ status = dcerpc_fetch_session_key(mapiadmin_ctx->user_ctx->p, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("SetUserInfo level %u - no session key - %s\n",
+ s.in.level, nt_errstr(status)));
+ mapiadmin_user_del(mapiadmin_ctx);
+ MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
+ }
+
+ arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
+
+ status = dcerpc_samr_SetUserInfo(mapiadmin_ctx->user_ctx->p, mapiadmin_ctx->user_ctx, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("SetUserInfo failed - %s\n", nt_errstr(status)));
+ if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
+ MAPI_RETVAL_IF(1, MAPI_E_BAD_VALUE, mem_ctx);
+ } else {
+ MAPI_RETVAL_IF(1, MAPI_E_CALL_FAILED, mem_ctx);
+ }
+ }
+
+ ZERO_STRUCT(u);
+ s.in.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
+ s.in.info = &u;
+ s.in.level = 21;
+
+ u.info21.acct_flags = ACB_NORMAL | ACB_PWNOEXP;
+ u.info21.fields_present = SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME;
+
+ u.info21.comment.string = talloc_asprintf(mapiadmin_ctx->user_ctx,
+ mapiadmin_ctx->comment ?
+ mapiadmin_ctx->comment :
+ "Created by OpenChange: %s",
+ timestring(mapiadmin_ctx->user_ctx, time(NULL)));
+
+ u.info21.full_name.string = talloc_asprintf(mapiadmin_ctx->user_ctx,
+ mapiadmin_ctx->fullname ?
+ mapiadmin_ctx->fullname :
+ "Account for OpenChange: %s",
+ timestring(mapiadmin_ctx->user_ctx, time(NULL)));
+
+ u.info21.description.string = talloc_asprintf(mapiadmin_ctx->user_ctx,
+ mapiadmin_ctx->description ?
+ mapiadmin_ctx->description :
+ "OpenChange account created by host %s: %s",
+ lp_netbios_name(global_mapi_ctx->lp_ctx),
+ timestring(mapiadmin_ctx->user_ctx, time(NULL)));
+
+ DEBUG(3, ("Resetting ACB flags, force pw change time\n"));
+
+ status = dcerpc_samr_SetUserInfo(mapiadmin_ctx->user_ctx->p, mapiadmin_ctx->user_ctx, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("SetUserInfo failed - %s\n", nt_errstr(status)));
+ MAPI_RETVAL_IF(1, MAPI_E_CALL_FAILED, mem_ctx);
+ }
+ retval = mapiadmin_user_extend(mapiadmin_ctx);
+ if (retval != MAPI_E_SUCCESS) {
+ DEBUG(3, ("mapiadmin_user_extend: 0x%x\n", GetLastError()));
+ mapiadmin_user_del(mapiadmin_ctx);
+ MAPI_RETVAL_IF(1, MAPI_E_CALL_FAILED,mem_ctx);
+ }
+
+ talloc_free(mem_ctx);
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * Delete a user from Active Directory
+ */
+_PUBLIC_ enum MAPISTATUS mapiadmin_user_del(struct mapiadmin_ctx *mapiadmin_ctx)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ NTSTATUS status;
+ struct samr_DeleteUser d;
+ struct policy_handle user_handle;
+ uint32_t rid;
+ struct samr_LookupNames n;
+ struct lsa_String sname;
+ struct samr_OpenUser r;
+
+ MAPI_RETVAL_IF(!mapiadmin_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!mapiadmin_ctx->username, MAPI_E_NOT_INITIALIZED, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "mapiadmin_user_del");
+
+ /* Initiate SAMR connection if not already done */
+ if (!mapiadmin_ctx->user_ctx) {
+ retval = mapiadmin_samr_connect(mapiadmin_ctx, mem_ctx);
+ MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
+ }
+
+ sname.string = mapiadmin_ctx->username;
+
+ n.in.domain_handle = mapiadmin_ctx->handle;
+ n.in.num_names = 1;
+ n.in.names = &sname;
+
+ n.out.rids = talloc_zero(mem_ctx, struct samr_Ids);
+ n.out.types = talloc_zero(mem_ctx, struct samr_Ids);
+
+ status = dcerpc_samr_LookupNames(mapiadmin_ctx->user_ctx->p, mem_ctx, &n);
+ if (NT_STATUS_IS_OK(status)) {
+ rid = n.out.rids->ids[0];
+ } else {
+ talloc_free(mem_ctx);
+ return MAPI_E_NOT_FOUND;
+ }
+
+ r.in.domain_handle = mapiadmin_ctx->handle;
+ r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ r.in.rid = rid;
+ r.out.user_handle = &user_handle;
+
+ status = dcerpc_samr_OpenUser(mapiadmin_ctx->user_ctx->p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("OpenUser(%s) failed - %s\n", mapiadmin_ctx->username, nt_errstr(status)));
+ MAPI_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_NOT_FOUND, mem_ctx);
+ }
+
+ d.in.user_handle = &user_handle;
+ d.out.user_handle = &user_handle;
+ status = dcerpc_samr_DeleteUser(mapiadmin_ctx->user_ctx->p, mem_ctx, &d);
+ MAPI_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
+
+ talloc_free(mem_ctx);
+ return MAPI_E_SUCCESS;
+}
+
+_PUBLIC_ enum MAPISTATUS mapiadmin_user_mod(struct mapiadmin_ctx *mapiadmin)
+{
+ return MAPI_E_NO_SUPPORT;
+}
Added: trunk/openchange/libmapiadmin.pc.in
===================================================================
--- trunk/openchange/libmapiadmin.pc.in (rev 0)
+++ trunk/openchange/libmapiadmin.pc.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@prefix@/share
+datadir=@datadir@
+
+Name: MAPI Administration
+Description: MAPI Administration Implementation
+Version: @PACKAGE_VERSION@
+Libs: @LIBS@
+Cflags: @CFLAGS@
+Requires: talloc dcerpc ndr samba-hostconfig ldb
Added: trunk/openchange/libocpf/Doxyfile.in
===================================================================
--- trunk/openchange/libocpf/Doxyfile.in (rev 0)
+++ trunk/openchange/libocpf/Doxyfile.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1276 @@
+# Doxyfile 1.5.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = "OpenChange Property Files"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = apidocs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = libocpf
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.h *.c *.doxy
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = *_private.h
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = *.yy.c *_private.h ocpf_api.*
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = libocpf/examples
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = doc/doxygen/pictures/
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER = "sed \
+ -e '20,40s/.*\<libmapi\/proto_private.h\>//' \
+ -e '20,40s/.*\<gen_ndr\/ndr_exchange.h\>//' \
+ -e '20,40s/.*\<param.h\>//' \
+ -e '20,40s/.*\<core\/error.h\>//' \
+ -e '20,40s/.*\<credentials.h\>//' \
+ -e '20,40s/.*\<ldb.h\>//' \
+ -e '20,40s/.*\<ldb_errors.h\>//' \
+ -e '20,40s/.*\<libmapi\/dlinklist.h\>//' \
+ -e '20,40s/.*\<libmapi\/defs_private.h\>//' \
+ -e '20,40s/.*\<libmapi\/mapi_nameid.h\>//' \
+ -e '20,40s/.*\<libmapi\/mapi_nameid_private.h\>//' \
+ -e '20,40s/.*\<libocpf\/proto_private.h\>//' \
+ -e '20,40s/.*\<libocpf\/ocpf_api.h\>//' \
+ -e '20,40s/.*\<libocpf\/ocpf.tab.h\>//' \
+ -e '20,40s/.*\<libocpf\/ocpf_dump.h\>//' \
+ -e '20,40s/.*\<libgen.h\>//' \
+ -e '20,40s/.*\<time.h\>//' \
+ -e '20,40s/.*\<sys\/*\>//' \
+ -e '20,40s/_PUBLIC_//'"
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html/libocpf
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER = doc/doxygen/header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = doc/doxygen/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET = doc/doxygen/apidocs.css
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = _PUBLIC_
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen will always
+# show the root nodes and its direct children regardless of this setting.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
Added: trunk/openchange/libocpf/examples/common_OLEGUID.ocpf
===================================================================
--- trunk/openchange/libocpf/examples/common_OLEGUID.ocpf (rev 0)
+++ trunk/openchange/libocpf/examples/common_OLEGUID.ocpf 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,29 @@
+/*
+ * OpenChange Property File
+ *
+ * Copyright (C) Julien Kerihuel 2008.
+ *
+ * Registers common OLEGUID
+ *
+ * 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/>
+ */
+
+OLEGUID PSETID_Appointment "00062002-0000-0000-c000-000000000046"
+OLEGUID PSETID_Task "00062003-0000-0000-c000-000000000046"
+OLEGUID PSETID_Address "00062004-0000-0000-c000-000000000046"
+OLEGUID PSETID_Common "00062008-0000-0000-c000-000000000046"
+OLEGUID PSETID_Note "0006200e-0000-0000-c000-000000000046"
+OLEGUID PSETID_Log "0006200a-0000-0000-c000-000000000046"
+OLEGUID PS_PUBLIC_STRINGS "00020329-0000-0000-c000-000000000046"
+OLEGUID PS_INTERNET_HEADERS "00020386-0000-0000-c000-000000000046"
Added: trunk/openchange/libocpf/examples/sample_appointment.ocpf
===================================================================
--- trunk/openchange/libocpf/examples/sample_appointment.ocpf (rev 0)
+++ trunk/openchange/libocpf/examples/sample_appointment.ocpf 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,67 @@
+/*
+ * OpenChange Property File
+ *
+ * Copyright (C) Julien Kerihuel 2008.
+ *
+ * Sample appointment
+ *
+ * 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/>
+ */
+
+TYPE "IPM.Appointment"
+
+FOLDER "olFolderCalendar"
+
+OLEGUID PSETID_Appointment "00062002-0000-0000-c000-000000000046"
+OLEGUID PSETID_Common "00062008-0000-0000-c000-000000000046"
+OLEGUID PS_PUBLIC_STRINGS "00020329-0000-0000-c000-000000000046"
+
+SET $subject = "[OCPF] Julien Kerihuel Birthday"
+SET $start_date = T2008-03-06 22:00:00
+SET $end_date = T2008-03-06 23:45:00
+SET $reminder = 45
+SET $keywords = { "candles", "friends", "family" }
+SET $private = B"true"
+SET $wrong = 0
+
+PROPERTY {
+ PR_CONVERSATION_TOPIC = $subject
+ PR_NORMALIZED_SUBJECT = $subject
+ PR_BODY = "Another year, another pleasure"
+ PR_START_DATE = $start_date
+ PR_END_DATE = $end_date
+ PR_SENSITIVITY = 2
+};
+
+NPROPERTY {
+ OOM:Label:PSETID_Appointment = 9
+
+ OOM:Start:PSETID_Appointment = $start_date
+ OOM:CommonStart:PSETID_Common = $start_date
+ OOM:End:PSETID_Appointment = $end_date
+ OOM:CommonEnd:PSETID_Common = $end_date
+
+ OOM:Location:PSETID_Appointment = "Home Sweet Home"
+
+ /* MeetingStatus */
+ MNID_ID:0x8217:PSETID_Appointment = $wrong
+
+ OOM:Private:PSETID_Common = $private
+
+ /* Set a reminder */
+ MNID_ID:0x8501:PT_LONG:PSETID_Common = $reminder
+
+ /* Add categories */
+ MNID_STRING:"Keywords":PS_PUBLIC_STRINGS = $keywords
+};
\ No newline at end of file
Added: trunk/openchange/libocpf/examples/sample_task.ocpf
===================================================================
--- trunk/openchange/libocpf/examples/sample_task.ocpf (rev 0)
+++ trunk/openchange/libocpf/examples/sample_task.ocpf 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,51 @@
+/*
+ * OpenChange Property File
+ *
+ * Copyright (C) Julien Kerihuel 2008.
+ *
+ * Sample task
+ *
+ * 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/>
+ */
+
+TYPE "IPM.Task"
+FOLDER "olFolderTasks"
+
+OLEGUID PSETID_Task "00062003-0000-0000-c000-000000000046"
+OLEGUID PSETID_Common "00062008-0000-0000-c000-000000000046"
+OLEGUID PS_PUBLIC_STRINGS "00020329-0000-0000-c000-000000000046"
+
+SET $subject = "[OCPF] Sample Task"
+SET $body = "This is the sample task body"
+SET $start_date = T2008-03-06 20:00:00
+SET $end_date = T2008-03-06 23:00:00
+SET $importance = 2 /* IMPORTANCE_HIGH */
+SET $task_status = 3 /* Waiting */
+
+PROPERTY {
+ PR_CONVERSATION_TOPIC = $subject
+ PR_NORMALIZED_SUBJECT = $subject
+ PR_BODY = $body
+ PR_IMPORTANCE = $importance
+ PR_SENSITIVITY = 2 /* needed to have private box ticked */
+};
+
+NPROPERTY {
+ OOM:Companies:PSETID_Common = {"OpenChange Project", "Samba Project" }
+ OOM:StartDate:PSETID_Task = $start_date
+ OOM:DueDate:PSETID_Task = $end_date
+ OOM:Status:PSETID_Task = $task_status
+ OOM:Private:PSETID_Common = B"true"
+ MNID_STRING:"Keywords":PS_PUBLIC_STRINGS = { "Category1", "Category2" }
+};
\ No newline at end of file
Added: trunk/openchange/libocpf/lex.h
===================================================================
--- trunk/openchange/libocpf/lex.h (rev 0)
+++ trunk/openchange/libocpf/lex.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,29 @@
+/*
+ OpenChange OCPF (OpenChange Property File) implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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 __LEX_H_
+#define __LEX_H_
+
+void error_message (const char *, ...) __attribute__ ((format (printf, 1, 2)));
+
+extern int error_flag;
+
+int ocpf_yylex(void);
+
+#endif /* __LEX_H_ */
Added: trunk/openchange/libocpf/lex.l
===================================================================
--- trunk/openchange/libocpf/lex.l (rev 0)
+++ trunk/openchange/libocpf/lex.l 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,320 @@
+/*
+ OpenChange OCPF (OpenChange Property File) implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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 <stdarg.h>
+#include <ctype.h>
+
+#include "libocpf/ocpf_private.h"
+#include <libocpf/ocpf_api.h>
+#include <libocpf/ocpf.tab.h>
+#include <libocpf/lex.h>
+
+struct ocpf *ocpf;
+unsigned lineno = 1;
+
+#define YY_DECL int ocpf_yylex(void)
+
+/*
+ * Prototypes
+ */
+
+int yyget_lineno(void);
+FILE *yyget_in(void);
+FILE *yyget_out(void);
+int yyget_leng(void);
+char *yyget_text(void);
+void yyset_lineno(int);
+void yyset_in (FILE *);
+void yyset_out (FILE *);
+int yyget_debug(void);
+void yyset_debug(int);
+int yylex_destroy(void);
+
+
+static void unterminated(const char *, unsigned);
+
+%}
+
+%%
+TYPE { return kw_TYPE; }
+FOLDER { return kw_FOLDER; }
+OLEGUID { return kw_OLEGUID; }
+SET { return kw_SET; }
+PROPERTY { return kw_PROPERTY; }
+NPROPERTY { return kw_NPROPERTY; }
+TO { return kw_TO; }
+CC { return kw_CC; }
+BCC { return kw_BCC; }
+RECIPIENT { return kw_RECIPIENT; }
+OOM { return kw_OOM; }
+MNID_ID { return kw_MNID_ID; }
+MNID_STRING { return kw_MNID_STRING; }
+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_SYSTIME { return kw_PT_SYSTIME; }
+PT_BOOLEAN { return kw_PT_BOOLEAN; }
+PT_MV_STRING8 { return kw_PT_MV_STRING8; }
+PT_BINARY { return kw_PT_BINARY; }
+\{ { return OBRACE; }
+\} { return EBRACE; }
+, { return COMMA; }
+; { return SEMICOLON; }
+: { return COLON; }
+\< { return LOWER; }
+\> { return GREATER; }
+= { return EQUAL;}
+\/\* {
+ int c, start_lineno = lineno;
+ int level = 1;
+ int seen_star = 0;
+ int seen_slash = 0;
+ while((c = input()) != EOF) {
+ if(c == '/') {
+ if(seen_star) {
+ if(--level == 0)
+ break;
+ seen_star = 0;
+ continue;
+ }
+ seen_slash = 1;
+ continue;
+ }
+ if(seen_star && c == '/') {
+ if(--level == 0)
+ break;
+ seen_star = 0;
+ continue;
+ }
+ if(c == '*') {
+ if(seen_slash) {
+ level++;
+ seen_star = seen_slash = 0;
+ continue;
+ }
+ seen_star = 1;
+ continue;
+ }
+ seen_star = seen_slash = 0;
+ if(c == '\n') {
+ lineno++;
+ continue;
+ }
+ }
+ if(c == EOF)
+ unterminated("comment", start_lineno);
+ }
+"\"" {
+ int start_lineno = lineno;
+ int c, c2;
+ char buf[0x4000];
+ char *p = buf;
+ int f = 0;
+ int skip_ws = 0;
+
+ while((c = input()) != EOF) {
+ if(isspace(c) && skip_ws) {
+ if(c == '\n')
+ lineno++;
+ continue;
+ }
+ skip_ws = 0;
+
+ if (c == '\\') {
+ c2 = c;
+ c = input();
+ if (c == '"') {
+ *p++ = c;
+ c = input();
+ } else {
+ *p++ = c2;
+ }
+ }
+
+ if(c == '"') {
+ if(f) {
+ *p++ = '"';
+ f = 0;
+ } else {
+ f = 1;
+ }
+ continue;
+ }
+ if(f == 1) {
+ unput(c);
+ break;
+ }
+ if(c == '\n') {
+ lineno++;
+ while(p > buf && isspace((unsigned char)p[-1]))
+ p--;
+ skip_ws = 1;
+ continue;
+ }
+ *p++ = c;
+ }
+ if(c == EOF)
+ unterminated("string", start_lineno);
+ *p++ = '\0';
+ ocpf_yylval.name = buf;
+ return STRING;
+ }
+W"\"" {
+ int start_lineno = lineno;
+ int c, c2;
+ char buf[0x4000];
+ char *p = buf;
+ int f = 0;
+ int skip_ws = 0;
+
+ while((c = input()) != EOF) {
+ if(isspace(c) && skip_ws) {
+ if(c == '\n')
+ lineno++;
+ continue;
+ }
+ skip_ws = 0;
+
+ if (c == '\\') {
+ c2 = c;
+ c = input();
+ if (c == '"') {
+ *p++ = c;
+ c = input();
+ } else {
+ *p++ = c2;
+ }
+ }
+
+ if(c == '"') {
+ if(f) {
+ *p++ = '"';
+ f = 0;
+ } else {
+ f = 1;
+ }
+ continue;
+ }
+ if(f == 1) {
+ unput(c);
+ break;
+ }
+ if(c == '\n') {
+ lineno++;
+ while(p > buf && isspace((unsigned char)p[-1]))
+ p--;
+ skip_ws = 1;
+ continue;
+ }
+ *p++ = c;
+ }
+ if(c == EOF)
+ unterminated("string", start_lineno);
+ *p++ = '\0';
+ ocpf_yylval.name = buf;
+ return UNICODE;
+ }
+\$[-A-Za-z0-9_]+ { char *y = yytext + 1;
+ ocpf_yylval.var = strdup((const char *)y);
+ return VAR;
+ }
+B\"true\"|-?B\"false\" { char *y = yytext + 1;
+ if (y && !strcmp(y, "\"true\"")) {
+ ocpf_yylval.b = true;
+ } else {
+ ocpf_yylval.b = false;
+ }
+ return BOOLEAN;
+ }
+T[0-9]{4}-[0-9]{2}-[0-9]{2}[ ][0-9]{2}\:[0-9]{2}\:[0-9]{2} {
+ ocpf_yylval.date = strdup((const char *)yytext + 1);
+ return SYSTIME;
+ }
+0x[0-9A-Fa-f]+ { char *e, *y = yytext;
+ ocpf_yylval.l = strtoul((const char *)y, &e, 0);
+ if (e == y)
+ error_message("malformed constant (%s)", yytext);
+ else
+ return INTEGER;
+
+}
+S0x[0-9A-Fa-f]+|-S[0-9]+ {
+ char *e, *y;
+ y = (yytext[0] == 'S') ? yytext + 1 : yytext;
+ ocpf_yylval.s = strtoul((const char *)y, &e, 0);
+ if (e == y)
+ error_message("malformed constant (%s)", yytext);
+ else
+ return SHORT;
+ }
+
+L0x[0-9A-Fa-f]+|-?[0-9]+ { char *e, *y;
+ y = (yytext[0] == 'L') ? yytext + 1 : yytext;
+ ocpf_yylval.l = strtoul((const char *)y, &e, 0);
+ if(e == y)
+ error_message("malformed constant (%s)", yytext);
+ else
+ return INTEGER;
+ }
+D0x[0-9A-Fa-f]+ {char *e, *y = yytext + 1;
+ ocpf_yylval.d = strtoull((const char *)y,
+ &e, 0);
+ if(e == y)
+ error_message("malformed constant (%s)", yytext);
+ else
+ return DOUBLE;
+
+ }
+[A-Za-z][-A-Za-z0-9_]* {
+ ocpf_yylval.name = strdup((const char *)yytext);
+ return IDENTIFIER;
+ }
+[ \t]+ ;
+\n { ++lineno; }
+. { error_message("Ignoring char(%c)\n", *yytext); }
+%%
+
+#ifndef yywrap
+int
+yywrap(void)
+{
+ return 1;
+}
+#endif
+
+void error_message(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ fprintf(stderr, "ERROR: %s:%d: ", ocpf_get_filename(), lineno);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ error_flag++;
+}
+
+static void
+unterminated(const char *type, unsigned start_lineno)
+{
+ error_message("unterminated %s, possibly started on line %d\n", type, start_lineno);
+}
\ No newline at end of file
Added: trunk/openchange/libocpf/ocpf-documentation.doxy
===================================================================
--- trunk/openchange/libocpf/ocpf-documentation.doxy (rev 0)
+++ trunk/openchange/libocpf/ocpf-documentation.doxy 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,834 @@
+/**
+\mainpage OpenChange Property File (OCPF)
+
+\section ocpf OpenChange Property File (OCPF)
+
+\section Contents
+<ul>
+ <li><a href="#revision"> Revision History </a></li>
+ <li><a href="#introduction"> 1. Introduction </a></li>
+ <li><a href="#purpose"> 2. Purpose and Scope </a></li>
+ <li><a href="#limit"> 3. Limitations and Bugs </a></li>
+ <li><a href="#syntax"> 4. Syntax </a></li>
+ <li><a href="#keywords"> 5. Top Level Keywords </a>
+ <ul>
+ <li><a href="#type"> 5.1. TYPE </a></li>
+ <li><a href="#folder"> 5.2. FOLDER </a></li>
+ <li><a href="#set"> 5.3. SET </a></li>
+ <li><a href="#oleguid"> 5.4. OLEGUID </a></li>
+ <li><a href="#recipient"> 5.5. RECIPIENT </a></li>
+ <li><a href="#property"> 5.6. PROPERTY section </a></li>
+ <li><a href="#nproperty"> 5.7. NPROPERTY section </a></li>
+ </ul>
+ </li>
+ <li><a href="#properties"> 6. Known Properties </a>
+ <ul>
+ <li><a href="#propname"> 6.1. Property Name </a></li>
+ <li><a href="#proptag"> 6.2. Property Tag </a></li>
+ </ul>
+ </li>
+ <li><a href="#nproperties"> 7. Named Properties </a>
+ <ul>
+ <li><a href="#OOM"> 7.1. OOM </a></li>
+ <li><a href="#MNID_ID"> 7.2. MNID_ID </a></li>
+ <li><a href="#MNID_STRING"> 7.3. MNID_STRING </a></li>
+ </ul>
+ </li>
+ <li><a href="#proptype"> 8. Supported Property Types </a>
+ <ul>
+ <li><a href="#boolean"> 8.1. PT_BOOLEAN </a></li>
+ <li><a href="#short"> 8.2. PT_SHORT </a></li>
+ <li><a href="#long"> 8.3. PT_LONG </a></li>
+ <li><a href="#double"> 8.4. PT_I8 </a></li>
+ <li><a href="#string8"> 8.5. PT_STRING8 </a></li>
+ <li><a href="#unicode"> 8.6. PT_UNICODE </a></li>
+ <li><a href="#systime"> 8.7. PT_SYSTIME </a></li>
+ <li><a href="#mv_string8"> 8.8. PT_MV_STRING8 </a></li>
+ <li><a href="#binary"> 8.9. PT_BINARY </a></li>
+ </ul>
+ </li>
+ <li><a href="#comments"> 9. Comments </a>
+ </li>
+ <li><a href="#tools"> 10. OCPF and openchangeclient </a>
+ <ul>
+ <li><a href="#syntax"> 10.1. ocpf_syntax </a></li>
+ <li><a href="#sender"> 10.2. ocpf_sender </a></li>
+ <li><a href="#dump"> 10.3 ocpf_dump </a></li>
+ </ul>
+ </li>
+</ul>
+<br/>
+
+<a name="revision"></a><h2>Revision History</h2>
+<table align="center" width="80%">
+ <tr>
+ <td style="text-align:center"><strong>Date</strong></td>
+ <td style="text-align:center"><strong>Revision Number</strong></td>
+ <td style="text-align:center"><strong>Author</strong></td>
+ <td style="text-align:center"><strong>Revision Content</strong></td>
+ </tr>
+ <tr>
+ <td style="text-align:center">01/04/08</td>
+ <td style="text-align:center"><strong>0.5</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:center">Add RECIPIENT support</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">29/03/08</td>
+ <td style="text-align:center"><strong>0.4</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:center">Add PT_UNICODE support and ocpf_dump option</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">06/03/08</td>
+ <td style="text-align:center"><strong>0.3</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:center">Add PT_BINARY and Streams support</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">05/03/08</td>
+ <td style="text-align:center"><strong>0.2</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:center">Improve PT_MV_STRING8 support</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">03/03/08</td>
+ <td style="text-align:center"><strong>0.1</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:center">Initial Revision</td>
+ </tr>
+</table>
+<br/>
+
+<a name="introduction"></a><h2>1. Introduction</h2>
+
+OCPF stands for OpenChange Property Files. This is a tiny file format
+designed for scripting and which facilitates third-party applications
+interaction and developers work using OpenChange. The main objective
+of OCPF is to offer the possibility to go beyond OpenChange tools
+default properties and create a custom message with user-defined
+fields.
+<br/>
+
+<a name="purpose"></a><h2>2. Purpose and Scope</h2>
+
+OCPF is designed to be used in various kind of applications and for
+different purposes:
+<ul>
+
+ <li><strong>Research on properties</strong>: OpenChange developers
+ have often requested for an easy way to test properties and
+ properties values. Prior to OCPF, developers had to write an application
+ linked with libmapi and compile it so that they could test
+ properties. Moreover, adding new named properties in trunk was kept
+ under OpenChange commiters agreement. OCPF solves this issue and
+ allow developers to write OCPF files with custom properties that they can
+ send using OpenChange tools. Furthermore OCPF will provide the
+ community a convenient way to agree on a particular property.</li>
+
+ <li><strong>Web Applications</strong>: OCPF offers a scripted
+ language with substitution variables which makes it possible to use OCPF
+ templates and use OCPF in conjunction with Web Forms. Since OCPF API
+ supports the parsing of multiple files, developers can plan to have
+ a file with variable declarations and a separate OCPF template that just
+ specifies variables.</li>
+
+ <li><strong>Backup/Restore</strong>: OCPF format may offer an easy
+ way for a restore/backup application to dump to the local filesystem
+ and restore messages on Exchange server. Furthermore, substitution of
+ variables can possibly be used to maintain the new hierarchy, such
+ as changing folders ID across Exchange servers and help migrating
+ database from a server to another.</li>
+
+</ul>
+<br/>
+
+
+<a name="limit"></a><h2>3. Limitations and Bugs </a></h2>
+
+OCPF is a pretty new library and it currently has a some limitations:
+<ul>
+ <li> It only supports a very limited set of property types </li>
+ <li> It doesn't support attachment yet </li>
+</ul>
+
+These limitations will be removed in later versions of OCPF.
+
+If you find bugs, limitations or encounter issues while using the OCPF
+library, please consider reporting them on <a
+href="http://trac.openchange.org">http://trac.openchange.org</a> and
+select the libocpf component. (Note: registration is required to create
+new tickets).
+
+For questions about its usage or about libocpf development, please
+post on the <a href="http://mailman.openchange.org/listinfo/devel">
+OpenChange devel mailing-list.</a>
+<br/>
+
+
+<a name="syntax"></a><h2>4. Syntax</h2>
+
+The general OCPF syntax is pretty basic. It mostly consists of
+top-level keywords, sections and properties types.
+<br/>
+
+
+<a name="keywords"></a><h2>5. Top Level Keywords</h2>
+
+<a name="type"></a><h3>5.1 TYPE </h3>
+<ul>
+ <li><strong>Format:</strong>
+\code
+ TYPE STRING
+\endcode
+ </li>
+
+ <li><strong>Description:</strong>
+
+ This keyword specifies the message class of the message. Users can
+ either specify their custom type or use on of the following standard
+ values:
+ <ul>
+ <li>"IPM.Appointment"</li>
+ <li>"IPM.Contact"</li>
+ <li>"IPM.Journal"</li>
+ <li>"IPM.Note"</li>
+ <li>"IPM.StickyNote"</li>
+ <li>"IPM.Task"</li>
+ <li>"IPM.Post"</li>
+ </ul>
+ </li>
+ <li><strong>Note:</strong>
+
+ TYPE can only be defined once and takes a string value as
+ parameter. String values must be quoted otherwise a <I>syntax
+ error</I> will be displayed on output.
+ </li>
+ <li><strong>Example:</strong>
+\code
+ TYPE "IPM.Appointment"
+\endcode
+ </li>
+</ul>
+<br/>
+
+<a name="folder"></a><h3>5.2 FOLDER </h3>
+<ul>
+ <li><strong>Format:</strong>
+\code
+ FOLDER STRING
+ FOLDER DOUBLE
+ FOLDER VAR
+\endcode
+ </li>
+ <li><strong>Description:</strong>
+
+ This keyword defines the destination folder of the message. Users
+ can either specify a default folder using the string value or a
+ custom folder ID using its PR_FID double value. It is also possible
+ to substitute the value with a variable, but it is limited to DOUBLE
+ value.
+
+ When FOLDER is set with DOUBLE custom value and ocpf_OpenFolder
+ public function used, it can be set to any folder identifier within
+ the message store. The function will loop over mailbox folders until
+ it finds the folder with the given folder ID and opens it.
+
+ Possible STRING values:
+ <ul>
+ <li> olFolderTopInformationStore </li>
+ <li> olFolderDeletedItems </li>
+ <li> olFolderOutbox </li>
+ <li> olFolderSentMail </li>
+ <li> olFolderInbox</li>
+ <li> olFolderCommonView</li>
+ <li> olFolderCalendar </li>
+ <li> olFolderContacts </li>
+ <li> olFolderJournal </li>
+ <li> olFolderNotes </li>
+ <li> olFolderTasks </li>
+ </ul>
+ </li>
+ <li><strong>Note:</strong>
+
+ FOLDER can only be defined once.
+ </li>
+ <li><strong>Examples:</strong>
+\code
+FOLDER "olFolderCalendar"
+\endcode
+
+or
+
+\code
+FOLDER D0x9504000000000001
+\endcode
+
+or
+
+\code
+SET $folder_id = D0x9504000000000001
+FOLDER $folder_id
+\endcode
+ </li>
+</ul>
+<br/>
+
+<a name="set"></a><h3>5.3. SET</h3>
+<ul>
+ <li><strong>Format:</strong>
+\code
+ SET VAR = PROPVALUE
+\endcode
+ </li>
+ <li><strong>Description:</strong>
+
+ This keyword registers a variable named VAR and sets its value to
+ PROPVALUE. Variables must be prefixed with a dollar sign ($) and their
+ value can be set to any supported property type. See section on
+ property values for further information.
+ </li>
+
+ <li><strong>Note:</strong>
+
+ SET can be used as many times as needed by the user, however VAR
+ name must remain unique. When a variable name is registered for the
+ second time, the OCPF parser displays a warning on the standard output
+ and skips the assignment.
+ </li>
+
+ <li><strong>Example:</strong>
+\code
+ SET $var1 = 0xdeadbeef
+ SET $var2 = "Hello World"
+ SET $var3 = T2008-03-06 23:30:00
+\endcode
+</ul>
+<br/>
+
+<a name="oleguid"></a><h3>5.4. OLEGUID</h3>
+<ul>
+ <li><strong>Format:</strong>
+\code
+ OLEGUID IDENTIFIER STRING
+\endcode
+ </li>
+ <li><strong>Description:</strong>
+
+ This keyword registers an OLEGUID couple (IDENTIFIER and STRING
+ value) that can then be used when declaring named properties (see
+ NPROPERTY). OLEGUID keyword takes two parameters: first the name,
+ used with named properties (PSETID_Appointment, PS_PUBLIC_STRINGS
+ etc.) and secondly a string representing a GUID value.
+ </li>
+ <li><strong>Note:</strong>
+
+ OLEGUID are identified by their IDENTIFIER and STRING. Users can't
+ register the same OLEGUID IDENTIFIER or STRING twice. If such case
+ occurs, a warning message will be displayed on stdout.
+ </li>
+ <li><strong>Example:</strong>
+\code
+ OLEGUID PSETID_Appointment "00062002-0000-0000-c000-000000000046"
+
+ [...]
+
+NPROPERTY {
+ OOM:Label:PSETID_Appointment = T2008-03-06 23:30:00
+ [...]
+\endcode
+ </li>
+</ul>
+<br/>
+
+<a name="recipient"></a><h3>5.5. RECIPIENT </h3>
+<ul>
+ <li><strong>Format:</strong>
+\code
+ RECIPIENT TO STRING;STRING;STRING
+ RECIPIENT CC STRING;STRING
+ RECIPIENT BCC STRING
+\endcode
+ </li>
+ <li><strong>Description:</strong>
+
+ This keyword declares recipients. RECIPIENT is followed by a
+ recipient type (TO, CC or BCC) and a set of STRING (recipients)
+ separated with semicolon.
+ </li>
+ <li><strong>Example:</strong>
+\code
+ RECIPIENT TO "recipient1";"recipient2";"recipient3"
+ RECIPIENT CC "recipient4"
+ RECIPIENT BCC "recipient5 at remote.corp";"recipient6"
+\endcode
+ </li>
+</ul>
+<br/>
+
+<a name="property"></a><h3>5.6. PROPERTY section</h3>
+<ul>
+ <li><strong>Format:</strong>
+\code
+ PROPERTY {
+ [...]
+ };
+\endcode
+ </li>
+ <li><strong>Description:</strong>
+
+ This keyword declares a <i>known property</i> section. PROPERTY is
+ followed by an opening brace, a set of property declarations and
+ is ended with a closing brace and semicolon. This section only
+ recognizes properties as described in <a href="#properties">6. Known
+ properties</a>.
+ </li>
+ <li><strong>Note:</strong>
+
+ While we suggest keeping a single PROPERTY section, nothing prevents
+ the user from declaring as many PROPERTY sections as needed.
+ </li>
+ <li><strong>Example:</strong>
+\code
+ PROPERTY {
+ PR_SUBJECT = "Hello World"
+ 0x1000001e = "Sample body content"
+ };
+\endcode
+ </li>
+</ul>
+<br/>
+
+
+<a name="nproperty"></a><h3>5.7. NPROPERTY section</h3>
+<ul>
+ <li><strong>Format:</strong>
+\code
+ NPROPERTY {
+ [...]
+ };
+\endcode
+ </li>
+ <li><strong>Description:</strong>
+
+ This keyword declares a <i>named property</i> section. NPROPERTY is
+ followed by an opening brace, a set of named properties declarations
+ and is ended with a closing brace and semicolon. This section
+ only recognizes named properties as described in <a
+ href="#nproperties">7. Named Properties</a>.
+
+ </li>
+ <li><strong>Note:</strong>
+
+ While we suggest keeping a single NPROPERTY section, nothing
+ prevents the user from declaring as many NPROPERTY sections as
+ needed.
+ </li>
+ <li><strong>Example:</strong>
+\code
+ NPROPERTY {
+ OOM:Start:PSETID_Appointment = T2008-03-06 22:00:00
+ OOM:Location:PSETID_Appointment = "Home Sweet Home"
+ /* Meeting Status */
+ MNID_ID:0x8217:PSETID_Appointment = 0;
+ };
+\endcode
+ </li>
+</ul>
+<br/>
+<br/>
+
+
+<a name="properties"></a><h2>6. Known Properties</h2>
+
+A known properties is any property where the value doesn't change
+across Exchange servers and versions. Known properties can only be
+registered within a PROPERTY section (See <a href="#property">5.6
+PROPERTY section</a>). Known properties have the same general syntax:
+
+\code
+ IDENTIFIER = [PROPVALUE | VAR]
+ INTEGER = [PROPVALUE | VAR]
+\endcode
+
+OCPF lets the user define <i>known properties</i> using two different
+methods: property names or property tags.
+
+Please note that OCPF doesn't check whether the value associated with
+the property matches the property type. For the moment it is the
+developer's responsibility to ensure that the property type matches
+its value.
+<br/>
+
+<a name="propname"></a><h3>6.1. Property Names</h3>
+
+ Property Names are defined with an IDENTIFIER which must match
+ one already registered in libmapi/conf/mapi-properties. For
+ example:
+\code
+ PR_SUBJECT = "Hello World"
+ PR_START_DATE = T2008-03-06 22:00:00
+ PR_PRIORITY = 2
+\endcode
+<br/>
+
+<a name="proptag"></a><h3>6.2. Property Tags</h3>
+
+ Property Tags are the other way to set a property. This is an
+ integer value represented using hexadecimal notation and
+ which has two parts: the upper 16 bits are the property ID and
+ the lower 16 bits are the property type.
+
+ While users may prefer to use the property name notation for
+ declaration, libmapi/conf/mapi-properties remains incomplete
+ and there may be cases where you need to use the property tag
+ notation. The example below sets properties described in
+ previous example using their property tag notation.
+\code
+ 0x0037001e = "Hello World"
+ 0x00600040 = T2008-03-06 22:00:00
+ 0x00260003 = 2
+\endcode.
+<br/>
+
+
+<a name="nproperties"></a><h2>7. Named Properties</h2>
+
+The OCPF syntax for different kind of named properties is quite
+generic. It supports each of the three kinds of property
+(OOM, MNID_ID, MNID_STRING) and can set known named properties
+(those listed in libmapi/conf/mapi-named-properties) or register
+new named properties (except OOM properties).
+
+The types of properties, and how they can be used, are described
+below.
+<br/>
+
+<a name="OOM"></a><h3>7.1. OOM</h3>
+
+OOM stands for Outlook Object Model and is a friendly name associated
+to a named property. It has no meaning to Exchange, but it can
+be useful for OpenChange or MAPI developers.
+
+OOM are human readable shortcuts for most named
+properties and OOM values are are considered reliable. This is the
+reason why OOM can only be used if it exists in
+libmapi/conf/mapi-named-properties. This method - in our opinion - is
+the best method to guarantee developers a common and validated
+mapi-named-properties file.
+
+Theorically, property names can have the same OOM, property ID
+(MNID_ID) or name (MNID_STRING). The only way to guarantee named
+property uniqueness is to associate its value with a OLEGUID.
+
+OLEGUID needs to be registered before they can be used with named
+properties. See <a href="#oleguid">5.4 OLEGUID</a> for more
+information on how to register a OLEGUID.
+
+OOM named properties have the following syntax:
+\code
+ OOM:IDENTIFIER:IDENTIFIER = [PROPVALUE | VAR]
+\endcode
+
+The first IDENTIFIER represents the OOM value while the second one
+represents the OLEGUID. Note that identifiers are not enclosed with
+quotes. Below are some OOM assignments examples:
+
+\code
+ OOM:Label:PSETID_Appointment = 9
+ OOM:End:PSETID_Appointment = $end_date
+ OOM:Private:PSETID_Common = B"true"
+\endcode
+<br/>
+
+<a name="MNID_ID"></a><h3>7.2. MNID_ID</h3>
+
+Named properties that Exchange converts using their property ID (16
+bits) are known as MNID_ID named property kind. OCPF provides two
+different ways to define MNID_ID. It can either be a new named
+property or an existing one which wouldn't have any associated OOM.
+
+MNID_ID named property kind has the following syntax:
+\code
+ MNID_ID:INTEGER:PROPTYPE:IDENTIFIER = [PROPVALUE | VAR]
+ MNID_ID:INTEGER:IDENTIFIER = [PROPVALUE | VAR]
+\endcode
+
+If the MNID_ID named property doesn't exist within
+libmapi/conf/mapi-named-property then you must specify its property
+type.
+
+As described in the example below, the main difference between known
+and custom MNID_ID named properties is whether or not we specify its
+property type. If your MNID_ID property has not been referenced within
+libmapi/conf/mapi-named-property, then you must supply its property
+type, otherwise you can skip it.
+
+Note: PROPTYPE can be any of the values described in <a
+href="#proptype"> 8. Supported Property Types </a>.
+
+\code
+ MNID_ID:0x8501:PT_LONG:PSETID_Common = $reminder /* Reminder */
+ MNID_ID:0x8217:PSETID_Appointment = 0 /* MeetingStatus */
+\endcode
+<br/>
+
+<a name="MNID_STRING"></a><h3>7.3. MNID_STRING</h3>
+
+Exchange also supports named properties which do not have a
+property ID but are described using property names. These named
+properties are known as MNID_STRING named property kind and Exchange
+maps these names to a temporary property type.
+
+MNID_STRING named property kind has the following syntax:
+\code
+ MNID_STRING:STRING:IDENTIFIER = [PROPVALUE | VAR]
+ MNID_STRING:STRING:PROPTYPE:IDENTIFIER = [PROPVALUE | VAR]
+\endcode
+
+MNID_STRING difference between known and custom is the same as
+MNID_ID one. If the MNID_STRING property doesn't exist in
+libmapi/conf/mapi-named-properties, then users have to supply its
+PROPTYPE.
+
+NOTE: PROPTYPE can be any of the value described in <a
+href="#proptype"> 8. Supported Property Types </a>.
+
+Considering the behavior described above, we could set the "Keywords"
+MNID_STRING named property using any of the following example:
+\code
+ MNID_STRING:"Keywords":PS_PUBLIC_STRINGS = {"one", "two" , "three" }
+ MNID_STRING:"Keywords":PT_MV_STRING8:PS_PUBLIC_STRINGS = {"one", "two" , "three" }
+\endcode
+
+<br/>
+
+
+<a name="proptype"></a><h2>8. Supported Property Types</h2>
+<a name="boolean"></a><h3>8.1. PT_BOOLEAN</h3>
+
+OCPF uses the following format for BOOLEAN values:
+\code
+ B"true"
+ B"false"
+\endcode
+<br/>
+
+<a name="short"></a><h3>8.2. PT_SHORT</h3>
+OCPF can use any of the following formats for SHORT values:
+\code
+ S0x1234
+ S32
+\endcode
+
+The short integer can either be in hexadecimal of decimal notation but
+must be prefixed with a "S" to specify this is a short integer
+value. If you omit to specify the "S", mismatch property type/value
+errors will occur while sending the message.
+
+<a name="long"></a><h3>8.3. PT_LONG</h3>
+OCPF can use any of the following formats for PT_LONG values:
+\code
+ 0xdeadbeef
+ L0xdeadbeef
+ 32
+\endcode
+
+The integer can either be in hexadecimal or decimal notation or
+prefixed with a "L" to specify this is long value. If you use the
+hexadecimal notation consider using the 'L' prefixed form since other form
+may disappear in further versions.
+<br/>
+
+<a name="double"></a><h3>8.4. PT_I8</h3>
+OCPF uses the following format for PT_I8 (uint64_t) values:
+\code
+ D0x9504000000000001
+\endcode
+<br/>
+
+<a name="string8"></a><h3>8.5. PT_STRING8</h3>
+
+OCPF defines a string as a set of characters (A-Za-z0-9_) enclosed
+with double quotes:
+\code
+ "I am a STRING"
+\endcode
+<br/>
+
+<a name="unicode"></a><h3>8.6. PT_UNICODE</h3>
+
+OCPF defines a unicode string as a set of characters enclosed with
+double quotes and prefixed with <strong>W</strong>:
+\code
+ W"I am a UNICODE string"
+\endcode
+<br/>
+
+<a name="systime"></a><h3>8.7. PT_SYSTIME</h3>
+
+OCPF defines date using the following format string:
+\code
+ TYYYY-MM-DD HH:MM:SS
+\endcode
+
+Dates are prefixed with a 'T' character and its content is represented
+with the syntax below:
+
+<ul>
+ <li> YYYY: year </li>
+ <li> MM: month </li>
+ <li> DD: day </li>
+ <li> HH: hours </li>
+ <li> MM: minutes </li>
+ <li> SS: seconds </li>
+</ul>
+
+\code
+ T2008-03-06 22:30:00 /* 2008, 6th of March 10:30:00PM */
+\endcode
+<br/>
+
+<a name="mv_string8"></a><h3>8.8. PT_MV_STRING8</h3>
+
+PT_MV_STRING8 are arrays ("multiple values") of strings. OCPF defines PT_MV_STRING8
+property values as STRING property values separated by commas and enclosed within
+braces.
+
+\code
+ { STRING, STRING, ..., STRING }
+\endcode
+
+At least one STRING property value is required to create a valid
+PT_MV_STRING8 property. If two or more STRING property values are set,
+then they must be separated with comma.
+
+\code
+ { "single multi-string value" }
+ { "one" , "two", "three", "owned" }
+\endcode
+<br/>
+
+<a name="binary"></a><h3>8.9. PT_BINARY</h3>
+
+PT_BINARY are blobs of data. OCPF defines PT_BINARY property values
+using two different methods. This can either be raw/inline blob of
+data or filename/external.
+
+If users wish to add raw data blob for a given property, they need to
+enclose INTEGER values within braces. However many cases occur where
+the data blob is large (such as HTML content; PR_HTML has PT_BINARY
+property type). In such cases, users may rather prefer to write an
+external file and specify a filename.
+
+\code
+ { INTEGER INTEGER [...] INTEGER }
+ < STRING >
+\endcode
+
+Note that if the blob of data (raw or pointed by filename) is too
+large to fit in the property values array, then OCPF will
+automatically open a stream for the property and write its data in the
+stream.
+
+\code
+ PR_HTML = { 0x48 0x65 0x6c 0x6c 0x6f } /* Hello */
+ PR_HTML = <"/tmp/sample.html">
+\endcode
+
+<a name="comments"></a><h2>9. Comments</h2>
+
+OCPF files can contain comments embedded in normal C-style comment
+markers. That is, a comment starts with a combination of / followed by *,
+and ends with combination of * followed by /.
+
+Anything contained with in comment markers is ignored by the OCPF tools,
+and is only for the convenience of human readers.
+
+\code
+/* This is a comment */
+\endcode
+
+<a name="tools"></a><h2>10. OCPF and openchangeclient</h2>
+
+OCPF support has been added to the openchangeclient utility.
+It now has the ability to parse and process OCPF files. Two different
+options are supported; you can either check an OCPF files' syntax
+(--ocpf_syntax) or process the files (--ocpf_sender).
+
+Users can set OCPF files using --ocpf-file=filename. Note that you can
+specify --ocpf-file multiple times if you have split the OCPF contents
+into different files. However the whole OCPF files you specify must
+only represent a single message.
+
+Sample OCPF files are provided in the distribution (libocpf/examples),
+and can also be browsed from the <a href="examples.html">Examples section</a>
+of this documentation:
+<ul>
+ <li> <a href="sample__appointment_8ocpf-example.html">sample_appointment.ocpf</a> </li>
+ <li> <a href="sample__task_8ocpf-example.html">sample_task.ocpf</a> </li>
+</ul>
+
+<a name="syntax"></a><h2>10.1 ocpf_syntax</h2>
+Process specified OCPF files, display syntax errors if detected and dump
+OCPF context content on standard output.
+
+\code
+openchangeclient --ocpf-syntax \
+ --ocpf-file=libocpf/examples/sample_appointment.ocpf
+\endcode
+
+<a name="sender"></a><h2>10.2. ocpf_sender</h2>
+
+Process specified OCPF files and create/send a message using OCPF context
+contents.
+
+\code
+openchangeclient --ocpf_sender \
+ --ocpf-file=libocpf/examples/sample_appointment.ocpf
+\endcode
+
+<a name="dump"></a><h2>10.3 ocpf_dump</h2>
+Process specified MAPI message and generates the corresponding OCPF
+file on the filesystem.
+
+\code
+openchangeclient --fetch-items=Appointment
+MAILBOX (1 messages)
+|== test ==| : AA13000000000001/20C140000000003
+ Location: paris
+ Start time : Sat Mar 29 09:00:00 2008 CET
+ End time : Sat Mar 29 09:30:00 2008 CET
+ Timezone: (GMT+01:00) Brussels, Copenhagen, Madrid, Paris
+ Private: False
+ Status: Completed
+ fetchitems : MAPI_E_SUCCESS (0x0)
+
+openchangeclient --ocpf-dump=AA13000000000001/20C140000000003
+OCPF output file: 20c140000000003.ocpf
+ OCPF Dump : MAPI_E_SUCCESS (0x0)
+\endcode
+
+*/
+
+/** \example sample_appointment.ocpf
+
+This example shows a sample OCPF file designed to create a calendar
+with the following details:
+- Event starting the 6th of March at 10:00PM and ending at 11:45PM
+- Reminder set 45 minutes before the beginning of event
+- Label set to Anniversary
+- Subject, Body, Location and Private flag set
+
+*/
+
+/** \example sample_task.ocpf
+
+This example shows a sample OCPF file designed to create a task with
+the following details:
+- Task starting the 6th of March at 8:00PM and ending at 11:00PM
+- Importance set to High
+- Waiting for someone else
+- Subject, Body and Private flag set
+
+*/
Added: trunk/openchange/libocpf/ocpf.h
===================================================================
--- trunk/openchange/libocpf/ocpf.h (rev 0)
+++ trunk/openchange/libocpf/ocpf.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,32 @@
+/*
+ OpenChange OCPF (OpenChange Property File) implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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 __OCPF_H_
+#define __OCPF_H_
+
+#include <libmapi/libmapi.h>
+#include <libocpf/proto.h>
+
+#define OCPF_SUCCESS 0x0
+#define OCPF_ERROR 0x1
+
+extern struct ocpf *ocpf;
+extern unsigned int lineno;
+
+#endif /* ! __OCPF_H_ */
Added: trunk/openchange/libocpf/ocpf.y
===================================================================
--- trunk/openchange/libocpf/ocpf.y (rev 0)
+++ trunk/openchange/libocpf/ocpf.y 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,452 @@
+/*
+ OpenChange OCPF (OpenChange Property File) implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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 "libocpf/ocpf_private.h"
+#include <libocpf/ocpf.h>
+#include <libocpf/ocpf_api.h>
+#include <libocpf/lex.h>
+
+void yyerror(char *);
+
+union SPropValue_CTR lpProp;
+struct ocpf_nprop nprop;
+int typeset;
+uint16_t type;
+int folderset;
+uint8_t recip_type;
+
+%}
+
+%union {
+ uint8_t i;
+ uint8_t b;
+ uint16_t s;
+ uint32_t l;
+ uint64_t d;
+ char *name;
+ char *nameW;
+ char *date;
+ char *var;
+ struct StringArray_r MVszA;
+}
+
+%token <i> UINT8
+%token <b> BOOLEAN
+%token <s> SHORT
+%token <l> INTEGER
+%token <d> DOUBLE
+%token <name> IDENTIFIER
+%token <name> STRING
+%token <nameW> UNICODE
+%token <MVszA> MVSTRING
+%token <date> SYSTIME
+%token <var> VAR
+
+%token kw_TYPE
+%token kw_FOLDER
+%token kw_OLEGUID
+%token kw_SET
+%token kw_PROPERTY
+%token kw_NPROPERTY
+%token kw_RECIPIENT
+%token kw_TO
+%token kw_CC
+%token kw_BCC
+%token kw_OOM
+%token kw_MNID_ID
+%token kw_MNID_STRING
+
+%token kw_PT_BOOLEAN
+%token kw_PT_STRING8
+%token kw_PT_UNICODE
+%token kw_PT_SHORT
+%token kw_PT_LONG
+%token kw_PT_SYSTIME
+%token kw_PT_MV_STRING8
+%token kw_PT_BINARY
+
+%token OBRACE
+%token EBRACE
+%token COMMA
+%token SEMICOLON
+%token COLON
+%token LOWER
+%token GREATER
+%token EQUAL
+
+%start keywords
+
+%%
+
+keywords : | keywords kvalues
+ {
+ memset(&lpProp, 0, sizeof (union SPropValue_CTR));
+ }
+ ;
+
+kvalues : Type
+ | Folder
+ | OLEGUID
+ | Set
+ | Property
+ | NProperty
+ | Recipient
+ ;
+
+Type :
+ kw_TYPE STRING
+ {
+ if (!typeset) {
+ ocpf_type_add($2);
+ typeset++;
+ } else {
+ error_message("%s", "duplicated TYPE\n");
+ return -1;
+ }
+ }
+ ;
+
+Folder :
+ kw_FOLDER STRING
+ {
+ if (folderset == false) {
+ ocpf_folder_add($2, 0, NULL);
+ folderset = true;
+ } else {
+ error_message("%s", "duplicated FOLDER\n");
+ }
+ }
+ | kw_FOLDER DOUBLE
+ {
+ if (folderset == false) {
+ ocpf_folder_add(NULL, $2, NULL);
+ folderset = true;
+ } else {
+ error_message("%s", "duplicated FOLDER\n");
+ }
+ }
+ | kw_FOLDER VAR
+ {
+ if (folderset == false) {
+ ocpf_folder_add(NULL, 0, $2);
+ folderset = true;
+ } else {
+ error_message("%s", "duplicated FOLDER\n");
+ }
+ }
+ ;
+
+OLEGUID :
+ kw_OLEGUID IDENTIFIER STRING
+ {
+ char *name;
+ char *guid;
+
+ name = talloc_strdup(ocpf->mem_ctx, $2);
+ guid = talloc_strdup(ocpf->mem_ctx, $3);
+
+ ocpf_oleguid_add(name, guid);
+ }
+ ;
+
+Set :
+ kw_SET VAR EQUAL propvalue
+ {
+ ocpf_variable_add($2, lpProp, type, true);
+ memset(&lpProp, 0, sizeof (union SPropValue_CTR));
+ }
+ ;
+
+Property :
+ kw_PROPERTY OBRACE pcontent EBRACE SEMICOLON
+ {
+ }
+
+pcontent : | pcontent content
+ {
+ memset(&lpProp, 0, sizeof (union SPropValue_CTR));
+ }
+ ;
+
+content :
+ IDENTIFIER EQUAL propvalue
+ {
+ ocpf_propvalue_s($1, lpProp, type, true);
+ ocpf_propvalue_free(lpProp, type);
+ }
+ | INTEGER EQUAL propvalue
+ {
+ ocpf_propvalue($1, lpProp, type, true);
+ ocpf_propvalue_free(lpProp, type);
+ }
+ | IDENTIFIER EQUAL VAR
+ {
+ ocpf_propvalue_var($1, 0x0, $3, true);
+ }
+ | INTEGER EQUAL VAR
+ {
+ ocpf_propvalue_var(NULL, $1, $3, true);
+ }
+ ;
+
+propvalue : STRING
+ {
+ lpProp.lpszA = talloc_strdup(ocpf->mem_ctx, $1);
+ type = PT_STRING8;
+ }
+ | UNICODE
+ {
+ lpProp.lpszW = talloc_strdup(ocpf->mem_ctx, $1);
+ type = PT_UNICODE;
+ }
+ | SHORT { lpProp.i = $1; type = PT_SHORT; }
+ | INTEGER { lpProp.l = $1; type = PT_LONG; }
+ | BOOLEAN { lpProp.b = $1; type = PT_BOOLEAN; }
+ | DOUBLE { lpProp.d = $1; type = PT_DOUBLE; }
+ | SYSTIME
+ {
+ ocpf_add_filetime($1, &lpProp.ft);
+ type = PT_SYSTIME;
+ }
+ | OBRACE mvstring_contents STRING EBRACE
+ {
+ TALLOC_CTX *mem_ctx;
+
+ if (!lpProp.MVszA.cValues) {
+ lpProp.MVszA.cValues = 0;
+ lpProp.MVszA.lppszA = talloc_array(ocpf->mem_ctx, const char *, 2);
+ } else {
+ lpProp.MVszA.lppszA = talloc_realloc(NULL, lpProp.MVszA.lppszA, const char *,
+ lpProp.MVszA.cValues + 2);
+ }
+ mem_ctx = (TALLOC_CTX *) lpProp.MVszA.lppszA;
+ lpProp.MVszA.lppszA[lpProp.MVszA.cValues] = talloc_strdup(mem_ctx, $3);
+ lpProp.MVszA.cValues += 1;
+
+ type = PT_MV_STRING8;
+ }
+ | OBRACE binary_contents EBRACE
+ {
+ type = PT_BINARY;
+ }
+ | LOWER STRING GREATER
+ {
+ int ret;
+
+ ret = ocpf_binary_add($2, &lpProp.bin);
+ type = (ret == OCPF_SUCCESS) ? PT_BINARY : PT_ERROR;
+ }
+ ;
+
+mvstring_contents: | mvstring_contents mvstring_content
+
+
+mvstring_content : STRING COMMA
+ {
+ TALLOC_CTX *mem_ctx;
+
+ if (!lpProp.MVszA.cValues) {
+ lpProp.MVszA.cValues = 0;
+ lpProp.MVszA.lppszA = talloc_array(ocpf->mem_ctx, const char *, 2);
+ } else {
+ lpProp.MVszA.lppszA = talloc_realloc(NULL, lpProp.MVszA.lppszA, const char *,
+ lpProp.MVszA.cValues + 2);
+ }
+ mem_ctx = (TALLOC_CTX *) lpProp.MVszA.lppszA;
+ lpProp.MVszA.lppszA[lpProp.MVszA.cValues] = talloc_strdup(mem_ctx, $1);
+ lpProp.MVszA.cValues += 1;
+ }
+ ;
+
+binary_contents: | binary_contents binary_content
+
+binary_content : INTEGER
+ {
+ TALLOC_CTX *mem_ctx;
+
+ if ($1 > 0xFF) {
+ error_message("Invalid Binary constant: 0x%x > 0xFF\n", $1);
+ }
+
+ if (!lpProp.bin.cb) {
+ lpProp.bin.cb = 0;
+ lpProp.bin.lpb = talloc_array(ocpf->mem_ctx, uint8_t, 2);
+ } else {
+ lpProp.bin.lpb = talloc_realloc(NULL, lpProp.bin.lpb, uint8_t,
+ lpProp.bin.cb + 2);
+ }
+ mem_ctx = (TALLOC_CTX *) lpProp.bin.lpb;
+ lpProp.bin.lpb[lpProp.bin.cb] = $1;
+ lpProp.bin.cb += 1;
+ }
+ ;
+
+NProperty :
+ kw_NPROPERTY OBRACE npcontent EBRACE SEMICOLON
+ {
+ }
+
+npcontent : | npcontent ncontent
+ {
+ memset(&lpProp, 0, sizeof (union SPropValue_CTR));
+ }
+ ;
+
+ncontent : kind EQUAL propvalue
+ {
+ ocpf_nproperty_add(&nprop, lpProp, NULL, type, true);
+ }
+ | known_kind EQUAL propvalue
+ {
+ ocpf_nproperty_add(&nprop, lpProp, NULL, type, true);
+ }
+ | kind EQUAL VAR
+ {
+ ocpf_nproperty_add(&nprop, lpProp, $3, type, true);
+ }
+ | known_kind EQUAL VAR
+ {
+ ocpf_nproperty_add(&nprop, lpProp, $3, type, true);
+ }
+ ;
+
+kind : kw_OOM COLON IDENTIFIER COLON IDENTIFIER
+ {
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ nprop.OOM = talloc_strdup(ocpf->mem_ctx, $3);
+ nprop.guid = $5;
+ }
+ | kw_MNID_ID COLON INTEGER COLON proptype COLON IDENTIFIER
+ {
+ nprop.registered = false;
+ nprop.mnid_id = $3;
+ nprop.guid = $7;
+ }
+ | kw_MNID_STRING COLON STRING COLON proptype COLON IDENTIFIER
+ {
+ nprop.registered = false;
+ nprop.mnid_string = talloc_strdup(ocpf->mem_ctx, $3);
+ nprop.guid = $7;
+ }
+ ;
+
+proptype : kw_PT_STRING8
+ {
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ nprop.propType = PT_STRING8;
+ }
+ | kw_PT_UNICODE
+ {
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ nprop.propType = PT_UNICODE;
+ }
+ | kw_PT_SHORT
+ {
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ nprop.propType = PT_SHORT;
+ }
+ | kw_PT_LONG
+ {
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ nprop.propType = PT_LONG;
+ }
+ | kw_PT_BOOLEAN
+ {
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ nprop.propType = PT_BOOLEAN;
+ }
+ | kw_PT_SYSTIME
+ {
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ nprop.propType = PT_SYSTIME;
+ }
+ | kw_PT_MV_STRING8
+ {
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ nprop.propType = PT_MV_STRING8;
+ }
+ | kw_PT_BINARY
+ {
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ nprop.propType = PT_BINARY;
+ }
+ ;
+
+known_kind : kw_MNID_ID COLON INTEGER COLON IDENTIFIER
+ {
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ nprop.registered = true;
+ nprop.mnid_id = $3;
+ nprop.guid = $5;
+ }
+ | kw_MNID_STRING COLON STRING COLON IDENTIFIER
+ {
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ nprop.registered = true;
+ nprop.mnid_string = talloc_strdup(ocpf->mem_ctx, $3);
+ nprop.guid = $5;
+ }
+ ;
+
+Recipient :
+ kw_RECIPIENT recipClass recipients STRING
+ {
+ char *recipient = NULL;
+
+ recipient = talloc_strdup(ocpf->mem_ctx, $4);
+ ocpf_recipient_add(recip_type, recipient);
+ talloc_free(recipient);
+
+ recip_type = 0;
+ }
+ ;
+
+recipClass : kw_TO
+ {
+ recip_type = MAPI_TO;
+ }
+ | kw_CC
+ {
+ recip_type = MAPI_CC;
+ }
+ | kw_BCC
+ {
+ recip_type = MAPI_BCC;
+ }
+ ;
+
+recipients : | recipients recipient
+
+recipient : STRING SEMICOLON
+ {
+ char *recipient = NULL;
+
+ recipient = talloc_strdup(ocpf->mem_ctx, $1);
+ ocpf_recipient_add(recip_type, recipient);
+ talloc_free(recipient);
+ }
+
+%%
+
+void yyerror(char *s)
+{
+ printf("%s: %d", s, lineno);
+}
Added: trunk/openchange/libocpf/ocpf_api.c
===================================================================
--- trunk/openchange/libocpf/ocpf_api.c (rev 0)
+++ trunk/openchange/libocpf/ocpf_api.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,578 @@
+/*
+ OpenChange OCPF (OpenChange Property File) implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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 "libocpf/ocpf_private.h"
+#include <libocpf/ocpf.h>
+#include <libocpf/ocpf_api.h>
+#include <libocpf/ocpf.tab.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <time.h>
+
+/**
+ \file ocpf_api.c
+
+ \brief ocpf Private API
+ */
+
+
+void ocpf_do_debug(const char *format, ...)
+{
+ va_list ap;
+ char *s = NULL;
+ int ret;
+
+ va_start(ap, format);
+ ret = vasprintf(&s, format, ap);
+ va_end(ap);
+
+ printf("%s:%d: %s\n", ocpf_get_filename(), lineno, s);
+ free(s);
+}
+
+const char *ocpf_get_filename(void)
+{
+ return ocpf->filename;
+}
+
+
+int ocpf_propvalue_var(const char *propname, uint32_t proptag, const char *variable, bool unescape)
+{
+ struct ocpf_var *vel;
+ struct ocpf_property *element;
+ uint32_t aulPropTag;
+
+ if (!ocpf || !ocpf->mem_ctx) return -1;
+ if (!propname && !proptag) return -1;
+ if (propname && proptag) return -1;
+
+ /* Sanity check: do not insert the same property twice */
+ if (proptag) {
+ aulPropTag = proptag;
+ } else {
+ aulPropTag = get_proptag_value(propname);
+ }
+
+ for (element = ocpf->props; element->next; element = element->next) {
+ OCPF_RETVAL_IF(element->aulPropTag == aulPropTag, OCPF_WARN_PROP_REGISTERED, NULL);
+ }
+
+ for (vel = ocpf->vars; vel->next; vel = vel->next) {
+ if (vel->name && !strcmp(vel->name, variable)) {
+ OCPF_RETVAL_IF(vel->propType != (aulPropTag & 0xFFFF), OCPF_WARN_PROPVALUE_MISMATCH, NULL);
+ element = NULL;
+ element = talloc_zero(ocpf->mem_ctx, struct ocpf_property);
+ element->aulPropTag = aulPropTag;
+ if (unescape && (((aulPropTag & 0xFFFF) == PT_STRING8) ||
+ ((aulPropTag & 0xFFFF) == PT_UNICODE))) {
+ element->value = ocpf_write_unescape_string(vel->value);
+ } else {
+ element->value = vel->value;
+ }
+ DLIST_ADD(ocpf->props, element);
+ return OCPF_SUCCESS;
+ }
+ }
+
+ OCPF_RETVAL_IF(1, OCPF_WARN_VAR_NOT_REGISTERED, NULL);
+}
+
+
+int ocpf_set_propvalue(TALLOC_CTX *mem_ctx, const void **value, uint16_t proptype, uint16_t sproptype,
+ union SPropValue_CTR lpProp, bool unescape)
+{
+ char *str = NULL;
+
+ OCPF_RETVAL_IF(proptype != sproptype, OCPF_WARN_PROPVALUE_MISMATCH, NULL);
+
+ switch (proptype) {
+ case PT_STRING8:
+ if (unescape) {
+ str = ocpf_write_unescape_string(lpProp.lpszA);
+ } else {
+ str = talloc_strdup(ocpf->mem_ctx, lpProp.lpszA);
+ }
+ *value = talloc_memdup(mem_ctx, str, strlen(str) + 1);
+ talloc_free(str);
+ return OCPF_SUCCESS;
+ case PT_UNICODE:
+ if (unescape) {
+ str = ocpf_write_unescape_string(lpProp.lpszW);
+ } else {
+ str = talloc_strdup(ocpf->mem_ctx, lpProp.lpszW);
+ }
+ *value = talloc_memdup(mem_ctx, str, strlen(str) + 1);
+ talloc_free(str);
+ return OCPF_SUCCESS;
+ case PT_SHORT:
+ *value = talloc_memdup(mem_ctx, (const void *)&lpProp.i, sizeof (uint16_t));
+ return OCPF_SUCCESS;
+ case PT_LONG:
+ *value = talloc_memdup(mem_ctx, (const void *)&lpProp.l, sizeof (uint32_t));
+ return OCPF_SUCCESS;
+ case PT_BOOLEAN:
+ *value = talloc_memdup(mem_ctx, (const void *)&lpProp.b, sizeof (uint8_t));
+ return OCPF_SUCCESS;
+ case PT_ERROR:
+ *value = talloc_memdup(mem_ctx, (const void *)&lpProp.err, sizeof (uint32_t));
+ return OCPF_SUCCESS;
+ case PT_DOUBLE:
+ *value = talloc_memdup(mem_ctx, (const void *)&lpProp.d, sizeof (uint64_t));
+ return OCPF_SUCCESS;
+ case PT_SYSTIME:
+ *value = talloc_memdup(mem_ctx, (const void *)&lpProp.ft, sizeof (struct FILETIME));
+ return OCPF_SUCCESS;
+ case PT_BINARY:
+ *value = (const void *)talloc_zero(mem_ctx, struct Binary_r);
+ ((struct Binary_r *)*value)->cb = lpProp.bin.cb;
+ ((struct Binary_r *)*value)->lpb = talloc_memdup(mem_ctx, (const void *)lpProp.bin.lpb, lpProp.bin.cb);
+ return OCPF_SUCCESS;
+ case PT_MV_STRING8:
+ *value = (const void *)talloc_zero(mem_ctx, struct StringArray_r);
+ ((struct StringArray_r *)*value)->cValues = lpProp.MVszA.cValues;
+ ((struct StringArray_r *)*value)->lppszA = talloc_array(mem_ctx, const char *, lpProp.MVszA.cValues);
+ {
+ uint32_t i;
+
+ for (i = 0; i < lpProp.MVszA.cValues; i++) {
+ if (unescape) {
+ str = ocpf_write_unescape_string(lpProp.MVszA.lppszA[i]);
+ } else {
+ str = (char *)lpProp.MVszA.lppszA[i];
+ }
+ ((struct StringArray_r *)*value)->lppszA[i] = talloc_strdup(mem_ctx, str);
+ talloc_free(str);
+ }
+ }
+ return OCPF_SUCCESS;
+ default:
+ OCPF_WARN(("%s (0x%.4x)", OCPF_WARN_PROP_TYPE, proptype));
+ return OCPF_ERROR;
+ }
+ return OCPF_ERROR;
+}
+
+int ocpf_propvalue_free(union SPropValue_CTR lpProp, uint16_t proptype)
+{
+ switch (proptype) {
+ case PT_STRING8:
+ talloc_free((char *)lpProp.lpszA);
+ break;
+ case PT_UNICODE:
+ talloc_free((char *)lpProp.lpszW);
+ break;
+ case PT_MV_STRING8:
+ talloc_free(lpProp.MVszA.lppszA);
+ break;
+ }
+ return OCPF_SUCCESS;
+}
+
+int ocpf_propvalue(uint32_t aulPropTag, union SPropValue_CTR lpProp, uint16_t proptype, bool unescape)
+{
+ struct ocpf_property *element;
+ int ret;
+
+ if (!ocpf || !ocpf->mem_ctx) return OCPF_ERROR;
+
+ /* Sanity check: do not insert the same property twice */
+ for (element = ocpf->props; element->next; element = element->next) {
+ OCPF_RETVAL_IF(element->aulPropTag == aulPropTag, OCPF_WARN_PROP_REGISTERED, NULL);
+ }
+
+ element = NULL;
+ element = talloc_zero(ocpf->mem_ctx, struct ocpf_property);
+ element->aulPropTag = aulPropTag;
+ ret = ocpf_set_propvalue((TALLOC_CTX *)element, &element->value, (uint16_t)aulPropTag & 0xFFFF, proptype, lpProp, unescape);
+ if (ret == -1) {
+ talloc_free(element);
+ return OCPF_ERROR;
+ }
+
+ DLIST_ADD(ocpf->props, element);
+ return OCPF_SUCCESS;
+}
+
+
+void ocpf_propvalue_s(const char *propname, union SPropValue_CTR lpProp, uint16_t proptype, bool unescape)
+{
+ uint32_t aulPropTag;
+
+ aulPropTag = get_proptag_value(propname);
+ ocpf_propvalue(aulPropTag, lpProp, proptype, unescape);
+}
+
+
+/**
+ \details Add a named property
+
+ This function adds either a custom or a known named property and
+ supplies either the lpProp value or substitute with registered
+ variable.
+
+ \param nprop pointer on a ocpf named property entry
+ \param lpProp named property value
+ \param var_name variable name
+ \param proptype variable property type
+ \param unescape whether the property value should be escaped
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR.
+ */
+int ocpf_nproperty_add(struct ocpf_nprop *nprop, union SPropValue_CTR lpProp,
+ const char *var_name, uint16_t proptype, bool unescape)
+{
+ enum MAPISTATUS retval;
+ int ret = 0;
+ struct ocpf_nproperty *element;
+ struct ocpf_nproperty *el;
+ struct ocpf_var *vel;
+
+ if (!ocpf || !ocpf->mem_ctx) return -1;
+
+ element = talloc_zero(ocpf->mem_ctx, struct ocpf_nproperty);
+
+ if (nprop->guid) {
+ ret = ocpf_oleguid_check(nprop->guid, &element->oleguid);
+ OCPF_RETVAL_IF(ret == -1, OCPF_WARN_OLEGUID_UNREGISTERED, element);
+ }
+
+ if (nprop->OOM) {
+ /*
+ * Sanity check: do not insert twice the same
+ * (OOM,oleguid) couple
+ */
+ for (el = ocpf->nprops; el->next; el = el->next) {
+ OCPF_RETVAL_IF((el->OOM && !strcmp(el->OOM, nprop->OOM)) &&
+ (el->oleguid && !strcmp(el->oleguid, nprop->guid)),
+ OCPF_WARN_OOM_REGISTERED, element);
+ }
+
+ element->kind = OCPF_OOM;
+ element->OOM = nprop->OOM;
+ retval = mapi_nameid_OOM_lookup(element->OOM, element->oleguid,
+ &element->propType);
+ OCPF_RETVAL_IF(retval != MAPI_E_SUCCESS, OCPF_WARN_OOM_UNKNOWN, element);
+ } else if (nprop->mnid_string) {
+ /*
+ * Sanity check: do not insert twice the same
+ * (mnid_string,oleguid) couple
+ */
+ for (el = ocpf->nprops; el->next; el = el->next) {
+ OCPF_RETVAL_IF((el->mnid_string && !strcmp(el->mnid_string, nprop->mnid_string)) &&
+ (el->oleguid && !strcmp(el->oleguid, nprop->guid)),
+ OCPF_WARN_STRING_REGISTERED, element);
+ }
+
+ element->kind = OCPF_MNID_STRING;
+ element->mnid_string = nprop->mnid_string;
+ if (nprop->registered == true) {
+ retval = mapi_nameid_string_lookup(element->mnid_string,
+ element->oleguid,
+ &element->propType);
+ OCPF_RETVAL_IF(retval != MAPI_E_SUCCESS, OCPF_WARN_STRING_UNKNOWN, element);
+ } else {
+ element->propType = nprop->propType;
+ }
+ } else if (nprop->mnid_id) {
+ /*
+ * Sanity check: do not insert twice the same
+ * (mnid_id-oleguid) couple
+ */
+ for (el = ocpf->nprops; el->next; el = el->next) {
+ OCPF_RETVAL_IF((el->mnid_id == nprop->mnid_id) &&
+ (el->oleguid && !strcmp(el->oleguid, nprop->guid)),
+ OCPF_WARN_LID_REGISTERED, element);
+ }
+ element->kind = OCPF_MNID_ID;
+ element->mnid_id = nprop->mnid_id;
+ if (nprop->registered == true) {
+ retval = mapi_nameid_lid_lookup(element->mnid_id,
+ element->oleguid,
+ &element->propType);
+ OCPF_RETVAL_IF(retval != MAPI_E_SUCCESS, OCPF_WARN_LID_UNKNOWN, element);
+ } else {
+ element->propType = nprop->propType;
+ }
+ }
+
+ if (var_name) {
+ for (vel = ocpf->vars; vel->next; vel = vel->next) {
+ if (vel->name && !strcmp(vel->name, var_name)) {
+ OCPF_RETVAL_IF(element->propType != vel->propType, OCPF_WARN_PROPVALUE_MISMATCH, element);
+ element->value = vel->value;
+ }
+ }
+ OCPF_RETVAL_IF(!element->value, OCPF_WARN_VAR_NOT_REGISTERED, element);
+ } else {
+ ret = ocpf_set_propvalue((TALLOC_CTX *)element, &element->value, element->propType, proptype, lpProp, unescape);
+ if (ret == -1) {
+ talloc_free(element);
+ return OCPF_ERROR;
+ }
+ }
+
+ DLIST_ADD(ocpf->nprops, element);
+
+ return OCPF_SUCCESS;
+}
+
+
+/**
+ \details Register OCPF message type
+
+ Register OCPF message type
+
+ \param type message type to register
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR
+ */
+int ocpf_type_add(const char *type)
+{
+ if (!ocpf || !ocpf->mem_ctx || !type) return OCPF_ERROR;
+
+ ocpf->type = talloc_strdup(ocpf->mem_ctx, type);
+
+ return OCPF_SUCCESS;
+}
+
+
+/* WARNING: This array doesn't hold all possible values */
+static struct ocpf_olfolder olfolders[] = {
+ { olFolderTopInformationStore, "olFolderTopInformationStore" },
+ { olFolderDeletedItems, "olFolderDeletedItems" },
+ { olFolderOutbox, "olFolderOutbox" },
+ { olFolderSentMail, "olFolderSentMail" },
+ { olFolderInbox, "olFolderInbox" },
+ { olFolderCommonView, "olFolderCommonView" },
+ { olFolderCalendar, "olFolderCalendar" },
+ { olFolderContacts, "olFolderContacts" },
+ { olFolderJournal, "olFolderJournal" },
+ { olFolderNotes, "olFolderNotes" },
+ { olFolderTasks, "olFolderTasks" },
+ { 0, NULL }
+};
+
+static int64_t ocpf_folder_name_to_id(const char *name)
+{
+ uint32_t i;
+
+ if (!name) return OCPF_ERROR;
+
+ for (i = 0; olfolders[i].name; i++) {
+ if (olfolders[i].name && !strcmp(olfolders[i].name, name)) {
+ return olfolders[i].id;
+ }
+ }
+ return OCPF_ERROR;
+}
+
+/**
+ \details Register OCPF folder
+
+ Register the folder where the OCPF message needs to be saved
+
+ \param name the name of the default folder if specified
+ \param id the folder id of the message if specified
+ \param var_name the substitution variable to use for folder ID if
+ specified
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR
+ */
+int ocpf_folder_add(const char *name, uint64_t id, const char *var_name)
+{
+ struct ocpf_var *element;
+
+ /* Sanity check */
+ if ((name && id) || (name && var_name) || (id && var_name)) return OCPF_ERROR;
+ if (!name && !id && !var_name) return OCPF_ERROR;
+
+ if (name) {
+ ocpf->folder = (uint64_t) ocpf_folder_name_to_id(name);
+ OCPF_RETVAL_IF(ocpf->folder == -1, OCPF_WARN_FOLDER_ID_UNKNOWN, NULL);
+ } else if (id) {
+ ocpf->folder = id;
+ } else if (var_name) {
+ for (element = ocpf->vars; element->next; element = element->next) {
+ if (element->name && !strcmp(element->name, var_name)) {
+ /* WARNING: we assume var data is double */
+ ocpf->folder = *((uint64_t *)element->value);
+ }
+ }
+ }
+
+ return OCPF_SUCCESS;
+}
+
+
+/**
+ \details Register new OLEGUID in ocpf context
+
+ This function registers a OLEGUID couple name, value in ocpf.
+
+ \param name the OLEGUID name
+ \param oleguid the guid string value
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR
+ */
+int ocpf_oleguid_add(const char *name, const char *oleguid)
+{
+ NTSTATUS status;
+ struct ocpf_oleguid *element;
+ struct GUID guid;
+
+ /* Sanity checks */
+ if (!ocpf || !ocpf->mem_ctx) return OCPF_ERROR;
+ if (!name) return OCPF_ERROR;
+
+ /* Sanity check: Do not insert twice the same name or guid */
+ for (element = ocpf->oleguid; element->next; element = element->next) {
+ OCPF_RETVAL_IF(element->name && !strcmp(element->name, name),
+ OCPF_WARN_OLEGUID_N_REGISTERED, NULL);
+
+ OCPF_RETVAL_IF(element->guid && !strcmp(element->guid, oleguid),
+ OCPF_WARN_OLEGUID_G_REGISTERED, NULL);
+ }
+
+ element = talloc_zero(ocpf->mem_ctx, struct ocpf_oleguid);
+
+ status = GUID_from_string(oleguid, &guid);
+ OCPF_RETVAL_IF(!NT_STATUS_IS_OK(status), OCPF_WARN_OLEGUID_INVALID, element);
+
+ element->name = talloc_strdup(ocpf->mem_ctx, name);
+ element->guid = talloc_strdup(ocpf->mem_ctx, oleguid);
+
+ DLIST_ADD(ocpf->oleguid, element);
+
+ return OCPF_SUCCESS;
+}
+
+
+/**
+ \details Check if the given OLEGUID has been registered
+
+ \param name the OLEGUID to check
+ \param guid pointer on pointer to the guid result
+
+ \result OCPF_SUCCESS on success, otherwise OCPF_ERROR;
+ */
+int ocpf_oleguid_check(const char *name, const char **guid)
+{
+ struct ocpf_oleguid *element;
+
+ for (element = ocpf->oleguid; element->next; element = element->next) {
+ if (element->name && !strcmp(element->name, name)) {
+ *guid = element->guid;
+ return OCPF_SUCCESS;
+ }
+ }
+
+ return OCPF_ERROR;
+}
+
+
+/**
+ \details convert a string to FILETIME structure
+
+ This function converts a string - representing a date under the
+ following format "Tyyy-mm-dd hh:mm:ss" - into a FILETIME structure.
+
+ \param date the date to convert
+ \param ft pointer on the converted date
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR
+ */
+int ocpf_add_filetime(const char *date, struct FILETIME *ft)
+{
+ NTTIME nt;
+ struct tm 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;
+ }
+
+ unix_to_nt_time(&nt, mktime(&tm));
+ ft->dwLowDateTime = (nt << 32) >> 32;
+ ft->dwHighDateTime = (nt >> 32);
+
+ return OCPF_SUCCESS;
+}
+
+
+int ocpf_variable_add(const char *name, union SPropValue_CTR lpProp, uint16_t propType, bool unescape)
+{
+ struct ocpf_var *element;
+ int ret;
+
+ if (!ocpf || !ocpf->mem_ctx) return OCPF_ERROR;
+ if (!name) return OCPF_ERROR;
+
+ /* Sanity check: Do not insert twice the same variable */
+ for (element = ocpf->vars; element->next; element = element->next) {
+ OCPF_RETVAL_IF(element->name && !strcmp(element->name, name),
+ OCPF_WARN_VAR_REGISTERED, NULL);
+ }
+
+ element = talloc_zero(ocpf->mem_ctx, struct ocpf_var);
+ element->name = talloc_strdup((TALLOC_CTX *)element, name);
+ element->propType = propType;
+
+ ret = ocpf_set_propvalue((TALLOC_CTX *)element, &element->value, propType, propType, lpProp, unescape);
+ OCPF_RETVAL_IF(ret == -1, OCPF_WARN_VAR_TYPE, element);
+
+ DLIST_ADD(ocpf->vars, element);
+
+ return OCPF_SUCCESS;
+}
+
+
+int ocpf_binary_add(const char *filename, struct Binary_r *bin)
+{
+ int fd;
+ struct stat sb;
+
+ OCPF_RETVAL_IF(stat(filename, &sb), OCPF_WARN_FILENAME_STAT, NULL);
+ fd = open(filename, O_RDONLY);
+ OCPF_RETVAL_IF(fd == -1, OCPF_WARN_FILENAME_INVALID, NULL);
+
+ bin->lpb = talloc_size(ocpf->mem_ctx, sb.st_size);
+ bin->cb = read(fd, bin->lpb, sb.st_size);
+
+ close(fd);
+
+ return OCPF_SUCCESS;
+}
+
+int ocpf_recipient_add(uint8_t recipClass, char *recipient)
+{
+ struct ocpf_recipients *element;
+
+ if (!ocpf || !ocpf->mem_ctx) return OCPF_ERROR;
+ if (!recipient) return OCPF_ERROR;
+
+ element = talloc_zero(ocpf->mem_ctx, struct ocpf_recipients);
+ element->name = talloc_strdup((TALLOC_CTX *)element, recipient);
+ element->class = recipClass;
+
+ DLIST_ADD(ocpf->recipients, element);
+
+ return OCPF_SUCCESS;
+}
Added: trunk/openchange/libocpf/ocpf_api.h
===================================================================
--- trunk/openchange/libocpf/ocpf_api.h (rev 0)
+++ trunk/openchange/libocpf/ocpf_api.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,183 @@
+/*
+ OpenChange OCPF (OpenChange Property File) implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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 __OCPF_API_H_
+#define __OCPF_API_H_
+
+#include <libmapi/libmapi.h>
+
+struct ocpf_var
+{
+ struct ocpf_var *prev;
+ struct ocpf_var *next;
+ const char *name;
+ const void *value;
+ uint16_t propType;
+};
+
+struct ocpf_oleguid
+{
+ struct ocpf_oleguid *prev;
+ struct ocpf_oleguid *next;
+ const char *name;
+ const char *guid;
+};
+
+struct ocpf_property
+{
+ struct ocpf_property *prev;
+ struct ocpf_property *next;
+ uint32_t aulPropTag;
+ const void *value;
+};
+
+struct ocpf_nprop
+{
+ const char *OOM;
+ const char *mnid_string;
+ uint16_t mnid_id;
+ uint16_t propType;
+ const char *guid;
+ bool registered;
+};
+
+enum ocpf_ntype {
+ OCPF_OOM = 0x1,
+ OCPF_MNID_ID,
+ OCPF_MNID_STRING
+};
+
+struct ocpf_nproperty
+{
+ struct ocpf_nproperty *prev;
+ struct ocpf_nproperty *next;
+ enum ocpf_ntype kind;
+ const char *OOM;
+ const char *mnid_string;
+ uint16_t mnid_id;
+ uint16_t propType;
+ const char *oleguid;
+ const void *value;
+};
+
+enum ocpf_recipClass {
+ OCPF_MAPI_TO = 0x1,
+ OCPF_MAPI_CC,
+ OCPF_MAPI_BCC
+};
+
+struct ocpf_recipients
+{
+ struct ocpf_recipients *prev;
+ struct ocpf_recipients *next;
+ char *name;
+ enum ocpf_recipClass class;
+};
+
+struct ocpf
+{
+ TALLOC_CTX *mem_ctx;
+ const char *type;
+ struct ocpf_var *vars;
+ struct ocpf_oleguid *oleguid;
+ struct ocpf_property *props;
+ struct ocpf_nproperty *nprops;
+ struct ocpf_recipients *recipients;
+ const char *filename;
+ struct SPropValue *lpProps;
+ uint32_t cValues;
+ uint64_t folder;
+};
+
+
+struct ocpf_olfolder
+{
+ int id;
+ const char *name;
+};
+
+#include <libocpf/proto_private.h>
+
+/**
+ * Defines
+ */
+#define OCPF_WARN(x) (ocpf_do_debug x)
+
+#define OCPF_RETVAL_IF(x, msg, mem_ctx) \
+do { \
+ if (x) { \
+ OCPF_WARN(("%s", msg)); \
+ if (mem_ctx) { \
+ talloc_free(mem_ctx); \
+ } \
+ return OCPF_ERROR; \
+ } \
+} while (0);
+
+#define OCPF_INITIALIZED "OCPF context has already been initialized"
+#define OCPF_NOT_INITIALIZED "OCPF context has not been initialized"
+
+#define OCPF_WRITE_NOT_INITIALIZED "OCPF write context has not been initialized"
+
+#define OCPF_FATAL_ERROR "Fatal error encountered"
+#define OCPF_WARN_FILENAME_INVALID "Invalid filename"
+#define OCPF_WARN_FILENAME_STAT "Unable to stat file"
+
+#define OCPF_WARN_PROP_REGISTERED "Property already registered"
+#define OCPF_WARN_PROP_TYPE "Property type not supported"
+#define OCPF_WARN_PROP_UNKNOWN "Property Unknown"
+
+#define OCPF_WARN_OOM_UNKNOWN "Unknown OOM"
+#define OCPF_WARN_OOM_REGISTERED "OOM already registered"
+
+#define OCPF_WARN_LID_UNKNOWN "Unknown MNID_ID"
+#define OCPF_WARN_LID_REGISTERED "MNID_ID already registered"
+
+#define OCPF_WARN_STRING_UNKNOWN "Unknown MNID_STRING"
+#define OCPF_WARN_STRING_REGISTERED "MNID_STRING already registered"
+
+
+#define OCPF_WARN_OLEGUID_N_REGISTERED "OLEGUID name already registered"
+#define OCPF_WARN_OLEGUID_G_REGISTERED "OLEGUID GUID already registered"
+#define OCPF_WARN_OLEGUID_UNREGISTERED "OLEGUID unregistered"
+#define OCPF_WARN_OLEGUID_INVALID "OLEGUID invalid"
+
+#define OCPF_WARN_VAR_REGISTERED "Variable already registered"
+#define OCPF_WARN_VAR_NOT_REGISTERED "Unknown variable"
+#define OCPF_WARN_VAR_TYPE "Variable property type not supported"
+
+#define OCPF_WARN_FOLDER_ID_UNKNOWN "Unknown Folder"
+
+#define OCPF_WARN_PROPVALUE_MISMATCH "Property type and value mismatch"
+
+#define OCPF_INVALID_PROPARRAY "Invalid property array"
+#define OCPF_INVALID_FILEHANDLE "Invalid file handle"
+
+
+#define OCPF_PROPERTY_BEGIN "PROPERTY {\n"
+#define OCPF_NPROPERTY_BEGIN "NPROPERTY {\n"
+#define OCPF_END "};\n"
+#define OCPF_NEWLINE "\n"
+#define OCPF_RECIPIENT_TO "RECIPIENT TO "
+#define OCPF_RECIPIENT_CC "RECIPIENT CC "
+#define OCPF_RECIPIENT_BCC "RECIPIENT BCC "
+
+#define DATE_FORMAT "%Y-%m-%d %H:%M:%S"
+
+#endif /* __OCPF_API_H_ */
Added: trunk/openchange/libocpf/ocpf_dump.c
===================================================================
--- trunk/openchange/libocpf/ocpf_dump.c (rev 0)
+++ trunk/openchange/libocpf/ocpf_dump.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,221 @@
+/*
+ OpenChange OCPF (OpenChange Property File) implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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 "libocpf/ocpf_private.h"
+#include <libocpf/ocpf.h>
+#include <libocpf/ocpf_api.h>
+#include <libocpf/ocpf.tab.h>
+#include <libocpf/ocpf_dump.h>
+
+/**
+ \file ocpf_dump.c
+
+ \brief ocpf Dump API
+ */
+
+static void ocpf_do_dump(const char *format, ...)
+{
+ va_list ap;
+ char *s = NULL;
+ int ret;
+
+ va_start(ap, format);
+ ret = vasprintf(&s, format, ap);
+ va_end(ap);
+
+ printf("%s\n", s);
+ free(s);
+}
+
+
+/**
+ \details Dump OCPF Type
+
+ Dump OCPF Registered Type
+*/
+_PUBLIC_ void ocpf_dump_type(void)
+{
+ OCPF_DUMP_TITLE(indent, "TYPE", OCPF_DUMP_TOPLEVEL);
+ indent++;
+
+ INDENT();
+ OCPF_DUMP(("* %s", ocpf->type ? ocpf->type : "Undefined"));
+ indent--;
+}
+
+
+/**
+ \details Dump OCPF Destination Folder
+
+ Dump OCPF Registered Destination Folder
+ */
+_PUBLIC_ void ocpf_dump_folder(void)
+{
+ OCPF_DUMP_TITLE(indent, "FOLDER", OCPF_DUMP_TOPLEVEL);
+ indent++;
+
+ INDENT();
+ OCPF_DUMP(("* 0x%llx", ocpf->folder ? ocpf->folder : -1));
+ indent--;
+}
+
+
+/**
+ \details Dump OCPF Recipients
+
+ Dump OCPF Recipients
+ */
+_PUBLIC_ void ocpf_dump_recipients(void)
+{
+ struct ocpf_recipients *element;
+
+ OCPF_DUMP_TITLE(indent, "RECIPIENTS", OCPF_DUMP_TOPLEVEL);
+ indent++;
+
+ INDENT();
+ printf("* To: ");
+ for (element = ocpf->recipients; element->next; element = element->next) {
+ if (element->class == OCPF_MAPI_TO) {
+ printf("%s;", element->name);
+ }
+ }
+ printf("\n");
+
+ INDENT();
+ printf("* Cc: ");
+ for (element = ocpf->recipients; element->next; element = element->next) {
+ if (element->class == OCPF_MAPI_CC) {
+ printf("%s;", element->name);
+ }
+ }
+ printf("\n");
+
+ INDENT();
+ printf("* Bcc: ");
+ for (element = ocpf->recipients; element->next; element = element->next) {
+ if (element->class == OCPF_MAPI_BCC) {
+ printf("%s;", element->name);
+ }
+ }
+ printf("\n");
+}
+
+
+/**
+ \details Dump OCPF OLEGUID
+
+ Dump OCPF Registered OLEGUID
+*/
+_PUBLIC_ void ocpf_dump_oleguid(void)
+{
+ struct ocpf_oleguid *element;
+
+ OCPF_DUMP_TITLE(indent, "OLEGUID", OCPF_DUMP_TOPLEVEL);
+ indent++;
+ for (element = ocpf->oleguid; element->next; element = element->next) {
+ INDENT();
+ printf("%-25s: %s\n", element->name, element->guid);
+ }
+ indent--;
+}
+
+
+_PUBLIC_ void ocpf_dump_variable(void)
+{
+ struct ocpf_var *element;
+
+ OCPF_DUMP_TITLE(indent, "VARIABLE", OCPF_DUMP_TOPLEVEL);
+ indent++;
+ for (element = ocpf->vars; element->next; element = element->next) {
+ INDENT();
+ printf("%s\n", element->name);
+ }
+ indent--;
+}
+
+_PUBLIC_ void ocpf_dump_property(void)
+{
+ struct ocpf_property *element;
+ const char *proptag;
+
+ OCPF_DUMP_TITLE(indent, "PROPERTIES", OCPF_DUMP_TOPLEVEL);
+ indent++;
+ for (element = ocpf->props; element->next; element = element->next) {
+ INDENT();
+ proptag = (const char *)get_proptag_name(element->aulPropTag);
+ printf("0x%.8x = %s\n", element->aulPropTag,
+ (char *)(proptag ? proptag : "UNKNOWN"));
+
+ }
+ indent--;
+}
+
+
+_PUBLIC_ void ocpf_dump_named_property(void)
+{
+ struct ocpf_nproperty *element;
+
+ OCPF_DUMP_TITLE(indent, "NAMED PROPERTIES", OCPF_DUMP_TOPLEVEL);
+ indent++;
+
+ OCPF_DUMP_TITLE(indent, "OOM", OCPF_DUMP_SUBLEVEL);
+ indent++;
+ for (element = ocpf->nprops; element->next; element = element->next) {
+ if (element->kind == OCPF_OOM) {
+ INDENT();
+ printf("* %s\n", element->OOM);
+ }
+ }
+ indent--;
+
+ OCPF_DUMP_TITLE(indent, "MNID_ID", OCPF_DUMP_SUBLEVEL);
+ indent++;
+ for (element = ocpf->nprops; element->next; element = element->next) {
+ if (element->kind == OCPF_MNID_ID) {
+ INDENT();
+ printf("* 0x%.4x\n", element->mnid_id);
+ }
+ }
+ indent--;
+
+ OCPF_DUMP_TITLE(indent, "MNID_STRING", OCPF_DUMP_SUBLEVEL);
+ indent++;
+ for (element = ocpf->nprops; element->next; element = element->next) {
+ if (element->kind == OCPF_MNID_STRING) {
+ INDENT();
+ printf("* %s\n", element->mnid_string);
+ }
+ }
+ indent--;
+
+ indent--;
+}
+
+
+_PUBLIC_ void ocpf_dump(void)
+{
+ indent = 0;
+ ocpf_dump_type();
+ ocpf_dump_folder();
+ ocpf_dump_oleguid();
+ ocpf_dump_recipients();
+ ocpf_dump_variable();
+ ocpf_dump_property();
+ ocpf_dump_named_property();
+}
Added: trunk/openchange/libocpf/ocpf_dump.h
===================================================================
--- trunk/openchange/libocpf/ocpf_dump.h (rev 0)
+++ trunk/openchange/libocpf/ocpf_dump.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,61 @@
+/*
+ OpenChange OCPF (OpenChange Property File) implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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 __OCPF_DUMP_H_
+#define __OCPF_DUMP_H_
+
+#define INDENT() \
+do { \
+ uint32_t i; \
+ \
+ for (i = 0; i < indent; i++) { \
+ printf("\t"); \
+ } \
+} while (0);
+
+
+#define OCPF_DUMP(x) (ocpf_do_dump x)
+
+#define OCPF_DUMP_TITLE(indent, txt, type) \
+do { \
+ int i; \
+ int txt_len; \
+ \
+ printf("\n"); \
+ INDENT(); \
+ printf("%s:\n", txt); \
+ \
+ INDENT(); \
+ txt_len = strlen(txt) + 1; \
+ for (i = 0; i < txt_len; i++) { \
+ printf("%c", type ? '-' : '='); \
+ } \
+ printf("\n"); \
+} while (0);
+
+
+#define OCPF_DUMP_TOPLEVEL 0
+#define OCPF_DUMP_SUBLEVEL 1
+
+
+int indent;
+
+
+
+#endif /* ! __OCPF_DUMP_H_ */
Added: trunk/openchange/libocpf/ocpf_private.h
===================================================================
--- trunk/openchange/libocpf/ocpf_private.h (rev 0)
+++ trunk/openchange/libocpf/ocpf_private.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,35 @@
+/*
+ OpenChange OCPF (OpenChange Property File) implementation.
+
+ Copyright (C) Julien Kerihuel 2009.
+
+ 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 __OCPF_PRIVATE_H_
+#define __OCPF_PRIVATE_H_
+
+#include "config.h"
+#include <stdlib.h>
+
+#ifndef HAVE_COMPARISON_FN_T
+#define HAVE_COMPARISON_FN_T
+typedef int (*comparison_fn_t)(const void *, const void *);
+#else
+# ifndef comparison_fn_t
+typedef __compar_fn_t comparison_fn_t;
+# endif
+#endif
+
+#endif /* ! __OCPF_PRIVATE_H_ */
Added: trunk/openchange/libocpf/ocpf_public.c
===================================================================
--- trunk/openchange/libocpf/ocpf_public.c (rev 0)
+++ trunk/openchange/libocpf/ocpf_public.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,558 @@
+/*
+ OpenChange OCPF (OpenChange Property File) implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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/>.
+*/
+
+/**
+ \file ocpf_public.c
+
+ \brief public OCPF API
+ */
+
+#include "libocpf/ocpf_private.h"
+#include <libocpf/ocpf.h>
+#include <libocpf/ocpf_api.h>
+
+#include <sys/stat.h>
+
+int ocpf_yyparse(void);
+
+struct ocpf *ocpf;
+extern FILE *yyin;
+int error_flag;
+
+
+/**
+ \details Initialize OCPF context
+
+ Initialize ocpf context and allocate memory for internal structures
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR
+
+ \sa ocpf_release, ocpf_parse
+ */
+_PUBLIC_ int ocpf_init(void)
+{
+ TALLOC_CTX *mem_ctx;
+
+ if (ocpf) return OCPF_ERROR;
+
+ mem_ctx = talloc_named(NULL, 0, "ocpf");
+ ocpf = talloc_zero(mem_ctx, struct ocpf);
+ ocpf->mem_ctx = mem_ctx;
+ ocpf->vars = talloc_zero(mem_ctx, struct ocpf_var);
+ ocpf->oleguid = talloc_zero(mem_ctx, struct ocpf_oleguid);
+ ocpf->props = talloc_zero(mem_ctx, struct ocpf_property);
+ ocpf->nprops = talloc_zero(mem_ctx, struct ocpf_nproperty);
+ ocpf->recipients = talloc_zero(mem_ctx, struct ocpf_recipients);
+ ocpf->lpProps = NULL;
+ ocpf->filename = NULL;
+ ocpf->cValues = 0;
+ ocpf->folder = 0;
+
+ return OCPF_SUCCESS;
+}
+
+
+/**
+ \details Uninitialize OCPF context
+
+ Uninitialize the global OCPF context and release memory.
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR
+
+ \sa ocpf_init
+ */
+_PUBLIC_ int ocpf_release(void)
+{
+ if (!ocpf || !ocpf->mem_ctx) return OCPF_ERROR;
+
+ talloc_free(ocpf->mem_ctx);
+ ocpf = NULL;
+
+ return OCPF_SUCCESS;
+}
+
+
+/**
+ \details Parse OCPF file
+
+ Parse and process the given ocpf file.
+
+ \param filename the file to parse
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR
+
+ \sa ocpf_init
+ */
+_PUBLIC_ int ocpf_parse(const char *filename)
+{
+ int ret;
+ struct stat sb;
+
+ if (!filename) return OCPF_ERROR;
+ if (!ocpf || !ocpf->mem_ctx) return OCPF_ERROR;
+
+ ocpf->filename = filename;
+ lineno = 1;
+
+ /* Sanity check on filename */
+ OCPF_RETVAL_IF((!filename || (stat(filename, &sb) == -1)),
+ OCPF_WARN_FILENAME_INVALID, NULL);
+
+ yyin = fopen(filename, "r");
+ OCPF_RETVAL_IF(yyin == NULL, OCPF_WARN_FILENAME_INVALID, NULL);
+
+ ret = ocpf_yyparse();
+ fclose(yyin);
+
+ return ret;
+}
+
+
+#define MAX_READ_SIZE 0x1000
+
+static enum MAPISTATUS ocpf_stream(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_parent,
+ uint32_t aulPropTag,
+ struct Binary_r *bin)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_stream;
+ DATA_BLOB stream;
+ uint32_t access_flags = 2; /* MAPI_MODIFY by default */
+ uint32_t size;
+ uint32_t offset;
+ uint16_t read_size;
+
+ mapi_object_init(&obj_stream);
+
+ /* Step1. Open the Stream */
+ retval = OpenStream(obj_parent, aulPropTag, access_flags, &obj_stream);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ /* Step2. Write the Stream */
+ size = MAX_READ_SIZE;
+ offset = 0;
+ while (offset <= bin->cb) {
+ stream.length = size;
+ stream.data = talloc_size(mem_ctx, size);
+ memcpy(stream.data, bin->lpb + offset, size);
+
+ retval = WriteStream(&obj_stream, &stream, &read_size);
+ talloc_free(stream.data);
+ OCPF_RETVAL_IF(retval, retval, NULL);
+
+ /* Exit when there is nothing left to write */
+ if (!read_size) return MAPI_E_SUCCESS;
+
+ offset += read_size;
+
+ if ((offset + size) > bin->cb) {
+ size = bin->cb - offset;
+ }
+ }
+
+ mapi_object_release(&obj_stream);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Build a SPropValue array from ocpf context
+
+ This function builds a SPropValue array from the ocpf context and
+ information stored.
+
+ \param mem_ctx the memory context to use for memory allocation
+ \param obj_folder pointer the folder object we use for internal
+ MAPI operations
+ \param obj_message pointer to the message object we use for
+ internal MAPI operations
+
+ \return MAPI_E_SUCCESS on success, otherwise -1.
+
+ \note Developers should call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
+
+ \sa ocpf_get_SPropValue
+ */
+_PUBLIC_ enum MAPISTATUS ocpf_set_SPropValue(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_message)
+{
+ enum MAPISTATUS retval;
+ struct mapi_nameid *nameid;
+ struct SPropTagArray *SPropTagArray;
+ struct ocpf_property *pel;
+ struct ocpf_nproperty *nel;
+ uint32_t i;
+
+ /* sanity checks */
+ MAPI_RETVAL_IF(!ocpf, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Step 1. Allocate SPropValue */
+ ocpf->cValues = 0;
+ ocpf->lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
+
+ /* Step2. build the list of named properties we want to set */
+ if (ocpf->nprops && ocpf->nprops->next) {
+ nameid = mapi_nameid_new(mem_ctx);
+ for (nel = ocpf->nprops; nel->next; nel = nel->next) {
+ if (nel->OOM) {
+ mapi_nameid_OOM_add(nameid, nel->OOM, nel->oleguid);
+ } else if (nel->mnid_id) {
+ mapi_nameid_custom_lid_add(nameid, nel->mnid_id, nel->propType, nel->oleguid);
+ } else if (nel->mnid_string) {
+ mapi_nameid_custom_string_add(nameid, nel->mnid_string, nel->propType, nel->oleguid);
+ }
+ }
+
+ /* Step3. GetIDsFromNames and map property types */
+ SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
+ retval = GetIDsFromNames(obj_folder, nameid->count,
+ nameid->nameid, 0, &SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(SPropTagArray);
+ MAPIFreeBuffer(nameid);
+ return retval;
+ }
+ mapi_nameid_SPropTagArray(nameid, SPropTagArray);
+ MAPIFreeBuffer(nameid);
+
+
+ /* Step4. Add named properties */
+ for (nel = ocpf->nprops, i = 0; SPropTagArray->aulPropTag[i] && nel->next; nel = nel->next, i++) {
+ if (SPropTagArray->aulPropTag[i]) {
+ if (((SPropTagArray->aulPropTag[i] & 0xFFFF) == PT_BINARY) &&
+ (((struct Binary_r *)nel->value)->cb > MAX_READ_SIZE)) {
+ retval = ocpf_stream(mem_ctx, obj_message, SPropTagArray->aulPropTag[i],
+ (struct Binary_r *)nel->value);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+ } else {
+ ocpf->lpProps = add_SPropValue(mem_ctx, ocpf->lpProps, &ocpf->cValues,
+ SPropTagArray->aulPropTag[i], nel->value);
+ }
+ }
+ }
+ MAPIFreeBuffer(SPropTagArray);
+ }
+
+ /* Step5. Add Known properties */
+ if (ocpf->props && ocpf->props->next) {
+ for (pel = ocpf->props; pel->next; pel = pel->next) {
+ if (((pel->aulPropTag & 0xFFFF) == PT_BINARY) &&
+ (((struct Binary_r *)pel->value)->cb > MAX_READ_SIZE)) {
+ retval = ocpf_stream(mem_ctx, obj_message, pel->aulPropTag,
+ (struct Binary_r *)pel->value);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+ } else {
+ ocpf->lpProps = add_SPropValue(mem_ctx, ocpf->lpProps, &ocpf->cValues,
+ pel->aulPropTag, pel->value);
+ }
+ }
+ }
+ /* Step 6. Add message class */
+ if (ocpf->type) {
+ ocpf->lpProps = add_SPropValue(mem_ctx, ocpf->lpProps, &ocpf->cValues,
+ PR_MESSAGE_CLASS, (const void *)ocpf->type);
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Get the OCPF SPropValue array
+
+ This function is an accessor designed to return the SPropValue
+ structure created with ocpf_set_SPropValue.
+
+ \param cValues pointer on the number of SPropValue entries
+
+ \return NULL on error, otherwise returns an allocated lpProps pointer
+
+ \sa ocpf_set_SPropValue
+ */
+_PUBLIC_ struct SPropValue *ocpf_get_SPropValue(uint32_t *cValues)
+{
+ if (!ocpf || !ocpf->lpProps) return NULL;
+ if (!ocpf->cValues) return NULL;
+
+ *cValues = ocpf->cValues;
+
+ return ocpf->lpProps;
+}
+
+
+static enum MAPISTATUS ocpf_folder_lookup(TALLOC_CTX *mem_ctx,
+ uint64_t sfid,
+ mapi_object_t *obj_parent,
+ mapi_id_t folder_id,
+ mapi_object_t *obj_ret)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_htable;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ uint32_t i;
+ const uint64_t *fid;
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(obj_parent, folder_id, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_init(&obj_htable);
+ retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_FID);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND && SRowSet.cRows)) {
+ for (i = 0; i < SRowSet.cRows; i++) {
+ fid = (const uint64_t *)find_SPropValue_data(&SRowSet.aRow[i], PR_FID);
+ if (fid && *fid == sfid) {
+ retval = OpenFolder(&obj_folder, *fid, obj_ret);
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&obj_folder);
+ return MAPI_E_SUCCESS;
+ } else {
+ retval = ocpf_folder_lookup(mem_ctx, sfid, &obj_folder, *fid, obj_ret);
+ if (retval == MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&obj_folder);
+ return MAPI_E_SUCCESS;
+ }
+ }
+ }
+ }
+
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&obj_folder);
+
+ errno = MAPI_E_NOT_FOUND;
+ return MAPI_E_NOT_FOUND;
+}
+
+
+/**
+ \details Open OCPF folder
+
+ This function opens the folder associated with the ocpf folder
+ global context value.
+
+ \param obj_store the store object
+ \param obj_folder the folder to open
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND.
+
+ \note Developers should call GetLastError() to retrieve the last
+ MAPI error code. Possible MAPI error codes are:
+ - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
+ - MAPI_E_INVALID_PARAMETER: obj_store is undefined
+ - MAPI_E_NOT_FOUND: The specified folder could not be found or is
+ not yet supported.
+
+ \sa ocpf_init, ocpf_parse
+ */
+_PUBLIC_ enum MAPISTATUS ocpf_OpenFolder(mapi_object_t *obj_store,
+ mapi_object_t *obj_folder)
+{
+ enum MAPISTATUS retval;
+ mapi_id_t id_folder;
+ mapi_id_t id_tis;
+
+ /* Sanity checks */
+ MAPI_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!ocpf, MAPI_E_NOT_INITIALIZED, NULL);
+
+ MAPI_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
+ MAPI_RETVAL_IF(!ocpf->folder, MAPI_E_NOT_FOUND, NULL);
+
+ /* */
+ mapi_object_init(obj_folder);
+ if (ocpf->folder >= 1 && ocpf->folder <= 26) {
+ retval = GetDefaultFolder(obj_store, &id_folder, ocpf->folder);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ retval = OpenFolder(obj_store, id_folder, obj_folder);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ } else {
+ retval = GetDefaultFolder(obj_store, &id_tis, olFolderTopInformationStore);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ retval = ocpf_folder_lookup((TALLOC_CTX *)ocpf->mem_ctx, ocpf->folder,
+ obj_store, id_tis, obj_folder);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ * We set external recipients at the end of aRow
+ */
+static bool set_external_recipients(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, const char *username, enum ulRecipClass RecipClass)
+{
+ uint32_t last;
+ struct SPropValue SPropValue;
+
+ SRowSet->aRow = talloc_realloc(mem_ctx, SRowSet->aRow, struct SRow, SRowSet->cRows + 2);
+ last = SRowSet->cRows;
+ SRowSet->aRow[last].cValues = 0;
+ SRowSet->aRow[last].lpProps = talloc_zero(mem_ctx, struct SPropValue);
+
+ /* PR_OBJECT_TYPE */
+ SPropValue.ulPropTag = PR_OBJECT_TYPE;
+ SPropValue.value.l = MAPI_MAILUSER;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_DISPLAY_TYPE */
+ SPropValue.ulPropTag = PR_DISPLAY_TYPE;
+ SPropValue.value.l = 0;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_GIVEN_NAME */
+ SPropValue.ulPropTag = PR_GIVEN_NAME;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_DISPLAY_NAME */
+ SPropValue.ulPropTag = PR_DISPLAY_NAME;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_7BIT_DISPLAY_NAME */
+ SPropValue.ulPropTag = PR_7BIT_DISPLAY_NAME;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_SMTP_ADDRESS */
+ SPropValue.ulPropTag = PR_SMTP_ADDRESS;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_ADDRTYPE */
+ SPropValue.ulPropTag = PR_ADDRTYPE;
+ SPropValue.value.lpszA = "SMTP";
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ SetRecipientType(&(SRowSet->aRow[last]), RecipClass);
+
+ SRowSet->cRows += 1;
+ return true;
+}
+
+
+/**
+ \details Set the message recipients from ocpf context
+
+ This function sets the recipient (To, Cc, Bcc) from the ocpf
+ context and information stored.
+
+ \param mem_ctx the memory context to use for memory allocation
+ \param obj_message pointer to the message object we use for
+ internal MAPI operations
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR.
+
+ \sa ocpf
+ */
+_PUBLIC_ enum MAPISTATUS ocpf_set_Recipients(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_message)
+{
+ enum MAPISTATUS retval;
+ struct ocpf_recipients *element;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue SPropValue;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ char **usernames = NULL;
+ int *recipClass = NULL;
+ uint32_t count;
+ uint32_t counter;
+ uint32_t i;
+
+ MAPI_RETVAL_IF(!ocpf, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+ MAPI_RETVAL_IF(!ocpf->recipients->next, MAPI_E_NOT_FOUND, NULL);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_7BIT_DISPLAY_NAME,
+ PR_DISPLAY_NAME,
+ PR_SMTP_ADDRESS,
+ PR_GIVEN_NAME);
+
+ /* Step 1. Group recipients and run ResolveNames */
+ usernames = talloc_array(mem_ctx, char *, 2);
+ recipClass = talloc_array(mem_ctx, int, 2);
+ for (element = ocpf->recipients, count = 0; element->next; element = element->next, count ++) {
+ usernames = talloc_realloc(mem_ctx, usernames, char *, count + 2);
+ recipClass = talloc_realloc(mem_ctx, recipClass, int, count + 2);
+ usernames[count] = talloc_strdup((TALLOC_CTX *)usernames, element->name);
+ recipClass[count] = element->class;
+ }
+ usernames[count] = 0;
+
+ retval = ResolveNames(mapi_object_get_session(obj_message), (const char **)usernames,
+ SPropTagArray, &SRowSet, &flaglist, 0);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, retval, usernames);
+
+ /* Step2. Associate resolved recipients to their respective recipClass */
+ if (!SRowSet) {
+ SRowSet = talloc_zero(mem_ctx, struct SRowSet);
+ }
+
+ count = 0;
+ counter = 0;
+ for (i = 0; usernames[i]; i++) {
+ if (flaglist->aulPropTag[count] == MAPI_UNRESOLVED) {
+ set_external_recipients(mem_ctx, SRowSet, usernames[i], recipClass[i]);
+ }
+ if (flaglist->aulPropTag[count] == MAPI_RESOLVED) {
+ SetRecipientType(&(SRowSet->aRow[counter]), recipClass[i]);
+ counter++;
+ }
+ count++;
+ }
+
+ /* Step3. Finish to build the ModifyRecipients SRowSet */
+ SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
+ SPropValue.value.l = 0;
+ SRowSet_propcpy(mem_ctx, SRowSet, SPropValue);
+
+ /* Step4. Call ModifyRecipients */
+ retval = ModifyRecipients(obj_message, SRowSet);
+ MAPIFreeBuffer(SRowSet);
+ MAPIFreeBuffer(flaglist);
+ MAPIFreeBuffer(usernames);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/libocpf/ocpf_write.c
===================================================================
--- trunk/openchange/libocpf/ocpf_write.c (rev 0)
+++ trunk/openchange/libocpf/ocpf_write.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,623 @@
+/*
+ OpenChange OCPF (OpenChange Property File) implementation.
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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/>.
+*/
+
+/**
+ \file ocpf_write.c
+
+ \brief public OCPF write API
+ */
+
+#include "libocpf/ocpf_private.h"
+#include <libocpf/ocpf.h>
+#include <libocpf/ocpf_api.h>
+#include <libmapi/defs_private.h>
+
+#include <time.h>
+
+struct ocpf_guid {
+ char *name;
+ const char *oleguid;
+};
+
+static const struct ocpf_guid ocpf_guid[] = {
+ { "PSETID_Appointment", "00062002-0000-0000-c000-000000000046" },
+ { "PSETID_Task", "00062003-0000-0000-c000-000000000046" },
+ { "PSETID_Address", "00062004-0000-0000-c000-000000000046" },
+ { "PSETID_Common", "00062008-0000-0000-c000-000000000046" },
+ { "PSETID_Note", "0006200e-0000-0000-c000-000000000046" },
+ { "PSETID_Log", "0006200a-0000-0000-c000-000000000046" },
+ { "PS_PUBLIC_STRINGS", "00020329-0000-0000-c000-000000000046" },
+ { "PS_INTERNET_HEADERS", "00020386-0000-0000-c000-000000000046" },
+ { NULL, NULL }
+};
+
+static char *ocpf_write_get_guid_name(const char *oleguid)
+{
+ uint32_t i;
+ static int idx = 0;
+ static struct ocpf_oleguid *guid = NULL;
+ struct ocpf_oleguid *element;
+ char *name;
+
+ if (!oleguid) return NULL;
+
+ if (!guid) {
+ guid = talloc_zero(ocpf->mem_ctx, struct ocpf_oleguid);
+ }
+
+ for (i = 0; ocpf_guid[i].oleguid; i++) {
+ if (!strcmp(oleguid, ocpf_guid[i].oleguid)) {
+ return ocpf_guid[i].name;
+ }
+ }
+
+ for (element = guid; element->next; element = element->next) {
+ if (!strcmp(oleguid, element->guid)) {
+ return (char *)element->name;
+ }
+ }
+
+ element->name = talloc_asprintf(ocpf->mem_ctx, "PSETID_Custom_%d", idx);
+ element->guid = talloc_strdup(ocpf->mem_ctx, oleguid);
+ DLIST_ADD(guid, element);
+ name = talloc_strdup(ocpf->mem_ctx, element->name);
+ idx++;
+
+ return name;
+}
+
+struct ocpf_proptype {
+ uint16_t type;
+ const char *name;
+};
+
+static const struct ocpf_proptype ocpf_proptype[] = {
+ { 0x2, "PT_SHORT" },
+ { 0x3, "PT_LONG" },
+ { 0x4, "PT_FLOAT" },
+ { 0x5, "PT_DOUBLE" },
+ { 0x6, "PT_CURRENCY" },
+ { 0x7, "PT_APPTIME" },
+ { 0xa, "PT_ERROR" },
+ { 0xb, "PT_BOOLEAN" },
+ { 0xd, "PT_OBJECT" },
+ { 0x14, "PT_I8" },
+ { 0x1e, "PT_STRING8" },
+ { 0x1f, "PT_UNICODE" },
+ { 0x40, "PT_SYSTIME" },
+ { 0x48, "PT_CLSID" },
+ { 0x102, "PT_BINARY" },
+ { 0x1002, "PT_MV_SHORT" },
+ { 0x1003, "PT_MV_LONG" },
+ { 0x101e, "PT_MV_STRING8" },
+ { 0x101f, "PT_MV_UNICODE" },
+ { 0, NULL}
+};
+
+static const char *ocpf_write_get_proptype_name(uint16_t type)
+{
+ uint32_t i;
+
+ for (i = 0; ocpf_proptype[i].name; i++) {
+ if (type == ocpf_proptype[i].type) {
+ return ocpf_proptype[i].name;
+ }
+ }
+ return NULL;
+}
+
+static void ocpf_write_propname(FILE *fp, uint32_t ulPropTag)
+{
+ const char *propname;
+ char *line;
+ ssize_t len;
+
+ propname = get_proptag_name(ulPropTag);
+ if (propname) {
+ line = talloc_asprintf(ocpf->mem_ctx, "\t%s = ", propname);
+ } else {
+ line = talloc_asprintf(ocpf->mem_ctx, "\t0x%x = ", ulPropTag);
+ }
+ len = fwrite(line, strlen(line), 1, fp);
+ talloc_free(line);
+}
+
+static char *ocpf_write_systime(const struct FILETIME *ft)
+{
+ char *line;
+ char tempTime[60];
+ NTTIME nt;
+ time_t t;
+ struct tm *tm;
+
+ nt = ft->dwHighDateTime;
+ nt = (nt << 32) | ft->dwLowDateTime;
+ t = nt_time_to_unix(nt);
+ tm = localtime(&t);
+
+ strftime(tempTime, sizeof(tempTime)-1, "T%Y-%m-%d %H:%M:%S\n", tm);
+ line = talloc_strdup(ocpf->mem_ctx, tempTime);
+
+ return line;
+}
+
+static char *ocpf_write_binary(const struct Binary_r *bin)
+{
+ uint32_t i;
+ char *line;
+
+ line = talloc_asprintf(ocpf->mem_ctx, "{");
+ for (i = 0; i < bin->cb; i++) {
+ line = talloc_asprintf_append(line, " 0x%.2x", bin->lpb[i]);
+ }
+ line = talloc_asprintf_append(line, " }\n");
+
+ return line;
+}
+
+static char *ocpf_write_escape_string(const char *value)
+{
+ char *str = NULL;
+ char *stmp = NULL;
+ int value_len;
+ int len = 0;
+ int tmp = 0;
+
+ value_len = strlen(value);
+ tmp = strcspn(value, "\\\"");
+
+ if (tmp == value_len) {
+ str = talloc_strdup(ocpf->mem_ctx, value);
+ return str;
+ } else {
+ str = talloc_strndup(ocpf->mem_ctx, value, tmp);
+ str = talloc_asprintf_append_buffer(str, "\\\%c", value[tmp]);
+ }
+ len += tmp + 1;
+
+ while (len < value_len) {
+ tmp = strcspn(value + len, "\\\"");
+
+ if ((tmp + len) == value_len) {
+ str = talloc_asprintf_append_buffer(str, "%s", value + len);
+ break;
+ } else {
+ stmp = talloc_strndup(ocpf->mem_ctx, value + len, tmp);
+ str = talloc_asprintf_append_buffer(str, "%s\\\%c", stmp, value[len + tmp]);
+ talloc_free(stmp);
+ len += tmp + 1;
+ }
+ }
+
+ return str;
+}
+
+char *ocpf_write_unescape_string(const char *value)
+{
+ char *str = NULL;
+ char *stmp = NULL;
+ int value_len;
+ int len = 0;
+ int tmp = 0;
+
+ value_len = strlen(value);
+ tmp = strcspn(value, "\\");
+
+ if (tmp == value_len) {
+ str = talloc_strdup(ocpf->mem_ctx, value);
+ return str;
+ }
+
+ str = talloc_strndup(ocpf->mem_ctx, value, tmp + 1);
+ if (value[tmp + 1] && value[tmp + 1] == '\\') {
+ len += tmp + 2;
+ } else {
+ len += tmp + 1;
+ }
+
+ while (len < value_len) {
+ tmp = strcspn(value + len, "\\");
+
+ if ((tmp + len) == value_len) {
+ str = talloc_asprintf_append(str, "%s", value + len);
+ break;
+ }
+
+ stmp = talloc_strndup(ocpf->mem_ctx, value + len, tmp + 1);
+ str = talloc_asprintf_append(str, "%s", stmp);
+ if (value[len + tmp + 1] &&
+ (value[len + tmp + 1] == '\\' || value[len + tmp + 1] == '"')) {
+ len += tmp + 2;
+ } else {
+ len += tmp + 1;
+ }
+ talloc_free(stmp);
+ }
+
+ return str;
+}
+
+static char *ocpf_write_mv_string8(const struct StringArray_r *value)
+{
+ char *str = NULL;
+ char *tmp = NULL;
+ uint32_t i;
+
+ str = talloc_asprintf(ocpf->mem_ctx, "{ ");
+ for (i = 0; i < value->cValues; i++) {
+ tmp = ocpf_write_escape_string((const char *)value->lppszA[i]);
+ if (i != value->cValues - 1) {
+ str = talloc_asprintf_append_buffer(str, "\"%s\", ", tmp);
+ } else {
+ str = talloc_asprintf_append_buffer(str, "\"%s\" }", tmp);
+ }
+ talloc_free(tmp);
+ }
+
+ return str;
+}
+
+static char *ocpf_write_property(bool *found, uint32_t ulPropTag, const void *value)
+{
+ char *line = NULL;
+ char *str = NULL;
+
+ switch (ulPropTag & 0xFFFF) {
+ case PT_STRING8:
+ str = ocpf_write_escape_string((const char *)value);
+ line = talloc_asprintf(ocpf->mem_ctx, "\"%s\"\n", str);
+ talloc_free(str);
+ *found = true;
+ break;
+ case PT_UNICODE:
+ str = ocpf_write_escape_string((const char *)value);
+ line = talloc_asprintf(ocpf->mem_ctx, "U\"%s\"\n", str);
+ talloc_free(str);
+ *found = true;
+ break;
+ case PT_SHORT:
+ line = talloc_asprintf(ocpf->mem_ctx, "S%d\n", *((const uint16_t *)value));
+ *found = true;
+ break;
+ case PT_LONG:
+ line = talloc_asprintf(ocpf->mem_ctx, "%d\n", *((const uint32_t *)value));
+ *found = true;
+ break;
+ case PT_BOOLEAN:
+ line = talloc_asprintf(ocpf->mem_ctx, "B\"%s\"\n", (*((const uint8_t *)value) == true) ? "true" : "false");
+ *found = true;
+ break;
+ case PT_DOUBLE:
+ line = talloc_asprintf(ocpf->mem_ctx, "D0x%"PRIx64"\n", *(const uint64_t *)value);
+ *found = true;
+ break;
+ case PT_SYSTIME:
+ line = ocpf_write_systime((const struct FILETIME *)value);
+ *found = true;
+ break;
+ case PT_BINARY:
+ line = ocpf_write_binary((const struct Binary_r *)value);
+ *found = true;
+ break;
+ case PT_MV_STRING8:
+ line = ocpf_write_mv_string8((const struct StringArray_r *)value);
+ *found = true;
+ break;
+ }
+
+ return line;
+}
+
+
+static char *ocpf_write_recipients(enum ocpf_recipClass recipClass)
+{
+ struct ocpf_recipients *element;
+ char *line = NULL;
+ bool found = false;
+
+ line = talloc_zero(ocpf->mem_ctx, char);
+ for (element = ocpf->recipients, found = false; element->next; element = element->next) {
+ if (found && element->class == recipClass) {
+ line = talloc_asprintf_append(line, ";");
+ found = false;
+ }
+ if (element->class == recipClass) {
+ line = talloc_asprintf_append(line, "\"%s\"", element->name);
+ found = true;
+ }
+ }
+ return line;
+}
+
+
+static int ocpf_write_add_recipients(enum ocpf_recipClass recipClass, const char *recipients)
+{
+ char *tmp = NULL;
+ uint32_t i = 0;
+
+ if (!recipients) return OCPF_ERROR;
+
+ if ((tmp = strtok((char *)recipients, ";")) == NULL) {
+ return OCPF_ERROR;
+ }
+
+ ocpf_recipient_add(recipClass, tmp);
+
+ for (i = 1; (tmp = strtok(NULL, ";")) != NULL; i++) {
+ ocpf_recipient_add(recipClass, tmp);
+ }
+
+ return OCPF_SUCCESS;
+}
+
+static bool ocpf_write_exclude_property(uint32_t ulPropTag)
+{
+ uint32_t i;
+ uint32_t propArray[] = { PR_DISPLAY_TO,
+ PR_DISPLAY_CC,
+ PR_DISPLAY_BCC,
+ 0};
+
+ for (i = 0; propArray[i]; i++) {
+ if (propArray[i] == ulPropTag) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ \details Specify the OCPF file name to write
+
+ Specify the ocpf file to create
+
+ \param filename output filename
+ \param folder_id the folder
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR
+
+ \sa ocpf_init
+ */
+_PUBLIC_ int ocpf_write_init(const char *filename, mapi_id_t folder_id)
+{
+ OCPF_RETVAL_IF(!filename, OCPF_WRITE_NOT_INITIALIZED, NULL);
+ OCPF_RETVAL_IF(!folder_id, OCPF_WRITE_NOT_INITIALIZED, NULL);
+ OCPF_RETVAL_IF(!ocpf || !ocpf->mem_ctx, OCPF_NOT_INITIALIZED, NULL);
+
+ ocpf->filename = talloc_strdup(ocpf->mem_ctx, filename);
+ ocpf->folder = folder_id;
+
+ return OCPF_SUCCESS;
+}
+
+
+/**
+ \details Create the OCPF structure required for the commit
+ operation
+
+ This function process properties and named properties from the
+ specified mapi_SPropValue_array and generates an OCPF structure
+ with all the attributes required to create an OCPF file in the
+ commit operation.
+
+ \param obj_message the message object
+ \param mapi_lpProps the array of mapi properties returned by
+ GetPropsAll
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR
+
+ \sa GetPropsAll, ocpf_write_commit
+ */
+_PUBLIC_ int ocpf_write_auto(mapi_object_t *obj_message,
+ struct mapi_SPropValue_array *mapi_lpProps)
+{
+ enum MAPISTATUS retval;
+ uint32_t i;
+ uint16_t propID;
+ struct SPropValue lpProps;
+ const char *type;
+ const char *recipient;
+ char *tmp_guid;
+ const char *guid;
+ struct MAPINAMEID *nameid;
+ uint16_t count;
+ struct ocpf_nprop nprop;
+
+ OCPF_RETVAL_IF(!ocpf->filename, OCPF_WRITE_NOT_INITIALIZED, NULL);
+ OCPF_RETVAL_IF(!ocpf || !ocpf->mem_ctx, OCPF_NOT_INITIALIZED, NULL);
+ OCPF_RETVAL_IF(!mapi_lpProps, OCPF_INVALID_PROPARRAY, NULL);
+
+ /* store message type */
+ type = (const char *) find_mapi_SPropValue_data(mapi_lpProps, PR_MESSAGE_CLASS);
+ ocpf_type_add(type);
+
+ /* store recipients */
+ recipient = (const char *) find_mapi_SPropValue_data(mapi_lpProps, PR_DISPLAY_TO);
+ ocpf_write_add_recipients(OCPF_MAPI_TO, recipient);
+
+ recipient = (const char *) find_mapi_SPropValue_data(mapi_lpProps, PR_DISPLAY_CC);
+ ocpf_write_add_recipients(OCPF_MAPI_CC, recipient);
+
+ recipient = (const char *) find_mapi_SPropValue_data(mapi_lpProps, PR_DISPLAY_BCC);
+ ocpf_write_add_recipients(OCPF_MAPI_BCC, recipient);
+
+ /* store properties and OLEGUID in OCPF context */
+ for (i = 0; i < mapi_lpProps->cValues; i++) {
+ propID = mapi_lpProps->lpProps[i].ulPropTag >> 16;
+ cast_SPropValue(&mapi_lpProps->lpProps[i], &lpProps);
+
+ if (propID < 0x8000) {
+ if (ocpf_write_exclude_property(lpProps.ulPropTag) == false) {
+ /* HACK: replace PR_CONVERSATION_TOPIC with PR_SUBJECT */
+ if (lpProps.ulPropTag == PR_CONVERSATION_TOPIC) {
+ lpProps.ulPropTag = PR_SUBJECT;
+ ocpf_propvalue(lpProps.ulPropTag, lpProps.value, lpProps.ulPropTag & 0xFFFF, false);
+ cast_SPropValue(&mapi_lpProps->lpProps[i], &lpProps);
+ }
+ ocpf_propvalue(mapi_lpProps->lpProps[i].ulPropTag,
+ lpProps.value, mapi_lpProps->lpProps[i].ulPropTag & 0xFFFF, false);
+ }
+ } else {
+ nameid = talloc_zero(ocpf->mem_ctx, struct MAPINAMEID);
+ retval = GetNamesFromIDs(obj_message, ((lpProps.ulPropTag & 0xFFFF0000) | PT_NULL),
+ &count, &nameid);
+ memset(&nprop, 0, sizeof (struct ocpf_nprop));
+ switch (nameid->ulKind) {
+ case MNID_ID:
+ nprop.mnid_id = nameid->kind.lid;
+ break;
+ case MNID_STRING:
+ nprop.mnid_string = talloc_strdup(ocpf->mem_ctx, nameid->kind.lpwstr.Name);
+ break;
+ }
+ nprop.propType = lpProps.ulPropTag & 0xFFFF;
+ tmp_guid = GUID_string(ocpf->mem_ctx, &nameid->lpguid);
+ nprop.guid = ocpf_write_get_guid_name(tmp_guid);
+
+ /* OLEGUID has to be inserted prior named properties */
+ if (ocpf_oleguid_check(nprop.guid, &guid) != OCPF_SUCCESS)
+ ocpf_oleguid_add(nprop.guid, tmp_guid);
+
+ nprop.registered = false;
+ ocpf_nproperty_add(&nprop, lpProps.value, NULL, nprop.propType, false);
+
+ talloc_free(nameid);
+ }
+ }
+
+ return OCPF_SUCCESS;
+}
+
+
+/**
+ \details Write OCPF structure to OCPF file
+
+ This function dumps the OCPF structure content into the OCPF file
+ defined in ocpf_write_init.
+
+ \return OCPF_SUCCESS on success, otherwise OCPF_ERROR
+
+ \sa ocpf_write_init, ocpf_write_auto
+ */
+_PUBLIC_ int ocpf_write_commit(void)
+{
+ FILE *fp;
+ struct ocpf_property *element;
+ struct ocpf_nproperty *nelement;
+ struct ocpf_oleguid *nguid;
+ char *line;
+ bool found = false;
+ char *definition = NULL;
+ ssize_t len;
+
+ fp = fopen(ocpf->filename, "w+");
+ OCPF_RETVAL_IF(!fp, OCPF_INVALID_FILEHANDLE, NULL);
+
+ /* message type */
+ line = talloc_asprintf(ocpf->mem_ctx, "TYPE \"%s\"\n\n", ocpf->type);
+ len = fwrite(line, strlen(line), 1, fp);
+ talloc_free(line);
+
+ /* folder id */
+ line = talloc_asprintf(ocpf->mem_ctx, "FOLDER D0x%"PRIx64"\n\n", ocpf->folder);
+ len = fwrite(line, strlen(line), 1, fp);
+ talloc_free(line);
+
+ /* OLEGUID */
+ for (nguid = ocpf->oleguid; nguid->next; nguid = nguid->next) {
+ line = talloc_asprintf(ocpf->mem_ctx, "OLEGUID %-25s \"%s\"\n", nguid->name, nguid->guid);
+ len = fwrite(line, strlen(line), 1, fp);
+ talloc_free(line);
+ }
+ len = fwrite(OCPF_NEWLINE, strlen(OCPF_NEWLINE), 1, fp);
+
+ /* RECIPIENT TO */
+ line = ocpf_write_recipients(OCPF_MAPI_TO);
+ if (line && strlen(line)) {
+ len = fwrite(OCPF_RECIPIENT_TO, strlen(OCPF_RECIPIENT_TO), 1, fp);
+ len = fwrite(line, strlen(line), 1, fp);
+ len = fwrite(OCPF_NEWLINE, strlen(OCPF_NEWLINE), 1, fp);
+ talloc_free(line);
+ }
+
+ /* RECIPIENT CC */
+ line = ocpf_write_recipients(OCPF_MAPI_CC);
+ if (line && strlen(line)) {
+ len = fwrite(OCPF_RECIPIENT_CC, strlen(OCPF_RECIPIENT_CC), 1, fp);
+ len = fwrite(line, strlen(line), 1, fp);
+ len = fwrite(OCPF_NEWLINE, strlen(OCPF_NEWLINE), 1, fp);
+ talloc_free(line);
+ }
+
+ /* RECIPIENT BCC */
+ line = ocpf_write_recipients(OCPF_MAPI_BCC);
+ if (line && strlen(line)) {
+ len = fwrite(OCPF_RECIPIENT_BCC, strlen(OCPF_RECIPIENT_BCC), 1, fp);
+ len = fwrite(line, strlen(line), 1, fp);
+ len = fwrite(OCPF_NEWLINE, strlen(OCPF_NEWLINE), 1, fp);
+ talloc_free(line);
+ }
+
+ len = fwrite(OCPF_NEWLINE, strlen(OCPF_NEWLINE), 1, fp);
+
+ /* known properties */
+ len = fwrite(OCPF_PROPERTY_BEGIN, strlen(OCPF_PROPERTY_BEGIN), 1, fp);
+ for (element = ocpf->props; element->next; element = element->next) {
+ line = ocpf_write_property(&found, element->aulPropTag, element->value);
+ if (found == true) {
+ ocpf_write_propname(fp, element->aulPropTag);
+ len = fwrite(line, strlen(line), 1, fp);
+ talloc_free(line);
+ found = false;
+ }
+ }
+ len = fwrite(OCPF_END, strlen(OCPF_END), 1, fp);
+ len = fwrite(OCPF_NEWLINE, strlen(OCPF_NEWLINE), 1, fp);
+
+ /* named properties */
+ len = fwrite(OCPF_NPROPERTY_BEGIN, strlen(OCPF_NPROPERTY_BEGIN), 1, fp);
+ for (nelement = ocpf->nprops; nelement->next; nelement = nelement->next) {
+ line = ocpf_write_property(&found, nelement->propType, nelement->value);
+ if (found == true) {
+ if (nelement->mnid_id) {
+ definition = talloc_asprintf(ocpf->mem_ctx, "\tMNID_ID:0x%.4x:%s:%s = ",
+ nelement->mnid_id,
+ ocpf_write_get_proptype_name(nelement->propType),
+ ocpf_write_get_guid_name(nelement->oleguid));
+ } else if (nelement->mnid_string) {
+ definition = talloc_asprintf(ocpf->mem_ctx, "\tMNID_STRING:\"%s\":%s:%s = ",
+ nelement->mnid_string,
+ ocpf_write_get_proptype_name(nelement->propType),
+ ocpf_write_get_guid_name(nelement->oleguid));
+ }
+
+ len = fwrite(definition, strlen(definition), 1, fp);
+ len = fwrite(line, strlen(line), 1, fp);
+
+ talloc_free(definition);
+ talloc_free(line);
+ found = false;
+ }
+ }
+ len = fwrite(OCPF_END, strlen(OCPF_END), 1, fp);
+
+ fclose(fp);
+ return OCPF_SUCCESS;
+}
Added: trunk/openchange/libocpf.pc.in
===================================================================
--- trunk/openchange/libocpf.pc.in (rev 0)
+++ trunk/openchange/libocpf.pc.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@prefix@/share
+datadir=@datadir@
+
+Name: OpenChange Property File
+Description: OCPF file format support
+Version: @PACKAGE_VERSION@
+Libs: @LIBS@ -locpf
+Cflags: @CFLAGS@
+Requires: libmapi
Added: trunk/openchange/mapiproxy/Doxyfile.in
===================================================================
--- trunk/openchange/mapiproxy/Doxyfile.in (rev 0)
+++ trunk/openchange/mapiproxy/Doxyfile.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1498 @@
+# Doxyfile 1.5.7.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = MAPIProxy
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = apidocs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene,
+# Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = mapiproxy \
+ mapiproxy/documentation \
+ mapiproxy/modules
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.h \
+ *.c \
+ *.doxy
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = *_private.h
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = *.yy.c \
+ *_private.h \
+ ocpf_api.*
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = doc/doxygen/pictures/
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER = "sed \
+ -e '20,40s/.*\<libmapi\/proto_private.h\>//' \
+ -e '20,40s/.*\<gen_ndr\/ndr_exchange.h\>//' \
+ -e '20,40s/.*\<param.h\>//' \
+ -e '20,40s/.*\<errno.h\>//' \
+ -e '20,40s/.*\<core\/error.h\>//' \
+ -e '20,40s/.*\<credentials.h\>//' \
+ -e '20,40s/.*\<ldb.h\>//' \
+ -e '20,40s/.*\<ldb_errors.h\>//' \
+ -e '20,40s/.*\<libmapi\/dlinklist.h\>//' \
+ -e '20,40s/.*\<libmapi\/defs_private.h\>//' \
+ -e '20,40s/.*\<libmapi\/mapi_nameid.h\>//' \
+ -e '20,40s/.*\<libmapi\/mapi_nameid_private.h\>//' \
+ -e '20,40s/.*\<libocpf\/proto_private.h\>//' \
+ -e '20,40s/.*\<libocpf\/ocpf_api.h\>//' \
+ -e '20,40s/.*\<libocpf\/ocpf.tab.h\>//' \
+ -e '20,40s/.*\<libgen.h\>//' \
+ -e '20,40s/.*\<time.h\>//' \
+ -e '20,40s/.*\<sys\/*\>//' \
+ -e '20,40s/_PUBLIC_//'"
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html/mapiproxy
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER = doc/doxygen/header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = doc/doxygen/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET = doc/doxygen/apidocs.css
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#namespace">Qt Help Project / Namespace</a>.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#virtual-folders">Qt Help Project / Virtual Folders</a>.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file .
+
+QHG_LOCATION =
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature. Other possible values
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = _PUBLIC_
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
Added: trunk/openchange/mapiproxy/dcesrv_mapiproxy.c
===================================================================
--- trunk/openchange/mapiproxy/dcesrv_mapiproxy.c (rev 0)
+++ trunk/openchange/mapiproxy/dcesrv_mapiproxy.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,676 @@
+/*
+ MAPI Proxy
+
+ This proxy is based on dcesrv_remote.c code from Stefan Metzemacher
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008-2009
+
+ 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 "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/dcesrv_mapiproxy_proto.h"
+#include <libmapi/dlinklist.h>
+#include <libmapi/defs_private.h>
+#include <util/debug.h>
+
+/**
+ \file dcesrv_mapiproxy.c
+
+ \brief mapiproxy main file
+ */
+
+
+static NTSTATUS mapiproxy_op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
+{
+ DEBUG(5, ("mapiproxy::mapiproxy_op_reply\n"));
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS mapiproxy_op_bind_proxy(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
+{
+ NTSTATUS status;
+ const struct ndr_interface_table *table;
+ struct dcesrv_mapiproxy_private *private;
+ const char *binding;
+ const char *user;
+ const char *pass;
+ const char *domain;
+ struct cli_credentials *credentials;
+ bool machine_account;
+
+ /* Retrieve parametric options */
+ binding = lp_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "binding");
+ machine_account = lp_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "use_machine_account", false);
+
+ private = dce_call->context->private;
+
+ if (!binding) {
+ DEBUG(0, ("You must specify a DCE/RPC binding string\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ user = lp_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "username");
+ pass = lp_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "password");
+ domain = lp_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "domain");
+
+ table = ndr_table_by_uuid(&iface->syntax_id.uuid);
+ if (!table) {
+ dce_call->fault_code = DCERPC_FAULT_UNK_IF;
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+
+ if (user && pass) {
+ DEBUG(5, ("dcerpc_mapiproxy: RPC proxy: Using specified account\n"));
+ credentials = cli_credentials_init(private);
+ if (!credentials) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ cli_credentials_set_conf(credentials, dce_call->conn->dce_ctx->lp_ctx);
+ cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
+ if (domain) {
+ cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
+ }
+ cli_credentials_set_password(credentials, pass, CRED_SPECIFIED);
+ } else if (machine_account) {
+ DEBUG(5, ("dcerpc_mapiproxy: RPC proxy: Using machine account\n"));
+ credentials = cli_credentials_init(private);
+ if (!credentials) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ cli_credentials_set_conf(credentials, dce_call->conn->dce_ctx->lp_ctx);
+ if (domain) {
+ cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
+ }
+ status = cli_credentials_set_machine_account(credentials, dce_call->conn->dce_ctx->lp_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ } else if (dce_call->conn->auth_state.session_info->credentials) {
+ DEBUG(5, ("dcerpc_mapiproxy: RPC proxy: Using delegated credentials\n"));
+ credentials = dce_call->conn->auth_state.session_info->credentials;
+ } else {
+ DEBUG(1, ("dcerpc_mapiproxy: RPC proxy: You must supply binding, user and password or have delegated credentials\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (((dce_call->pkt.ptype == DCERPC_PKT_BIND) && dce_call->pkt.u.bind.assoc_group_id) ||
+ ((dce_call->pkt.ptype == DCERPC_PKT_ALTER) && dce_call->pkt.u.alter.assoc_group_id)) {
+ struct dcerpc_binding *b;
+ struct composite_context *pipe_conn_req;
+
+ /* parse binding string to the structure */
+ status = dcerpc_parse_binding(dce_call->context, binding, &b);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
+ return status;
+ }
+
+ DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(dce_call->context, b)));
+
+ switch (dce_call->pkt.ptype) {
+ case DCERPC_PKT_BIND:
+ b->assoc_group_id = dce_call->pkt.u.bind.assoc_group_id;
+ break;
+ case DCERPC_PKT_ALTER:
+ b->assoc_group_id = dce_call->pkt.u.alter.assoc_group_id;
+ break;
+ default:
+ break;
+ }
+
+ pipe_conn_req = dcerpc_pipe_connect_b_send(dce_call->context, b, table,
+ credentials, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
+ status = dcerpc_pipe_connect_b_recv(pipe_conn_req, dce_call->context, &(private->c_pipe));
+
+ talloc_free(credentials);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ dce_call->context->assoc_group_id = private->c_pipe->assoc_group_id;
+
+ } else {
+ status = dcerpc_pipe_connect(dce_call->context,
+ &(private->c_pipe), binding, table,
+ credentials, dce_call->event_ctx,
+ dce_call->conn->dce_ctx->lp_ctx);
+
+ talloc_free(credentials);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ dce_call->context->assoc_group_id = private->c_pipe->assoc_group_id;
+ }
+
+ DEBUG(5, ("dcerpc_mapiproxy: RPC proxy: CONNECTED\n"));
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details This function is called when the client binds to one of
+ the interfaces mapiproxy handles.
+
+ \param dce_call pointer to the session context
+ \param iface pointer to the dcesrv interface structure with
+ function hooks
+
+ \return NT_STATUS_OK on success, otherwise NTSTATUS error
+ */
+static NTSTATUS mapiproxy_op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
+{
+ struct dcesrv_mapiproxy_private *private;
+ bool server_mode;
+
+ DEBUG(5, ("mapiproxy::mapiproxy_op_bind: [session = 0x%x] [session server id = 0x%"PRIx64" 0x%x 0x%x]\n", dce_call->context->context_id,
+ dce_call->conn->server_id.id, dce_call->conn->server_id.id2, dce_call->conn->server_id.node));
+
+ /* Retrieve server mode parametric option */
+ server_mode = lp_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "server", false);
+
+ /* Initialize private structure */
+ private = talloc(dce_call->context, struct dcesrv_mapiproxy_private);
+ if (!private) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ private->c_pipe = NULL;
+ private->exchname = NULL;
+ private->server_mode = server_mode;
+ dce_call->context->private = private;
+
+ if (server_mode == false) {
+ return mapiproxy_op_bind_proxy(dce_call, iface);
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Called when the client disconnects from one of the
+ endpoints managed by mapiproxy.
+
+ \param context pointer to the connection context
+ \param iface pointer to the dcesrv interface structure with
+ function hooks
+ */
+static void mapiproxy_op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
+{
+ struct dcesrv_mapiproxy_private *private = (struct dcesrv_mapiproxy_private *) context->private;
+
+ DEBUG(5, ("mapiproxy::mapiproxy_op_unbind\n"));
+
+ mapiproxy_module_unbind(context->conn->server_id, context->context_id);
+ mapiproxy_server_unbind(context->conn->server_id, context->context_id);
+
+ if (private) {
+ talloc_free(private->c_pipe);
+ talloc_free(private);
+ }
+
+ talloc_free(context);
+
+ return;
+}
+
+
+/**
+ \details This is the function called when mapiproxy receives a
+ request. The request has already been extracted and its information
+ filled into structures
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param pull pointer on pointer to the ndr_pull structure
+ \param r generic pointer on pointer to the pulled ndr content
+
+ \return NT_STATUS_OK on success, other NTSTATUS error
+ */
+static NTSTATUS mapiproxy_op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
+{
+ enum ndr_err_code ndr_err;
+ const struct ndr_interface_table *table;
+ uint16_t opnum;
+
+ DEBUG(5, ("mapiproxy::mapiproxy_op_ndr_pull\n"));
+
+ table = (const struct ndr_interface_table *)dce_call->context->iface->private;
+ opnum = dce_call->pkt.u.request.opnum;
+
+ dce_call->fault_code = 0;
+
+ if (opnum >= table->num_calls) {
+ dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+
+ *r = talloc_size(mem_ctx, table->calls[opnum].struct_size);
+ if (!*r) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* directly alter the pull struct before it got pulled from ndr */
+ mapiproxy_module_ndr_pull(dce_call, mem_ctx, pull);
+
+ ndr_err = table->calls[opnum].ndr_pull(pull, NDR_IN, *r);
+
+ mapiproxy_module_pull(dce_call, mem_ctx, *r);
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0, ("mapiproxy: mapiproxy_ndr_pull: ERROR\n"));
+ dcerpc_log_packet(dce_call->conn->packet_log_dir, table, opnum, NDR_IN,
+ &dce_call->pkt.u.request.stub_and_verifier);
+ dce_call->fault_code = DCERPC_FAULT_NDR;
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details This is the function called when mapiproxy receive a
+ response. The response has already been extracted and its
+ information filled into structures
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param push pointer to the ndr_push structure
+ \param r generic pointer to the data pushed
+
+ \return NT_STATUS_OK on success, otherwise a NTSTATUS error
+ */
+static NTSTATUS mapiproxy_op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
+{
+ struct dcesrv_mapiproxy_private *private;
+ enum ndr_err_code ndr_err;
+ const struct ndr_interface_table *table;
+ const struct ndr_interface_call *call;
+ uint16_t opnum;
+ const char *name;
+
+ DEBUG(5, ("mapiproxy::mapiproxy_op_ndr_push\n"));
+
+ private = dce_call->context->private;
+ table = (const struct ndr_interface_table *)dce_call->context->iface->private;
+ opnum = dce_call->pkt.u.request.opnum;
+
+ name = table->calls[opnum].name;
+ call = &table->calls[opnum];
+
+ dce_call->fault_code = 0;
+
+ if (private->server_mode == false) {
+ /* NspiGetProps binding strings replacement */
+ if ((mapiproxy_server_loaded(NDR_EXCHANGE_NSP_NAME) == false) &&
+ table->name && !strcmp(table->name, NDR_EXCHANGE_NSP_NAME)) {
+ switch (opnum) {
+ case NDR_NSPIGETPROPS:
+ mapiproxy_NspiGetProps(dce_call, (struct NspiGetProps *)r);
+ break;
+ case NDR_NSPIQUERYROWS:
+ mapiproxy_NspiQueryRows(dce_call, (struct NspiQueryRows *)r);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* RfrGetNewDSA FQDN replacement */
+ if ((mapiproxy_server_loaded(NDR_EXCHANGE_DS_RFR_NAME) == false) &&
+ table->name && !strcmp(table->name, NDR_EXCHANGE_DS_RFR_NAME)) {
+ switch (opnum) {
+ case NDR_RFRGETNEWDSA:
+ mapiproxy_RfrGetNewDSA(dce_call, (struct RfrGetNewDSA *)r);
+ break;
+ default:
+ DEBUG(0, ("exchange_ds_rfr: OTHER DS-RFR CALL DETECTED!\n"));
+ break;
+ }
+ }
+ }
+
+ mapiproxy_module_push(dce_call, mem_ctx, (void *)r);
+
+ ndr_err = table->calls[opnum].ndr_push(push, NDR_OUT, r);
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0, ("mapiproxy: mapiproxy_ndr_push: ERROR\n"));
+ dce_call->fault_code = DCERPC_FAULT_NDR;
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details This function is called after the pull but before the
+ push. Moreover it is called before the request is forward to the
+ remote endpoint.
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r generic pointer to the call mapped data
+
+ \return NT_STATUS_OK on success, otherwise NTSTATUS error
+ */
+static NTSTATUS mapiproxy_op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
+{
+ struct dcesrv_mapiproxy_private *private;
+ struct ndr_push *push;
+ enum ndr_err_code ndr_err;
+ struct mapiproxy mapiproxy;
+ const struct ndr_interface_table *table;
+ const struct ndr_interface_call *call;
+ uint16_t opnum;
+ const char *name;
+ NTSTATUS status;
+
+ private = dce_call->context->private;
+ table = dce_call->context->iface->private;
+ opnum = dce_call->pkt.u.request.opnum;
+
+ name = table->calls[opnum].name;
+ call = &table->calls[opnum];
+
+ mapiproxy.norelay = false;
+ mapiproxy.ahead = false;
+
+ if (!private) {
+ dce_call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+
+ DEBUG(5, ("mapiproxy::mapiproxy_op_dispatch: %s(0x%x): %zd bytes\n",
+ table->calls[opnum].name, opnum, table->calls[opnum].struct_size));
+
+ if (private->server_mode == false) {
+ if (private->c_pipe->conn->flags & DCERPC_DEBUG_PRINT_IN) {
+ ndr_print_function_debug(call->ndr_print, name, NDR_IN | NDR_SET_VALUES, r);
+ }
+
+ private->c_pipe->conn->flags |= DCERPC_NDR_REF_ALLOC;
+ }
+
+ if ((private->server_mode == true) || (mapiproxy_server_loaded(NDR_EXCHANGE_NSP_NAME) == true)) {
+ ndr_print_function_debug(call->ndr_print, name, NDR_IN | NDR_SET_VALUES, r);
+ status = mapiproxy_server_dispatch(dce_call, mem_ctx, r, &mapiproxy);
+ ndr_print_function_debug(call->ndr_print, name, NDR_OUT | NDR_SET_VALUES, r);
+ if (!NT_STATUS_IS_OK(status)) {
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+ } else {
+ if (table->name && !strcmp(table->name, NDR_EXCHANGE_NSP_NAME)) {
+ if (opnum == NDR_NSPIDNTOMID) {
+ mapiproxy_NspiDNToMId(dce_call, (struct NspiDNToMId *)r);
+ }
+ }
+ }
+
+ if (private->server_mode == false) {
+ ahead:
+ if (mapiproxy.ahead == true) {
+ push = ndr_push_init_ctx(dce_call,
+ lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx));
+ NT_STATUS_HAVE_NO_MEMORY(push);
+ ndr_err = call->ndr_push(push, NDR_OUT, r);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0, ("mapiproxy: mapiproxy_op_dispatch:push: ERROR\n"));
+ dce_call->fault_code = DCERPC_FAULT_NDR;
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+ }
+
+ status = mapiproxy_module_dispatch(dce_call, mem_ctx, r, &mapiproxy);
+ if (!NT_STATUS_IS_OK(status)) {
+ private->c_pipe->last_fault_code = dce_call->fault_code;
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+
+ private->c_pipe->last_fault_code = 0;
+ if (mapiproxy.norelay == false) {
+ status = dcerpc_ndr_request(private->c_pipe, NULL, table, opnum, mem_ctx, r);
+ }
+
+ dce_call->fault_code = private->c_pipe->last_fault_code;
+ if (dce_call->fault_code != 0 || !NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("mapiproxy: call[%s] failed with %s! (status = %s)\n", name,
+ dcerpc_errstr(mem_ctx, dce_call->fault_code), nt_errstr(status)));
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+
+ if ((dce_call->fault_code == 0) &&
+ (private->c_pipe->conn->flags & DCERPC_DEBUG_PRINT_OUT) && mapiproxy.norelay == false) {
+ ndr_print_function_debug(call->ndr_print, name, NDR_OUT | NDR_SET_VALUES, r);
+ }
+
+ if (mapiproxy.ahead == true) goto ahead;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Register an endpoint
+
+ \param dce_ctx pointer to the dcerpc context
+ \param iface pointer to the dcesrv interface with function hooks
+
+ \return NT_STATUS_OK on success, otherwise NTSTATUS error
+ */
+static NTSTATUS mapiproxy_register_one_iface(struct dcesrv_context *dce_ctx, const struct dcesrv_interface *iface)
+{
+ const struct ndr_interface_table *table = iface->private;
+ int i;
+
+ for (i = 0; i < table->endpoints->count; i++) {
+ NTSTATUS ret;
+ const char *name = table->endpoints->names[i];
+
+ ret = dcesrv_interface_register(dce_ctx, name, iface, NULL);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1,("mapiproxy_op_init_server: failed to register endpoint '%s'\n", name));
+ return ret;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Initializes the server and register emsmdb,nspi and rfr
+ interfaces
+
+ \param dce_ctx pointer to the dcesrv context
+ \param ep_server pointer to the endpoint server list
+
+ \return NT_STATUS_OK on success, otherwise NTSTATUS error
+ */
+static NTSTATUS mapiproxy_op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
+{
+ NTSTATUS ret;
+ struct dcesrv_interface iface;
+ char **ifaces;
+ uint32_t i;
+ static bool initialized = false;
+
+ if (initialized == true) return NT_STATUS_OK;
+
+ /* Register mapiproxy modules */
+ ret = mapiproxy_module_init(dce_ctx);
+ NT_STATUS_NOT_OK_RETURN(ret);
+
+ /* Register mapiproxy servers */
+ ret = mapiproxy_server_init(dce_ctx);
+ NT_STATUS_NOT_OK_RETURN(ret);
+
+ ifaces = str_list_make(dce_ctx, lp_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "interfaces"), NULL);
+
+ for (i = 0; ifaces[i]; i++) {
+ /* Register the interface */
+ if (!ep_server->interface_by_name(&iface, ifaces[i])) {
+ DEBUG(0, ("mapiproxy_op_init_server: failed to find interface '%s'\n", ifaces[i]));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ret = mapiproxy_register_one_iface(dce_ctx, &iface);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("mapiproxy_op_init_server: failed to register interface '%s'\n", ifaces[i]));
+ return ret;
+ }
+ }
+
+ initialized = true;
+ return NT_STATUS_OK;
+}
+
+
+static bool mapiproxy_fill_interface(struct dcesrv_interface *iface, const struct ndr_interface_table *tbl)
+{
+ iface->name = tbl->name;
+ iface->syntax_id = tbl->syntax_id;
+
+ iface->bind = mapiproxy_op_bind;
+ iface->unbind = mapiproxy_op_unbind;
+
+ iface->ndr_pull = mapiproxy_op_ndr_pull;
+ iface->dispatch = mapiproxy_op_dispatch;
+ iface->reply = mapiproxy_op_reply;
+ iface->ndr_push = mapiproxy_op_ndr_push;
+
+ iface->private = tbl;
+
+ return true;
+}
+
+
+static bool mapiproxy_op_interface_by_uuid(struct dcesrv_interface *iface, const struct GUID *uuid, uint32_t if_version)
+{
+ const struct ndr_interface_list *l;
+
+ for (l = ndr_table_list(); l; l = l->next) {
+ if (l->table->syntax_id.if_version == if_version &&
+ GUID_equal(&l->table->syntax_id.uuid, uuid) == 0) {
+ return mapiproxy_fill_interface(iface, l->table);
+ }
+ }
+
+ return false;
+}
+
+
+static bool mapiproxy_op_interface_by_name(struct dcesrv_interface *iface, const char *name)
+{
+ const struct ndr_interface_table *tbl;
+
+ tbl = ndr_table_by_name(name);
+
+ if (tbl) {
+ return mapiproxy_fill_interface(iface, tbl);
+ }
+
+ return false;
+}
+
+
+/**
+ \details register the mapiproxy endpoint server.
+
+ \return NT_STATUS_OK on success, otherwise NTSTATUS error
+ */
+NTSTATUS dcerpc_server_mapiproxy_init(void)
+{
+ NTSTATUS ret;
+ struct dcesrv_endpoint_server ep_server;
+
+ ZERO_STRUCT(ep_server);
+
+ /* Fill in our name */
+ ep_server.name = "mapiproxy";
+
+ /* Fill in all the operations */
+ ep_server.init_server = mapiproxy_op_init_server;
+
+ ep_server.interface_by_uuid = mapiproxy_op_interface_by_uuid;
+ ep_server.interface_by_name = mapiproxy_op_interface_by_name;
+
+ /* Register ourselves with the DCE/RPC subsystem */
+ ret = dcerpc_register_ep_server(&ep_server);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("Failed to register 'mapiproxy' endpoint server!"));
+ return ret;
+ }
+
+ /* Full DCE/RPC interface table needed */
+ ndr_table_init();
+
+ return ret;
+}
+
+/**
+ \details Register mapiproxy dynamic shared object modules
+
+ This function registers mapiproxy modules located
+ */
+
+/**
+ \details Entry point of mapiproxy dynamic shared object.
+
+ This function first registers exchange endpoints and ndr tables,
+ then attempts to register the mapiproxy interface.
+
+ \return NT_STATUS_OK on success, otherwise NT_STATUS_UNSUCCESSFUL;
+ */
+NTSTATUS samba_init_module(void)
+{
+ NTSTATUS status;
+
+ /* Step1. Register Exchange endpoints */
+ status = dcerpc_server_exchange_emsmdb_init();
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ status = dcerpc_server_exchange_nsp_init();
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ status = dcerpc_server_exchange_ds_rfr_init();
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ /* Step2. Register Exchange ndr tables */
+ status = ndr_table_register(&ndr_table_exchange_emsmdb);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ status = ndr_table_register(&ndr_table_exchange_nsp);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ status = ndr_table_register(&ndr_table_exchange_ds_rfr);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ /* Step3. Finally register mapiproxy endpoint */
+ status = dcerpc_server_mapiproxy_init();
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ return NT_STATUS_OK;
+}
+
+/* include server boiler template */
+#include <gen_ndr/ndr_exchange_s.c>
Added: trunk/openchange/mapiproxy/dcesrv_mapiproxy.h
===================================================================
--- trunk/openchange/mapiproxy/dcesrv_mapiproxy.h (rev 0)
+++ trunk/openchange/mapiproxy/dcesrv_mapiproxy.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,69 @@
+/*
+ MAPI Proxy
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 __DCESRV_MAPIPROXY_H__
+#define __DCESRV_MAPIPROXY_H__
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <talloc.h>
+#include <dcerpc.h>
+#include <samba/session.h>
+
+#include <dcerpc_server.h>
+#include <util.h>
+#include <param.h>
+#include <credentials.h>
+
+#include <gen_ndr/exchange.h>
+#include <gen_ndr/ndr_exchange.h>
+#include <mapiproxy/libmapiproxy/libmapiproxy.h>
+
+struct dcesrv_mapiproxy_private {
+ struct dcerpc_pipe *c_pipe;
+ char *exchname;
+ bool server_mode;
+};
+
+enum exchange_handle {
+ EXCHANGE_HANDLE_NSP,
+ EXCHANGE_HANDLE_EMSMDB,
+ EXCHANGE_HANDLE_DS_RFR
+};
+
+/* Forward declarations */
+struct composite_context;
+
+#define MAXHOSTNAMELEN 255
+#define SERVERNAME "/cn=Servers/cn="
+
+#endif /* !__DCESRV_MAPIPROXY_H__ */
Added: trunk/openchange/mapiproxy/dcesrv_mapiproxy_nspi.c
===================================================================
--- trunk/openchange/mapiproxy/dcesrv_mapiproxy_nspi.c (rev 0)
+++ trunk/openchange/mapiproxy/dcesrv_mapiproxy_nspi.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,208 @@
+/*
+ MAPI Proxy - NSPI
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/dcesrv_mapiproxy_proto.h"
+
+/**
+ \file dcesrv_mapiproxy_nspi.c
+
+ \brief NSPI hook functions
+ */
+
+/**
+ \details Retrieve the servername from a DN string
+
+ \param dn the DN string
+
+ \return a talloc'd server name
+ */
+static char *x500_get_servername(const char *dn)
+{
+ char *pdn;
+ char *servername;
+
+ if (!dn) {
+ return NULL;
+ }
+
+ pdn = strcasestr(dn, SERVERNAME);
+ if (pdn == NULL) return NULL;
+
+ pdn += strlen(SERVERNAME);
+ servername = strsep(&pdn, "/");
+
+ return (talloc_strdup(NULL, servername));
+}
+
+
+/**
+ \details This function replaces network address from the binding
+ strings returned by Exchange for the PR_EMS_AB_NETWORK_ADDRESS
+ property and limit the binding strings scope to ncacn_ip_tcp.
+
+ \param dce_call pointer to the session context
+ \param r pointer to the NspiGetProps structure
+
+ \return true on success, otherwise false
+ */
+bool mapiproxy_NspiGetProps(struct dcesrv_call_state *dce_call, struct NspiGetProps *r)
+{
+ uint32_t i;
+ uint32_t propID = -1;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SRow *SRow;
+ struct StringArray_r *slpstr;
+ struct SPropValue *lpProp;
+
+ /* Sanity checks */
+ if (!r->out.ppRows) return false;
+ if (!(*r->out.ppRows)->cValues) return false;
+
+ /* Step 1. Find PR_EMS_AB_NETWORK_ADDRESS index */
+ propID = -1;
+ SPropTagArray = r->in.pPropTags;
+ for (i = 0; i < SPropTagArray->cValues; i++) {
+ if (SPropTagArray->aulPropTag[i] == PR_EMS_AB_NETWORK_ADDRESS) {
+ propID = i;
+ break;
+ }
+ }
+ if (propID == -1) return false;
+
+ /* Step 2. Retrieve the SLPSTRArray */
+ SRow = *r->out.ppRows;
+ lpProp = &SRow->lpProps[propID];
+
+ if (!lpProp) return false;
+ if (lpProp->ulPropTag != PR_EMS_AB_NETWORK_ADDRESS) return false;
+
+ slpstr = &(lpProp->value.MVszA);
+
+ /* Step 3. Modify Exchange binding strings and only return ncacn_ip_tcp */
+ slpstr->cValues = 1;
+ slpstr->lppszA[0] = talloc_asprintf(dce_call, "ncacn_ip_tcp:%s.%s",
+ lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx),
+ lp_realm(dce_call->conn->dce_ctx->lp_ctx));
+ strlower_m((char *)slpstr->lppszA[0]);
+
+ return true;
+}
+
+
+/**
+ \details This function replaces the Exchange server name with
+ mapiproxy netbios name for the PR_EMS_AB_HOME_MDB property and
+ saves the original name in a global variable for further usage -
+ such as mapiproxy_NspiDNToMId.
+
+ \param dce_call pointer to the session context
+ \param r pointer to the NspiQueryRows structure
+
+ \sa mapiproxy_NspiDNToMId
+*/
+bool mapiproxy_NspiQueryRows(struct dcesrv_call_state *dce_call, struct NspiQueryRows *r)
+{
+ struct dcesrv_mapiproxy_private *private;
+ uint32_t i;
+ uint32_t propID = -1;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SRowSet *SRowSet;
+ struct SPropValue *lpProp;
+ char *lpszA;
+ char *exchname;
+
+ private = dce_call->context->private;
+
+ /* Sanity checks */
+ if (!r->out.ppRows) return false;
+ if (!(*r->out.ppRows)->cRows) return false;
+ if (!r->in.pPropTags) return false;
+
+ /* Step 1. Find PR_EMS_AB_HOME_MDB index */
+ propID = -1;
+ SPropTagArray = r->in.pPropTags;
+ for (i = 0; i < SPropTagArray->cValues; i++) {
+ if (SPropTagArray->aulPropTag[i] == PR_EMS_AB_HOME_MDB) {
+ propID = i;
+ break;
+ }
+ }
+ if (propID == -1) return false;
+
+ /* Retrieve the lpszA */
+ SRowSet = *r->out.ppRows;
+ lpProp = &(SRowSet->aRow->lpProps[propID]);
+
+ if (!lpProp) return false;
+ if (lpProp->ulPropTag != PR_EMS_AB_HOME_MDB) return false;
+
+ if (private->exchname) {
+ if (strstr(lpProp->value.lpszA, private->exchname)) {
+ lpProp->value.lpszA = string_sub_talloc((TALLOC_CTX *) dce_call, lpProp->value.lpszA, private->exchname,
+ lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
+ }
+ } else {
+ lpszA = talloc_strdup(dce_call, lpProp->value.lpszA);
+ if ((exchname = x500_get_servername(lpszA))) {
+ private->exchname = talloc_strdup(NULL, exchname);
+ lpProp->value.lpszA = string_sub_talloc((TALLOC_CTX *) dce_call, lpProp->value.lpszA, exchname,
+ lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
+ talloc_free(exchname);
+ }
+ talloc_free(lpszA);
+ }
+
+ return true;
+}
+
+
+/**
+ \details This function looks if the server DN string in the request
+ holds the mapiproxy netbios name and replaces it with the original
+ Exchange server one fetched from NspiQueryRows or NspiGetProps.
+
+ \param dce_call pointer to the session context
+ \param r pointer to the NspiDNToMId structure
+
+ \return true on success or false if no occurrence of the mapiproxy
+ netbios name was found.
+*/
+bool mapiproxy_NspiDNToMId(struct dcesrv_call_state *dce_call, struct NspiDNToMId *r)
+{
+ struct dcesrv_mapiproxy_private *private;
+ const char *proxyname;
+ uint32_t i;
+
+ private = dce_call->context->private;
+ proxyname = lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx);
+
+ if (!private->exchname) return false;
+
+ for (i = 0; i < r->in.pNames->Count; i++) {
+ if (strstr(r->in.pNames->Strings[i], proxyname)) {
+ r->in.pNames->Strings[i] = string_sub_talloc((TALLOC_CTX *) dce_call, r->in.pNames->Strings[i], proxyname, private->exchname);
+ return true;
+ }
+ }
+
+ return false;
+}
Added: trunk/openchange/mapiproxy/dcesrv_mapiproxy_proto.h
===================================================================
--- trunk/openchange/mapiproxy/dcesrv_mapiproxy_proto.h (rev 0)
+++ trunk/openchange/mapiproxy/dcesrv_mapiproxy_proto.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,153 @@
+/*
+ MAPI Proxy
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 __DCESRV_MAPIPROXY_PROTO_H__
+#define __DCESRV_MAPIPROXY_PROTO_H__
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+__BEGIN_DECLS
+
+/* definitions from dcesrv_mapiproxy.c */
+NTSTATUS dcerpc_server_mapiproxy_init(void);
+NTSTATUS samba_init_module(void);
+
+NTSTATUS dcerpc_server_exchange_nsp_init(void);
+NTSTATUS dcerpc_server_exchange_emsmdb_init(void);
+
+/* definitions from dcesrv_mapiproxy_nspi.c */
+bool mapiproxy_NspiGetProps(struct dcesrv_call_state *, struct NspiGetProps *);
+bool mapiproxy_NspiQueryRows(struct dcesrv_call_state *, struct NspiQueryRows *);
+bool mapiproxy_NspiDNToMId(struct dcesrv_call_state *, struct NspiDNToMId *);
+
+/* definitions from dcesrv_mapiproxy_rfr.c */
+bool mapiproxy_RfrGetNewDSA(struct dcesrv_call_state *, struct RfrGetNewDSA *);
+
+/* init functions definitions from gen_ndr/ndr_exchange_s.c */
+
+NTSTATUS dcerpc_server_exchange_store_admin3_init(void);
+NTSTATUS dcerpc_server_exchange_store_admin2_init(void);
+NTSTATUS dcerpc_server_exchange_store_admin1_init(void);
+NTSTATUS dcerpc_server_exchange_ds_rfr_init(void);
+NTSTATUS dcerpc_server_exchange_sysatt_cluster_init(void);
+NTSTATUS dcerpc_server_exchange_system_attendant_init(void);
+NTSTATUS dcerpc_server_exchange_mta_init(void);
+NTSTATUS dcerpc_server_exchange_drs_init(void);
+NTSTATUS dcerpc_server_exchange_xds_init(void);
+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_unknown_init(void);
+
+/* definitions from samba4: librpc/ndr/ndr_table.c */
+NTSTATUS ndr_table_init(void);
+NTSTATUS ndr_table_register(const struct ndr_interface_table *);
+const struct ndr_interface_table *ndr_table_by_uuid(const struct GUID *);
+const struct ndr_interface_list *ndr_table_list(void);
+const struct ndr_interface_table *ndr_table_by_name(const char *);
+
+/* The following definitions come from dcesrv_mapiproxy_unused.c */
+void dcesrv_ec_store_admin3_dummy(struct dcesrv_call_state *, TALLOC_CTX *,struct ec_store_admin3_dummy *);
+void dcesrv_ec_store_admin2_dummy(struct dcesrv_call_state *, TALLOC_CTX *,struct ec_store_admin2_dummy *);
+void dcesrv_ec_store_admin1_dummy(struct dcesrv_call_state *, TALLOC_CTX *,struct ec_store_admin1_dummy *);
+enum MAPISTATUS dcesrv_RfrGetNewDSA(struct dcesrv_call_state *, TALLOC_CTX *,struct RfrGetNewDSA *);
+enum MAPISTATUS dcesrv_RfrGetFQDNFromLegacyDN(struct dcesrv_call_state *, TALLOC_CTX *,struct RfrGetFQDNFromLegacyDN *);
+void dcesrv_sysatt_cluster_dummy(struct dcesrv_call_state *, TALLOC_CTX *,struct sysatt_cluster_dummy *);
+void dcesrv_sysatt_dummy(struct dcesrv_call_state *, TALLOC_CTX *,struct sysatt_dummy *);
+void dcesrv_MtaBind(struct dcesrv_call_state *, TALLOC_CTX *,struct MtaBind *);
+void dcesrv_MtaBindAck(struct dcesrv_call_state *, TALLOC_CTX *,struct MtaBindAck *);
+void dcesrv_ds_abandon(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_abandon *);
+void dcesrv_ds_add_entry(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_add_entry *);
+void dcesrv_ds_bind(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_bind *);
+void dcesrv_ds_compare(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_compare *);
+void dcesrv_ds_list(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_list *);
+void dcesrv_ds_modify_entry(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_modify_entry *);
+void dcesrv_ds_modify_rdn(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_modify_rdn *);
+void dcesrv_ds_read(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_read *);
+void dcesrv_ds_receive_result(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_receive_result *);
+void dcesrv_ds_remove_entry(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_remove_entry *);
+void dcesrv_ds_search(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_search *);
+void dcesrv_ds_unbind(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_unbind *);
+void dcesrv_ds_wait(struct dcesrv_call_state *, TALLOC_CTX *,struct ds_wait *);
+void dcesrv_dra_replica_add(struct dcesrv_call_state *, TALLOC_CTX *,struct dra_replica_add *);
+void dcesrv_dra_replica_delete(struct dcesrv_call_state *, TALLOC_CTX *,struct dra_replica_delete *);
+void dcesrv_dra_replica_synchronize(struct dcesrv_call_state *, TALLOC_CTX *,struct dra_replica_synchronize *);
+void dcesrv_dra_reference_update(struct dcesrv_call_state *, TALLOC_CTX *,struct dra_reference_update *);
+void dcesrv_dra_authorize_replica(struct dcesrv_call_state *, TALLOC_CTX *,struct dra_authorize_replica *);
+void dcesrv_dra_unauthorize_replica(struct dcesrv_call_state *, TALLOC_CTX *,struct dra_unauthorize_replica *);
+void dcesrv_dra_adopt(struct dcesrv_call_state *, TALLOC_CTX *,struct dra_adopt *);
+void dcesrv_dra_set_status(struct dcesrv_call_state *, TALLOC_CTX *,struct dra_set_status *);
+void dcesrv_dra_modify_entry(struct dcesrv_call_state *, TALLOC_CTX *,struct dra_modify_entry *);
+void dcesrv_dra_delete_subref(struct dcesrv_call_state *, TALLOC_CTX *,struct dra_delete_subref *);
+void dcesrv_xds_dummy(struct dcesrv_call_state *, TALLOC_CTX *,struct xds_dummy *);
+void dcesrv_exchange_mta_qadmin(struct dcesrv_call_state *, TALLOC_CTX *,struct exchange_mta_qadmin *);
+void dcesrv_exchange_store_information_dummy(struct dcesrv_call_state *, TALLOC_CTX *,struct exchange_store_information_dummy *);
+
+
+/* NSPI protocol functions */
+enum MAPISTATUS dcesrv_NspiBind(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiBind *);
+enum MAPISTATUS dcesrv_NspiUnbind(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiUnbind *);
+enum MAPISTATUS dcesrv_NspiUpdateStat(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiUpdateStat *);
+enum MAPISTATUS dcesrv_NspiQueryRows(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiQueryRows *);
+enum MAPISTATUS dcesrv_NspiSeekEntries(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiSeekEntries *);
+enum MAPISTATUS dcesrv_NspiGetMatches(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiGetMatches *);
+enum MAPISTATUS dcesrv_NspiResortRestriction(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiResortRestriction *);
+enum MAPISTATUS dcesrv_NspiDNToMId(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiDNToMId *);
+enum MAPISTATUS dcesrv_NspiGetPropList(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiGetPropList *);
+enum MAPISTATUS dcesrv_NspiGetProps(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiGetProps *);
+enum MAPISTATUS dcesrv_NspiCompareMIds(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiCompareMIds *);
+enum MAPISTATUS dcesrv_NspiModProps(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiModProps *);
+enum MAPISTATUS dcesrv_NspiGetSpecialTable(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiGetSpecialTable *);
+enum MAPISTATUS dcesrv_NspiGetTemplateInfo(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiGetTemplateInfo *);
+enum MAPISTATUS dcesrv_NspiModLinkAtt(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiModLinkAtt *);
+enum MAPISTATUS dcesrv_NspiDeleteEntries(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiDeleteEntries *);
+enum MAPISTATUS dcesrv_NspiQueryColumns(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiQueryColumns *);
+enum MAPISTATUS dcesrv_NspiGetNamesFromIDs(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiGetNamesFromIDs *);
+enum MAPISTATUS dcesrv_NspiGetIDsFromNames(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiGetIDsFromNames *);
+enum MAPISTATUS dcesrv_NspiResolveNames(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiResolveNames *);
+enum MAPISTATUS dcesrv_NspiResolveNamesW(struct dcesrv_call_state *, TALLOC_CTX *,struct NspiResolveNamesW *);
+enum MAPISTATUS dcesrv_EcDoConnect(struct dcesrv_call_state *, TALLOC_CTX *,struct EcDoConnect *);
+enum MAPISTATUS dcesrv_EcDoDisconnect(struct dcesrv_call_state *, TALLOC_CTX *,struct EcDoDisconnect *);
+enum MAPISTATUS dcesrv_EcDoRpc(struct dcesrv_call_state *, TALLOC_CTX *,struct EcDoRpc *);
+
+
+void dcesrv_EcGetMoreRpc(struct dcesrv_call_state *, TALLOC_CTX *,struct EcGetMoreRpc *);
+enum MAPISTATUS dcesrv_EcRRegisterPushNotification(struct dcesrv_call_state *, TALLOC_CTX *,struct EcRRegisterPushNotification *);
+enum MAPISTATUS dcesrv_EcRUnregisterPushNotification(struct dcesrv_call_state *, TALLOC_CTX *,struct EcRUnregisterPushNotification *);
+void dcesrv_EcDummyRpc(struct dcesrv_call_state *, TALLOC_CTX *,struct EcDummyRpc *);
+void dcesrv_EcRGetDCName(struct dcesrv_call_state *, TALLOC_CTX *,struct EcRGetDCName *);
+void dcesrv_EcRNetGetDCName(struct dcesrv_call_state *, TALLOC_CTX *,struct EcRNetGetDCName *);
+void dcesrv_EcDoRpcExt(struct dcesrv_call_state *, TALLOC_CTX *,struct EcDoRpcExt *);
+enum MAPISTATUS dcesrv_EcDoConnectEx(struct dcesrv_call_state *, TALLOC_CTX *, struct EcDoConnectEx *);
+void dcesrv_unknown_dummy(struct dcesrv_call_state *, TALLOC_CTX *,struct unknown_dummy *);
+
+__END_DECLS
+
+#endif /* ! __DCESRV_MAPIPROXY_PROTO_H__ */
Added: trunk/openchange/mapiproxy/dcesrv_mapiproxy_rfr.c
===================================================================
--- trunk/openchange/mapiproxy/dcesrv_mapiproxy_rfr.c (rev 0)
+++ trunk/openchange/mapiproxy/dcesrv_mapiproxy_rfr.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,49 @@
+/*
+ MAPI Proxy - RFR
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/dcesrv_mapiproxy_proto.h"
+
+/**
+ \file dcesrv_mapiproxy_rfr.c
+
+ \brief NSPI Referral hook functions
+ */
+
+
+/**
+ \details This function replaces the Exchange server FQDN with
+ mapiproxy one.
+
+ \return true on success, otherwise false
+ */
+bool mapiproxy_RfrGetNewDSA(struct dcesrv_call_state *dce_call, struct RfrGetNewDSA *r)
+{
+ /* Sanity checks */
+ if (!r->out.ppszServer) return false;
+
+ *r->out.ppszServer = talloc_asprintf(dce_call, "%s.%s",
+ lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx),
+ lp_realm(dce_call->conn->dce_ctx->lp_ctx));
+ strlower_m((char *)*r->out.ppszServer);
+
+ return true;
+}
Added: trunk/openchange/mapiproxy/dcesrv_mapiproxy_unused.c
===================================================================
--- trunk/openchange/mapiproxy/dcesrv_mapiproxy_unused.c (rev 0)
+++ trunk/openchange/mapiproxy/dcesrv_mapiproxy_unused.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,772 @@
+/*
+ MAPI Proxy
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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/>.
+ */
+
+#define _GNU_SOURCE 1
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <talloc.h>
+#include <dcerpc.h>
+
+#include <gen_ndr/exchange.h>
+
+#include <dcerpc_server.h>
+#include <util.h>
+#include <param.h>
+
+#include "gen_ndr/ndr_exchange.h"
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/dcesrv_mapiproxy_proto.h"
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+/*
+ endpoint server for the exchange_store_admin3 pipe
+*/
+
+/*
+ ec_store_admin3_dummy
+*/
+void dcesrv_ec_store_admin3_dummy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ec_store_admin3_dummy *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ endpoint server for the exchange_store_admin2 pipe
+*/
+
+/*
+ ec_store_admin2_dummy
+*/
+void dcesrv_ec_store_admin2_dummy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ec_store_admin2_dummy *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ endpoint server for the exchange_store_admin1 pipe
+*/
+
+/*
+ ec_store_admin1_dummy
+*/
+void dcesrv_ec_store_admin1_dummy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ec_store_admin1_dummy *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ endpoint server for the exchange_ds_rfr pipe
+*/
+
+/*
+ RfrGetNewDSA
+*/
+enum MAPISTATUS dcesrv_RfrGetNewDSA(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct RfrGetNewDSA *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ RfrGetFQDNFromLegacyDN
+*/
+enum MAPISTATUS dcesrv_RfrGetFQDNFromLegacyDN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct RfrGetFQDNFromLegacyDN *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ endpoint server for the exchange_sysatt_cluster pipe
+*/
+
+/*
+ sysatt_cluster_dummy
+*/
+void dcesrv_sysatt_cluster_dummy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct sysatt_cluster_dummy *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ endpoint server for the exchange_system_attendant pipe
+*/
+
+/*
+ sysatt_dummy
+*/
+void dcesrv_sysatt_dummy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct sysatt_dummy *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ endpoint server for the exchange_mta pipe
+*/
+
+/*
+ MtaBind
+*/
+void dcesrv_MtaBind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct MtaBind *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ MtaBindAck
+*/
+void dcesrv_MtaBindAck(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct MtaBindAck *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ endpoint server for the exchange_drs pipe
+*/
+
+/*
+ ds_abandon
+*/
+void dcesrv_ds_abandon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_abandon *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_add_entry
+*/
+void dcesrv_ds_add_entry(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_add_entry *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_bind
+*/
+void dcesrv_ds_bind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_bind *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_compare
+*/
+void dcesrv_ds_compare(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_compare *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_list
+*/
+void dcesrv_ds_list(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_list *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_modify_entry
+*/
+void dcesrv_ds_modify_entry(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_modify_entry *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_modify_rdn
+*/
+void dcesrv_ds_modify_rdn(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_modify_rdn *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_read
+*/
+void dcesrv_ds_read(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_read *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_receive_result
+*/
+void dcesrv_ds_receive_result(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_receive_result *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_remove_entry
+*/
+void dcesrv_ds_remove_entry(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_remove_entry *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_search
+*/
+void dcesrv_ds_search(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_search *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_unbind
+*/
+void dcesrv_ds_unbind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_unbind *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ ds_wait
+*/
+void dcesrv_ds_wait(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct ds_wait *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dra_replica_add
+*/
+void dcesrv_dra_replica_add(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dra_replica_add *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dra_replica_delete
+*/
+void dcesrv_dra_replica_delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dra_replica_delete *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dra_replica_synchronize
+*/
+void dcesrv_dra_replica_synchronize(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dra_replica_synchronize *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dra_reference_update
+*/
+void dcesrv_dra_reference_update(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dra_reference_update *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dra_authorize_replica
+*/
+void dcesrv_dra_authorize_replica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dra_authorize_replica *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dra_unauthorize_replica
+*/
+void dcesrv_dra_unauthorize_replica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dra_unauthorize_replica *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dra_adopt
+*/
+void dcesrv_dra_adopt(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dra_adopt *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dra_set_status
+*/
+void dcesrv_dra_set_status(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dra_set_status *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dra_modify_entry
+*/
+void dcesrv_dra_modify_entry(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dra_modify_entry *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dra_delete_subref
+*/
+void dcesrv_dra_delete_subref(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dra_delete_subref *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ endpoint server for the exchange_xds pipe
+*/
+
+/*
+ xds_dummy
+*/
+void dcesrv_xds_dummy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct xds_dummy *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ endpoint server for the exchange_mta_qadmin pipe
+*/
+
+/*
+ exchange_mta_qadmin
+*/
+void dcesrv_exchange_mta_qadmin(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct exchange_mta_qadmin *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ endpoint server for the exchange_store_information pipe
+*/
+
+/*
+ exchange_store_information_dummy
+*/
+void dcesrv_exchange_store_information_dummy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct exchange_store_information_dummy *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ endpoint server for the exchange_nsp pipe
+*/
+
+/*
+ NspiBind
+*/
+
+enum MAPISTATUS dcesrv_NspiBind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiBind *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiUnbind
+*/
+enum MAPISTATUS dcesrv_NspiUnbind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiUnbind *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiUpdateStat
+*/
+enum MAPISTATUS dcesrv_NspiUpdateStat(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiUpdateStat *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiQueryRows
+*/
+enum MAPISTATUS dcesrv_NspiQueryRows(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiQueryRows *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiSeekEntries
+*/
+enum MAPISTATUS dcesrv_NspiSeekEntries(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiSeekEntries *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiGetMatches
+*/
+enum MAPISTATUS dcesrv_NspiGetMatches(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiGetMatches *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiResortRestriction
+*/
+enum MAPISTATUS dcesrv_NspiResortRestriction(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiResortRestriction *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiDNToMId
+*/
+enum MAPISTATUS dcesrv_NspiDNToMId(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiDNToMId *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiGetPropList
+*/
+enum MAPISTATUS dcesrv_NspiGetPropList(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiGetPropList *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiGetProps
+*/
+enum MAPISTATUS dcesrv_NspiGetProps(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiGetProps *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiCompareMIds
+*/
+enum MAPISTATUS dcesrv_NspiCompareMIds(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiCompareMIds *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiModProps
+*/
+enum MAPISTATUS dcesrv_NspiModProps(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiModProps *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiGetSpecialTable
+*/
+enum MAPISTATUS dcesrv_NspiGetSpecialTable(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiGetSpecialTable *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiGetTemplateInfo
+*/
+enum MAPISTATUS dcesrv_NspiGetTemplateInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiGetTemplateInfo *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiModLInkAtt
+*/
+enum MAPISTATUS dcesrv_NspiModLinkAtt(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiModLinkAtt *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiDeleteEntries
+*/
+enum MAPISTATUS dcesrv_NspiDeleteEntries(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiDeleteEntries *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiQueryColumns
+*/
+enum MAPISTATUS dcesrv_NspiQueryColumns(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiQueryColumns *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiGetNamesFromIDs
+*/
+enum MAPISTATUS dcesrv_NspiGetNamesFromIDs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiGetNamesFromIDs *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiGetIDsFromNames
+*/
+enum MAPISTATUS dcesrv_NspiGetIDsFromNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiGetIDsFromNames *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiResolveNames
+*/
+enum MAPISTATUS dcesrv_NspiResolveNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiResolveNames *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ NspiResolveNamesW
+*/
+enum MAPISTATUS dcesrv_NspiResolveNamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct NspiResolveNamesW *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ endpoint server for the exchange_emsmdb pipe
+*/
+
+/*
+ EcDoConnect
+*/
+enum MAPISTATUS dcesrv_EcDoConnect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcDoConnect *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ EcDoDisconnect
+*/
+enum MAPISTATUS dcesrv_EcDoDisconnect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcDoDisconnect *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ EcDoRpc
+*/
+enum MAPISTATUS dcesrv_EcDoRpc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcDoRpc *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ EcGetMoreRpc
+*/
+void dcesrv_EcGetMoreRpc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcGetMoreRpc *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ EcRRegisterPushNotification
+*/
+enum MAPISTATUS dcesrv_EcRRegisterPushNotification(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcRRegisterPushNotification *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ EcRUnregisterPushNotification
+*/
+enum MAPISTATUS dcesrv_EcRUnregisterPushNotification(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcRUnregisterPushNotification *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ EcDummyRpc
+*/
+void dcesrv_EcDummyRpc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcDummyRpc *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ EcRGetDCName
+*/
+void dcesrv_EcRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcRGetDCName *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ EcRNetGetDCName
+*/
+void dcesrv_EcRNetGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcRNetGetDCName *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ EcDoRpcExt
+*/
+void dcesrv_EcDoRpcExt(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcDoRpcExt *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ EcDoConnect Ex
+*/
+enum MAPISTATUS dcesrv_EcDoConnectEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcDoConnectEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ endpoint server for the exchange_unknown pipe
+*/
+
+/*
+ unknown_dummy
+*/
+void dcesrv_unknown_dummy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct unknown_dummy *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
Added: trunk/openchange/mapiproxy/documentation/mapiproxy-documentation.doxy
===================================================================
--- trunk/openchange/mapiproxy/documentation/mapiproxy-documentation.doxy (rev 0)
+++ trunk/openchange/mapiproxy/documentation/mapiproxy-documentation.doxy 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1467 @@
+/**
+\mainpage
+
+<center><img src="mapiproxy.png"></center>
+
+\section Contents
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<ul>
+ <li><a href="#revision"> Revision History </a></li>
+ <li><a href="#introduction"> 1. Introduction </a>
+ <ul>
+ <li><a href="#purpose"> 1.1. Purpose and Scope</a></li>
+ <li><a href="#overview">1.2. General Overview</a></li>
+ <li><a href="#bugs"> 1.3. Bugs and Limitations </a></li>
+ </ul>
+ </li>
+ <li><a href="#install"> 2. Installation</a>
+ <ul>
+ <li><a href="#download"> 2.1. Download MAPIProxy</a></li>
+ <li><a href="#samba4"> 2.2. Samba4 installation</a></li>
+ <li><a href="#mpinstall"> 2.3. MAPIProxy installation</a></li>
+ </ul>
+ </li>
+ <li><a href="#config"> 3. Configuration</a>
+ <ul>
+ <li><a href="#minute"> 3.1. 5-Minute Configuration</a></li>
+ </ul>
+ </li>
+ <li><a href="#concepts"> 4. Technical Concepts</a>
+ <ul>
+ <li><a href="#bindings"> 4.1. NSPI Bindings Replacement</a></li>
+ <li><a href="#rfr"> 4.2. NSPI Referral FQDN Replacement</a></li>
+ <li><a href="#retrograde"> 4.3. Force EMSMDB Protocol Version</a></li>
+ <li><a href="#idl"> 4.4. OpenChange IDL file</a></li>
+ </ul>
+ </li>
+ <li><a href="#mod_dev"> 5. Stackable Modules </a>
+ <ul>
+ <li><a href="#mpm_overview"> 5.1. General Overview</a></li>
+ <li><a href="#mpm_ep"> 5.2. Module entry point</a></li>
+ <li><a href="#mpm_hooks"> 5.3. Module Hooks</a></li>
+ <li><a href="#mpm_mapiproxy">5.4. mapiproxy structure</a></li>
+ </ul>
+ </li>
+ <li><a href="#modules"> 6. Available Modules </a>
+ <ul>
+ <li><a href="#mod_downgrade"> 6.1. Downgrade Module</a></li>
+ <li><a href="#mod_pack"> 6.2. Pack Module</a></li>
+ <li><a href="#mod_cache"> 6.3. Cache Module</a></li>
+ </ul>
+ </li>
+ <li><a href="#server_mode"> 7. Server Mode </a>
+ <ul>
+ <li><a href="#server_conf"> 7.1. 5-Minute Configuration</a></li>
+ <li><a href="#server_overview"> 7.2. General Overview </a></li>
+ </ul>
+ </li>
+ <li><a href="#faq">8. Frequently Asked Questions</a>
+ <ul>
+ <li><a href="#notcompleted"> 8.1. The action could not be completed</a></li>
+ <li><a href="#cantopen"> 8.2. Profile creation goes fine, but Outlook can't open your default e-mail folders</a></li>
+ <li><a href="#dc"> 8.3. Does MAPIProxy need to be domain controller?</a></li>
+ <li><a href="#gnutls"> 8.4. Generating Samba's private keys takes infinite time</a></li>
+ <li><a href="#gmake"> 8.5. On Ubuntu <i>make samba-git</i> exits with <i>gmake: not found</i></a></li>
+ </ul>
+ </li>
+</ul>
+</td>
+</tr>
+</table>
+<br/>
+
+<a name="revision"></a><h2>Revision History</h2>
+<table align="center" width="80%">
+ <tr>
+ <td style="text-align:center"><strong>Date</strong></td>
+ <td style="text-align:center"><strong>Revision Number</strong></td>
+ <td style="text-align:center"><strong>Author</strong></td>
+ <td style="text-align:center"><strong>Revision Content</strong></td>
+ </tr>
+ <tr>
+ <td style="text-align:center">01/02/09</td>
+ <td style="text-align:center"><strong>0.6.1</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">Add configuration info for server mode.</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">04/01/09</td>
+ <td style="text-align:center"><strong>0.6</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">server mode documented, update
+ mapiproxy naming to MAPIProxy.</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">29/12/08</td>
+ <td style="text-align:center"><strong>0.5.5</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">Add 3 new questions to FAQ section</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">09/12/08</td>
+ <td style="text-align:center"><strong>0.5.4</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">Add dcesrv:assoc group checking
+ to smb.conf configuration requirements</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">10/07/08</td>
+ <td style="text-align:center"><strong>0.5.3</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">Rename smbd process to samba
+ session API and update documentation</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">08/26/08</td>
+ <td style="text-align:center"><strong>0.5.2</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">documentation update on NSPI
+ replacement and new FAQ question added</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">08/26/08</td>
+ <td style="text-align:center"><strong>0.5.1</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">documentation on NSPI referral added</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">08/11/08</td>
+ <td style="text-align:center"><strong>0.5</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">unbind hook added, cache
+ module documentation and scenario added </td>
+ </tr>
+ <tr>
+ <td style="text-align:center">07/23/08</td>
+ <td style="text-align:center"><strong>0.4</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">MAPIProxy API hooks, IDL
+ update, mapiproxy structure description and documentation
+ added for the cache module</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">06/25/08</td>
+ <td style="text-align:center"><strong>0.3.2</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">Minor installation update</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">06/04/08</td>
+ <td style="text-align:center"><strong>0.3.1</strong></td>
+ <td style="text-align:center">Brad Hards</td>
+ <td style="text-align:left">Minor edits</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">05/27/08</td>
+ <td style="text-align:center"><strong>0.3</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">Available modules section
+ added</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">05/24/08</td>
+ <td style="text-align:center"><strong>0.2</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:left">EMSMDB protocol version
+ subsection updated, modules system section added, 5-minute
+ configuration updated</td>
+ </tr>
+ <tr>
+ <td style="text-align:center">05/15/08</td>
+ <td style="text-align:center"><strong>0.1</strong></td>
+ <td style="text-align:center">Julien Kerihuel</td>
+ <td style="text-align:center">Initial Revision</td>
+ </tr>
+</table>
+<br/>
+
+<a name="introduction"></a><h2>1. Introduction</h2>
+
+<a name="purpose"></a><h3>1.1. Purpose and Scope</h3>
+
+MAPIProxy is an endpoint server for Samba4 which proxies ExchangeRPC
+traffic from MAPI clients (Outlook, openchangeclient, etc.) to
+Microsoft Exchange Server (and back). It can either act as a
+transparent proxy, for hacking, monitoring or debugging purposes or
+modify traffic on the fly and so provide new features. It is primarily
+developed for - but not limited to - third-party implementors looking
+for a development framework they can use for MAPI acceleration
+purposes.
+
+This project is originally based on dcerpc_remote.c code from Stefan
+Metzemacher (Samba4 trunk) and is released under GPLv3 or later. It
+creates a dynamic shared object file which is loaded into samba and
+uses the Samba configuration file (smb.conf) to set common options.
+
+<br/>
+<a name="overview"></a><h3>1.2. General overview</h3>
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mapiproxy_overview.png" />
+</td>
+</tr>
+</table>
+<center>Figure 1. General MAPIProxy network overview</center>
+
+The MAPIProxy traffic can be divided into 3 different parts as
+described in the figure above:
+
+<ul>
+<li style="text-align:justify;"><strong>[1] clients to
+MAPIProxy:</strong><br/>The origin of a client connect does not
+have much importance: it can either be an incoming connection from a
+real MAPI client, a connection relayed from another third-party
+proxy or another MAPIProxy instance. MAPIProxy runs as an endpoint
+server registered when samba starts. When the Samba4 endpoint mapper
+receives an incoming connection asking for one of the ExchangeRPC
+endpoints: NSPI (Name Service Provider Interface - Address Book) or
+EMSMDB (Exchange Message Store), the endpoint mapper redirects
+ExchangeRPC traffic to MAPIProxy which will pull, push and dispatch
+MAPI operations.</li>
+
+<li style="text-align:justify;"><strong>[2] MAPIProxy to
+MAPIProxy:</strong><br/>The main objective of MAPIProxy is not to
+directly connect to the remote message server, but rather to relay
+some kind of modified MAPI traffic to the next MAPIProxy hop. This
+configuration can be used to add a compression layer between MAPIProxy
+instances, or to send specific third-party vendor information.
+However, a proxied connection directly from a MAPI client to an
+Exchange server (i.e. <i>client-MAPIProxy-server</i> is possible and
+such a configuration could be used for many other purposes.<br/></li>
+
+<li><strong>[3] MAPIProxy to server:</strong><br/>This last node is
+responsible for restoring MAPI contents and pushing it to the real
+Exchange server. </li>
+</ul>
+<br/>
+
+<a name="bugs"></a><h2>1.3. Bugs and Limitations</h2></a>
+
+If you find bugs, limitations or have features you would like to see
+included in MAPIProxy, please register on the OpenChange Ticket System
+and create new tickets for the MAPIProxy component:
+<ul>
+<li><a
+href="http://trac.openchange.org">http://trac.openchange.org</a>
+(OpenChange Ticket System)</li>
+<li><a
+href="http://trac.openchange.org/query?status=new&status=assigned&status=reopened&component=mapiproxy&order=priority">MAPIProxy
+Component Tickets</a></li>
+</ul>
+<br/>
+
+
+<a name="install"></a><h2>2. Installation</h2>
+<a name="download"></a><h3>2.1. Download MAPIProxy</h3>
+
+MAPIProxy is only available through SVN at the moment. A tarball
+release will only be made when we have a stabilized API with a
+preliminary set of useful features. You will need a <a
+href="http://subversion.tigris.org/">SVN client</a> to download
+openchange (including MAPIProxy)..
+
+\code
+ $ svn co https://svn.openchange.org/openchange/trunk openchange
+\endcode
+
+<a name="samba4"></a><h3>2.2. Samba4 installation</h3>
+
+The MAPIProxy implementation requires a very recent Samba4 version
+in order to run properly. If Samba4 is planned to be installed
+from scratch for MAPIProxy only, please use the <i>make samba-git</i>
+compilation rule provided in the build system. This command will
+automate most part of the samba4 installation process. The only
+requirement for this step is to have an up to date <a
+href="http://git.or.cz/">GIT version</a> installed on the system.
+
+\code
+ # make samba-git
+\endcode
+
+When the installation process is finished, a running samba4
+installation will be located in <i>/usr/local/samba/</i>. You will possibly be
+required to run <i>ldconfig</i> before you move to next steps. Please
+refer to <i>doc/howto.txt</i> for further information on openchange
+compilation.
+<br/>
+
+<a name="mpinstall"></a><h3>2.3. MAPIProxy installation</h3>
+
+If you have existing OpenChange DSO in the
+<i>/usr/local/samba/modules/dcerpc_server/</i> folder, such as
+<i>dcesrv_exchange.so</i>, <strong>please remove them prior loading
+samba with MAPIProxy.</strong>
+
+\code
+ $ ./autogen.sh
+ $ ./configure --prefix=/usr/local/samba
+ $ make
+ # make install
+ # rm -rf /usr/local/samba/modules/dcerpc_server/dcesrv_exchange.so
+\endcode
+
+<br/>
+
+
+<a name="config"></a><h2>3. Configuration</h2>
+<a name="minute"></a><h3>3.1. 5-Minute Configuration</h3>
+
+This 5-Minute configuration will help you set up a minimal MAPIProxy
+using specified credentials and relaying traffic from Outlook clients
+to a remote Exchange server. This configuration will be performed in three
+steps:
+
+<ul>
+<li><strong>[1] Provision Samba</strong>:<br/>From samba4/source4
+directory, run under the root account:
+\code
+# ./setup/provision --realm=OPENCHANGE.LOCAL --domain=OPENCHANGE \
+ --adminpass=openchange --server-role='domain controller'
+\endcode
+
+If you don't have DNS resolution and your realm can't be resolved,
+samba will be unable to authenticate the user in its user database. You
+must specify a realm which MAPI clients and MAPIProxy can resolve.
+
+If everything works fine, the provisioning script will have created
+all the databases, populated the AD (Active Directory) and generated a
+valid smb.conf file.
+</li>
+
+<li><strong>[2] Add a user account</strong>:<br/>
+
+In this configuration, we'll set the same credentials both for the
+user in the windows domain and on the Samba4 server. Let say there is
+already a user named <i>testuser</i> with its password set to
+<i>openchange</i> on the Exchange server:
+\code
+# ./setup/newuser testuser
+New Password: openchange
+\endcode
+</li>
+
+<li><strong>[3] Configure MAPIProxy options</strong>:<br/>
+
+In this final step, we only need to customize a small set of parameters:
+<ul>
+
+ <li style="text-align:justify;"><strong>dcerpc endpoint
+ servers</strong>:<br/> MUST include epmapper and mapiproxy separated
+ with comma.</li>
+
+ <li
+ style="text-align:justify;"><strong>dcerpc_mapiproxy:binding</strong>:<br/>
+ This is the binding string used to connect to the remote Exchange
+ server. The format of this string is: transport:address[flags]. In the
+ example below, we'll be using the TCP over IP transport, connect on
+ 192.168.1.1 and add the print flag so MAPI packets get dissected on
+ samba stdout (or logfile).</li>
+
+ <li
+ style="text-align:justify;"><strong>dcerpc_mapiproxy:username</strong>
+ and <strong>dcerpc_mapiproxy:password</strong>:<br/>The specified
+ credentials we will be using to connect to the remote Exchange
+ server.</li>
+
+ <li
+ style="text-align:justify;"><strong>dcerpc_mapiproxy:domain</strong>:<br/>
+ The Windows domain the remote Exchange server belongs to.</li>
+
+ <li
+ style="text-align:justify;"><strong>dcerpc_mapiproxy:interfaces</strong>:<br/>
+ In our case, we want to relay the whole ExchangeRPC traffic, so we
+ need to load both the EMSMDB and NSP interface. In the meantime,
+ people interested in NSPI proxy only would only have to load the
+ exchange_nsp interface.</li>
+
+<li
+style="text-align:justify;"><strong>dcerpc_mapiproxy:modules</strong>:<br/>
+MAPIProxy provides a stackable modular system which primary objective
+is to provide developers an API for modules development. In our case
+we want to activate the <i>downgrade</i> module responsible for the
+EcDoConnect/EcDoRpc EMSMDB RPC functions negotiation.</li>
+
+</ul>
+
+\code
+[globals]
+ netbios name = MAPIPROXY
+ workgroup = OPENCHANGE
+ realm = OPENCHANGE.LOCAL
+ server role = domain controller
+
+ ### Configuration required by mapiproxy ###
+ dcesrv:assoc group checking = false
+ dcerpc endpoint servers = epmapper, mapiproxy
+
+ dcerpc_mapiproxy:binding = ncacn_ip_tcp:192.168.1.1[print]
+ dcerpc_mapiproxy:username = testuser
+ dcerpc_mapiproxy:password = openchange
+ dcerpc_mapiproxy:domain = EXCHANGE
+ dcerpc_mapiproxy:interfaces = exchange_emsmdb, exchange_nsp, exchange_ds_rfr
+ dcerpc_mapiproxy:modules = downgrade
+ ### Configuration required by mapiproxy ###
+
+
+[netlogon]
+ path = /usr/local/samba/var/locks/sysvol/openchange.local/scripts
+ read only = no
+
+[sysvol]
+ path = /usr/local/samba/var/locks/sysvol
+ read only = no
+\endcode
+</li>
+</ul>
+
+We are now ready to run samba:
+\code
+ # samba -d5 -i -M single
+\endcode
+
+If everything works properly, the following lines should be displayed
+in samba output:
+\code
+DCERPC endpoint server 'exchange_emsmdb' registered
+DCERPC endpoint server 'exchange_nsp' registered
+DCERPC endpoint server 'exchange_ds_rfr' registered
+DCERPC endpoint server 'mapiproxy' registered
+dcesrv_interface_register: interface 'epmapper' registered on endpoint 'ncacn_np:[\pipe\epmapper]'
+dcesrv_interface_register: interface 'epmapper' registered on endpoint 'ncacn_ip_tcp:[135]'
+dcesrv_interface_register: interface 'epmapper' registered on endpoint 'ncalrpc:[EPMAPPER]'
+MAPIPROXY module 'downgrade' registered
+MAPIPROXY module 'downgrade' loaded
+mapiproxy_module_load 'downgrade' (Downgrade EMSMDB protocol version EcDoConnect/EcDoRpc)
+dcesrv_interface_register: interface 'exchange_emsmdb' registered on endpoint 'ncacn_np:[\pipe\lsass]'
+dcesrv_interface_register: interface 'exchange_emsmdb' registered on endpoint 'ncacn_np:[\pipe\protected_storage]'
+dcesrv_interface_register: interface 'exchange_emsmdb' registered on endpoint 'ncacn_ip_tcp:'
+dcesrv_interface_register: interface 'exchange_nsp' registered on endpoint 'ncacn_np:[\pipe\lsass]'
+dcesrv_interface_register: interface 'exchange_nsp' registered on endpoint 'ncacn_np:[\pipe\protected_storage]'
+dcesrv_interface_register: interface 'exchange_nsp' registered on endpoint 'ncacn_ip_tcp:[]'
+dcesrv_interface_register: interface 'exchange_ds_rfr' registered on endpoint 'ncacn_np:[\pipe\lsass]'
+dcesrv_interface_register: interface 'exchange_ds_rfr' registered on endpoint 'ncacn_np:[\pipe\protected_storage]'
+dcesrv_interface_register: interface 'exchange_ds_rfr' registered on endpoint 'ncacn_ip_tcp:[]'
+\endcode
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<strong>You should now be able to configure Outlook to use
+an Exchange account with the proxy IP address and run Outlook
+seamlessly (both online or cached exchange mode).</strong>
+</td>
+</tr>
+</table>
+<br/>
+
+<a name="concepts"></a><h2>4. Technical Concepts</h2>
+<a name="bindings"></a><h3>4.1. NSPI Bindings Replacement</h3>
+
+When Outlook sets up an Exchange account using either the mail applet
+from the configuration panel or the account editor within Outlook, it
+uses the NSPI protocol (Name Service Provider Interface, effectively
+the address book provider). In this case, NSPI is used to resolve the
+Exchange username and fetch from Exchange server all information
+needed by Outlook to initiate direct connection to the EMSMDB pipe
+(effectively the message store) the next time it connects to the server.
+<br/>
+
+At some point of the profile's creation process, Outlook queries
+Exchange for some specific connection information using the
+<strong>NspiGetProps (0x9) RPC operation </strong>. More specifically,
+when Outlook requests for the
+<strong>PR_EMS_AB_NETWORK_ADDRESS</strong> MAPI property, Exchange
+returns a list <strong>binding strings</strong>. Outlook next stores
+these binding strings at some location - associated to the Outlook
+profile - in the windows registry and uses them for future
+connections.<br/>
+
+Outlook can also rely on other information returned by NSPI functions
+and connect to the real Exchange server rather than MAPIProxy. Such
+case occurs when Outlook is able to resolve the exchange server using
+its hostname. This reference to the original Exchange server can be
+found when Outlook requests for the
+<strong>PR_EMS_AB_HOME_MDB</strong> MAPI property during the
+<strong>NspiQueryRows (0x3) RPC operation</strong>. MAPIProxy replaces
+the Exchange server name with its own netbios name and forward the
+reply to the client.<br/>
+
+In the meantime, this information is next used by Outlook to query a
+minimal entry ID for a distinguished name using this server
+name. MAPIProxy needs to substitute the server name in the inbound
+request string with the original exchange one.<br/>
+
+MAPIProxy needs to avoid Outlook clients being aware of this remote
+server address and trying to communicate directly with the remote server
+instead of using the proxy. In order to do this, MAPIProxy alters the
+Outlook-Exchange MAPI traffic and replaces these binding strings with
+the MAPIProxy FQDN and netbios name.
+
+<br/>
+<a name="rfr"></a><h3>4.2. NSPI Referral Replacement</h3>
+
+The Address Book Name Service Provider Interface (NSPI) Referral
+Service is a service used by Outlook to retrieve the name of an NSPI
+server. No NSPI connection should be initiated without first querying
+for the correct NSPI server. In this case, RFR returns the fully
+qualified domain name of the real Exchange server and starts using it
+if available. <br/>
+
+MAPIProxy needs to avoid Outlook clients being aware of this server
+address and trying to communicate directly with the remote server
+instead of using the proxy. In order to do this, MAPIProxy alters the
+Outlook-Exchange MAPI traffic and replaces the server DN returned by
+<strong>RfrGetNewDSA (0x0) RPC operation</strong> with the MAPIProxy
+realm as specified in smb.conf.
+
+<br/>
+<a name="retrograde"></a><h3>4.3. Force EMSMDB Protocol Version</h3>
+
+When Outlook starts and presumably calls MapiLogonEx, it first opens a
+connection to the Exchange server on the NSPI pipe, then on the EMSMDB
+pipe. Under Outlook 2003, the very first EMSMDB RPC call Outlook makes
+can be considered as a kind of <i>protocol version
+negotiation</i>. Depending on which version of Outlook is used, and how
+the Exchange server replies to the EMSMDB connect request, Outlook will
+either keep using the same pool of RPC calls or downgrade.
+
+For example Outlook 2003 (default behavior) tests if the remote server
+supports the 2 new EMSMDB calls (EcDoConnectEx/EcDoRpcExt2) introduced
+in Exchange 2003. If Exchange replies to the EcDoConnectEx request
+with a dcerpc_fault, it means the server does not support the RPC
+operation, presumably has a version before 2003, and Outlook needs to
+downgrade its version in order to communicate with the server:
+<ul>
+ <li>EcDoConnectEx (0xa) call
+ <ul>
+ <li>On success, Outlook will use EcDoRpcExt2 (0xb) to handle MAPI traffic</li>
+ <li>On failure (dcerpc_fault: nca_op_rng_error), Outlook calls
+ EcDoConnect (0x0) and use EcDoRpc (0x2) to handle MAPI
+ traffic</li>
+ </ul>
+ </li>
+</ul>
+
+If MAPIProxy runs in an environment with Outlook clients and
+Exchange servers using a version above 2003, a last step is required
+to successfully use Outlook. The EcDoConnect RPC reply returns the Exchange
+server version (as an array of 3 short integers). When Outlook detects this
+particular server version, it automatically closes the connection and keep
+requesting indefinitely for EcDoConnectEx. To deal with this, MAPIProxy
+modifies the EcDoConnect reply sent by Exchange and replaces the server version
+with a one equal to that sent by Exchange 2000.
+
+In the meantime, if we reproduce this test with Outlook 2000 which
+doesn't support these 2 new RPC calls, Outlook will directly call
+EcDoConnect.
+
+The main difference between the EcDoConnectEx/EcDoRpcExt2 operations and
+the EcDoConnect/EcDoRpc operations is that the former use
+both XOR 0xA5 obfuscation and LZ77 compression/Direct2 encoding;
+while the latter only use the XOR obfuscation to handle MAPI content.
+If MAPIProxy wants to act as an intelligent proxy (for example, to
+be able to analyze MAPI content on the fly, compress MAPI data etc),
+receiving non compressed MAPI traffic would probably improve the
+overall process.
+
+Below is a list of Exchange/Outlook pairs and the EMSMDB connect
+function they will use by default:
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+ <tr style="border:none">
+ <td style="border:none"><strong>Exchange version</strong></td>
+ <td style="border:none"><strong>Outlook version</strong></td>
+ <td style="border:none"><strong>EMSMDB connect function</strong></td>
+ </tr>
+ <tr>
+ <td style="border:none;border-bottom:1px solid #e0e0e0;">5.5/2000</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0;">any</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0;">EcDoConnect (0x0)</td>
+ </tr>
+ <tr>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">2003</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">2000</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">EcDoConnect (0x0)</td>
+ </tr>
+ <tr>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">2007</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">2000</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">EcDoConnect
+ (0x0)<br/>Microsoft officially says it is unsupported</td>
+ </tr>
+ <tr>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">2003</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">2003-2007</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">EcDoConnectEx (0xa)</td>
+ </tr>
+ <tr>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">2007</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">2003</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">EcDoConnectEx (0xa)</td>
+ </tr>
+ <tr>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">2007</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">2007</td>
+ <td style="border:none;border-bottom:1px solid #e0e0e0">EcDoConnectEx (0xa)</td>
+ </tr>
+</table>
+
+MAPIProxy reproduces the Exchange 2000 behavior and prevents Outlook
+from communicating with the Exchange server using the
+EcDoConnectEx/EcDoRpcExt2 as described in Figure 2 below. When Outlook
+sends an EcDoConnectEx request, MAPIProxy does not relay the request to
+the remote Exchange server and immediately returns a dcerpc_fault to
+Outlook. Outlook, assuming the server doesn't support this call uses
+EcDoConnect instead. From this call, MAPIProxy relay the information
+to Exchange.
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mapiproxy_emsmdb_graph.png" width="75%" height="75%" />
+</td>
+</tr>
+</table>
+<center>Figure 2. MAPIProxy behavior on Outlook EMSMDB connection</center>
+
+From the Exchange side, the server will analyze this EcDoConnect
+request as a call sent by Outlook 2000 or below version. Exchange
+works fine using this protocol version unless Exchange 2007 SP1 which
+appears to introduce client version restrictions <i>by default</i>. In
+the meantime, existing tests demonstrate similar restrictions would
+apply to Outlook 2003 connection (without MAPIProxy) and prevent
+Outlook version before 2007 connecting to Exchange 2007. Further information
+and solution is available at the following addresses:
+<ul>
+ <li><a href="http://support.microsoft.com/kb/555851">Earlier Outlook clients cant connect to Exchange 2007 Server</a></li>
+ <li><a href="http://msexchangeteam.com/archive/2006/02/20/419994.aspx">Exchange 12 and Public Folders</a></li>
+</ul>
+<br/>
+
+<a name="idl"></a><h3> 4.4. OpenChange IDL File </h3>
+
+IDL stands for Interface Definition Language and OpenChange uses this
+format to describe ExchangeRPC communications. This file is processed
+by pidl (Perl IDL compiler provided by Samba4) which turns this
+protocol description into C-code dealing with the push, pull and print
+operations.
+
+OpenChange development policy in trunk used to push a new MAPI call in
+the IDL only when the associated libmapi implementation and mapitest
+unit is developed, but this was preventing from distributing MAPIProxy
+with further openchange releases. Furthermore, the OpenChange IDL is
+now almost complete and merging back to the trunk helps improving
+libmapi reliability.
+
+<br/>
+
+
+<a name="mod_dev"></a><h2>5. Stackable Modules</h2>
+<a name="mpm_overview"></a><h3>5.1. General Overview</h3>
+
+The MAPIProxy stackable modules system provides implementors a
+development framework to add new features. This stackable mechanism
+allows developers to write modules with a very specific scope of
+which modifications will transparently be relayed to the next module
+until it is finally pushed by MAPIProxy to
+the next hop (Figure 3.).
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mpm_stack.png" width="75%" height="75%" />
+</td>
+</tr>
+</table>
+<center>Figure 3. MAPIProxy module stack and EcDoRpc interaction </center>
+
+With this system, developers can focus their effort on ExchangeRPC
+traffic - or any other protocol samba supports - interception,
+modification, analysis and avoid spending time on implementing a new
+endpoint server. Furthermore it provides an easier way for
+implementors to divide the work in smaller units and develop each of
+them in a separated module.
+<br/>
+
+MAPIProxy modules are dynamic shared objects with an entry point and a
+limited set of hooks. These modules have to be installed in the
+<i>dcerpc_mapiproxy</i> folder within the samba4 modules directory
+(e.g. <i>/usr/local/samba/modules</i>). MAPIProxy modules specified
+in the Samba configuration file (smb.conf) will be loaded into MAPIProxy
+at runtime and interact with each other in the same order they were
+defined:
+
+\code
+ dcerpc_mapiproxy:modules = downgrade,dummy
+\endcode
+
+All MAPIProxy modules will be registered but only those specified on
+the <strong>dcerpc_mapiproxy:modules</strong> parametric option line
+will be added to the chained list of effective modules.
+<br/><br/>
+
+
+<a name="mpm_ep"></a><h3>5.2. Module entry point</h3>
+
+MAPIProxy modules must have an entry point function named
+<strong>samba_init_module</strong>. This function needs to set general
+information about the module, specify the module's hooks and finally
+call the <strong>mapiproxy_module_register</strong> function to
+register itself in the MAPIProxy module subsystem.
+
+\code
+NTSTATUS samba_init_module(void)
+{
+ struct mapiproxy_module module;
+ NTSTATUS ret;
+
+ /* Fill in our name */
+ module.name = "sample";
+ module.description = "A sample module";
+ module.endpoint = "any";
+
+ /* Fill in all the operations */
+ module.init = sample_init;
+ module.push = sample_push;
+ module.ndr_pull = sample_ndr_pull;
+ module.pull = sample_pull;
+ module.dispatch = NULL;
+ module.unbind = NULL;
+
+ /* Register ourselves with the MAPIPROXY subsytem */
+ ret = mapiproxy_module_register(&module);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("Failed to register 'sample' mapiproxy module!\n"));
+ return ret;
+ }
+
+ return ret;
+}
+\endcode
+
+<ul>
+ <li><strong>module.name</strong>:<br/>
+ This is the module name. This name will be used by
+ dcerpc_mapiproxy:modules in smb.conf to load the module</li>
+
+ <li><strong>module.description</strong>:<br/>
+ This field lets developers specify a brief module description for
+ information purpose only.</li>
+
+ <li><strong>module.endpoint</strong>:<br/>
+ This field defines the interface which this module is designed to
+ work with. The primary objective is to avoid calling the module
+ hooks if the module doesn't have any impact on the requests or
+ replies. For example, a module only interacting with the EcDoRpc
+ function should define <i>exchange_emsmdb</i>.
+
+ In the meantime, it can happen that a module requires to interact
+ with more than a single interface. In such case, use the
+ '<strong>any</strong>' keyword which will call the modules functions
+ with any endpoints proxied by MAPIProxy.</li>
+</ul>
+
+
+<a name="mpm_hooks"></a><h3> 5.3. Module Hooks</h3>
+
+MAPIProxy offers a set of hooks which modules can implement to
+modify/change/alter client to server MAPI traffic. The figure below
+shows how and when hooks are called during a request/response
+lifetime.
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mapiproxy_hook_life.png" />
+</td>
+</tr>
+</table>
+<center> Figure 4. Usage of MAPIProxy Hooks during a request/response life time </center>
+
+<ul>
+
+<li><strong>init</strong>: This is the initialization function for the
+module which is only called once - when the module is loaded. It is
+generally used to retrieve smb.conf parametric options for the module
+and initialize some global structures</li>
+
+<li><strong>pull</strong>: This is the function called when MAPIProxy
+receives a MAPI request. The request has already been extracted and
+its information filled into MAPI structures
+
+<li><strong>push</strong>: This is the function called when MAPIProxy
+receive a MAPI response. The response has already been extracted and
+its information filled into MAPI structures</li>
+
+<li><strong>dispatch</strong>: Similarly to the MAPIProxy
+top-level dispatch function, it is used to dispatch the
+information. This function is called after the pull but before the
+push. Moreover it is called before the request is forward to the
+remote endpoint.</li>
+
+<li><strong>ndr_pull</strong>: This is the function called before
+data from a request is extracted from the NDR blob.</li>
+
+<li><strong>ndr_push</strong>: This is the function called before
+data from a response is extracted from the NDR blob.</li>
+
+<li><strong>unbind</strong>: This is the function called when the
+connection closes. It can be used to free data associated to a given
+session and stored within a module global list.</li>
+
+</ul>
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<strong>Please note that the module API is still under development and
+is likely to change in further revisions.</strong>
+</td>
+</tr>
+</table>
+
+
+<a name="mpm_mapiproxy"></a><h3> 5.4. mapiproxy structure </h3>
+MAPIProxy uses a structure modules can modify in their dispatch routine
+and which impact on the general MAPIProxy behavior.
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mapiproxy_struct.png" />
+</td>
+</tr>
+</table>
+<center> Figure 5. overview of mapiproxy structure variables scope </center>
+
+<ul>
+
+<li><strong>norelay</strong>: This boolean variable can be used by
+modules to tell MAPIProxy not to relay the incoming
+<strong>request</strong> to the remote server through
+<i>dcerpc_ndr_request()</i> but directly jump to the push (response)
+MAPIProxy code. This variable is for example in use within the cache
+module when we read stream from the local filesystem and play it back
+to MAPI clients.</li>
+
+<li><strong>ahead</strong>: This boolean variable can be used by
+modules to tell MAPIProxy not to relay the incoming
+<strong>response</strong> to the client through the <i>push</i> and
+<i>dcerpc_ndr_request</i> routine but loop over the dispatch
+routine. This variable is for example in use within the cache module
+when we want to read a stream ahead from Exchange server to the remote
+MAPIProxy instance.</li>
+
+</ul>
+
+<br/>
+
+
+
+<a name="modules"></a><h2> 6. Available Modules </h2>
+<a name="mod_downgrade"></a><h3> 6.1. Downgrade Module</h3>
+
+The <strong>downgrade</strong> module implements the
+EcDoConnect/EcDoRpc negotiation as described in <a
+href="#retrograde">section 4.2</a>. It ensures Outlook will not send
+compressed information or use functions other than EcDoRpc for
+EMSMDB transport. In order to use the downgrade module, edit smb.conf
+and add <i>downgrade</i> to <i>dcerpc_mapiproxy:modules</i>.
+
+\code
+ dcerpc_mapiproxy:modules = downgrade
+\endcode
+
+<br/>
+
+<a name="mod_pack"></a><h3> 6.2. Pack Module </h3>
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<strong>Note that this module only works with an infrastructure using two or
+more instances of MAPIProxy as described in <a href="#overview">Figure
+1</a></strong>
+</td>
+</tr>
+</table>
+
+The <strong>pack</strong> module implements routines designed to
+manipulate and factorize MAPI content between different MAPIProxy
+instances. It also offers a developer overview on how to manipulate
+mapi requests. Last but not least, it provides data which can next be
+used by subsequent MAPIProxy modules for example to compress or
+encrypt this proxypack blob.
+
+<ul>
+
+<li>First, MAPIProxy extracts and removes specific MAPI calls from the
+request, pack them within the proxypack MAPI call data blob, prefix
+them with their real offset in the array of mapi requests and finally
+append this custom call at the end of the mapi requests array (Figure
+4).</li>
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mpm_pack_pack.png" />
+</td>
+</tr>
+</table>
+<center> Figure 6. Pack process </center>
+
+<li>Final MAPIProxy hop will seek the mapi requests array looking for
+the proxypack call. If found, it unpacks MAPI data and restore these
+calls at their initial location within the mapi requests array (Figure
+6).</li>
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mpm_pack_unpack.png" />
+</td>
+</tr>
+</table>
+<center> Figure 7. Unpack process </center>
+
+</ul>
+
+
+This module has two configuration options:
+<ul>
+ <li><strong>mpm_pack:opnums</strong><br/>
+ This option takes a list of MAPI calls to pack into the proxypack
+ data blob. It can take one or more MAPI opnums, each of them
+ separated with a comma.</li>
+
+ <li><strong>mpm_pack:lasthop</strong><br/>
+ This options takes either <i>true</i> or <i>false</i>.the lasthop
+ option defines whether this is a MAPIProxy directly connected to
+ Outlook/Exchange or yet another proxy inserted within the MAPIProxy
+ chain of hops. If this MAPIProxy instance is not a last hop, then it
+ will skip the pack/unpack operations and forward the request to the
+ next one.</li>
+</ul>
+
+\code
+ mpm_pack:opnums = 0x70,0x75,0x76,0x77,0xa
+ mpm_pack:lasthop = true
+\endcode
+
+In order to use the pack module, edit smb.conf and add <i>pack</i> to
+<i>dcerpc_mapiproxy:modules</i>.
+
+\code
+ dcerpc_mapiproxy:modules = downgrade,pack
+\endcode
+
+<br/>
+
+
+<a name="mod_cache"></a><h3> 6.3. Cache Module </h3>
+
+The <strong>cache</strong> module implements a cache mechanism for
+streams related to messages or attachments. This module reduces
+communication latency between MAPI clients (using <i>online</i> mode)
+and Exchange. When configured with online mode, MAPI clients retrieve
+data from Exchange each time they access a message and don't have any
+offline storage mechanisms enabled - data are downloaded and stored
+within a <i>temporary files</i> folder. This module also offers a
+preliminary synchronization mechanism which can be used to transfer
+files between different MAPIProxy instances and use different
+protocols than MAPI for data transfer (such as rsync or wget).
+
+The cache module is designed to cover different cases:
+
+<h4>Scenario 1: Replay attachments</h4>
+
+This scenario only requires a single MAPIProxy instance and requires a
+single configuration option:
+\code
+ mpm_cache:path = /tmp/cache
+\endcode
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mpm_cache_case_one.png" />
+</td>
+</tr>
+</table>
+<center> Figure 8. Replay stream scenario </center>
+
+<ul>
+
+ <li style="text-align:justify;"><strong>1. Outlook reads a stream for the first time</strong>:<br/>
+ MAPIProxy monitors the Outlook-Exchange traffic and store the
+ attachment on the local filesystem. </li>
+
+ <li style="text-align:justify;"><strong>2. Outlook requests this stream again</strong>:<br/>
+ MAPIProxy looks over its cache, find the requested stream and
+directly communicate with Outlook without forwarding requests to the
+remote server.</li>
+
+</ul><br/>
+
+<h4>Scenario 2: Read stream ahead</h4>
+
+This scenario requires two MAPIProxy instances and requires different
+configuration options for local and remote MAPIProxy:
+
+<ul>
+<li><strong>local MAPIProxy smb.conf sample</strong>:<br/>
+\code
+ mpm_cache:path = /tmp/cache
+ mpm_cache:ahead = false
+ mpm_cache:sync = true
+ mpm_cache:sync_cmd = /usr/bin/rsync -z mapiproxy at 192.168.102.2:__FILE__ __FILE__
+\endcode
+</li>
+
+<li><strong>remote MAPIProxy smb.conf sample</strong>:<br/>
+\code
+ mpm_cache:path = /tmp/cache
+ mpm_cache:ahead = true
+ mpm_cache:sync = false
+\endcode
+</li>
+
+</ul>
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mpm_cache_case_two.png" />
+</td>
+</tr>
+</table>
+<center> Figure 9. Read ahead scenario with synchronization mechanism </center>
+
+<ul>
+
+<li style="text-align:justify;"><strong>This scenario uses 2 MAPIProxy instances</strong>. We call
+<i>remote MAPIProxy</i>, the MAPIProxy instance connected to the
+Exchange server network and <i>local MAPIProxy</i> the instance
+connected to the MAPI clients network.</li>
+
+<li style="text-align:justify;"><strong>1. Outlook wants to read an attachment for the first
+time</strong>:<br/> The remote MAPIProxy monitors the first ReadStream
+request and read the full stream ahead on its own and stores it on its
+local filesystem.</li>
+
+<li style="text-align:justify;"><strong>2. remote MAPIProxy replies to local MAPIProxy and local
+MAPIProxy runs the synchronization mechanism.</strong> The current
+implementation provides a fork/execve/waitpid process which allows to
+run any command with parameters. When local MAPIProxy finishes to
+store the file locally through the synchronization mechanism, it marks
+the stream as being cached.</li>
+
+<li style="text-align:justify;"><strong>3. local MAPIProxy plays the attachment back to the client
+from cache</strong>.</li>
+
+</ul>
+
+
+The module monitors OpenMessage, OpenAttach, OpenStream, ReadStream
+and Release MAPI calls and stores streams on the local filesystem with
+indexation in a TDB database. Note that the module doesn't yet provide
+semantics needed to remove entries from the TDB database.
+
+
+This module has different configuration options and modes:
+<ul>
+ <li style="text-align:justify;"><strong>mpm_cache:path</strong><br/>
+ This option takes the full path to an existing folder on the
+ filesystem. This folder will be the storage root path for the cache
+ module and will hold the TDB store, a folder hierarchy and stream
+ files.
+
+\code
+ mpm_cache:path = /tmp/cache
+\endcode
+</li>
+
+<li style="text-align:justify;"><strong>mpm_cache:ahead</strong><br/>
+This option takes a boolean value (true or false) and defines whether
+the ahead mechanism should be enabled or not. This mode should only be
+enabled on the remote MAPIProxy instance. It can be enabled on local
+MAPIProxy instance, however there won't be any benefit but Outlook
+unexpectedly falling in some time out mode and close the connection.
+
+\code
+ mpm_cache:ahead = true
+\endcode
+</li>
+
+<li style="text-align:justify;"><strong>mpm_cache:sync</strong><br/>
+This option takes a boolean value (true or false) and defines whether
+the synchronization mechanism should be enabled or not. This mode only
+makes sense on the local MAPIProxy instance and
+<strong>mpm_cache:sync_cmd</strong> must also be configured.
+
+\code
+ mpm_cache:sync = true
+\endcode
+</li>
+
+<li
+style="text-align:justify;"><strong>mpm_cache:sync_cmd</strong><br/>
+This option takes the command line to execute for the synchronization
+process. A preliminary substitution variable mechanism is available
+but should be improved over time. For the moment, the cache module
+only provides <strong>__FILE__</strong> which will be substituted by
+the full path to the cached file. The synchronization process
+currently assumes local and remote MAPIProxy instances have the same
+storage path (<i>mpm_cache:path</i>).
+
+\code
+ mpm_cache:sync_cmd = /usr/bin/rsync -z mapiproxy at 192.168.102.2:__FILE__ __FILE__
+\endcode
+
+</li>
+
+</ul>
+
+In order to use the cache module, edit smb.conf and add <i>cache</i>
+to <i>dcerpc_mapiproxy:modules</i>.
+
+\code
+ dcerpc_mapiproxy:modules = downgrade,cache
+\endcode
+<br/>
+
+<h4>Notes</h4>
+
+<ul>
+<li style="text-align:justify;">While the cache module implements a
+preliminary <i>session</i> mechanism (multiple clients support), this
+mode is currently only implemented up to 50%. Multiple clients will
+work for files already cached, but will cause unexpected behaviors
+while synchronizing a remote file at the same moment from different
+session. This bug should be fixed when the streaming and lock
+mechanism will be implemented.</li>
+
+<li style="text-align:justify;">The synchronization mechanism is yet
+experimental and we have deliberately changed the storage path
+permissions from 0700 to 0777 for trivial setup. File permissions will
+become parametric smb.conf options in the future.</li>
+
+</ul>
+
+<br/>
+
+
+<a name="server_mode"></a><h2>7. Server Mode</h2>
+
+<a name="server_conf"></a><h3>7.1. 5-Minute Configuration</h3>
+
+This 5-Minute configuration will help you set up a preliminary
+OpenChange server. This configuration will be performed in three
+steps. Before running these commands, make sure you have followed
+<strong>step 1 (Provision Samba)</strong> and <strong>step 2 (Add a
+user account)</strong> in <a href="#minute">MAPIProxy 5-Minute
+configuration section</a>.
+
+<ul>
+
+<li><strong>[1] Provision OpenChange</strong>:<br/>From openchange
+root directory, run under the root account:
+\code
+# ./setup/openchange_provision
+\endcode
+
+This script will extends Samba4 Active Directory with Exchange classes
+and attributes needed to run OpenChange server. Note that this
+operation may require several minutes to complete.
+</li>
+
+<li><strong>[2] Create the Exchange user account</strong>:<br/>
+OpenChange <strong>does not create</strong> the user account the way
+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:
+\code
+# ./setup/openchange_newuser --create <username>
+\endcode
+where username is the user account you want to give access to
+OpenChange server
+</li>
+
+<li><strong>[3] Configure OpenChange server options</strong>:<br/>
+OpenChange server only requires a very limited set of options to be
+added to <i>smb.conf</i> in order to run. Note that the following
+configuration also works with existing MAPIProxy configuration. This
+configuration will turn MAPIProxy into OpenChange server only and no
+remote connection to Exchange server will be made:
+
+\code
+[globals]
+ netbios name = MAPIPROXY
+ workgroup = OPENCHANGE
+ realm = OPENCHANGE.LOCAL
+ server role = domain controller
+
+ ### Configuration required by OpenChange server ###
+ dcerpc endpoint servers = epmapper, mapiproxy
+ dcerpc_mapiproxy:server = true
+ dcerpc_mapiproxy:interfaces = exchange_emsmdb, exchange_nsp, exchange_ds_rfr
+ ### Configuration required by OpenChange server ###
+
+[netlogon]
+ path = /usr/local/samba/var/locks/sysvol/openchange.local/scripts
+ read only = no
+
+[sysvol]
+ path = /usr/local/samba/var/locks/sysvol
+ read only = no
+\endcode
+</li>
+</ul>
+
+<br/><br/>
+<a name="server_overview"></a><h3>7.2. General Overview</h3>
+
+Although <a href="#purpose">section 1.1</a> only describes MAPIProxy
+as a proxy, recent work makes it possible to turn MAPIProxy either into a
+<strong>complete and real stand-alone server</strong> or server/proxy
+hybrid.
+
+MAPIProxy behaviour is controlled through the <i>dcerpc_mapiproxy:server</i>
+parametric option. To use MAPIProxy as an independent server, set
+
+\code
+ dcerpc_mapiproxy:server = true
+\endcode
+
+<ul>
+ <li style="text-align:justify"><strong>dcerpc_mapiproxy:server = true</strong><br/>
+ When this parametric option is set to true, MAPIProxy will not initiate
+ connections to a remote server, but instead will direct client connections to
+ its own default NSPI, RFR and EMSMDB servers and work as a
+ stand-alone server.<br/>
+ </li>
+
+ <li style="text-align:justify"><strong>dcerpc_mapiproxy:server = false</strong><br/>
+ If this option is unset or set to false (default behavior),
+ MAPIProxy will work in proxy mode only and initiates a connection to
+ a remote server using the binding/credentials configuration as
+ specified in <a href="#minute">section 3.1</a> (5-Minute
+ Configuration).
+ </li>
+</ul>
+<br/>
+
+In addition to the server mode described above, MAPIProxy provides an
+additional set of configuration options which makes possible to
+override and customize MAPIProxy behavior. The server mode has been
+designed to supply a modular mechanism somewhat similar to the modules
+one described in <a href="#mod_dev">section 5</a>. While MAPIProxy
+modules are stackable and can be chained, server modules only
+support a single module for a given endpoint:
+<ul>
+
+ <li style="text-align:justify">When dcerpc_mapiproxy:server is set
+ to true, MAPIProxy registers dynamic shared object stored at a
+ specific location (modules/dcerpc_mapiproxy_servers) and load server
+ modules tagged with the <strong>MAPIPROXY_DEFAULT</strong>
+ status. For each of the endpoints MAPIProxy can handle
+ (exchange_nsp, exchange_emsmdb, exchange_ds_rfr), the associated
+ default server will be loaded. These default servers are located
+ within mapiproxy/servers/modules. (Figure 10.)<br/>
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="dcerpc_mapiproxy_server_true.png"/>
+</td>
+</tr>
+</table>
+<center>Figure 10. Server mode enabled</center>
+</li>
+
+ <li style="text-align:justify">When dcerpc_mapiproxy:server is set
+to false, MAPIProxy still registers server dynamic shared objects but
+does not load any of them, which means that ExchangeRPC traffic will be
+relayed to remote server.</li>
+</ul>
+
+However there may be some cases where developers would like to run a
+custom server they have developed, or handle a limited set of
+ExchangeRPC traffic on their own for a given endpoint. This
+configuration is made possible through 3 parametric options:
+
+\code
+ dcerpc_mapiproxy:nspi_server = nspi_server
+ dcerpc_mapiproxy:emsmdb_server = emsmdb_server
+ dcerpc_mapiproxy:rfr_server = exchange_ds_rfr
+\endcode
+
+Each of these options specifies the server module name to be loaded
+for a given endpoint. Note that these options override the
+dcerpc_mapiproxy:server state:
+<ul>
+
+ <li style="text-align:justify">If dcerpc_mapiproxy:server is set to
+ true, specifying one or all of these options will override default
+ servers with your own custom servers. For example Figure 11 shows a
+ mapiproxy configuration where server mode is enabled but where the
+ NSPI server has been replaced with a custom one.
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="dcerpc_mapiproxy_server_true_custom_nspi.png"/>
+</td>
+</tr>
+</table>
+<center>Figure 11. Server mode enabled but custom NSPI server loaded</center>
+</li>
+
+ <li style="text-align:justify">If dcerpc_mapiproxy:server is set to
+false, specifying one or all of these options will force MAPIProxy to
+relay the associated traffic to default or custom server. For example,
+Figure 12 shows a mapiproxy configuration where NSPI traffic is
+handled by OpenChange NSPI server while EMSMDB and RFR traffic is
+relayed to the remote server.
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="dcerpc_mapiproxy_server_false_nspi.png"/>
+</td>
+</tr>
+</table>
+<center>Figure 12. Server mode disabled but NSPI server loaded</center>
+</li> </ul>
+
+<br/>
+
+<a name="faq"></a><h2>8. Frequently Asked Questions</h2>
+<a name="notcompleted"></a><h3>8.1. The action could not be completed</h3>
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mapiproxy_error_001.png"/>
+</td>
+</tr>
+</table>
+<center>Figure 13. Outlook error: The action could not be completed</center>
+
+If you have followed the <a href="#minute">5-Minute Configuration</a>
+instructions and the above error message box (Figure 13) is displayed
+each time you click the <i>Check Name</i> button, then you need to:
+<ul>
+<li>Click on <strong>More Settings</strong></li>
+<li>Open the security Tab</li>
+<li>Tick the <strong>Always prompt for username and password</strong>
+checkbox in the User Configuration section (Figure 14)</li>
+</ul>
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mapiproxy_error_001_fix.png" />
+</td>
+</tr>
+</table>
+<center>Figure 14. Resolution: Always prompt for username and password</center>
+
+Next time you click on <i>Check Name</i>, Outlook will prompt for
+username and password. A similar credentials dialog will be displayed
+each time Outlook is launched.
+
+<br/>
+
+<a name="cantopen"></a><h3>8.2. Profile creation goes fine, but Outlook can't open your default e-mail folders</h3>
+
+The profile was properly created using the mail applet from the
+configuration panel (or using Outlook wizard). However when I launch
+Outlook, I keep having the following error message:
+
+<table style="clear:both; margin: 0.5em auto; width:80%; text-align: center; background-color:#ffffff; border:2px solid #e0e0e0; padding:5px;">
+<tr style="border:none;">
+<td style="border:none;">
+<img src="mapiproxy_error_002.png"/>
+</td>
+</tr>
+</table>
+<center>Figure 15. Outlook error: Unable to Open your default e-mail folders</center>
+
+This probably means Outlook is unable to lookup the resolved name of
+your MAPIProxy/samba4 server. You can either:
+<ul>
+ <li>1. Make your Windows workstation points to a domain name server
+ able to resolve MAPIProxy fully qualified name.</li>
+
+ <li>2. Open \code C:\WINDOWS\system32\etc\drivers\hosts \endcode file and
+ add an entry for mapiproxy. For example if I have
+ mapiproxy.openchange.local pointing at 192.168.102.2, then hosts
+ file should hold the following line:
+ \code
+ 192.168.102.2 mapiproxy.openchange.local mapiproxy
+ \endcode
+ </li>
+</ul>
+
+<br/>
+
+<a name="dc"></a><h3>8.3. Does MAPIProxy need to be domain controller?</h3>
+
+No it doesn't. MAPIProxy works fine as a member server of a Windows
+domain. However, since delegated credentials and forwarded kerberos
+credentials don't yet work, you'll need to force samba to rely on the
+local SAM database. To force this behavior, add to smb.conf within the
+global section:
+
+\code
+ server role = member server
+ aux_methods:member server = sam
+\endcode
+
+<br/>
+
+<a name="gnutls"></a><h3>8.4. Generating Samba's private keys takes infinite time</h3>
+
+For some configuration, the private keys generation process at Samba
+startup can be very long. In case private keys are not generated
+within a couple of minutes, it is suggested to recompile Samba with
+gnutls disabled as in the example below:
+
+\code
+ $ ./configure.developer --enable-debug --disable-gnutls
+ $ gmake idl_full
+ $ gmake
+ $ sudo gmake install
+\endcode
+
+<br/>
+
+<a name="gmake"></a><h3>8.5. On Ubuntu <i>make samba-git</i> exits with <i>gmake: not found</i></h3>
+
+On Ubuntu, I have the following output while trying to install samba4 from OpenChange sources:
+
+\code
+ To build Samba, run /usr/bin/make
+ Step2: Compile Samba4 (IDL)
+ ./script/installsamba4.sh: 332: gmake: not found
+ Step3: Compile Samba4 (Source)
+ ./script/installsamba4.sh: 332: gmake: not found
+ Error in Step3 (error code 127)
+\endcode
+
+gmake is make on Ubuntu. Creating the following symbolic link will fix
+the issue:
+
+\code
+ $ sudo ln -s /usr/bin/make /usr/bin/gmake
+\endcode
+
+*/
Added: trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_false_nspi.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_false_nspi.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_false_nspi.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,116 @@
+PNG
+
+
+IHDR X Ùíüg sBITÛáOà pHYs êe¤ IDATxíÝw\S×ûð'Â!²ÄàÖ¨¨¸q (â®ý"ŪTk£íÐV«Ö
q! *â¸Ø(È=d¯@BB ÷÷Çý~ó£z÷¾âåäÜOÎIî¹,¢ !b*9ÒB!°~X,ÖH§hÏ(ê'·yóf^ïKL>,µ16é ¨½¨oûýfee©¨¨4Û¬íã½ï? áFyæÌ}}ý÷LúdpDøåïիʪU«dƯ¤¤¤¥¥åëëdmm¤¤¤§§·oß> `±XÃ
+³°°°¶¶¦ÿ;|øðA)**Î;·ªªª^õv*{ºÚ;fϨ¨hccSSS û÷ï×ÕÕe³Ù&&&ÞÞÞößµkWF¿T/^bbâ¸qã´µµW¯^-HN8!''túôi999:¢çÍÿZmÞ¼YSSÃátïÞ===½áѨ»G6¯¯/JE"ÆÊ+éãÙôl9%:Tï@É´$3Bè£PèKaiiÙ¹sçððð#G Àüùó)2dÖ^½zõúõë!CDFFîÚµ <x ZZZO<INN¦(
+ :wîFwòÇÔë¡ÞN K.QQQ
+3gÎlß¾ (züøqdddBBËíܹs£ýË¢6ü½QoÈ!tcÇÀÞ½{)rpp044TWWß°aÃëׯàÔ©SÏ?[·nQU\\L§UVVvttLLL¼uëVaaaãQwÿüó Ü»wÏËË BBBèãÙôQm Þ¡ËÊÊ [[Û¬¬¬F}XZ!ô1°~9Ølö¬Y³(¢ÇRôQ6=sæ̺mäååUUUà×_ ;;;Y ¨ÛÉÒ¥KëõP Ì;¢¨ùóç@MMÍÕ«WàÒ¥KEíÛ·ÏÔÔT]]ÍfÓ¯ºö_·Öû½QÍfÏ=»^øøx àp8tµ?~ü#Ö¯_o``PSSS/íÞ½{ÍÍÍÔðhÔÝcmm±±ñ²eËlmmû÷ïßÂ(ó¦Fý½7z è/µ$3Bècà{_¾}ûDDDÈ6ZZZ>}úôÑ£G;vd±X¹¹¹ìСC||üرc·mÛÆápêöF÷Y¯¾}ûÖÛ/ý·&{¢( ضm[ß¾}:´eËFûob×ôFY<KKË/^GDD
T*uqqéÑ£Gii©««ë¹sçÖ¬YcggðÍ7ßÐa²³³UTT´µµÀÄÄäæÍ
£G¾zõjãQwrrr{öì©®®Þ³g,C³Ö¯_¿z[D"Qã?¹w(Z3#>éJ>ÐÐÐ=z())9::ÂÿÆqqqcÆQTTìСÃ+Wèwé¬%
+ F1dÈcgg'
+ëõPo§²§Ó#B¢èáÅ)Ú´iJ>}Æÿ«õú:#Âz_ªÛ?ý½XYYq8MMMggg±X¼cÇ
ðððëׯÀÙ³gkjj ))©^B¢&O¬ªªÊf³ÜðhÔk%''§¨¨(\mö ʼװÑE©%BEáõ¨5þüK.µ}ÿd×b±xæÌ"èñãÇÓB9ðS£èý(Õ±qãFÒqêSRRJHHÍd"P³ð=Bô/ÍÎÄÆÆÊkjj~Âþ?ÉäÎp ÞN"b4E!ÄhXB1Â/Óg´dsûÚþ~/õûBè}áeÐá¢ÛïÒÂMk%¼BG_\t»ÙE·Y,ÖСC---UTTd+V×[ÕºõÔ{"4¹$wk/á]¯«zGæÖ[
+O HKK0`@Ý£Ñè¬áAl...ônv5ðý4<µ:ó£OÝnvÑmz
+ÒÖÖ¦7Ö[ÕºõÔ{"ÕäܽwîêYº?ÊFÆ»~dõYXXèéé
>|>>ͮް°Ñs ¡Ö
ðËnSÍ-º-Këàà {XoUë&ÖSïMÞÖ^»aWõLáѣÑè¬a³'[³«7ì§álô@¨µá{_\t»ÙE·eiY,l§õVµn:a]õøÃ?4qx[{ ïz]YYYÕ;2Ðàdhôh4ú#kجáÉÖÕÀëõÓð ¶üà#ô)®ÄèÁE·]t»aZªÁªÖM$¬§Þ©æänÕ%¼ëuµdÉzG¦áÉÐèÑhbùïºÍèMYYyùòå °hÑ¢fWoØOÃØè9PkÃBþå]Û ÿO²kH4iÒ$++«î¡µÀ!66666¶¬¬~3oÏ=¤[<øüÔ(z?L^t»ïm)55uܸqÚÚÚ;wîtuu]»vm½x¬Ðg×Eï<¤ijjêèèÓÆü½¿/<Vè3
!£áÔ(B!FÃBBÑ°"b4,!
+!B!FÃBBÑ°"b4,!
+!B!FÃBBÑ°"b4,!
+!B!FÃBBÑ°"b4,!
+!B!FÃBBÑ°"b4,!Y
ðîÝ»\.7>>þÕ«W\.7((¨ ËåzzzÀ¨Q£öíÛ ööö7no¿ývÉ% ðÛo¿M0 x<Ëåóù·nÝâr¹IIIQQQ\.÷Ñ£G¹¹¹\.×ËË ¸\î ÀÎÎnÓ¦M àââ²lÙ2 عsçäÉàäÉ\.W ܸqËå&''s¹Ü'Oäääp¹\ooïÚÚZ.{øða °µµÝ²e 8;;;::
+ ;vËåD¢ëׯs¹Ü´´´.ûüùóÌÌL.ëëë+H¸\î#G `Æ?ýô 899999ÀO?ý4cÆ 8räËH$¾¾¾\.733óùóç\.7$$$--Ëå^¿~]$q¹ÜcÇ 8:::;;À-[lmmàðáÃ\.·¶¶ÖÛÛËåæää<yòËå'''s¹Ü7n.{òäI <yòÎ;`Ù²e... °iÓ&;;; 8pà Ë ///.ûèÑ#.ÄåroݺÅçó¹\.Ç &üöÛo °dÉo¿ý 6nÜhoo ûöí5j xzzr¹Ü .ûêÕ«øøx.{÷îݲ²2.{æÌ °¶¶Þ½{7 ,\¸pݺu °~ýúùóçÀ={Æ çÏçr¹ÅÅÅ\.766666Ëås¹ÜóçÏÀ1cöìÙ óçÏ_¿~= ¬[·náÂ
°{÷nkkk 8sæË-++Ãsµ
+ÎUhlÒÚNJJÊÔ©S;ëDÄ%ÕÔÔðÂØäôJ©<_ LLÏ
+©ÓßæGÆ+¨GÆäTVò#c2róË+Á1o2søá³q¯SÒùax\¨ª/¾zZ*®å iYÁ1|05;782¦¸_[X\UUWPVQùÿ]E¿Kͤ»ªäóù᫤ÔÂJ1_ LHÏzËS²s#cJÊ+²ò#còJjjjèT¥üÊàÈì\¾@ø4:6.5/½N,+-å/SrJ+øa|j¦VT¬,UIyEfnApdL~q) GÆdæWGƤfçòÂ'Q±ñ©|046¡¨ /¾LJÕ,,åq©jÑÿª_OwÅf³#c²òé®Rþ×UBz_ IÈ}ãÕ:tàq©JÚ¯ùáÌàȲÊ̼ÿ¦R#c²óËù²TÁ1 iY|0$&>+3/F%$+)+óÂ×)érêÚ²®Ê+tªÂÒ²*482&;¿°¨´<82&ým^
@Å_¼OOMçñoØl6}VHÔÿ¿«
+Aú[º«ò|pdLN~QaiypdLZN*)#/¾xFw |0&9M,¯È2²é³"-'î
+ØÁ1oKÿ*¿¼âÿO°ç/ãâÓù!«w®~»~ãý{³²²
+
+ ÿmB¤±("¡¹¬ûnìøÎ",*<ìÉ£'ÖÔÔ$Æ B Á1¤# Ú«AýIG@ä1è=Ây3¦Üñ÷#!DÞ«WæÍK:"A
PQQ±G¯ÞZZ¤ ÈÓÒÖîÑ«7Ã!S£!æ©Q¾}ûví
+ÇÇA¤ Ⱥwwí
+ÇÂÂBÒAy*R©T ¨¬©©!!D^MD ¨J¥¤ òpj!Ä\85Q#Âß~Þúty!ÏüöóÖÒAy*B¡ðyðãÜÒABä½ÍÎ~üX$ÈéQsáÔ(FKJJN=µ!1/£O=ÂçóIAä1¨u?K:B¼¸WgÝc!DÀ¨©Q©Tzïi(ÃQPP !DD"©®®2z8Å"Æ ¡@ xx?'+tyÙï
BÒAy*»wüB:B¼ÐçÏvïø¹´´tD¦F«««/^ó×ÑÕí ·CéÊËÊ
+ÙÍÄ÷JFµµµ¥%%b±ty"QUiI .±Q
ðíÛ·ß}³"øaé !òÜÿî¸è6 6é m§K.»÷63ïN:B¼Ñ㬻ëèèÈcÐPAAÁØÌL½CÒABäihh±Ù waP!ÌÌÌ\8kúÝ[7HAwóúÕ
³¦çååÈwss#¡ÈËË(åÀÁÚ;Î"LQQÑÌÜ|ÚäItD. (êQøK%'Ç q0B¨QR©¢¨qCÈcPIHMMµ6ðé !ò¼==¬
+ÌÎÎ&Ç B¨©©¹`é²î={"¯g>.SWW'Ç ©QÀû"þ
+ïGQ#¹6nù]#!D¯Ï\I¹¹¹¤ òTúö·è×Ï" tttûö·À"À©QáÔ(FÂé3|5vüDÒYÚ£6®/)."}iLL7ý¼tFÞ½íëu1ðþ=]]]ÒYaZ^¢(D"%¤JOyÃçóÍÍÍIA_øøxE
vúGF*J$æP4"mÒÒ93xõêUÒAÐcôèÑb±ø¯ã<ÒAÞ §F0êÃ2ùùù;·þöâ9é !ò^<
+Þ¹õÇÒAyítÖ¢5TUU
<<l8é !òòÞ¾
+y.Hiï|}Oòù|Ò)>¢¢b·nÝ
+³i¶%
+¡_À#Ò)BíÂìyógϯ¯¯O:H»væ̾.]ºòÞ¤R©··×¢E[ÒA
°¤¤äÄC£¬Æöµ°$!DXLtÔó§ÁíÕÐÐ ¥:{ö¯êêê>¿uÉ¥RéÉÇõô:ôì9´%íôaii©Ï=1!tyq±1<÷
+ÒAÚ©³gÿÅoÔÖVæpZ:ÒcÐÐÌÌìÞÓPÒABäÍ]°h½é íÑÙ³D¢òÞ>
+£F÷oùgf¤"/#-õþ-¡PH:H»sîÜþÏ·
+º»ÐÒRz¯**
{~ÛJ:E555¤S Ô^¼ØóÛÎÒÒRÒAÚsçö
ÂÏ·
+jj***¾÷´¦F»vízÎû¶NGÒAÈP×ÐpZ<Êô³íç+«¨a63m§§G:H;rþü¡P8hÐ ÒAÞÛÇTA`Ô°¦¦¦° ¿©3!ÓgÙ=¸ßaæÔçNÀqÐÑÑÙ¾};ý¸W¯^ôÀÀÀ#F3fèСÿüó tîÜyܸq¸ÿ> ´ñmÕÕÕ3f̨ý
ôÚÛòrR©ÔÖÖ¶ººt/P ,,Èÿ°Såtþü@ð9WA¥«À¨annîÕή6ÏqhÑ%_Û¹óÎóÜËJKÜáoñ×ï5:TWW÷÷÷ÿþûïëÞÔ{Í5< _VÓ³Ljjj>LOO7oÞ¤I>,ªT*ké«´º/^¼8sæLyyùÛo»"''7cÆGGGÒY¾@ìßë`;ÍÐÐtòJJâââ´´´>|H:Ë{ËÌÌÐÐPTTüðrÆ BØ¥K=ÿ11íF:1Kïû *øü÷-òòòNNNGýád555ïÝ»7kÖ¬:hiiɶ5ìä÷ß÷ññÑÐа²²úú믫ªª(:~üx¿~ý ÀÌÌlòäɯ^½:tè1cæÎ+Hàëëûí·ß¾«ñ£GèÏ_¾|ùøñã Z·óþùîÝ»>>>7oÞ<{ölRRT*åp8rrrE¹¸¸<~üxÅêêêçÏÏÏÏwssspp ÃwëÖmÊ)tuëÖÅÄÄ8::*))õïß? ))©ÞNéuÕíA ÈÅÎ;é¯ÚØؼ|ù²ººúÌ3½{÷>}úòå˱¶1ã'éà
+J @"véÖÍtö1Uµè¶D"¹ìG[»£ZMÛ(/+ó<Û.Ö®õ»â-é;Å¢(ªÆâ¯o^½2hÐ &Ý677ýúõ#?>`À HOOßµkWpp°Úßÿ=lØ0ssóäääèèè5kÖÓÿubffª££#J§M¶{÷¥-_¾<(( tuuú÷ï»eË?????¿ &ËúïÙ³gbb" L:µ^û?ÿü399ùåËAAAªªª&Lpss³²²
+(uuu#""´µµ¥¬¬\TT4~üøW¯^Ñ×m`mm½{÷îáÃN>½°°°áNëú=TWWË@GGÇßßÄ!!![¶l =z$%%}~ÛkÏnóùåe¥¥ógÚ°Ù¼K~~®Ï±Ï´Þ¸qGCÍb±~ÉÉi©iïf{`йd-©Ñ
+>ÿâ¹3m¼Ó&ÈκòËË/á)¶àVÝK,qwwm111¡G`ÑÑÑãÆJ¥û÷ïoØÃéÓ§7nÜ(.]ëêêJo}]MM.lýúõ+,,,((8wîܶmÛfÌÑDãvîââb``ð×_©ªª@JJ ȦU;tè`ddD?¾råÊñãÇåååþÿu @ZZÚðáÃ`Ø°a***î´º=Ô=666 ¤¤4bÄ >|xFFF£ßúTnû]?²ïج,E*ººº¶üd1ØÇ×ý°yÖÜy¤öNKsùÏÒºÃAM-í¥N¶sç9-´oI«V²²²]Ô£G èÒ¥ý¹ú=Âw=}Ø°acǽ{÷>tèPïÞ½@"Ð
+ê¾½·xñâ#Gdgg0 ÙÆ4ssóììlCCÃí×®]»{÷î£GÚÚÚêêêvëÖíéÓ§£F
+È꾢ܾ}ûË/E"QÝB[ï%§±±qXXØСCÃÃÃé²×hȺêöP÷P¤¤¤ H$
+
+
+6lXxx8]/srrLMMßu0ÑÇ<lø-?ÕÏGÅ B¨®®>mæ,yrÓ r,ñIsî'(¢K ¦][ÞªªªÝÁéÿþþûï G"8p Ù§Ï;W(ÅâÕ«WÏ=ÛÅÅE(ÊËË;ÖÍÍ^ãEuíÚõ·ß~ãÇ7Ý6oÞ¼7o:;;×konnÎáp¾ùæ^½z}ýõ×þþþGqrr EEÅû÷ï×ûl½½ý¸q㬦¦ö®ïåСCË/WVVîÓ§½^eC6<ô
+
+3gÎlØ°A,>} nÞ¼){}ZfæÝMLUðR"Ĩ÷SRRÌÍÍLfgf.²ñݦ-vÚx×u%ƽ^ùÕ¢º£Àº%ð˸1ouuõ9süüüZþ¡Ó&HèOè
mØ°áñãÇÙa½÷S¥RéìÙ³½½½ßëJ»Òß#ôò8wdÿÞ,¿G¨¢¢Íbq(Jú û¯ª¦¥%´Ê¡Æ÷ߦ¦æ¢e=z5P¾T§OÕÒÖ^üõò÷~F8¿¿Ûì+$$äǤ(J"=z´ÞWKJJæÌ#ûï¤I¶nÝú^ýËÉÉùùù} ¨1½ûö[´ÌQ½Í?:×þÕÖR,XEEéö©¤¤ò)+ë§Å BرcÇUk]I§ ¦¨ `ð°;ÿÜÇá|%°í=úÉ'ïúª¶¶öû^Uw8ZÅÀAá=0jeôôôÙÇßò»F:::Í[´« B´ëW¼gOK:"A
PYYyàà!:ºHA§ÛIoàà!_ê{è½0hjTOOoû®?I§@µ#Æ´£M:"A#ÂU_/yptywnúzIAAé <ÿ«±Ø"jH^¡¡ûaÏJkËÊ>×*ÇÎxNj&N6qê´NðCM©))ùò?OÄ ©Ñüü|·ÍC?#!DÞ³àÇn7ÈcP!¬ªªzYTøyÕBª° ÿed¤X,&Ç ©Q«wI§h×rss?÷%ÖP»RRRBßë£5wÞ¬¹óºtéB:"A
°¸¸øèÁýVÖÖý,ÎÒN
Ô]¡7dÈÒ÷22âYðcCûqqÄ BXVVvñÜi½.±6jóÎß««q}b**ítD÷úâ¹Óþ¶a=µµ >åZ£í
+¡Yàóp·ajçúôkü·}æ-Z2Çaé íX\õæM"§wê~/55Ü¡³`PU¨¨¨¸éwÍbÀ@3ó KM~ûêå°~=¸å$3ÉË×öêeN:EbЧFÿÚõktd8é !ò"BCþÚõkYYé <.\½¡¥
K"`íìcÆvîÜtDF$'+SPYI:B¼ÊʬÌÒAy*¹¹¹?¬]ý4ø!é !òþ°vuQQé <MvéÒeßãF&&¤ È7aywÒAy²ÙlÝNzÊ**¤ ÈSVQÖí¤'//O:"A
0++ë«y³îÜ"!DÞí~_ÍO:"AS£ººº·mïgËÊ `Èð·m×ÒÒ"Ǥ3|ÊÊÊrrM
+pÕÕÕ'MÆVPh³H¡vËØÔÌÀ°«
+¾W Ø_̪
+=zôh¢AjjêäÑÃ]7mã°°ÍR!Ú§+<ìßehhH:"
+ Ã
+4ié$.""âÎ;Í6ÓÒÒZ긢Wï¾m !ÔÎõéשã
+uuuÒAyl 9r䯿þJ:É;zôhK
+¡¶¶öÕkÚ B¨ýë?``ÿñÖõ©ÑôôtÛcý¯ù"ï·íıoß¾%Ç B¨¢¢2tÄH½ÎxCjtÖ×:b¤îºÞ
AOtêÔé§_wNjF²1ÊJ[WáGL*ÙÙÙ+.\ôÕ×Ö¦ÎÒ®ÍdmdjJ?výa³y÷ÆL6cÍ àøáþ×|o>ÐG±ªÅbÛÙ¼cGmFwÈVMMÍñ/e±XôF¢ÁV~3zµ,Ï¥ö7óäCQá.ñÄq IDAT[¸ì?Á¶îü5 úòÜ»uÓû¢ÇãA:u"Æ BÈb±8®¨ÔeC'xu·¨©©§¥$SÅb±ãã444éíþÜuèÄ)-í PÁç_ö8×h3Yä¯]¿^¾pnþe²e¥¥ß._V·^¹èY¯J¥Ò>¸çyÕ N9|Þç ±ðIúɳå9Å"Ç Bh``päÔYÒ)>Wý,ľcÉõé׿ /Þ¨¦®úüÙèqÖªªjê:¼«ë×UNó,m*Uë\ÌzóoaAÁÚÃGZüõòù¶6CGLyd3Ã6ðîbGço¬'M9~ø`A^þÚ ÷6~~í^PVFÆ¿l§¤[AaÿÑM/³kÂä©&OÕÕÕ%Ç BÿÓÆõ3ìæ9tvJ(¤ë
+ üºw 0aÊÔë>Þ 0sÎÜ÷é¯nÿíÓî§O)«¨|·i˻եޡX$íE"¤&¿qÛõ§¬ÁôÙs<N
+I
ÁfæÝÅb±íÜyåeeë[Oâ¼fÝÃ{t³%sle `ß®_V®^k1pP£ãHhO?¼sÃïÊåK;v$Æ B(âbcFK:H{×pj MÍ23Ò¤R©i7sÙÆÎúúßoý âwïøù]Íꪬ¨PRV®»ìÌÌ_ÚÌ=æ]aÌÌ»À£Àû~W¼åäåËËÊÎÿ6;Ûbà À*PRTS]]M:H{Q]-©ªNñ!jjj?²1¨_¹ÝȵÐÔ³¤ÒÚº[²22º@GÚÚÚw5©©©9zð¯I6ÓënTïС²¢¢î¢dååþû.ïØ?§/ùTWW/sÓtN}CÃQý-â5aæûsì»tÁë©þ+4ôU@ÀsÒ)>DYYéر}>¦Ââââ#û÷?±?Þ¢Iu§F\ÖXH?8Õ¦^Ëó¼éil
ÚµßoÚûÛÎFѲXr5Éñã/m¤(JTUõëºíõÃZîè1vdÇM´v¥cÏÞ}½£äú·þ±Ó
+ 8
+ýï¢ÆEG?}ôÐâïC¸¸Ë(ÔNñ!ÂÂ"?² ¸ººîß¿ÿãÓ°X¬ùóç_ºt©Þãpssëׯ½½ýì÷èÑ£...Í.ºbnnNdÑíìÌÌEv3¾Û´¥î_vA^ç°èvxxxppðªU«hëãs¬[7ã6ö ݸqGCÝè¶ön¶Öz±õÏ?ÿ´¼ý;|||Z)[·nâíæa)BÃâ¥Ã¢¿ì* C¹xñ¢©©éþýû
B!é8íÔG¤¤¤ñãÇ+))iiiùúþk
+Ï®]»º¸¸Ðm¬ôôôöíÛ ,kèС***²- àååÕª×ô_õöJM~Óz»@}.¯z{UVVÒê¶oß¿~ýz,ú¨B¸xñâèèè;wî<~ü¸W¯^ïjóæÍçÏ÷Ýwßÿýà ;;ûÌ3½{÷þý÷ß ++ lmm館¨èà»^FE´Þ.BÈ°Ðî*kîCÈ_éÓ§< °6ê£>,mcc3nܸ¦ÛPeee%JàéÓ§ 0jÔ¨GFF =;¡¬¬ÜªÓFFF¯ßÔÔÔj½]¼ìʹ²ÒÒ¶ß;B¨¡Ñc-/,,$¥Õ_¿~ñâÅôç±×¯_¿k×®Í7;;;«4÷é3&ø¨BhiiùôéÓGuìØñ]³¹¹¹ìСC||üرc·mÛÆf³á3¢4
ÂÂÂÜÜÜþ4sÿþýYe±XÐæ*ÕÖÔ À±Ã>ÐÆ»F5Át¶Äb±(¢Ç$
ëׯÿå_|}}Ì0ÁGÂóçϯZµjÊ)§On´Í
¾ùæ¥K²X,iÓ¦5Ú쫯¾:sæÌСC³³³?,D"i¶Í/P#´º ºú¢¯þCdסz^EG½x¼iÓ¦:ÎÒêÊÊÊöíÛG@ J¥½{÷vss3¦ñµ,å£
+aïÞ½=z$ûoÝë e{öìT÷Y²/]ºtIv}
»»»»»ûÇIHHhúòªªªç<»ëvÒû}µ+Ê%Nm¿kPCùy¹9YY«¾^¢¨¨H:K«[µj]éسgO777{{{¼ÊÆ êååå545pÒ#¥¨¨¤¡©ÉJÉãýwÑD,bбÈÊÊúÏû»·IAw÷æÿ,°ÏÏÏ'¤Õýþûï¤O>^^^±±±XëaаS§N?nßÙ·¿é !òqGªwØ©¥Eàcäm)33344ÔËËGM`P!TUU;aÃ!!D¡q§Î]^xì J#""ðþÃMcд´41ÜW[w!7ÐgÁ×ë¢ÍîÛ·oIi]&&&XÅ B¨¥¥µl
s¯>ýHA××ÂbÙ
+g&\;Å ©Qmmíå«VNjúYèg1 !FÓÒÒ¦[¾qõ
+é !ò|/_n=úE-Á B¨ªª:j̸.¤ È3045fé <MvêÔiË_I§@µÃG>r¶¶6é <³³³/r¼wty÷nù/_äÀêQ³TåääTUÕ8
+x!BØlUU5¼Æ£¦FõõõäNjÆO2~ò]]]ÒAyz5·uë§Á¤ È{òèÁÖ
+®ÅÅŤ òTÅbñ¤¼G<B JKJÞ$%´ä>¦èÇÄÄDÙ}?G-ifll|ù~R! 0ÓnîL»¹;w&ÇÛ·oß¾ýåߨ¨¨èÐÞ?ÆMd1pé,!¢ÂÃõÿçoMMMÒYaìçÏÎði5Ý ¼¼ÜçâC##,¡¤xöÿ¹!b1t6Ò[·Ç¯H§@µó|5ÉW¤ òôaòòroOä¤DÒABä%ÆÇy{zTVVÈcP!,**:¼ïÏWѤ È?¼ïϲ²2ÒAyº ÞØØØÛÿ®ºÞu!3ìæ0©K.¤ ò4"ÅI ñx!B ÊJâ«««IAä1¨æååmýWA <yôpë÷¸²`ÔÔ(½Ö¨¡a3WY `üä)=ûôÁµF0jDHß} @:B<¼ûaÐI@ß0è>®²Âû¢ÿÇ ©ÑN:mÝù[ï¾ýHA7|ähM--¼C=FBUUU®Õ%%%ÒABäéhëtÄ?556ÃÚÊÿ/é !ò®^öamõöí[ÒAy*ÚÚÚË¿Yݧé !òúYX.ÿfu¸ÂbÒÔ¨Ö2'gÒ)BíB_˾X0jDf3ëçëC:B¼+^mÆpqj£
+¡ÚØ »"¯«ñØ IAä1hjTWW÷Çí;I§@µÃ¸#qGjiiÈcP!ÌÊÊúzþÜ¥N¦ØÎÒ~ÍdmdjZYQ1oѳd[ @¯s;k´Ï¥ö7»GEE/Xº,>66:"lá²ÿ?¢;G¨mÜñ÷»tþì³'Ázzz¤³ ÂTåååµ´µ9¤´kÊ**NðBÁÊ%é"GoiºÌu¡T*mt «÷<¯úÀÉ#Ïû\1ÖZãÛAè]´´µq5*úúúû$âó {ï¤a×|
+Ö®t>r¯ÏÐ#SÞ$ÙÌ°
+¼{§¤¤ØÑùëIS àøáyùkW:@ÞÛúAfzúµ{AYü²Rl
ýGOà)ÔzÆM<nâd\t£
+a^^Þß±3o¤ÕÒYÚ¯*¡pÍÿ$'%îؽW¶
®Uã&L3a£mhÓgÏñ8}>^:vÃ3óîb±Øvî¼ò²²uÎËéBè¼fÝÃ{t³%sle `ß®_V®^k1pл}*Ánú]½~ÅGGGtD
+auuuFjjetvMYEåðÉÓ1/£<ÏðqGÂ;¦Fëµi´3óî ð(ð¾ßo9yùò²²f÷þ6;Ûbà À*Z_ZSSC:"A
ÐÈÈèâõ¤S|ú[
+«ÒSSL̺½W¢èòròôÞ±N_ò©®®^æ0§ÙýêƼêo9G¨µMe7}]çÎIAä1èoMQQÑ?v½ äó0Ón¯×Å÷m3|ä¨Öº\½|I¶eÜÄIkW:<rHYE¥Ù®ÿqë±V;.[ï²R*~XrZ"2,ôÀ»ÊZ0Q¾x,ÙKø/^jjj=Ö~¿ÉÎaAÛï}í
+G òçå¶ß5B¨¡ËÎ=¸?==ÝÐÐtòòós}|uëfL:ȸqãÅb5üÓ6SÓÞÍöÀ ¡ÙÐ("U!ÔÞ8,þêAhª`XXéí
+aYYÙ¥ógß$&"/1îõ¥óg+**Hiu%%%Cõ÷÷gÎüßûbP!,..þçÀ¾Q¤ ÈøçÀ¾òòrÒAZÝ)SfÎÉÀrÈbµ¨Æ1èS£ÆÆÆWnßWSS'!Díûñ§téÒ
t¶°}ûö©S§FDDÌ9sÐ A;vì>}z½7ÕÒÒ2
+I%ü@CC£ÞF¢D"¶Q÷ôÀ B(^ǼêÞ£§é,!Â
+SÞ$ÙÅPL2eøðá¡¡¡EEGG7Z»w79r,Ù&$$45õ_P%(nØ°³
Wa1¨æççÿüÃ×Mçt%S
+ìßÛ|;PëKÏNNTWgÄ,¡¡aHH Ð&Õ+ PS#ÉÉyC8å
+ÑÐøÿZFWAW×-½é
+¡ÁÞ9}RJKJ¼<ÎÚ;B¨¡'N@]###·mÛÖ»wo5µæ/óý,PTWs\]·¼ÇA
Åb)((ÈýoÅ6và¸;ý"UR\TÿÕ<;C:K[ظqãþýûéÇrrrR©tôèÑnnn&L üü\¢é>
+êj
uëÜ
+MÞë*ÙÙÙ+.tÝ´yöß;.P»x÷Îý{§ÏbÂ¥ùùùG EQÔÈ#e%ðAWÁµkݺv5yßç2¨êééýüÛî}ú"oĨÑut´µµIi{öìD 0jÔ¨/¯ EDÂ^»v»É<A
PYYyÈpnKV¼D}ñôºèkhj)))Òêèá`ÝÐ/X,¿nÝv##Ó{:
+azzºíı¤¦FBíÊuËGöïÍÊúò§F=zäçç×t TTTªªªMNþ,ß)TQQ[¿þ.]>üZt»´´ôÇÜàâì(B(.6&24dï®_rùj
+! GÆjG¬õ'Ç 2¦¦¦N5ìúoÒABäù\¼0yÔ°ÒAy*êêê¦Í026!!DÙ¤i3TðÓs§FBLS£5"ÌÊÊújÞìû·o"ïöë_ÍO:"A
ÍfëvÒSQU%!D²n'=yy2k.¢v§FBÌ
S£5"ÌÍÍݸÆåÙãG¤ È{¸qKQQé <BD]YYI:B¼ÊÊÜìÒAy85b.EÀ¨aaaá¾ß'!D^xè}¿ÿRVVF:"A
°¢¢âÖëéi©¤ ÈKKN¾uãº@ S£!æ©Qyå%ÆÇ"/þu¬çY^EEé <Ââââc¼yI:B¼WQÇ(//'Ç ©ÑÚÚZÿ Ç*ªjL¸'5B¨i¢ª*¡P0cü\\1hDXUU^TP@:B¼ü¼¨p±XL:"A
0??ÇæB_<%!DÞó'Á;6ÿPRRB:"AS£"è¬×ÎúúÚuHgAV\Tû
ó8é,0B¡TsrrV}½äaà}ÒABäܹ½êë%ø¡À& íèéé¹íÚÓ£WoÒABäqÆèvÒÓÖÖ&Ç B¨¬¬l9hªªé !ò:uÒSUUUTT$Ç ©Ñôôt»)nݸF:B¼ëW¼í¦LÈÍÍ%'ïææF:CãªÒQGtaòòò]fØLÅA!bÐån#þ
+ÝFÀ¨©ÑÔÔÔ Ü!×|."ÏÛÓcwHNNé <Buuõ鶳MLÍHAgjn>Ýv¶ªª*é <E1N"`Ô033s±ÝÌ{·n"ïßµÅv3óòòHAä1¨*((t5RSÃëB ¦¦nÐÕÍfеÔè]pj!Ä\85Q#ÂÜÜÜ
+«<z@:B¼÷7¬v.**"Ç BXSSSX/ªª"!D^PXX_[[K:"§FBÌ
S£5",,,Üóë¨ð0ÒABä
½x¾ç×¥¥¥¤ òT+++ïß¹N:B¼Ìô´ûwn
BÒAy85b.EÀ¨aiiéyÞÉĸפ È9Ï;YQQA:"A
°¤¤ääïc_"/&:êäÃååå¤ ò45Z[[{ëáSe¼ýBH,W
ÓGËÉ1h<Å 3 ªª*ìųü<¼!5BòÞæ½x&HAä1¨æççÿ²msxÈsÒABä½xúämKJJHAä1hjT,÷¾Ú©s-mmÒYBæçå0ÃáÎcТ¨êêj©WTB´VZ]]Í j
+aNNÎêåË"/ðÞÕËÈcн¸:wîüË¿Ì{ô$!DÞÈ1c;ëëwìØtD
+¡¢¢b~ýÕÔÔIA×QGGII ß DÀ¨©Ñ¹6nû_'!DÞ
+ß+sm&åæâõTäÝÜÜHgh#rrrÕµ
+騣C:B06ÛÈÄtúÔ)¸ÂbÐån#þ
+ÝFÀ¨©ÑqC\½|ty/7t at vv6é <B
+
+
+»yóÍÌ»"ϼG/»yóÕÔÔHAäáÔ(B¹pj£FgM¿{óé !òü¯ù.5=//tD
+!Ã163Sï A:B<
+MMc33ÒAyº|BMMMNY-äùScÓ
+>ßóÜií9ÎÇ8^ç.îÿü-ªªêjlâåqîmvV·î=nù]{Õ§_ÿÇAî<$2,ôƵ+ý,¤¥$_ñò465+//»xîLG]6}Æý¸¢b'½Î'ª®w52¾xîLÞÛnÝ{ø_ó}Ý»oÿ÷?´48"4Äÿ¯ÅÉI¾/vëVRR|éüYÝNXrrgÝO())éèv:ùÏáaW#ϳ¼ü<3óî7|}âcczõí÷àþݧZòÜÿúUËAâ}/_23ï^RTxÉãl§Îs§N(«¨hwÔq?úwmmA×®Îð
+òͺ_¿â׫OßÀ{w?¶00ôù³~W÷úª·y
ù^ç:wéR[[{wRUMMSKÛýèß%Õ7ìêÁs/.*4íf~ÍÛëMbBÏÞ}ïÞ~ñ4¸ÿ!ÏÜò»6pÈиW×|.wïÕ+?7×ëÂùÎúú5ÉùÓîjêê§ }Ãs§Nuó½|1åͽzß¿}3ôù³þ?y|ûÆõÁÃǾ¾æs¹gï>osr.{×74ÄgNuÐÐPSWçÿÅbu108{ò8¿¼ÜØÔì×ÅôÔî={Ý»åò¢
å³ÇîÞô4tXLtÔõ+Þ½úôÍÉÊô¾èaØÕHTUåq榦*ïÄQyyùÎúú¼ãÿTVVú\¼Ú½g¯;þ~á¡}û[>}üðþí{áçëÓ»_¿ÌôtKºÎò4µ´N8Æf³;wÑ?uìHPhdlrÙó|VFy·ü®½èÓß"øaPàÝÛ÷»êÓ·¿EzZªÏ%O<W[ï\d3}âÔi½ºþËÈcÐ ÒRé_|{FzP(ðà¹ÇÅÆ Çi÷ÐçÏ à·WÐý» pïÿ
+_ xüèÒù3 åÁs¯SßxðÜKKóór=xîYéÊJ{|l, xðÜÃC^ ïåîÀ½þ7¯]§zyèÈp{µDò&Éç^VZëÁsÏÎ̬àó=xî qu»ºréâ£À ¸ãïwÓï <yôð²çy óà¹×ÔÔ¼ILð๽ÍÉñ๿ÍÎâóË=xîI ñÒÚZ{dX( x{z?Û7®ß¾q z{z @dX¨Ï]Z[ïÁsçóËßfgyðÜßæäyðÜß$&ÔÔÔxðÜ#Ãà à²çù'ÀM¿kwüý àQ`ÀK <ä
Ï â<xî|~vf¦Ï=?7·¬´Ôçò&©Z"ñà¹GGǹ§tW×®Þ»é îû^þWWñ±±<wAeeVfºÏ=?/·´¤Øçü¦Z,öà¹ÇDGÀ¥óg?¾>÷nù@Ðý»×¼½ ôù3Óî ãÁs
+éi<÷üâ¢B{ZJ²H$òà¹Ç¾Kçμx ~¾Þwo@àÝ;×½/@ÈÓ'gOÀë<wQUUFZϽ¨ ¨ Àç&ªªò๿y gO<} ×½/Þ½ woûùzÀ'ÁÎØÑ<wHçj«Ñõaêêj%%% DrrrUUU
+
+
+
+
+
+B¡Ífs8ªª*999EEE±XLQRuuuMMD"H$ÊÊʵµµvÅápØlvîèûÒ]ÕÖÖ*++7ì¢(±XÜò®Äb±T*u¥¢¢"ûe]±X,H$ëþNÛ¦+ÙA£»RVVJ¥õºÿªª*yyyÓò®dÇ¿^W²&X,ý£¬×ìø·^Wqá¹ú »jû?A¨}bV!D!êaÖÔ(B!TBB
!£a!D!ÄhXB1BB
!£a!D!ÄhXB1t BXRRÒÖ[}||V®\Éb±èÇoáRb¹¹¹ß}÷D"a³Û®Lxzzòx< HKK[½zõ9sÚ`¿¸ÄB}¢££X·õë×/66öÞÚòòò
+
+ß¼ycjj
+ ÞÞÞ!!!{÷îm]ãÔ(jS/_¾7oÅ6lXÝíûöíc±X«Vâóù²kÖ¬3fì¿IIIôs¿þúk++«¨¨¨zÛ£¢¢mÓJêîZ ´ä)ÑÑÑ,«¦¦¦õR!T}ÖÅÆÆnݺUAAaÃ
+)))ýúõ[ºt)}*¾~ýzÖ¬Y®®®ööö?ýôìçÏ>}º¡¡!ÇÝ»w/Y²díÚµ&Mzúô) ¤¥¥
+2Åb>}ºnK 4h££ãÚµkY,Ö5k **jöìÙk×®1cF\\\Ýb±¸¶¶633þ¯ÝÖ[éÇ
+%Ûïßÿ=zôh¥££sìØ1 عsg=}â¸qãþ»o
+¡¶EW&ccãÒ[ª««G]ïl
+
ôù_ï¹¢(×·oßÛßÕ¦U¿zwÑ¡CióçÏ2eì÷ë_~5 ¶) IDAT±±±yóæÍwß}GoJ¥=zô¸}û6EQb±ØÖÖVöt???¢.^¼¨§§GQÔùóçkkk)º{÷n÷îÝëînyáºeMM¾¾~@@ EQ¢÷.J»uëFQÔ+WFY/ó¦M8ΤIþúë¯äädY¼FEï÷æÍô.455³²²(òóó;{ölHÃBÚ}8p`Ú´iô³gÏ<x°^!<}ú´µµµì×úwyþü¹BÃí¶IMM<x0 >|xìرÈÈÈpppX³fͪU«V®\YQQ±eË6½~ýúäää¾}û
+><222''gìرӦMD~;D¶7mÚ4S§NQµuëV{{{WW×3gîÝ»×ÞÞ V®\yéÒ%º]»v-^¼xÍ5'N|òäIÝ´õºµµµ]·nÝܹs·mÛFQTddä¬Y³Ö¬Y3}úôׯ_êúÕýEHII2e
+½½¦¦fôèÑC©¬¬¤·¼yó dÿûtzcDDýëy÷îÝyóæ999ÙÛÛ³X¬º-+**ê¶LJJ==$$ÞHïèÛo¿]·nUÃØoß¾=yòä9s8ί¿þÚijê&¤(ÊÙÙyûöíE-]º´ªªªåO¤°¢¶G
åå庺º±±±E999Ñë69s¦X,¾xñbÇeå§îïöÎ;ÇÛp{Ómè<ÏÒÒòòåËô~þùçeËQ
+^,{{{Ë^E.[¶¬Þ_wíºîKcúW1??¢¨½{÷6¶ðUvÃí;¾FLÖÄÜ«««Þ«W¯èÿ6QëØ'**J¶å]-©ÿB@@5(åååôù|~Ý=òùüÛ·oÓ¿Eyzzª¨¨4ñ¬zß`dd¤AZZÚúõëë~_Í>¢(|¡¢¢âââ²gÏÛ·oO:µÞWcbbºwïÎápììì àÊ+u¿ºzõêeË¥¤¤xzz¾«ÿwµ;v,ýïË/eû2e¯¯/ lÞ¼¹¢¢báÂ
¿üò ØÙÙegg
¥¥¥uêÔIUUµ%ßµµ5 ôêÕ+??ßÈÈhܸq#FøñÇ7lØа}§N,X°bÅ'O&''¿««¤¤$+++ àp8ׯ_OIIIII9{ö¬««ëíÛ·ååå[1¦¦& \¿~½ÿþû÷ï_´h}ânݺõèÑ~ÏO$Í7¯Ñ§êêjmmm ÈÈÈhz_fffúúú/^¼ ððpzc·nݺuëF¿{µxñâºOIII±±±¡Ç Àf³õõõ}ÌÀõõõ,X°|ùòìî_Zúê¡ODör¬°°PCCÃÁÁ¡¶¶¶ÞðÛo¿upppvvvvvîß¿£#¿Fûla ½B|ö캺:ý¸Þå?þøcñâÅßÿ}jjjÓßN£é6111»wï633³··¯¯å¯²¾loúõ5b²¤¤¤ùóçËêÿܼy3 @KKkâÄqqqÔÿfÝ]]].]úäÉÒÒRúéß}÷ìñæÍ·mÛ6xðà5kÖÐEeóæÍïjIQT@@À A·nÝ*''G<yòÚµk.\Xïw*//ÏÞÞÞÒÒÒÉÉiÅ3fÌx׳dûrqq)--¥¹»»=ºn-|"BÔÖêþÿé§Î;Gý»
ÂÙ³gËÚÇÇdzX¬ÄÄDêÓB¢,,,|||èÇnnn_}õEQ×®];uꧧg¿~ýè·544è¯6ûí4|øÓO?Ñ-:tè@~],_¹r
¢¨´´4 ÈÈÈ ÷ÞD!¤§FïÞ½KQTUU½½==5êïïOQTffæÌ3[þS@¨µÒó>>>ýû÷'§)XQ½P]»vlcaa!½qõêÕÅÅųfÍ5jTBBýÕ'NhhhXYY]ºtIöR.//¯a...QQQ¶iø20==]öa'''>ÿ®ËK,
+
+júÛqqqÉÎÎnøÒxÙ²e'Nttttuu6mX,:tèòåË<HwÒòWÙõ^¶SM¾¾F¬CÍ?õêÕãÇ'§)xA=BïbjjêàààããC:B¨µàk½Ó9súôé³råJÒABG!
+/@!ÄhXB1BB
!£a!D!ÄhÿÅ=Ýhy IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_true.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_true.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_true.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,111 @@
+PNG
+
+
+IHDR û ËU¶ sBITÛáOà pHYs êe¤ IDATxíÝwXÉû ð7!t"ÅHÔÐAT°q]T<¥è)bå<»¢gC
+r"O=£ ]P@]iFB òûcïoÔSQbÖù<÷ÜvgwÞ
+ËëÌÏAq@u èQGñ1!88XÔQ|st:}óæÍ¢â»ò%¸\noVWQQ±aÃéµ>·¢O/O§ÓCBBzX¾¡õãºu몪ªNAA¶¤¤¤ÄÁÁAJJJSSÁ`ÙØØHIIÑh´²²2 Ã
+ÓÒÒÚ²e@pqqÑÒÒRSSKNNî¾¹p]Øúúúûöíëß¿¿¾¾þëׯ`Ë-d2YJJjÄ
+
+
+Xá.{ÖÒÒÚºuë{W O¡P$%%---óóó÷íÛ'''÷üùó¹sçêéé±X¬U«V©ªªr8êêj"xòäIá¶ÛÊ+åääÈdò²eË ËáW4aÂ''' HKK#ÿ®>ñ7²gÏlCðW)øнºùQP©ÔP(ìL°²²200ÈÏÏOOOojj²²²²··/++suuuttäóù ¯¯_TTTYY ÍMLLºo.\ Ðh´¬¬,áÛ¶mãóùiii>ÌÌÌ$HXá.{+W~h $
+
µ°°àñx®®®FFFD"1--Ïç?~ü ®^½)++ÛÔÔTQQÑÐÐ)''óàÁìp_¸¢óçÏׯ_/Z´HWWÇã}ü»|òÿÖå7²`Á ¨¨¨¨¨¨èòUûнºJX?. >¿xñb,aH¤E
+H$IIIyyyIIIÄçó`É%ØZ lí²¹0 X¶lYÁÁÁ|>Ë-
+
+
+ °yóæ÷îYø/¶û*AH$©ËÚ¿ÿþ ¸¸¸L6môèÑÓ§Oïä¶mÛ
+¤¬¬¼víÚî/\Q[[ÒîÝ»UUU7nÜøßÀÓë²våÊ6D¯zåÊGð=t¯îAúÆ
+8äûehhYZZ-177§Óé÷ïßoii¡P(fff[·níèè(//ÇÊHJJ
+ö ØÜÐаûæd2Y¸: .ø|> lß¾}êÔ©îîîóæÍãÿÿ=ë.{Ö} ¤Á§§§ckMLL:::~ûí7[[Û;wî\ºtiÒ¤I àïïÏãñ.\¸ oÞ¼!É `bb|ãÆàààmÛ¶u9üåË*6mÚöíÛëëë}|| à?¿+Á7,üc[[ðRRR P\\¬ªª*¼¹¢¢byyyRR ä{«û kX?®VVV3FII [«¬¬lgg7mÚ´¶¶¶'NÄ &TWWwßÒرc«««8Ð}óOcþüùçÏOLLûÐ?R©°cÇq¹\+++.ûÇlܸ±¢¢âÊ+Ë-[°`Amm- L<YVVL&=®ÀþýûÍÌÌV¯^]ÃúøáÏ3§¾¾ÞÑÑÑÀÀà?<ø·.k'O¬¥¥E¡PF!¼|éÒ¥×®];vì`É'VC¢nâ!â
+þ¿{Ò{îy¥l6F£-\¸°';ADµ°oBFHzzº¨Ãù99¹æææß~ûMÔ _ÀGOº#"&PA± b%,AÄJX
+°(a!"6PÂBDl
Ø@ A± b%,AÄJX
+°(a!"6PÂBDl
ØÀñL³
+
+
+^"Lµ÷óÏñgÎèXLöpóvªº®áHWâ²GÊêZvT«ºIÊÙÞ¶G¨zW?Üe¨Y¹¨´lÌ(÷þZºôäÛ'ü¤onu:áÌiSiCÜÂ÷
/`ë2rýúõ7n´°wZ¼øPDÅæçÙ³Ï^¸8h°ùÄ~JIÏTÓ1>lèçÏûP·¥RÞ56·ñ%8ÚuH5®Ãdúåí¡¦cp~s×x#õ¸SÞÓ§Ù±;,,pÑ"ë¡Ã׬^²%ÄÜÎ)páÂ#Q43/$^Ö66?nlFvîAz.ÎNO^¾S`G³b6·6wr:9p$¤^¾©9ÜU¡¯jN~çÑõ®^O<qÂ`ªÝ±ã3½gØ»yìرsé Ú·ßVÚ¶m»ãÂþñuæôi^»®ih2nô¨;÷òúkéu°^Q)ÕGÅÞÚÀnolëæìÈ{ZþÚc[þêY¹÷~7FÓÐ$ñÏ+S&O4³qþÃgæL£~ÿý÷+VP]~
+Þjbm?ßßïøzféS¦ütCÃ`ð÷wúiê8ÛÙ¾ª®#;ØZ³Ú¹LÛe¨QV¡ìÙËQ#+©i¦eÝï9VÛØì¥ĩS&YÚ8rdî{7-![~[µâ8lŲå{öîL³ó7ïä©Óº¦S'MLº<PßhÔá÷KªÔ¶·¦V2ê@JÎÑÎÍá×Ô7º
+BW,yôd´ÇȾRÒÒ'üä©gJI8w~úÔÉVÃ<àçkë:rãëÖ®µtºlÉ}ûSm
O¶[©ijº#]]J=VVײµ¢ÔÔ7rÎvm<Bå;æp¡Ò}T
+<>Ù,¨q§ãgLJâ¶7<üùóm\F¬_·®ËÉ6gö¬ó/iyyz¦ff©ê¸
+òðéÁÉÖÊ#q´ï$H¾®®áæ"«Ü/¿ðí¯ôI^(Ö±'ã¼gL³u¹{÷nÁɶeës[§E¿üu4ÚÀ6ÛÛûÒå?µL;&ãàd{-«ÜßÎÚª¾¥¹;ÔÉK~ù¦ê-¯Àsìh
+}ã+]<ÑËf,&Fp²-[º6ÄuÕ¯«vlßajãðËüùÑïr²åå÷×Òâ`÷òMUK'¿¬´¢¢"V||ü¾½{FyþdemÓÀdªkh2ëÞ
+ÒÕÓ74b¼}k4ØD[G·¶¦ÚÜÒJ]}`Ý»wT²JSc#ÕÚVN^®Í¦ÙÚIJJvvvÚ88ò¸< °stje·JIIÙ:8²XMd²µMcC}ßþýÍ,(õõÌÆ&¦uïÞéêëë¾}[k<ØTkÎÛ
+UU]YWG¡Z+*)³¨6¶²rrmÖvöÇÖÞÃá{'g6»EJJÚÆÞÕÔÔG±
fÝØÐÐÀ SËzf¶Ñ`ºw]}]}Fm±©ö ·µ5VV¨Õ3V4E%¥fjc++#ÛÖÖfmç@$¸\®V£sKK´µ«©QQIÙJk¨¯ ªfjnÁdÖiji®{ÇÐ70ÔÑÓ[[kbn®¡¥Íx[K¡ÒúöïßP_oemCîÓ§¥¹fc+--ÓÞÞfcgO y\®SgGH´wÂb5ÉÊÊÑlí-¬¨
+
+
+ªªj&fæõÌ:Aë}##]½·µ5&æ55Þ1Tjß~ýêh6drf´´tG{» ðx<[§öövdçäÌjj£ÙØ555*«ôµ X5Ô׫©ljƬ«¤««ohÄx[kh4x®îÛê3
+EM}`Ý;
JSéÛ¯©±jm#¯ Àni¡ÙØIJJvvtØØ;ðù<>oçèÔÚÚ*))iëàÄb5)`ç@cCß~ýÌ-)ÿ:Ùt°Þlªª:³î
flVÖ¶òòòÿ:Ùìø< Ø;9·²[$¥¤mYMMä>}¬hÂ'[½º±i]Ý;]=}=CìÐÔÖ~[[ciE ¦V_WG¡ÒUXMMTkáôÿ'['@°wÒÒÜ,--8Ù)TëÆÆ~ý±©¡¥
lzúºúokjLÌÌ4µ´µµjÿªõL&
fý¿MV¶fkO$¹\®£cgG'v´°XÒ²2Övö¬¦Æ>JJTZCC}ÿ.'¡oh¤£§ÿ¶¶ÆÄÌâ`Ø®Ü;3fÌÀóÉ Wl°IåSmÍMlllð|
+KRRRVhæ(AÄ´´àû¢ûõë×ø²[E =²o×ö
+6 ¾gÍa0o$L5 8zõò
½¥©¡¡![XÍÍÍ5U<OÔ Ò#̺:øîÞ¾}{ãoÁìQ HüqøàîÝ»ß]Âæææ¿S³¨©xÎË{̺w³àù/¹¢¢"'+Ãéu ôÈ¢¢üü|ÀwðÎ;{wnkkmu ôÈÙS'=
+øîr8ÛwïKKKQÇ ÈëèhBµÆs«¤¤$þDLGG¨A¤Gnþ}=11ðÝ%,))9w¢½½MÔ Ò#·®_¾|ðÝ%Q ÈW0fønaeggïÝñ;ºè âîì©QQQïUYYÅápD =RZ\TPP ¨K XÀ0%%eãªl¶¨A¤G¢#¾VKKKmM5zùAÄ]C=óÝ»wºüw ¯_¿0¯¥Ö â-|×öuëÖ¾¤¤¤¼¼<z-AÄ .! bÿ]ÂK.ùLñjf±D =²eÝê ÀóüWýû÷7³°Ds|!¸Ó30466 Ô%DD,à¿KxúôiÏáÃXMM¢AYµ$pÎ9ï.¡±±±§×$I))Q H8
+s¡6|w ù|~z~1 ø|>ÑÈ·ð]ýáðx¼¡4"çÖñãÇýüü®¥¤÷QTu,"v&.öÈþpQG
+CCÃcg.:ÿ ò«¯«çegg·xE°¬¬¨ù.°°0QGóçÏ×ÕÕ:4c&ÕÄð}
+K__äè±$¤¨ù^¬X±BÔ! bàÑ£G©©©¢â_lÌßw ¼<7³Ð]BokÍ7ðÝÂ6lØúÛeeåD =òsÀ/ÖfÆï±zÒAÄ®®.à;a]¾|yîôɨK ânûÆuË-|w Gv(RN^AÔ Ò#+~µ³0|·°¨£@¤§$DìoÏ +))iù vK³¨é
+-ÍÍhôz¯íÚ´ià;aM0áÓgåÈ¢¤7ÈÊÉ-ï{öÔɶ¶¶/Ø\MMmûöíØg++«GGÇaÃ9889r[®íêêJ¥R±b_+økmmõööþÜz-¼ÿäííýe¿D`õæ{öì|'¬ÆÆÆWå?H»H$45"<lÚ¸Q_¶úöí{þüyÁø÷ÁÁÁ×®]KOOÏÉÉ1c¶PEE%55õÊ+6lø² ?ýw!\2..ÎËËëËjüxzzÆÇÇ:
+ñV[S]YY øNX©©©!kkeÿ(P=f ¦fCC}DxØÔq¶$%%çÍýH&SRRX, (++ÔÒÒbuĵ¼¼|øðá®®®¿ÿþ;öã¨Q£êìì\RR sçÎÈÌ̼¼¼îÅ%
T/_vwwïR8%%ÅÇÇ /^|ñâÅ:;;6» \.×ßßßÜÜüÈ#ÑÑÑnnnæææ/^Ô"X t:ÝÔÔÔÇÇÇÂÂâ½ñw!¼yc·°°ðññ133»}û6VØÃÃ#11ñÈ{<¼wï^À÷h
+---72îôí×ÿ»zïü¢_ÿë÷
+k @ ðù|E%¥Ùóü'Lx.!òÀ¾4p¬¬¬îܹãèèãààpùòå;w¦§§ÉäCÙÚÚbe
+KJJ.]ým~êÔ)###;;;>O Æ¿sçNSSÓW¯^ÐéôfddÔÖÖÆÇÇ:thåÊááá] VR___F+((è¾ÏeËq8æææØØXww÷Ý»w[YYñx<ìש©«¨¨èää+++Ëd2=<<òòòº¬-..vssãñxUUUÝëêòu o¾jÕ*ác×ÐÐÈÍÍåñxóæÍÃúÎCø¿èojþüù©©©ßÕËÏõL¦3Õ¼oß¾x~¬áÕ«Wé)É?M,%%Ý;52ëÞý¶,¨wêú ¾¤¤$ÃÁþjjl6·¤üç²²²³gÏ ¬µUTTäççý3LWWW>Þuà//¯-[¶DDDÌ5ËÃã´´tÑ¢Eت èׯ¾¾¾¾¾þòåË;;;333wïÞíïïߥ d÷ðºï3((ÈÀÀ ¬¬ ª««±Vúöí«¡¡-ILL"£ûZ hhhÐÔÔ %%¥÷ÖÕ
ðæ]]QQÛÉüÏïùDEyÄ6§§'VNNÎþÝ;ÝÇíµÕÙÙùøa©%eªZïÔØÇ{ùìàG¬Õ¯ÿO`gáÂ
Céìì|üø±±±1 ¨©© ÚàØ5¬÷nH"BCCÛÛÛíìì<<<LMM÷ï߯§§ GâììL$»÷
+䦦Æd2»^±bEttôêÕ«/_¾¬¦¦V\\lii)haæwÛ¶m[^^ͦÑhoF¸
+%%¥ªª*×ØØ ï
+Lðæ]½±±±²²Çã ºÒËnÈ;ª@Wç ëçÖ1¥ôþ£ÓfÎvsÕËb.OK¾ D"Çãéèéû-ââv&.öS6:uêBCCKJJddd8ΧJsíÚµ¶µµa×8ØÜÜL$]\\BBB%gÎI¥Rsrr>^LØ nÞ¼Ù¥°ººº¿¿MMMTTTxxx@@FÛ·o_=xyy¹¸¸XZZÉï¿e¼fÍ#GR©T¬
õ½÷ØUTTVZuÿþýbètºXß4øì?3jø¾¿ÿp_LïÔX[S=uܨ»E°::Ú§UÏd!ª°¶@ÂÉã¿õ=c³Ù~~~ ß®
+.+!!ñúõë3fdgg÷dWÂö0ÞÞÞ111²â3.Ûwx
+ëjâEÊ`ÃY³fá¹
UVVvé\Â{-aÖÕKëL}C#ß_ RÈÉÉ}Ól 6mb0ØÃ>Â'L ø1$$ÄÅÅå³vþÿ¤Þ¢W¾xó5{öìA¦ÿ}±::Ús³³¶íÙ§TÕk\]]ÓÒÒÞ»JQQñ³F³ëÒ¼B¾=Qøæ+++k÷¶-m¢¤7ð¸¼ÐC]£l
àOÂÉãØsxnaUWWßÏ»ËápDHo at C×#8ö¸ì!t´¾Ö)STõE =µyÇnüw ×\Æþa^ÍA¼:¸oçÎïÕÚÚZÏdâ÷±
+ùQ°°gzñÜ%ôôôT8HÔQ ÒSÁë6â¿KxíÚµ@ß9!SS{¶o]³f
+à;aÉÊÊ*)« »ü"îÈä>}ú ¾»#FR ê(¾#¢YYY¢¡«AË°.!Ö
¯\yôdÂ^yýqÈ+
+týúuQlÀïÇæ5¿ëë>|Ï K]]jmKB©4eü¤)¢A¾±©¹à»
åììü«lQG HOyÏÿ»§NãâÄjB3?#x^üˬY³ ß-,IÓ¼{ ?A¾.á#)&FïE¥RçÎÿERRRÔ Ò#cÆ{á¿K;ÂÁº©±AÔ Ò#KçûN:ðݲ··_üwAÄÝÔ³©¦Æ北£ã2b$º"Þ¬¬mÌ ß]³gÏNãÞÌBw D¼[¹ÔßßðÝÂruuÝ´}¬¼¨A¤Gæ-Xhcn ¤þýû:/4nܸØØØPTTÔÖÑýqæ©G¼RUMFKz÷î«««¨Cú<§Onú¯'BÿüóO??¿k)é8ï1 ߧ7èëê$&& `ìر¿þú«¨Cú<ÿYfôèÑ{Wè
x¾slvKa~¾¨£@ÄúÀºú¢âK³³4|_Ãâóù<®XÎuüÕÕVW¯^¶XÔQ âÄkêô«×:ðø|.øNX7nÜ^üê
+DEE
+:TÔQ bÀÝÝ]Ô!üË¡=¡ÿëâQ^Qlø¨£@ÄÀ÷öBÛÚ-Û,MßÏa1ÌçOrTÇ*+*ÊËËß +==ý÷
+kZ[Ù¢A9¹ÿ~À÷5,ooï¾Zº¨K ânGø'+sÀwëùóç·®s8¢A¹=Éçu÷îÝC{ÃÚZ[E =réLüñãÇá+&,,üáSÐéôÍ7º7o^ê½BôL»Ä^¼x¾E«¢¢bÃ
+XN§|õ0ùùùÑÚÚÚ¾Ñþ¿7I×®ðxèAY®&^<}ú4ô$a888HIIijj2Ár--[·@QQF+++ 0tèP---mmmì&å={°å=;÷{üøñÕÄKßbçß¡^ׯ\æ '9|ÉL½M§Ó¡' kÎ9uuu999 222ÝÌ;D"+**úùùa***âãã`Á PQQñÅa|ĬY³®¥¤ûü(w 8©½mgÈFï ã>7mikk»ººººº1 ÔÕÕW¯^Z½zµºº: ¤¤¤8::6ÌÁÁáÈ#*¦íææ6lØ°Å···ïßÆÆûw²´¶¶z{{îVVVVß"oG8à.Á{{{ã¦{±ûàḸ8èIÂzðàF:t(ù}S+?xð ÀÆÆ&++ëÞ½{ØBWWWggg ¨¯¯ ÐÔÔüâ0>"33sgÈÆ碻´o ¼ùÜ´¥¢¢ ªªªwïÞÅVݽ{WUU ¯]»3cÆSQQ¹}ûvzzºÎ¶mÛ÷ö¹Çõéý\áqqq^^^[xzzbÍ8uüØ¡C 'ÏaÓéôû÷ï·´´P(îÌÌÌ$$$¶nÝÚÑÑu @BBë òù| ââbKKË/äCjkkõfÿ¨½
+ ZëÌ^«TØ·ÑQ
+õ Àx[»3dãñ¨#ó,4üÙoäØÛÛçääðù|l{22zôh2¬¬¬ü¡bAAACÙ²e` Íÿ×xååå¾¾¾<oäȳgÏ^°`ÍæñxÖÖÖ>}ú!Còòò¢¢¢Ö[÷¡gÏÅö|ùòåS§Nd0Ç[¼x±I@@FÛ·o p¹\ÿÀÀ@Ï`0BBB&OíÖÂÂ;äÀÀ@}}ýeËY[[t©Ë¢ËvÙÞÞþÞ½{YYYK.9r¤àY¿~½ Æ.Åôôô¨T*öJ0Ëåúøø:tÈÍÍÍÃÃÃ×××××÷sõß¡ÏJòÿÿ944ÿù
+mmmI$ººúÛ·o`åÊXÂ>ÚØØH¤~ýúZµJxàC^^ |níÖÖÖøùFãz®¢" \¿~ýCߧËÌ3ù|>
B),,\ºté%K(
+ÏùòåLLLìììîÞ½û¡bØÿ1VVVÂû711Y·n]{{» @\\\nn.Ïçñx?ýôSii)Ï///wwwçóùêêêÏ=ãóùYYY|>Å)))))@¥Rù|~÷K.
+üùçù|þÈ#ïß¿Ïçó¹\.¶Æ7oX,
ÍæóùuuuÖÖÖÝ
+puu¨¨xõ꺺ú{ëÖ}-¶«ìFþB?Ée IDATkìRÌÍÍíÕ«Wª1Äâ>|¸ððttt¼¦NOÏ/þ~þÃûò
Btàÿ[LÂ( 'ø¡2ÖÖÖ¯_¿þ² D¢´´ôG
+p¹ÜÎÎNII)èÅ4ÒÙÑ1PSk_@ïUùoÇFÖVWa# 7lø1ãÖ/ÿÈVXMx
Byðà ¿::: PTTäçç÷Þbííí$©Ëþ?îííÝ¢ //¯-[¶DDDÌ5«´´tÑ¢EØò èׯ¾¾> 899-_¾¼³³333s÷îÝþþþ*ÙE÷}`wª««±ë>Äÿ¶oß¾ØÈD"1111**@ ßS.ÐÐÐ]ÍPRRzo]D°+===ìËþB<<<>T¬¾¾^[[[P5FQQ)¢þ·sdxºþºuëÄõÕ))©ñãÇ_ºté#e®_¿¾vÃÆûué|SAóäååG{ïµ
åfgUW¾ "Èçó¸ºÍ¿PÏÀðåóg_°·¹sç
+ÿøøñcccc PSSüÓ½ÀáÃÇÓe¡²²òÓ§O?H¤ÐÐÐööv;;;SSÓýû÷ëéé@gg'å >|xHH³³3HüxIÉì^rÅÑÑÑ«W¯¾|ù²v9Çãa{n#oÛ¶-//ÍfÓh4ÁBáJJJUUU<¯±± º×%¬ûZÁ®÷)ü
` ë½Å±[UXÕÆÆÆÊÊJuØàp µÍf³ßï;¬¦%ê(zÕ±ÈÀq¥ªOÜÉdºººb¯]»}={¶pÐÐÐ#|í¼K1&éææÆår-,,öîÝ+¼>ßÚÚºcÇAák×®<x°ÍÇÇgòäÉÍÍÍD"ÑÅÅ¥Ëz3gΤR©999 pàÀÄL0áæÍ]Jª««ÛÚÚúûû×ÔÔDEE
`OÞ`×°yyy¹¸¸XZZ¾÷ ¬Y³fäÈT*kæ|<ªO¹ËòÞµk×5ÊÊÊJEEE°PEEeÕªU÷ïß?xð ÐétÜÜvX±z6ó3 BCCÅnd'''55µ·°®^½ºzíº=Qò
+½7J2ÖÂÚ¹ïP¯Õ(µjIà°á#æÍÿ¥KªzùüÙÏÓ&]¿~½{¯Øl¶_BB·«ËåJHH¼~ýzÆÙÙÙß®¢/ãíí#ûE ëêêZÙÚ?#îþ=d°^hh([Xòòòý¨ßé
ð¯îéãG'Î]ÒÑÓu ß99¹o ##cÓ¦M{þ¹ÆÆÆ &~ qqqù¦ñtñ¿7))«ôë×ðÝ%>|¸¤¸NböfÏóu?WW×´´´UTTìrùbAXÏ£5?~úOcY,Q Hl\µ{+Ï-,
+
+
+{'gÁuAÄ%ÅÂØ ð°Vȼÿþ bdúì9øï<yrÔP¦¦Æÿ. ÈwlÅÂùØ«ìxnaYXXL=GZú=#I "FFceb¸OX3öÅÞ¯FD|¹;út =íX¨K bnù/ØFxna9::.ÿmÌ=éKóæÍuxó潨£ø鳦â½K¨¥¥å4Ô
Dú¾&Ý rE¯©ÓE"6(6vV4QGñ?æ
+Åð°Î;çççw-%MÓ¯ÿïç½0ù\~]¡¯«HS§Nu¸êû÷äÉ55µqssÛ²+LV®÷ÆAä[ð[¸ØÆ|0 lmm@0±¸ÐÓÓ300øx2¬6P£ûHI¾ýúa3G
+Å+W®ÌG]B¡[7ÿ¯KWcÆ9p4FN¾÷ÃBä[XöÛZ;À÷sX§íGãAp¬£½ãÏ ëæÍ«²[E =rxßßÿðýXäI$ûôU ÿ(3?#^ÿ}#ÅðÝÂb0e¥%Ü^HAoáÕËØdKxNX;6ohme:Az$îX46»3gÎì?È u DÜíÚáL5|·°>}ú÷ÕËݧ´DD¼ÜÉLONN|'¬{÷îEØ×l@1wùüÙ'O¾»¾¾¾V¶¢â{±~ù⪪*QG!ÃGú.X$ê(þsÓÏ ëîÝ»öý%PFåååd2ÙÙÙYÔ b !!¡¡¾^ÔQüOâ¹3ÏóçÎçõüùó]õñ
+@ ãææÝjA£Óé¢á_r³358OXÞÞÞÆæ¢AÚ¹ïþ§ùJOO߶q]+=
âíä±£û÷ï|_ê««{ò¨Çã:Azäuy¹øNX'Nì7è?ùCäû·~ëvüw étú¯AØìQ HDmݺð°¸\ngg/ê8éNg'öÊ
+»cÆQPÕu½§³£CMsàÑÒUkðß%¼råJÀì-Í?Ê ~Yi{¶o©u òíÙøNXd2YCKëÇ5gÛûùyÞÆ¡´
àLUUlZ?<ÿ1»¹¹mÞ±[öH$Î
+XÀápþ¼xþsÓ¶¶¶««+J^âêêºsçÎ÷ GGÇaÃ9889rä«Qkk«··÷çneeeõÕ#éIëׯ2dHRRðBooﶶ¶¯nùýµ°ð|
+ëìÙ³K-?~æ,êXzÉpÑ1+ßTp8«ÿú3qܳ}ýUÕÔ?¾¡JjjjKK`ÉG
+ @ppðÍ7ûöí õ}õÇã}bSW¸d\\קlõÝâñxýõ×ýû÷
DOOÏøøx___Æ&FÖÿºÜHO7::Ï kÐ AC\\I¤Þ>Æ'm]¿¦+PVéû¦â5 ðx<'H[O*Åb}ü½Ë.ÈdrJJÊèÑ£Éd²²²2 /X°Ífóx¼ÈÈHkkëÖÖÖL>}È!yyyQQQëÖûPɳgÏbû¿|ùò©S§ºìÁ`?~<..nñâÅnnn&&&4mß¾} ÀårýýýsrrI$R||<Á <y2 XXXØÛÛck.\H§Ó-[fmm]XXXRRÒ=~áÃOII
+
+¢R©\.;X___7räÈõë×wù®°Ã9qâ¼¼¼««ëñãÇÇ/8@___°>%fil >®oûgôr;C6>yTÖË
+c³[ªÞ¼üH$y<¹ñvêÔ©zùY[[[WW·¨¨(!!aÌ1Ø=== X·n»»{÷ P^^¾sçÎôôt2|èÐ![[ÛñãÇïܹÓÔÔôÕ«Wt:}àÀúúúÙÙÙñññZ¹r¥§§gxxøJ
+¢¢ÑhÝ÷¹lÙ2ÓÜÜëîî¾{÷n+++AÓLSS377WQQÑÉÉ)77WVVÉdzxxäååuY[\\ìææÇãñªªªº×%ü-
+><66 °Â§N222²³³ãóù¡ËW*8++«ÂÂBá%ÂG×_õ7¤««kek¿bõ:Qò?ø^æÄóç/¸tãV>½VéêM[z®÷Z8wvMUÇàr¹f¿_i¶v³'z~d+´´´¬¬¬={ö`ù¨{°K ÐÑÑ¢¢"??¿¼¼¼ÒÒÒEþD©££ úõëý:99-_¾¼³³333s÷îÝþþþ*ÙE÷}@uu5vEIÐìÛ·¯¶$111**@ 0îk ¡¡ASS Þ[°úúzmmmAa//¯-[¶DDDÌ5ËÃãKáîó¡DþÓÒ~º:çÎÃs¢P(>~þÒÒ?ÐØ2y¹wJK±Ï¦XªúôÍ7nÜøâŬmõ?~lll jjjXSÝÔÔtÿþýØZìI?áKWà qvv&/QSSc2ÝK®X±"::zõêÕ/_VSS+..¶´´´°;Û¶mËËËc³Ù4
+[Ò¥)¤¤¤TUUÅãñß¿0eeå
+ À
+H¤ÐÐÐööv;;»î «ûá/a0XÞD>ÅhÏñV&FïÙïÙR?Ò³1QG ÀÒêû©JÀÏÏïèÑ£ØÁÿ,ZRR"##Ãáp àÀÍÍÍD"ÑÅÅ%$$DxÛ3gR©Ôÿ,0aÂÍ7»TWW·µµõ÷÷¯©©
+\ÃæåååââbiiIþÀ5kÖ9J¥b¦GµvíÚQ£FYYY©¨¨ Àµk×<ØÖÖ&¸ñéètº¸ßOèMnî£PÍß×°bbbüüü®¥¤÷QTu,½!/÷Î?οð½©jöDÏñãÇ× ~l6ÛÏÏ/!!áÛUÁår%$$^¿~=cÆìììoWQÞÞÞ111²²²½VãgùÞ®aúÎÑ×ÕILLÄsËÉÉ)xÝFïõøêTúö;}\ÔQ|Mrrrß4[@FFƦMÆ={º¬jll0aàÇíç³
+À·>.ñþyÍÔðÝ%8p µ=$)ê@z¡¨C?®®®iiiï]¥¨¨(|Ûáã>«0ò¹Qp?Uý
¼'kf5:AzdÓêà
¾[X#Fø}w¸¬¼¨A¤G/±57|·°deeûöë÷ã¼ü x¥¨¨½Jç?æk×®-çÓÒÌu ôHض-«W¯|w Çqì¼Âòæ3àÕ5ëí-Mß-¬ööö¦¦F4k;vKÅ|·°nݺµfùk)é?Æ£ÿ©¨¨èÀ¢MMß×½õÈáøptòäÉÒÊýÈ}DÈ÷"#####CÔQ ÈgÛ¸}#Åðݪ-¾_ ®>ø#½Nø!ÇÏ%~_ÃB¾:¢¨CøçO(J444ð°233C·næ6Í% ?Êÿþ=£«ãîîçÛÛÛïä)ÉÝWCD°Ù-ÎVæ
+
+
+x¾KøèÑ£?/ï> â%3õö7 ß5Ü¿?&2¢½ÍM âíjâEl|<w Acº#ò-àæçÜÜÜ{BÑìo"î.|'¬/_Þ¾y£]ÃB177++PA±ÿ.aZZÚÖõkZÙlQ HÄ|?é^__ÿòù3ôò3»ªÊ7}d¥ u øï&%%X´ ¥¥EÔ Ò#÷nÞ¼ð°Ð93¨K Àðòå˾ÞS[E =²}Óúå˾²²²®¾5AĦ¶¶6 .! bÿ]Â3gÎL=õN ÈçZ»b©¯¯/àûÁQ]]]7÷Qh¸QwÖvö
+u øïÆÆƺÙQE =0oÊ)ï.!Jõ[¸XZZFÔ Ò#?Mlebøî¢I(~I(N>=Îmu DÌýºx¡ H`¯â¼¼¼¼JÿÁ&fßÓ|.ee cõôôðÜÂRUUµ°¢Jð|A~úFF&&&ï»/^=i|3=8 âmËÚß/^ø¾èþúõëøKÚ9:£YÚD¬Þ·1lggç´´t>èågwròò
+
+
+ï.á_ýè÷sK3KÔ Ò#{wü¾nÝ:ÀwðíÛ·ß46Ew D¼½|ñÜÞÂÄØØÏ-,6ýÁ@³æ ¸kl¨¯¯¯|w SRRÖÿº¼&¡@ñ}èÀ®]» ß]Bõ×íõèº;µwoß:Z©©©áù/¹²²2ÿn.Ó)ê@é² ß]Âììì°m[ÚZ[E =rædldd$à»KØÙÙ/++Fk@±ÖÖÖ6j.++çViiéùøS¢A¹}óÆÕ«Wß]¢¢¢¸c´··:Az$éÚ. ¾»ÆtG¼Àÿî999ûví@ÝDÜ|'¬W¯^e¥§r8Q Hß/¸{÷. .! bÿ]ÂÛ·oo^ók+-ê@écaaaïi¾X,VeEzùAÄ£¶¶¦ .! bÿ]¿ÿþ{é¿4Z·ý¡;6lØ øNXRRÒèµw$II)))À÷¼úúú¯ªkïYR._8÷ôQ±iÂÉØÚê*=Ãcl¶ö C{ÃH$²Jä}dEEIâØájê--Í'£ÒÓ«©ª=>ØÜüÉ£GçOÇQmíòïæ^M¼hcïr+=å
ftíÊý¼{fçÎ<úÄh°Iü·okõô
+þ8|¨MS[;bo´t%ŨûBÌÃj²X'ÿ8ªk`PõæMÂã¦?emïp/'ûúÖv©·è©·-©´ëW.ß/05·¸x6¡üÅsCãÁ§«{ÇÐÕ78q ³³c ¦VÄÞ0i2¹ÏÑûTTø<~LäauMÍƸcÑzF¯_9kF±zø øBüiǬ¤«W¬íìSè7²3Ò-¨ýø ¸ÐÄÌâBÂéWå/
+ÇÅD×3:zúöq¹\5õÃ÷ÈÊÉÉÉÉG: Ò¯Ã9uDCK«Yw*æcãWå/Ï<aaE}PTx1!ÞÎÉ9;=~ý/ݤë¹ÙêÕKÊ63?wúä×FÆ'¢£éêÙ¿ P=²o¯¼LtÄÁ¾ýûwvtÄÔ4èãíéãǼ|öôì©4ë¼Äsgì2RSoüMµ±¥_ÿë^ÎsÕÏ?.{8ØÔìLܪÊJ}C£¨ÃÍͬA:ºáaD ¢Jß~ûÃÈd¤ä±Ãú«ª¶¶²ODG
+ÒÕ«©lföôÉ£s§â¨6¶÷î^¹xÞÖÁ1=%9õÖM+k]-¸kfI¹|þìÓÇMLN¯®Ö30<v$¢µUkΡ=»%¥¤£ì룤D$PUWoifü㨾~uUe|ìqs'eÏ>E³³¿sçZâ%{Ôä©)ªõßWÿ,*È7µ°¼t.áųgFMNÇƼ{ûVWß :â`GG»¦VÄÞ0)irÅ£÷+*+@Läa5
+¦¦Æ¸?¢õßT¼N8kfI){P¹Ùׯþimgûæ¬ô´N¶Âû¦æÏÄÿs²ÅüÁ¬{§£§ôÐ~£>PãpøYYy
£(÷íËãqG¨©ÕPÏ;ö¾QEyù'̬J/$¶utºq㯫4[»dzRNfº
õÚåK¥ÅE&fæçãOU¼*702>yìhCC½®^ä}<oâÔé>3¦¾[X PRxÿîl (¸w÷~~ äfg@fêíg@Êͤ×å/;:;éIÕ-Í-Éô¤wïÞ60Éô$VSÓÛÚÚdzR[këׯéI<ïåógiÉ7àQéìô4¬¢{9w ÿ^nQA> ÜÉÌ(+)ÛÉ/>áóùÉô¤×¯Ê;Ú;éIÕÕUÍ,V2=YWWϬÃ*ª©®J¦'µ··UüE/=MOI²ÒÙé P|¿ /7 òrîß/ ;ie¥ =ùÖgOy<^2=©âõ«¶¶ÖdzRmM5ÕLOª¯«c¾{LOjifau´·W'Ó àù'©É ððAINV æçåßÍ{9wJ
+ï@VzÚ㥠rëåóg\.7ô¦â5VÑÛ¦ÆÆdzR}=óLOjii©®|LOêììxõòEÊÍ$ xúäQFj
+ çde@aA~Á½»XE
+ 3=õqÙC H½u³üÅsLOªzó¦ÝLOb¼mh¨O¦'564`±Ù-UoéI\çÕË·oÒàÉ£²¬´T (-)º
y÷
+óîÀÝì¬Ò" ÈJK}ò¨ nߤ¿zùUTùÍnI¦'½c0éI
+
+õ·µÉô¤VvkÕ7Éô$Sþâyê ð¸ìafz* <(*ÄÎ{wò 'ë-#5åéGØÉöêåÎN¶7--ÿTT_ÏL¦'556¾©I¦'µµµ¾©xLOâr¹/?KK¹ fu9Ùîææç@NVÆÃ% üüÉ H¦'Uw´·'Ójª«ZYÉô$æ»wõuuÉô$«©¶¦«è_'[ò-ìd»öÏÉs òrs°-;#ý-%YødkooÃ*b55%Óêu̺ºdzR3UýÏÉÖñúUy2=Ïç¿xú$ãv2 ÜÉÌ ¢üü{ÿ:Ù²ÓÓ> ´ä/?üEãü¢; xó x b%,AÄJX
+°(a!"6PÂBDl
Ø@ A± b%,ä먬¬ôññ!C^)%%µtéRÁ*ºÿ~ÁL&ÓÇÇD"-^¼8 ÀÕÕµ¨¨H°påÊï-ðÕã®ñSÊ?{öLFFæ«ü>|%O>ÔÐÐÈÎÎÆp8wwwyyyA¢¢"SSS*ÚeCiiiìó¹sçlmm»,|oo¿ ¯[ùZPùDâòåËwíÚ
ýxáÂ///áqqqgÎ)+++)yÿ`°&&&Ï={ï*A{{{ýû÷»¹¹@QQÑÄ/_>cÆ «W¯½~ýº±±qPP¡¡¡»»{mmmjjª±±ñ©S§ºï¿µµÛù={ôôôvïÞ-XµtéÒ¹sçN>ýÈ#Û·oçp8/ÇÖîܹóç^ºté¸qã222>´/^L>}ùòåS¦L L2eÉ%'N|òäÉ'|Í?0QgL?°FGSSJYYÏ÷õõ}úô©
ÕÙÙ9cÆ>?}úô+VtÙû¼gϱcÇò?ÜÂÂ
+<}ú@ ܾ}ÏçGGGóù|{÷îñùüãÇÏ5+¼páÂààุ¸¿ÿþÏçÇÄÄ`455ýòË/ïû@ JKKSSSµ´´°µ¡±±1,,¬{+!!ûI¥Rß»>O£ÑÒÒÒ°ocÌ1|>ßÜܼ´´Ïçÿý÷ßîîî_òÕÿ0ð< "d2yáÂ
¡¡¡3fÌððð^uãÆ
+www ðñññóóÛµkôÏÈáp~ù嶶6 î»íRÅbDìz¿¿MMÍ'Oh4 ØÚÚ®^½Ûj×®]
+¥¥¥åðáà 0}úôÕ«W3K.Í9ó#GA$MMM>}Z__-0`
B6lX```PPÐëׯ»l¢ªªêííM&±Fb÷ÔÖÖ:;; Dº~ýzMMÍÃ=
+ mmmD"êô|JXÈ×·dÉ##£æææ/_
+'$$H¤»wïr¹Üææ椤$OOOlDüÈ>»`±X$IBBûÿaݬSSSÛÛÛ¥¥¥åää¦O[\\¼`ÁW Âÿ#HyyyW®\Ù¾}ûùóçÃÃÃ
˳X¬qãÆ={öìÊ+ïÝ öÐmÜî°°0¬pssóG¢BP:G¾¾,Y²ÄÓÓSP ¡¡AVV6666222::záÂ
'NøZ5ª««@^^Þ#°åGY¾|ùСC7mÚ-Y°`Á;lmm?·7oÞlÛ¶mâÄÑÑÑ÷îÝÄf;wî ´µµµ··÷íÛ stjjj
+%;; :::¦L¢¦¦fbb UUUO£º
|uuu³gÏøí·ßfÏ-))¹xñâqãÆyxxÔ××óùüööv///iié°°0ÁÕb( IDAT£ËÞV¬XñÞ%MMMØÂÂB//¯eËM6¶¶ÏçïÝ»×ØØøþýûaaa6lÀJ:;;ca¼7þ+V`Î9³iÓ&IIÉÐÐP>ÿîÝ;77·ÀÀÀI&ÅÆÆr¹Ü¡CÎ?Çضoßîàà4wî\III è¾>ÿôéÓiÓ¦-_¾|Î9Ø5¸±cÇ.]ºtÎ9oÞ¼ùê¿<AC$#?òòrµk×:tHÔ± _]ÃB~ S¦LÑÕÕýý÷ßEò
PA±.º#"6PÂBDl
Ø@ A± bãÿ ³U¸ýÕƨ IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_true_custom_nspi.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_true_custom_nspi.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/dcerpc_mapiproxy_server_true_custom_nspi.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,100 @@
+PNG
+
+
+IHDR
+ ³ ¾ sBITÛáOà pHYs êe¤ IDATxíÝg@ÙðbE¤wD6t]W\]}ÖX ;+*k[º®½°bEÁDAT)^"E¤"½CÊû0»yy X¢ç÷)Lnæþg{'Ïê
+èd@$svv¦Ñhd§hFsvv&;Å7¼sçN²StvX°Ðgãr¹Ù]~~þ¶mÛÚoÓa>·£Ooìââ"bwë;õèÑ#%%%uuõøøxb Í:t¨D¿~ýJKK,!!ann 4mÔ¨Qªªª»ví¢Ñh£GVUUUVV~üøqÛ÷E¼PEEESSóèÑ£½zõÒÔÔÌËË]»vÉÊÊJHH7®²²hÜjͪªª»wï~ïSÂâââLMMÅÅÅMLLâââ=*--ýêÕ«E
+0 ¦¦fÃ
+JJJ§¸¸N§_ºtI0v[¿~½´´´¬¬¬¹Õæwdkk;|øp
+
+¥Ñhaaaíï«O|G:D¼ ¼«m»ûðÑwI__àÀ)))¦¦¦Ä¯V\\ܳgϪ««ÍÌÌ,--ÓÒÒ¬
+Æçó@SS3))©°° /×××oûrá¾ ÀÜÜ<""BøÁ={ø|~hhè/ÂÃÃѸÕ`ýúõzJÉØØØÔÔxÖØØÇãY[[ëèèÐéôÐÐP> wïÞ=uêTuuu~~~ee%Ï>wî\JJJHH¹ÕæwtãÆ
+·råJ
+
+
+×þ¾ìîÿ¯Õ;²lÙ2 ÈÏÏÏÏÏoµ«O<hÛÝ÷ÖwJLLÌÑÑÏç¯^½(XcåÊC\\¼{÷îâââÏçÀo¿ýF< ϶z¹0 prrjõÀÙÙÏçïÚµKEEEFF vîÜùÞ5ÿŶ}JÁ`´z600 ¬¬¬IF=kÖ¬I&ýç?ÿN¸gÏþýû+((lÙ²å½/ÜQcc£¼¼ü¶oßþÑ}%ùÿZ=»~ýzÁ ¢Õ®^¿~=Ãì¶Ý}?ßx :)mmíðððÔÔÔ°°0bQpppBBB]]©©©¡¡¡ØîÝ»srr6âââ5^®Ýöå²²²ÂݵzÀçó௿þ9sæ /^Ìÿ÷ëVkÖö)A$==½gÏÏêëë777oܸÑÂÂâùóç7oÞ>}: 888ØÛÛóx<___ (((Ó××üøñ÷ìÙ 6íÚµºuë6kÖ¬¿þú«¢¢bÁm·ÝW=,üccc£ð ¬¤¤$ür99¹ AË÷v÷ÀcXß©'NþøãòòòÄ.(((2dÖ¬Y/^¤Ó鶶¶ÅÅÅm× //?yòäâââãÇ·}ù'ÆXºté7nݺ%--ý¡5·Ó©°³gÏr¹\333.ëéé¹}ûöüü|''§e˽yó fÌ!%%%++;iÒ$::vìØ1CCÃM6 aµ¿ùL&³¢¢bØ°aZZZm,òÿZ=;cÆUUUSSÓqãÆ /_³fM@@ÀÙ³gK>±;j"{º$øwzÒk½Óúúzssó+V²D"a¡¯ORȳgÏÈó?ÒÒÒµµµ7n$;úB4>~Ó!ÔEà!Ôe`ÁBuX°¾wx.áë´Á:LÇïüúl\.Wðuªßê[]mup$§kÇge&e?ª#÷ GXß)<Pø\B6räHUUU555ÁW1[`ØN0a^ÕÎnd0ßâÄíí¶ßö
vBÇïöÛà÷°¾Wx.¡ð¹ `ffFüÁÁømN0l'°V¯jg7;vì[ø¡½ÝvóÛ¾°ÕNèø=Ð~{>KøÝÂs Û&äñx`ü6'¶LX«Wµ³¿Ñ9íìímþvBÇïî<õÂs Aè\B"ñá FÛÛ &ÐêUíìÆotNb;{»Õæ·Õj'tüøèNÀcXß)<>pF í íôþ¡Wuü9íhµùÕñ{à£íqJ¾|ç~»Mî0"JÙö °Ð×÷]KØi7¶VÿµwäÀs B]°B],P!Ôe`ÁBuX°B],P!Ôe`ÁBuX°B],P!Ôe`ÁBuX°B],P!Ôe`ÁBuX°B],P!ÔeP¼`íÛ·ïàÁ °eËÓ§OÀªU«®]»ÆçóLf```UUÉÈÏÏg2l6;%%
ÉdæååEFF2ÌÊÊÊ &Éãñ®_¿¾råJ 8sæÌæÍàСC{÷î;v¸¹¹ÀÚµk½¼¼ `É%þþþõõõL&óéÓ§%%%L&3>>>##ÉdfeeÅÄÄ0ÌÒÒÒÇ3̦¦¦[·n988 ÀÅׯ_ Ç'îQþç=z 6lØpîÜ9 X¾|¹¯¯/Ãa2>,++c2QQQ¯_¿f2iiiIIIL&³°°0,,ÉdÖÖÖ,Z´ ¼½½ûí7 8uêÔÖ[ÀÕÕÕÕÕ þøã pttôññ
Þ»w¯¦¦Éd
0Ìäää/^0ÌÅd2ËËËL&ùqãÆ+ àìÙ³Ä-9BÜØÎÅÅåÄ °nÝ:ânéööö·oßnlld2!!!oß¾e2±±±L&3333..Éd¾yóæÉ'L&³¡¡áÎ;vvv àååµnÝ: 8yòäÎ;௿þ:|ø0 lÚ´ÉÓÓ V®\yãÆ
+.Ëd2<xPQQÁd2?Ëd2SSSÙl6É,((g2ÕÕÕ÷ïßg2 põêUâF³§OÞ²e 8p`ÿþý °mÛ6www X³fÍ+W `ñâÅwïÞe2Ï=+**b2/_¾d2ÙÙÙÑÑÑL&óÝ»w>d2---~~~Ë-óçÏÿþûï pìØ1âÎc»ví"n¥åìì|á XºtéÍ7Læ£GÞ½{Çd2cbb^½zÅd2ÓÓÓLfqqqhh(ɬ««»{÷î%K àòåËÄM·þþûïíÛ·w¹?
+Á_4o¤zâÄ ]~jÏgE¾-ÓÌdEÓ¥º÷ÑÒdE©iëq»ÉD²¢YªVD²¢"âh4Z$+*,.©0?/É
+gGÇEFEų#¢ã²³2ÃâÙѱÍMMañìVtoeeaìVTÔ
+Í"£¢{ª¨uSìÉÒ1ø®®9eÔ]F&TQQNtøÏúcâ1qÉ DGeañì¨î22âÙQÑå5õÚfÏ£¤äUD²¢4ôëÉ2µ´ê¥¤D¬¿¹©)IlHDlBÄsVX<;"&EôSXP@< ų#£bòJÞX`EñÅ%ûéE²¢újhѺËG²¢Ì-
+Ë«#YQá±qq¢£âb¢£XAþØöXlæËDþúúzâbfñìȨèºf®ÑÀHV²J÷Þ*¬(m#Ó&n$+Ê|x¢¼<±þêª*bG¥¥¦D²¢ÂãÙÿvC¼¥oßë²gG°¢KÊ+uÍ-#XQ2r½5t"YQýuÄ$#YQÆCûªëçr¹¬¨°Ø¤¼×¬¨°øäÈßñ¸HVtX<;<*6/ç5±~G<èÓWÅÈÉn¡1ÔôM"³Ô4ÄåzF²¢ôÌT×G²¢Ä&JJJ½+-%vTb\Â?ïHL|Ä¿¥¥°7¢¦ºX¿¼üÀxvdTLUC¦É VlÞr}Õ"YQ&5\z$+jà°=zF²¢Âbê#YQáqÉ/Ó¿QÄ;óï¼))"ÖÏïW®mß°>(ð¾
ïâyÑkÅudA}¹¢"¿kÞûv»¨««S¹`@X<졯`¤¹1PûÖþýûÇZ!$äÄÑM###@8TIIâââiY#S3² ¾FWìÑóçÉ?þðÃTÖ××?~+¯ @vÐãp8µ55F
+§òðøñã¿LKv
+H^¾H:~tLLPûk
+?ýôSmì!¨ôSÛâò§Pû »²²²¾Ù)B"ÖÕ7j¬³gÏ.ý+Ù)B"ÉÊx¹pÖôÄÄD öpÖ¬Yy²S DÒ_}ÀëëëµGXbbbd§@N§KÐét vÁòññY·r)Ù)B"yå´Ü>55 ¨ü=¬{!ÏtôôÉúr
+
+y¹9³mêÞ½;GXåååyyd§@¤©©)?/·¡¡¨=%ô÷÷ß½uÙ)B"ÉÏËqÙ¼!##¨=%¬©©yݳwo² ¾\KKKeEù±£$$$¨<ÂJOO}òì!TWU>~TVVÔ>zôèä!W²S DR\Txüàþׯ_µ§\.÷Y\2Aå/Ç"Dy|>ËåZ[Ñh4*°ÂÃÃ/>Ev
+HÞ¾)9çñw~~>P{JpÇï:Ù)B")/+»ã{½¤¤¨=%¼¦;BTAýkºøÓ
ì!æçíßµ#++¨]°
+
+
+ØI d§@¤¾¾PSS8%Du ÔúúúnY·ì!ä¾ÎÞ´Ö1--
+¨]°êêjÉN Ç««år¹SBP@L ©ü-ðK.¹:ì~Þì äóüûäKv"Ù)P1ÉvúøIÉNñW®»w^õ¾bbbBåõÃ?()+¢S(,ÈÏÈÈ?~<ÙAPàëëka5ìÿ#.!¡¤Ü§[·n@íÖ´iÓz¨i¢³0`À7ÈN:;>O\=½óP믾Ëõ®®.Pû »»»ûÛÈNIzÚY?Oj,MMÍ¡V#ÈNì?1JAA¨=%´±±êÙì!ôUé·vã µGX4rÙ)B"yÁN¶±Âb±ÚkèСs-&;BH$={÷·ÈNEE¨=%´°°¨å!$½zÏ7¿oß¾@íÖáòþ^ºóx<²# ôM¼HI4rXTTP»`M8qݦ?ÈNÑA
+
+þܶ9÷uö7í
F£IKK÷/¡ÑhÎÎÎ àïﯡ¡Á`0úôésäÈâ)F§ÓõõõCƬ¾¾^UUõܹsÜoGn/Ï744Ü»woÇt×ñúªôsþc;õº«««±$;E駦ÆçÃÂYÓ]¶lü¦e«¡¡ÁÍÍMxɲeËtuuÓÓÓ¯]»¦-XøòåK:¾téR{$Îzý²ösæÌ1ÃçÊÏÏ߶mÛ¿ü³6ÇãÙÙÙíß¿¿®®î{ìÌdde
+±j,ùÓ§¢ã,´_
+ .5ÝeËoT¶´µµO<ÙØØ(XR[[v÷î]yyù)S¦eddtttÆK\ä½Ö¯_/---++ëää III077OKK£Ñh£FRUUݵkíðáà 44F£
µj Âí]x{{1BJJJÐ@EEESSóèÑ£½zõÒÔÔÌËËÛ°aÃ)..¦Óé.]jF£9RUUUMM-''§mr6zôhUUUeeåǪªêîÝ»?k{
7Á`´ÚÞö÷MUUUPPм£^ÆË´9¶?ÅÇǵÖôéÓw¹";EÇQS×k3F£ñx¼'¿QÙ2e¼¼ü
Kóóó×®]kjj*<âp8 jjjZÕ©S§ÜÜÜX,- ,Z´Á`$''ËÉÉÙÙÙ@QQѽ{÷-[¶`Áýúu
+
+#F´m,Ü^ÐÍÖÒÒüXWWwãÆììl//¯;wîdgg_¾|ÙÞÞþíÛ·AAAþþþ¿üòKÛ¨µµµ>>>ùùùÞÞÞm@MMMPP²²²££ão¯`;Öj{Ûß?Ä6&''¨ë.MM]cÏÁ£zzz@íO »wﮨأ#{,ÈË»~¥õÿçõïÅcðO=|ò0x̯8Y ÓéëÖ;|ø°`É;~ÿý÷S§N<x ?~âÄ /¯^-ã?þpqq©®®^±bÅ1cRRRh4ÚàÁ«ýôÓO&&& ðóÏ?ËÉÉ]»vÍÏÏoÙ²e4mcáö2jÔ(bä"xPQQ¡££3zôh//¯êêê©S§ÊÊʶ}¡µµµÑ¾mr 1b¡¡áÈ#Oúàå>º½MÐÕÕݱcðö@;ûGxÀK=C¡¢¸¸8P»`yyymݺõItÇ]ÖýÝ»··}¯÷ìÝ[B\¢Ã:Æçÿßg
|ÏçÇEG))÷é.%ùµzY¸páöíÛ?®Y³Éd6LQQ±©©XÈd2·lÙÒ·o_IÉö«¯¯ÿøñã8;;ïÙ³ÇÐÐPLLl÷îÝÍÍÍ999k×®%~G [·n³fÍú믿***,X ÍíÄÄÄZ= þòìííy<¯¯ï{£Uhß*9 §¦¦
â}îö
+oBÛím»ÉÂûØÆöu×¹r1ÓT'bøðáT.XóçÏSVéø~ÿ:tLÏÀ°ãû³§Ü.y ÆçóØ-ýùé{wn¯(}óµzZ½zõ;ÓÓÓmll*++544ÜÝÝ
òòòÄÇ:í &>Ä1/ÚÛÛÛÚÚÊËË/Y²¤Uc&yúôéaÃÓöÌ;wË-
+
+
+Äa¬1c££#N4iÒǶþ=Éí<yrccã+W¾Åö¶ß>88X^^þÃw9´´ÝÎ]266j_q4##Ãï^ÐÑc:¬ÇÄøØßöò!¥`ÕTWÿúMC}= (öèA* n à²ecEéâ|÷ïJCC®®îÎ;Û)jD³#FXZZþý÷ß_ÐF[¿~=1îx|>ßÈÈhþüù7oþ*k£Óé«Ö:ÿg>Sôµ}ÕÕUIñqË-PTT¤òëæÍÛ:vJH®ëÞ^
+õõ=z.°sªïT^^ÞGIKKëèèlܸ ç°ÁÁÁ£F}ù¥ì¾âªÚA£ÑRSS¿Å;¼×¬w²jAñ)á²eËÔõÉNÑAjª«C?\³a3ª/ <ÏøئPûXxÑÑÓ÷¹`nnÔ>裢úÁÕ©¤®¶öµíZ®®¶6.&zÌÐÁTþý
+
+:¼÷O²Stå¾}±Z!J*,È?¸g׫W¯Ú#¬uëÖYY!$#ÀgÏ---Úßt¹yÍì!½+õõ¹\\\Ô.XÏ?¿|þ,Ù)B")}óæò9Ï öÐÙÙÙrìD²S Db`lò02f¨¹1P{õðáÃcö!$¢Â£û÷fggµVVVÖó°gd§@¤¦º:"ì)qÚ9§+V¬0²ü^.üQïÞ½óôô$;êì:á¹zºú727j¬Û·ot÷ر×ì B^^Ù)úly¹9<uò¸®®.VUUUqqÙ):
Û]ÖoÞJv
+ÔetëÖÎîjin.)*$®\DåµpáÂÆæd§è$%%áÃ×¥B¨3ÓÔÖ9íåcbBõO ½½½×,³#;BH$¯_eýæ°$%%¨]°$$$¤¥»!$:.Ý]¸H,§¿þú«Ò ]²S DÒ_cÀ¾£'õõõÚ#¬3gÎ,ù; ºÌôógØ&$$ µ¡)Ù)B"621%îfDå)áäÉeUÉNªÚ¦»qPyuìر©ãG!$´Ô)cFFGGµÙÏ¿üJv
+H{Lñ« 0ÆKv/4yòd᣷5räH¾´\åA}½íV¬VSS Æ'Oôôô>zÏËÎ&44ô£]]];øÎÏ¡¯.´r13"âß;?ÛÙÙµ?Téôôô>Úfܸq%åU¦óklh¨¬¨ ;êJzôê%..Nv
+ å>*ë7¨««µ?%ÔÓÓ=nÙ):
gOBþÜön¾ç¯újjë @N^~Ìx={µN
>}Z^^쨳KJJÚ³gÙ)þ'=-õÿ¦T5uêÔF#;E'2eÊ>}úuv?üðÙþªú¿öëèè µ¿ÖУGµþêd§@¤[·njêRRR@íuþüù¥æ!$¬Ìt»¹³ÚÇ°æÌ#¥Ðì!hÐ:â~ÆÐШ=Ââr¹ì!ðù|CÜÊëúõë׬";BH$9¯_ýî¸âÅðF#¾}*xð)wîÜùµ2´bggwÎçÆ7Z9B¨chéè]¸ægffßb¿mÛ¶OlìââòÕ3Þ¼yþò¼³áñx5ÕÕd§@èëklhÈLYWW¢,6=tèP ~ýú
+«ªªîÞ½ ,!!ann 4mäȪªªjjj999 pèÐ!b¹h[ô~{w~jéìêètú?]þܶ%?/ì,}Mù¹{¶ÿ ¢,&YVVÆb±|||$ßw©E1ääd999;»î^S[[ëããïíí
+ Ë-üüü/Ñß~ûífÐão±æÎi¿ôaà½3l¿ l©©©Y[[[[[7 úôé³iÓ&â©M6_7
+ 6lبQ£êîîþ¡fjjjcÆ5jÔêÕ«{É Ö?xðà+W®|¥Íý9s>ûK-ļ£n|Î9èëÓ30ºóð©
òµ¥KðÆ)))4mðàÁÍÍÍû_[[[[YY@EE ÈÈÈ @¿~ý¾8F;ØlvðýÿÌg~wBZ:ºV£Ã>yxïQÐýñ&/tX¦ªÖÿS^«¨¨øôéSÁJJJÄõÒ ::¸³³óÃ{ôèÿ¾}ïm¦¨¨øäÉ 8xðà={víÚ%XCCÃðáÃçÍ÷YÛÅãñèôOúÏ*ÜÒËËkÚ´iÕÅL2ÅÛÛ{É%dUeyùà ûôµTTT¾|edd^SSÓ¶¡¡¡±±ñõëׯ_¿~àÀb¡1$J $''qv<yòäÔñ#ßbÍÖe+Fãóù<ïÑÀ/m,--Y,ÖóçÏJ,
+ !Þk
5ptt^R__ß½ûÿn¼3vìXkkë?ÿüøqâÄ#G´²²b³Ù `ll¼hÑ¢9sæ8::@ll¬C;-+¿}ûö Zµ Y°` ¬^½ÚÏÏïÅVVV£Frrr"^ÅåríííÜÝÝÏ93fÌ###???Áj
+
+,X`llüÞüÂÞÙÞÞÞÔÔôôéÓ.466öôôlµO>Ô,$$ÄÐÐpþüù\.W|ÁÄ °±±¹uëÖ'¾ÝYIIû±Ã¹¹¹ ÊëÂ
CéÕ«ñ%ÔV.^¼hoookk+//ÿ¡2?cÆË/
+`¨±±ñÒ¥K×®]k¿D·nG¶þCúvZÀÑ~1wúfq¹\>Ïãr ø~À£ û½Gyy¹µµ5 ¨¨¨³¶Ù³g?ÏçÛÙÙÝ¿ .^¼¸oß¾;vÈÊÊ<y¢·m&Ð[7Á÷àõ¿}ûvúôéÍÍÍÄ?ªððð}ûö
+2x÷ûí·#Gäææ:88mÛ¶MSS322ÒÛÛ{Ä>>>sçÎm§¥ ÷EEÅEHå IDATµjéïï¿zõêÚÚÚ3fL0ÁÍÍÍÌÌÇ㯪¨¨pqq>|xTTCyy¹Í3Ú6èÑ£Gpp0Ç#uÛTÂ{£í³Äª^¾|© 0räHIIIá}"è±U3999âàÿDyyùÞ½{y<ÞâÅÇ ½zõ*,,üßNÊÈÄìY\òpsc¥`
+¦ðïIø©©iLLðKÚ¶4hP^^ÞôÎãñ8Nçü^h«Qä\KÇãùûùÖ××ð@LLËå
+ll:ØÞU+ZM ÀÔԸ׮ ±D]]ýÔ©S dggûÞfMMM£Õú_½z5gÎbÌ2mÚ´]»v¹¹¹Í7ÏÆÆ&55uåÊDûææf èÙ³'Q¾víÚðððØÛÛ¨e+m×éè訥¥E|
+T\\üÏåÿN${ôè¡¢¢B,¹uëFþLI¸Aee%q4¸FÛ¾ÚO"XÕ\.·Õ>ùP³
+â
+ËoÈÉÉaÊËËÛî.¤¨èæuÕ];ÕÕÕ»ê©9ÒÒÒK,ñôôl§Í'víÞÝÁÇÝl3ÈbÈ2G§ìTà¾ÿíººZ Óé<ÏÔ|ÝòUÆfïßûµ-Z´HøÇôôt]]] PVV·j&ð÷ßÿøã*((÷ Ápuumjj2dÁ±cÇɶ´´P±cǺ¸¸XYYÑéôö[ËËËÛ¶\·nÝ3g6mÚtûömeeåäädÁÁ/á¬÷ìÙ[__/| V¸¼¼|QQÇ«ªª¶} kû¬`UÂëlµO>ÔLAAø¨èxPXXÈãñ³õÒÒR¢Àuuî¬s\Õ
Ö§ptt4³²&;EÇáp8ç=ÜÇf¥ê_+@@@ ñ`þüùÂm\]]Ùl¶¤¤$Ã9xð `y«fåååcÆár¹ÆÆÆ^?ÏohhØ»w¯ £'N466Ç?¾jÕªÚÚZ:>zôèV_Ð;wîÀY,ÖG[lmm>|تe>},,,ìííKJJ<<<9âàà@|óæèÑ£Ö0mÚ´Ñ£GwÄkkóæÍãÇ8p 1Ìi?Õ§dn»O>dË-'N433STT$(**nØ°!!!áÄÄàà`j|ì g`xçásc Àºâ%GÑþ+ àïÓwîî°T ðëdÖcÖl áò÷ýoïsÙ>håe+[ªàû÷þܶ¹¨¨èû¹V}}½Ï·ëËååååÍ=;22òÛuôeæÌsîÜ9âª,åÁ&Mê<W-ÈË»èéqâÈ!mmm*°¾«oºs8Tv²ÛÙ>ª¢6iiéoZ ,,lÇ¥¥¥Ä÷[©ªª²µµüèââ2ztÙüÖßaÿ÷Mw*,;;;CÈNÑAÄÄÄ~ÿc;Ù)¾/ÖÖÖ¡¡¡zVNN®ÕçèËhéè^¸ægff¿ZÃß¾«5|£Ó"]Nv¶óêå_ùj
+Çãr;ã÷B|â«
@í)áìÙ³UtÉNÆ Íïâ£çÏwÀkº#ÔÅeeüïîT.X=zô诮Nv
+HºIJö×@|?ÊS©S§*ôÓ ;BH$ªjý·ïÙGýûº¹¹Íüi"Ù)B"I:}Ò8âÜU*°ôôôF@vNdöìÙÄejGYYÙþÏòòc&L$.ÄFå5nÜ8
Þd§èzöêe1tXCsKCsërj
ÑMÒbè0i¡+«O_Çõ444ÚËÕÕuë¶mÇ|æCÌ-¾/ý#IMNZm¿(,,lØ°a ¸ÿ~g~Ô»wï>ÚfäÈvËWv@з£¤ÜÇ~¥#qý/¢¢bRRÒ{/ÚÉ×oYy·c ¾
=~>¸c £Ë>ݱcǶnÝú$º½+m":¹´TöÊÅÌáÃSùÖäÉ«ñ3B]J?µM;viiiµ¿¥¢¢bô±/ :9éîÝ
+ÿ¹î+Ö3gÎNv
+H2ÓÓü:-!!¨ýµ3guÿì!ôW°ÿØI}}} öK\\\JJì!ÐÅĤ¤¥ÅÄÄÚËÛÛÛi¹=Ù)B"yý*ó7%Äí/©<%\¸paÏ~êd§@DSKç´q§^*°ªªª¨p«n¾gÍÍÍÅ
@íuûöm-ÉNI~^ÎM¿gdd µ§+W®Ô21ÿx»ï@}}ÝAmd§@]Ãõ}úv;ÝëêÜx0hÐ vÁÊÌÌ|úˬÙd!Ãyôè¡¡a¿~ýÈÎ:»wïÞÅÅÅͳ_NvTWWE=µ27îÓ§ÖÃÜK`íÚµvvvd§@q«z²SüOqQáÑý{gNBñåììla=ì!<z3t9Pû ûóçϽÎy!$Ò·o.y)(( j¬ØØØ[×®!$²wïü®^)..jt_»víàÑ8%D¨k302|öÜÒܨ=Â
+
+
+:ô×n²S DRX`Ï®W¯^µVnnnBÞ¡®®¶6!6ºªª
+¨=%\¶lÅp²St>O£ÑÈNÐW¦£§ï}+ÀòSÂ7oný}-Ù):ÎU¯÷îÜâp8dAèkÊËyýÇz§/_µV}}}Ue%Ù):θïýsî´)X¶p8Êò vÁ?þ3çÉNÑqz+)ÿdûKIqÑþ];fÛNþ¬²¥¦¦fmm=pà@///á%ÖÖÖûöí{o 6lبQ£êîîþÕ·¨¡¡aÎ9û*33³¯D.¶nÝ:bÄ á
sæÌ!.?>j¶Û¹KÆÆTzyy²[Hv5=Á woß~VÙRTT|úôixxøÁ
<}útÓ¦Mïm ÎÎÎÏ=c±X³g·w
+ÇûÄMnéåå5mÚ´O|açÄãñîÝ».8Ù
ØÀ)S¦x{{ËÈÎÊ\±xÍjtïÞ½{=;¾_vR¢û±#ß/ACS++#ø« ÊÖùÓî³,ú×ÖÔÔHJJ~zYYÙI&ÉÊÊ*(( @NNβeËêëëy<Þ©S§
+tñâÅ°°°#FÄÆÆzxx9sæC-®]»F¬ÿöíÛ/_nÕ²´´ôüùó^^^«W¯3f¾¾¾¹¹ùÑ£GËåÚÛÛ³X¬U«V1ooïÒÒR3f ±±±¥¥%ñì+
+Èf³Û¦ÞüGGÇr¹\bc,YÂãñÆ¿uëÖVûJ°áÝ»w·¶¶>þüÔ©Shcc³dÉ%K|Êûòc0=z Ïçç
+gwpKæÌ|Wú¶;ÖÔÔÔP_/øF£ñùüZÚÙY:ùYMMMCC#))ÉÇÇçÇ$0 þøã &´m 999ûöí{ö쬬ìÉ'-,,¦Nºoß>ÜÜ\ààà¾}û
½yóÆÛÛûäÉëׯ2eÊ1c>ÔRSSSÊÜÜ<>>¾mK'''S[[{áÂ
&8pÀÌÌÇãÑét èׯ_TTÜðá㢢¤¤¤ÊËËmllbcc[=<fÌ///7tèТ¢¢¶} 辰cÇ^¸p Æ/_ÖÑÑ2dÈ{?lYbb¢ðááþVÏ_õÕÔÖ!;Ëÿ47j°<<<öüµ÷Ê»Ùé9Ù]+---sl'766òy<111.k`dl·b¾Á1#Ûy¡¢¢bhhhDDÄ¡CzDÌÛi êêê§N¤¤$;;»ØØØÔÔÔ+WÏ677@Ï=555555×®]ÛÒÒ~àÀ øP˶ÙÚ¶tttÔÒÒJKKââbâQ G***Ä[·nyxxÐh´ÒÒÒ¶Ï@ee%qÉyyù÷ö%¬¢¢BMMMÐxÚ´i»vírss7oM«Æm7çCÚñ2mÇFgÿ;·ÍÍÍ©\°ÔÕÕY%;E
+
+ðûæ
+ñß^ÏÀÐnŪÁà ººêS^neeµ}ûöììlblõÑéé麺º ¬¬LÕ
+;F<ûÏÇ:ÿÖ±cǺ¸¸XYYKÚi) ¬¬\^^Þ¶åºuëÎ9³iÓ¦Û·o+++'''FXÂ={öÄÆÆÖ××ÿs)ÇVC!yyù¢¢"G|/±m_Âòóóà/12®®®MMMCi[°ÚnðÒÒR¢n¢l9ø'Aå5qâDé^}ÉNÑqZZZ.=
+ Æ&vËW¥êsÙÙÙ>}ødð£
+\]]Ùl¶¤¤$Ã!Æ?~|ÕªUµµµt:}ôèÑ...Î;wàÀ,ø±¶¶¶>lÕ²O>ööö%%%GqppÃ6mÚ´Ñ£Güsßà¶6oÞ<~üøí§Ú²eËÄÍÌÌ àÄ,ø]û»úç ¦¯J¿õ[¶ÿE¨|ëðáÃ;vî¼ÿ4ì äî-¿ »w/[ѶTUWWM3²cXS}}½Ï·ëËååååÍ=;22òÛuÔÊ9sÎ;'%%Õa=~ºÎvëE
+{í
+'!!Ta
+2dÖÜÏþ××uõUéçvîÙ)¾&iiéoZ ,,lÇ¥¥¥jõTUUàGÑ£G¿w%ÞRà[oôìÕkÖ¼}ûöjO ---èÝÈNÑq
+±$;B×cmmúÞ§äää?vhǧ·D_ g¯ÞóÙýóQ Ùa¾¡Cý8êKã :)É6VC£TaÙØØV×!$¾*ýÖmú8èN妦æÐá#ÈN¬ìCF§RP¹`¹»»ÏöÙ)B"IùbÖÏâââÚSÂ_~ù
Ãøº#DIjýÕw¹"¾¢L嬬lo%e²S DÂï¤,!!Ôa]ºtiëÖO¢ÈÒYÄÄÄÈÈÈuvIIIdGø?ÙY+3µ"Nå5oÞ<Ù^}ÈNÑxxxxxx¡Ï£¡©}ÒóP{ÕÔÔT[[KvNAFFÖ÷~ðÇÛ!ô/E2®%÷^\.§¶¦¸%¯¯/N t:ç¡.*/çõ¦µ#>Ê'?=TUëOvÐkjjzSR<}Òx)))*JÏNÄáB][}]mrB|uu5Pûk
+þ|ÏUB]HaA¾ëîÄê©<%lll|/ó+·!º.[_Wg3ÂÁ`PypÇÌ+¬#DW^öîïõ ö0<<üÂé¯wOPGz[Rrþ´;q5}*O Û|!¾â6_Ta=zôèÄ!W²S DR\TxìÀ¾×¯_µVzzú³'ÉNIueå³ÇeeeSBP@ý)¡¿¿ÿ®?6!$ü¼\Í222Ú«¼¼¼ /ì!456äç544 N B]õ§>>>ëV,%;BH$¯³_9-·OMMj,!ÑMì!Ði4qq :8%Du Ô={vñì_ÉNIVFú¿$&&µ²²²®¾Ù)B"Ò50$îSBP@ý)áñãǧÙ%;BH$/_¤N?:&&¨]°LLL~üy*Ù)B"QPPüñçi½{÷jO ù|þ³¸dâÓPP×ÅãñF6j°öïß?nè ²S Dhma b;wî$;Ï·"!!!!+ghlJvУÓÅzöêýóäeee©<%¬««{Ýyn`ú§ºªr²õqqq*O O81ãÇ d§@äåi6cO ©|«úþ¹Kvhú©öߺ{¯¶¶6Pû {¯^½hi!$IIIMmmiii vÁ:wîý¼ÿ!$¬ÌôųMJJjO ÿóÿtS$;BH$êÜ<Ú#,4Ù)B¢üS¹`]½zõ÷Õ+ÈNIÎëWëV.{ñâPûÔ·oßÞy¦¥£KvÐklh(ÈÏõóÝ»w§ò«´´4'ûÙ)B"ill|ý*«¾¾¨=%¼{÷îí!$üÜÝ[7gffµ§µµµ"£{ôìEvÐkii!NÍ ò+---$øÙ)B"©ª¬|ü ðÝ»w@í)áãÇÿ>zì!<|0''¨=%Äø!D|>ÏçdB£Ñ¨üÇêù÷ ²S Dò¶¤äôÉãyyy@í)arrò½;·ÉNIyyÙ½;7ß¼yÔÞæ!ª þm¾îß¿¿×²S DR·w綬¬, vÁ***JKM!;BH$õõõi©ìÀ)!B¨K þðÆÖ:!$Ü×Ù~[Ô.X§©±ì!ðøü¦¦FÔ¾/¡±±qvAÑ«Ìm]=_+oß¾Q éuîLcC£J?Õ3nÇ%$ºÉþðÃy÷ääi4ð:wFI¹oMuÕU¯ê4
+
+|}®è¿LM½ã{ÝÜÂ2õüqp ©ù ÐG1Ï#
+Mü_¾HÕÑÓ¿uýjQaÁ M-ïçjª«Uû«uw£Ñh=zö<ëîÖ]FV\\â§GÏ^½¼/Sí¯þöíW¼´õô_efÞº~Õdà Ä¸Ø ÿ-ÂCD=325{x¨g`x÷¦oîëlMmëW.õ×иxÆÃiQêÓ×óïRÝ»Ë\8í.¯ Èãr/÷ì£Ò¯¢¢üÚå´tòr^ß¼æmhbèÓwÐKVDØÓÇL?yø >6ÆÀÈø¾ÿíÌôÚºz~W½ß«Ð¼|γ¾¾®ZÿÓnǼ¼Â9¿e£Óé^gÏôVîS[SsõÒ
þê
+}}.ëe¼|qûƵÄF±Ý73ü,äqÔóCcÓ÷°uõ
+nû^/ÈË ¥íséBuU¥Zõ³§Ü={õ:ë~Rº»L7ÉnÏx(öìÕÜÔä}á\?ÕþïJK¯_¹¤«ý*ëÖu3ó¤ø¸ûþ·Í-D>
+}bl:ðñÀäx=C£»·ür²_iéè^÷ö*+}×_cÀ¥³§ú¨¨q;.ÑMRFVöÂiw9yù¼§r_ªÊÊk^54µ
+òóü®^102IKaßñ»>hÈШÈð§M?}e`dx÷NÆË4=ý×}44µ®\8WW[£ªÖÿÛ 1¼â¹Sn22²ø¥³§{õVª¯¯÷¹x^M]ãMqñ
+ï˺úé/o߸f6È">6:ø^Ù ÁaOCXáaF&¦Á÷沈uõ
+îøÝÈÏÍÑÔÖ¹êu±¢¢¼¿ºÆ
Ó§8\No%eÏ¿OHIIKJI]<sJ±GÏæ+ΪôS+{WzýÊ%MmÝÜ×Ù7¯ùLIJ¸}ÓÜbHdس°§Í>JÑ74¾wçVWùÓ=vüO¶¿65j° "ô)+" BÄÇD@àÝ;©ì$ ð÷óÍÊHojlò÷ó-È˪ªò÷ó-}û¦ôí[?ßꪪ¼\?ߦÆÆWþ~¾|>?-
x× bbB> VDXDèS
+yËz Á÷ï%'& ÀÝ[~/ÓZZ8þ~¾¹¯³kkküý|KÊËÞùûùVøûù6ÔÕçd¿ò÷óår¹éi©÷nßäø÷ õ<ìÉc {ú$*2 &ÆÇÀ=ÿ[i©)<.×ßÏ7;+³¡¾ÞßÏ·¨ ²²ÂßÏ·¬´ômI±¿oMMu~n¿ossSVzúݾ ÀNL|pï. ÄFG=} a¡ÏÃÀGÁqÑQ tïnjròÿvTS¿o~nNMuµ¿ïâ²ÒR?ßÊÊÂü|?ßì¬,?_ʾç6 $ÄÅ<
+ VDxxèS xò8õ ÞKN{wn¥§½àp8þ~¾9Ù¯êjkýý|+ÊËýý|ËÊÞúûùÖÖÖæ¾Îö÷ómá´d¼L»wç& $%ÄßÿgG
<Ð'¬ð0âO@ÿ;i©l>Oì¨Æz?ßÂüªÊÞñ7oüý|««ªóssýý|²2Óýý| %9)(À âc¢C àyسÈg¡ ðôáøh ß»ËNJÛ~/_¶47ûûùæåæÔÔ;ªä]i©¿oEyyaA¾¿o}}ÝëÞqÎËÔÔ{þ· ).îÑ@ ~þÏ;þäñ¿ïøý¤øx ¸}3ýÅ.ëïçû:ûU}}¿oQaÁ?;ê]iIq±¿omMMnÎk?ßææô´»·ü %)áÁ½ b
>~Ôåþ4Ñ?袰BT!Ôe`ÁBuX°B],P!Ôe`ÁBuX°B],P!Ôe`ÁB_AQQÑܹsi4ÚÈ#
:uJ\\|ÕªU%fffÇüXVV6wî\±|ùòÅ[[[³ÙlÁB''§÷6øêù
{üöYYY_=ú8>B_Cff¦¸¸xß¾}###%gܸqÝ»w´ILLÔ××777oõÂnݺ¯_¿niiÙjá{|ü^¾ncôá}5t:ÝÉÉiÿþýľ¾¾Ó¦MnpéÒ%/^¤¤¼ÿÒÕúúúít¡¯¯dii)))yìر1cÆhkk@RRÒ/¿ü²víÚÙ³gþþûït:ýܹs:::Ë/×ÔÔ7nÜ7o=z¤««{ñâÅ÷®¿¡¡XùáÃ5448 xjõêÕL&sÖ¬Yîîî»wïæp8Ë/¿|ù2ñìÞ½{Læ5k&Oú¡deeÍ9ÓÉÉiÚ´iëÖ_ýõ·ß~6mZûÛ p
¾bÐQ]]¨¨Æçó,Y)aµ´´Ì9ÏçÏ5ËÙÙ¹ÕÇGýé§øa
+233i4Ú'Oø|¾§§'Ï×××áóùgÏ7oÏ_¾|ùƽ½½ïß¿O,;w.ϯ©©YµjÕòh4ZZZÚ'OTUUg
+
+h4ZccceeåÁÛ°®]»F<333{ïJø|¾Yhh(±7&MÄçó
+
+
+_¼xÁçó'Lð%»þ{ »`"J]¾|¹««ëìÙ³'L üT``àÄ`ÁK.Ý·oñÃqrrjllóçÏ·]m«UUUt:8^fggWRRann [¶l WWW33³ººº'N ÀìÙ³7oÞ\VVvóæÍ9sæ´¿t:]OOOLL¬¢¢X¢¤¤dff6bÄU«V9::7õÖ§O
ÊÉÉÕÔÔ¼zõê½+)))INN¶²² XRRæáá xòÂ
¾²5kÖhkk×ÖÖúøø¼~ýZ°üêÕ«222l6ÃáTWWÿøãÄSãèÑ£í¬³Uªª*!¨wü÷]ÓMFFÆÜÜ<44´¹¹YBBBZZzÖ¬YçÏg³ÙíoÁ íWc0111ýõß#GÛ×ÔÔL4)11Q[[;++ëÆï] F£µêîàÁDãÚÚÚö!¬èè+ëÝ»÷5k¦L"(( P^^.##ãááqôèÑ'O.[¶ìCG¾@>}´µµ ::zܸq àîî¾víÚaù¸¸Í/_¾wïÞA}A{öì±µµõðð'.1NÔ¦ÆÆÆÆÆF ®Ñ(++FFF@SSÓÌ3õõõਨhéÒ¥_íûBòQBYYÙüùóÅÄÄ6nÜ(XX]Ø0öÁ $IDAT]=þ|qqñÕ«WO<ÙÆƦ¢¢Ïç755M:8&-xáªU«JKK[mݺuïm XR]]M,·µµurr9sæ7o>¬««@^¶mÛF4³²²"2|(ÿºuëW¯^ݱc¸¸¸««+Ï÷îÝ1cVZ5}úô.p¹Ü#G.]ºtïÞ½ÄvïÞmiiI¶+áóù3gÎ\»víüùó>}ÊçóÙlöäÉ׬Y3þü¼¼¼¯ýÎP
+^"}rrr·lÙròäI²³ /Ç°ÐwaÆøóÏ?ÉD#,PÝB],P!Ôe`ÁBuX°B]ÆëNÔW$ÞÏ IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mapiproxy.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mapiproxy.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mapiproxy.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,261 @@
+PNG
+
+
+IHDR Û æ ¸¤ tIMEØ·f( pHYs ' 'iQ gAMA ±üa IDATxÚì½i°e×u¶Ç3Üé=£C73 Ap(R´äPJdÅr¥*U©üq¹r)R©Êq"§ì[²bY¶HQQgP $H3ÐãßδÏÞYkíso¿nÎÅ~ÝØ_=6ï=÷Ü3½o{íµ¾Ås, `@ëh9 `» 0r@@@ÀvA`äíÀÈÛ¶#lFØ.°]9 `» 0r@@@ÀvA`äíÀÈÛ¶#lFØ.°]9 `» 0r@@@ÀvA`äíÀÈÛ¶#lFØ.°]9 `» 0r@@@ÀvA`äíÀÈÛ¶#lFØ.°]9 `» 0r@@@ÀvA`äíÀÈÛ¶#lFØ.°]9 `» 0r@@@ÀvA`äíÀÈÛê\_À+ÖÿëcÃðÈñÞÃxÏù¹¾Ê¸Ãÿúþ®§XÃøÆø>ȯ|ý[ǹDÖÅÿ9Úêð/l/é_㣹?x èx
+k,R'0)¼U¢n^p$h9
+9¢WÞè_àaÎ'ñ A}
+ú·¢Ýà9Ii8£íìáà2Ä.,Fþ `Ù¸B¶5Õ¤XÉ´$ë&4D£µs%)â5ìÌ«)R1¥éHï ³j®-Ü 5ÇÅ!øpA 0ò±àlX°QXX&$suRJpÔ°b°¾"èED¯O)èÅôqÿÔáË!©¹¢ä®!$Õp8oùÂè(g¹aë#VÐEÕL*Öj1!X*X2áYôY~OÄ×Ç+¶¾ÿAQá³÷üÁçÙ¹¦ù@;ÖBL# àüC`äï`7`[Åã
+YVº¼æ ûZ)E1PÊ.ÜÇ"4q¼EO Õþ\r-ªv>´,·¬¬©X'b1g(,7|6*ºxyÓ
+K _Õ,ítÄJ
+åª9N¥,ÖHÁdrº= ý3ÿ¢fÃH7¨zÍY[£d¶7#FQ±¼pëïYQ³³¼tqÄ«
+iZk&4ëôðüRæWÕÄxq÷û1²²?Oôg´$Ø-nÖ8ÀÈÑÑ8^ضÈkj×/Åê/,+Jü´¦<3`4ÇqM/j!É&)&¢¡Lp}OÐ:Äý3æT0
+õªsS"é»YÉò/ àlC¼¢Ù/
+3¶1r#6*8cH¦ë8÷æ(pl,/jÚy¶Çæ`»£,cKIXÿú45>¶d%ÿ×ö£÷~¬ãH¯èÚàjÇfïiqÖv³lÁ+³j}äÆ%_°réGgÙÌ,g² Õ\³Í1ËkäèùîÓJØE]¤Ýu$H|5kþÅüÊkùL5G|ÍÏ<¥\j;LÉ ªÏ
+Ôø-ÁZqcl¼Ù:ffn±~ÎW6ë,¯-WI,AcBfJqп\:ñ4b=x±f!P5½öqãL²º¥1(Q4VÚÌåkÞUMììè_ÝìðÉçïÎß·ÌäékC2¹¢ñY¸dSÍvPæËÊ8×x%22ÄÌ°¥5·¶Q¯@õrø±ò¬"ôH#Ç5N$ ¯kGÄ
+ÉËq¶Øc°[1Ùn ªlö[Mòá<ùÚIpOþuþÕ?mdÃã'ªýkªþ.]ÂÐ2ËÙÉ1ÞÅLEE*èåsW#2·1`K,«\åX`@R¶{<R:x+E!Üi»4ᨩ¯6HǦÆÌÊ"{*yoyÍ1bUM7J¹&UÙ£µí }û±#ÈõÄ+ãÇG½åEnñÅ/Ó
+/¬!/¼R¹®]]Û¡d|µoÆ
á\Äí¤ÓáƸ¬àJ³²¨³Æ)r+ÊÒCÉÇ1ÆmÅ\é½"bEÎÚm&æÀ¥-5wSκ¹2+
+g
+d1ÑÎĽÇ[4Y äY¶(ëïGþD?tï?ø¯ø FMÚrU㢦|PòðóÇ+«Êå
Yº¬ÃBÖ éÊ£øÕ\˺ªlijÍU%q#IaýPå½@Ædä¥ÚubÞí pFiÉ]ª¹ð©W¼0ý7Ëãx8fg¦-WÞ±ãs1Ic¹%UþM¾
+Þê÷#ùûýêÉØ`,39:uä%®CºÍ¤ÁÀ( àçËÊs»6dy%9Ö«#÷^
©2)Üv7ZÝ lWæ%©¹ã¬Óa3=6?Ko
+óà±%&a\¯|©_NÕq~£75bóÕûX3§rDöpNR^Èð®hBÌnKÝD«ùÖXÇOiÛó2Ì LÉÚ1¾ Õ<³T±ðsÅ
ÌÈpgÐqf×G<3bó¬°5P,ã@ÇFÌÊÔÖ:ØÄ+;¤ÛÀ¹Æ´Â ©ÔÆøckdR!ÐhG$F9Ös2/ö?vSvÄw I¹ zPܶÂÄg¡X<(Ñ«W³°Û&ìà\KVßð6ÅF>{:n4~ªüe7Iÿ0+̶Fÿeº9Äp9åHs.XF¶0
+¯ÝÆ°^ºQîÆ¥àRÖµ+òÂÕ¥@»ÒúÙºuUe0!lÍ¥P3³ªÝEÁ«5æZ CùznuDÊð¾#E£
¹×û·aHzv3cãD(|Ì>ðUgQxY¢jî(LáðØ«ãÒa³Hæ5úoü¤ËÓ_¼o.U§>K\ÌÔä7*XQàrå@Ê߸`ÙÔleÓ®öëþÈÖÎéH[lm]¯q.*c
+¨¶Y*áB´Zq·'cʹ躩Fíh4,$Q3èY¥±ÖO ÎH¬ut£Dæ§Ì%[ÖFlcÀòu;øǬ§°\pPàa;)î²FFƲE
+Ýä-7ei0@Íh< ðæDv2 ü j>½}¢v[¶ÃaËf8Z`¢Áø<ÉÁ z.¥q( àï
+&#r{b9;µ2é¨ÓkëDÕTßak;ÊÊñ¸*Ê
+¾è¨)Ûz!@IWlã «ÒEZè{æÕ
+§ú lrI,)¡(ÖQXwJsþá5[^býzÞÃ>À«æi-=gRüÑÎ"-9.$
s]²6ërÂN{¥ã:É
c%gUÎ&1MòêLì07¼þÚÉò \ȸ¦µô2HÐ-z ã£à³a¹/ àï#ÃÝÆvy=?¶4çH4^/ívpqV¡ý<Ö<³uU;Ìô 8ÂI)u$êÚe]׸)R¥±rRq`IëàqYk,Îè#Ähð5Æ¡ggôÌöasRL±p"j'k\ªWWèt1cd I\"AÃ
µZ¸xj6b.ð~e±hx°°ÒbÄ$ùlÌÚêtö
!j^ÎYW¹®â_þÄÌ^mi¥*¦mv¶gäáéc p^l¢uû
+pk4*§×Ö¬ë_s@ÀueåÖúfe3;¹Üïë´ÕÞ¹ÐY\»m¡%¦²U¼à'R¹;há¢+pcÈcÎu±æJ:TÍ×Ê
+Y[J#7Û$T ú¼ÒÚµÚºÓæ^&Û2.¢¦:¨öøI7èÃ÷éè{?ϺÂS
+ªÕÜNÑ H¦1c¤?E«5IWF%*ÖX²®Fvö¨[)°§`g¸gð-jÝMRëÜæGWô)¼¦ùPxU7²á§£qhä8rÌ¥çúp!âbäµÍj_åÖÁ Óhv®=×Ó»i(æ0*8ÈÏAtùLöç¹(Ø$Æl¡ÅÀnmËduÉÈÈÜÖ!¶µ Jít$v¡i>£l9àqNügKÍ\ñA=Øtã1¶|
+,0¢äY[!cVK`Èëa
+ZÍ)@׳4ÅÃͦ£cqJKbaA5xõ5Óx
0¯ÚR$Â'oË®vVx)q[Öa=òÀ[¢ºR=ý~¶¸@èr׫ýx×ñL"YTn ³ùÙ¨×smÞÒg|î|3gý1jg´ß!1 ,tì¨ßsQbë°Í3g0Ä!`;Ǥ<D ©8²,s}ú7"W{FUÔð´VlP ¹±Ñ°ÊÆNèXcð£LW:]%@ÕkËÃkÀÛD*5b«R;P¼(±w¤d\ç\5 8OãvKÉEÊÆPÓOÅ$ûùætïlïö1 þMï7HÓsVøYâaäS«Åñ¥lm`ÒíT<J³zY.t§wÛPÜk±DRáƸIá\U;cxe±u&(f©ÿ^YYºSu9ðubxÂHnWÄ.ÝÚÓó}©pNÁ]¬â«1òêHf^U.¬%W#Aý»)ñ#IxSãÀE(1Óç;¾Úù¼æíîûJk»%4Qû¸°j·Êä¼|mKm1¸ÃVTR7Y}
!O%³þ÷ìD.Ñ!-. àgóáòGY½²Qm
+ðb«¥ãHÙÚªê¶EFC·¶Y` EáS)LögÛ(÷¶ZY25ÎrNáÒ¨'¾ñ6"Õ
¹ú¸?»òɬ
j*¡Äd;É)+1s[µR¢×ð]XSaW¨|±(Cá8¡|â3ÖòÛà
+ûQ5Hûpe±qîlÞu*EÊm±hDnî{tò<¸Áª t=ßJ`·ÈýuâÓ}µaçÕ1OQ{»gí0>@©®ØæÐÁ#m¡lÿÙøë¼Âq~32\û8skýêäÊ8+ÌÜ\k×d&1¥oÊqnW˦?BÝk [¢H&1¹È#{bµªjÊUp!$VBS´ùh,½Õ½5Ò¨ .½¤Ú\íjVÍ`7 ÜÑØg¬ai Ö*m#{
+_TR#)dV´âémò"!+¼qTP¶Ó%¾1²êî¨3Ö !Fþà ü1Ç2^¹¢E.ÉH»µpBÁh"yðb³ÆI*NÎvðÌÞl¢ð±À©%ÏSH9 àïó;
+åfy-[^+VûA׶øSf/Ì´"Ë£á ¦àÝî|¯½14£ÌäyeJ`j^WcÎ1÷kWJr±ðJå¦Â»¯¦¯²S>Ç3|ì¶gÚ_ EiZDT1h"£z<áb4·;q«ðyÁ9b®ÉÓSÁ?Å}£(B2£X5F¶
ã'´"(µ×Á×»hÀC¢Â°u#umÂÞS?%íðÔpýºEzæÖ6õį.UÈËpI±¯Lá¬ß¥e´à»Hw#üpkd`OOV7²¢²2Jâ8I½s>Þµ ZÌÊTá¨X]ÔVè$Xí¬µ^ó&R,ESÝ4it.e,Óö4)êâ¼ ¾Ô¹¦öÕ"ø¹k>67Ë|\eÅ8ôÅ^«%¼!cMu6o1CSìB9`®æe îÆ<8Æà/6æÔv±¹´¨ãµ®©öÙʹTl¸×X>·üI4Ù`¿¢tBóc> $MFQ:|+Xê@Ê'Çye-_ÝÈóÒZ.¡¸3UVUÍ6ÜL[Ì÷ÏN;b½1e«¤Fø¦úø° <^N/8Ñ´±xSåY̲àD\¡Di¦¤}®1èÁ$
+¹q´7n"Öé견E©ªÒ¹R-¹t@ïÄj
+IÍàÿÕé;æÓ×dËð&spRÌRRá5-b÷?*æ.k¶9Âoár¢$ËfÞè3Þ¸Í)sl0ÀxH%(|ª.IÙkd©yY0ã19xø;æÛ¼Z â"籦¾$%Kj3ºW<ÎKD6Vû WQÅÒZ(Ák=ÛKg{ªLªtëýl0*@¥ÎÎu@ÆzÉYVy 4¢X(ò(ÅI2;Ò¹xг!RöÔT3b*Fi
+¤<$PúlÜ<_ªÐ-gC§LSL\ï¬ØõÙ^\ûPP\V¹¼ªk¦`Ø)ðu,éñ@S0¦©ð»>ií4) ÑIÐëî%KmÓ@ìíêFá§ê]ÇÒ¤¹4Æ=wPÃÅn8NFàeÔÈtÀ6QðpèÒçîèüp>2²µn×'WFQ%uiÌh\U¢GÀÎRs·ÓL"äU`äæy>ÄççÚq¬JãòùV§È¹ÖÁ)üSÜó¯/Ó#áL¯ýGòá`øçBÒT¿.(4<!q/·-Å4oÖâmñÖq2:üy½ Ö~Á-QDÃCSýÂÁ¢wEHªæú"ábI
+¦ÂÝÄSEÇdÐìõö(GzÅúR»óîúëÜRêv«¡ÃѢᡠæmù¹Ã=ßÔ*§ÅL1+ à ÃfÐ(¤Äü48ÿ¹(íÚFqruÁYê8Ò¥q^º,r6¸¤Æ
+8űÄÜ7£ #LÆýÍaêÅ
v»åÌôÑæÂ'²!fÖüÚßä<6ù,7,©vXÈZ;F´%-ù=Þð2Ñ«^cüÁÐÂZgD({§í +2{âdùÕm%5ZcÚ2&
¦X
+øtÑÛÑùÔ=A¾&íìCd3)Y51+
+[[g¦tí6ö²Â¤iGö6#àYÕ×-õèðÑaabÙâ0ò<
+Í~Bg\ÛTÇÆa^Y«µZO÷ïî )#òº?4£Üe®.$Ð1®Ê¡»±BjÜT50ZH¸õå͵Õ~«¥öî]h/®¨,¨fÔ¼b\öñ
+ÒÉ
9oô¬b8Ìs>àá¼
+ÖÔ+¤j24|°¸ {eM!ùÌRÖ
+zÿe÷úYZ*67r¸rà審Èö
@Ø{úºgéWéWtLǸx©¼á=
yã1#§1Zd F6F,Øøµ*) OáµqjÈOʦõK
ýÓÃmÐíæÎO5c³ØJ¥ðà|bäÚº¢¬_>Ñ?qjssXê(êv;³½´ÛÝTöº±&QªmsTÆuåÉ!ñùÌb¯¹T ¦S®EUÑ +²¢ÓiÍÏ·
+Ê=&;$3§HoP¹ »LöEÆlß0%g4IruÝÍëyRßÈáùôf7¡qfWWê"7^
+dí¤ôÌîdÚ\Èã(ÀUc®O+MÚ²ðCAE±aäkŲ3."
¦EpF yÇ®Î
+ÀõNSÀZR,ÛÕg8/gDÊ@Äp¢£½½ôg1(óÇ#³cVÀÉ?6Î'FÝ»¼
+ªþØP×M$âH+ÑNÕÆ%NÒ1{Ìå v-eM`K=LnC(9! GàØt6eëÃV³ÓÒÊ2;.áÈå²&à4çhßrá48Þ±³F¦´6G¦§#Ëc×Èmgêºîv£nÙßçuøÝ[^¶±aÑÖH¹8æ~cMeÙÀÂ(jÿ,e@û6Øâ9í9ÑdÎpIh:+ÑG^Ϥz\:Ô¼@Öãm¬»;Ãb¨i>÷Ò-mýhPímtØ08U|î
++K'
m;¢ç#oôócKã'ûãÜÎ#ÅÇж1Õ<Ò<VFéKêPÃm5¶A¹(U¤lÃ3ØÎ)Ñ+¸¸©ìÚÊf33
|ZÔ®¨\MbIw-®@vl':;/K_l¸Öú(Âë¨{²¡r©¦¤l76úv47ú|g)¦qj.ExCÖï£Y±» RÓN"eÄi
ÕwVá@Ôò5dd'é"\
¸)Eaqçxýè}ÓÛÖrVfNcáWÔªá[)ÖPÇ©ªKà
+óÆ%hÁ¾îºi åç
+#ç¥]ßÌ_8:è
+40ü¤*é"GcId¤TD-ú;
ÚÄ3öÄB6^ÁX9Ý,ÕÕµ©Gì*«ÞLÒiëH 7E
ûP{sdôòÄÊëÚ«dG4ÝD9|F³g[¼áSãI;tÁ¤Ö}©l«*¥Ê;gÛm¸¿¦ªM¨îìÔ)LzVQD;TG©¯(¥:gÞä¦Ø4ÈXï:YÉ>NbɵC¢XÆoùp¢¶sQM]f
+©ãaßIé`ó^ø¶RìÈ¢oúV¼0<°.O×sm¡U^üh7<ÊÊO׳h2ÄqD\r¿FÆZDJ¡N^¤ ¤¦k`T`ÔÄhN)h¸ ØJ¥9yb¹6fÏÞ
ÙÙVK£Õ½³xwÜÇ-ÿùX)rJ
+®jò¾¤\5$ójM21X³xDYèÜí(¥duÈ kÊôèñ¼?0:³/"å¬Öh¥Ø#ºf9e;3,ëPBk
{\K9ÒØNï)ÁõZP¿ã¾Òû{p¿vcïQSÁHÌ1®ÌUVh1»nFØ-°ªÜ|Gr@ÀÄùÁÈ 1O,-úh}¶¨ù$$"E$¢XµSE ¬ÆRÑ÷hÈÏ6"yCÃ@BR@Ã%¨¡(>Ìý²¬ô gççÚs3 PÏf¿fµÄ6aVmÎ3IuצBñÚ7åR7áfKöo5iU\ÑðzÞ[clÚR´éλ¡á²:]®©Sõ5³´TPO&\+¡4oÊXRûÂODt
+Ï åZ$-j<HËÞ; H.¹ª8Ü4fM^»k[b<Æ Hó$f))箩ñ[/Ù\Dt%;jâÿÉ1N¬~ÎF®k;UGO
+WØTÅÒÔÿq\£K&òr%S7¥@
±QÇ$_D)Vå Ê»À5:ZD&ÖJ7
+ò°iXÀÍÂÚÚJ¿ßÍÎtvîèÂNyiAÖ/o}´Ð¬ú· È©KÆN§[`ïÚQ:'+"ZñÃÚhgj[UM÷SúMê±¢:i:|C¬À¶ëcvôX%A³føjCPêE- |¶²!ßgt)¢Û-ᣪ
+kÀÜP'l]Y wNr®×âyQà\©gáQ)£«Æ#«æµÃ1õCIqaЧкÆ[Ès×\r@ÀÃyÀÈÖºSkãåõ|}P ´ZZëôZUÙóW¹J¦è}Ì|ZÍô¨þCÁc))Ay±æ$±¯¥U?å×ú5áI©æ£¶ÆR/ó¼3д»wuz)lïçØt}7ý8Шӥ©â{'O8ZUÕ8<ÈIß;×doUÑD<(STyçÀ°33)0ÄÔ~ôiíüÒkðN̳¨Q,Ç>í¬èva£Dr¸ÆÂ<I`Aå9<I×féjg )G\³6¯K»Z°«K± Gbò±rÞ¤al®¥¸Èø¾~®Õÿ|ØE@Àüíßþís}
+?eUoö«ÕU!aÎA&£àPDg%ºaò
@¿T)ÒS2c>¶ÐØd2ïFìLýòT
+ô ¢µ8øJNJNS½°Ð²/¯³Ò&îÄÄfY¹qf)Bõô: JAÏ¡xZ_ïHGÄäK6lBÉÅWb°¦í´ÑWá·¬6µËÈ°}D|µÅØ·1µÁjq&|ÏUAdCu(xZº]\1òjtOfØ×
+_§ñ#ªQ|<¶¥åíhK;'NjbUJwQ#³~åÐÁoÆQúv¬0&"hYWaF äóÃr×@80én§Ñ\/%HÁ
+ ÐwØç\ù¸Ese³¥±ðíôpÍ÷¢CæõéÃ0¿GCùÖý¨kÈ\SßhKñÜ(ÖiÇåÚúdu'í&%µ_¢ÐoûÞ½öET:(¬"YIÁ
+GVG%v2ä(qn°FZí#{9:ø9}L9|E^F#Î5V
PÜ3§QvSÔºØ%ÏgCóÆ2 ` ]=:Üû°gYeÖ¢kð8á2My7BM]Ô®áê)×n²§'E4ZòÜ )3\QÄC
ð$aôÒ
B¾óÀSJYPÞ0 èµÍq¥ÁD©
Òµõk˲ö6AU]+¦qÍòÞ¨½ÖuñéÉt'mÀ%@l,M¶ OiþíMúï0á[P®±3s½l/¯gQ¹s>íÆ2Õ|#Ã0+Fx)§®£á
+@ÉÒÂѸ*éÈB¨ _7
+L1
+¹" (ZÊ35
s¢Vc©Q"_V(âwïì
Ùö
j[+°¨ÛÅXÇesZ¾R8\XiÐO¹°ÙßþǼq6¶Ûh¡7< Mëù.Û=ïã`$
+¶¾[á¥a^.JÊî',pÁ. àb»Ç²fÕåñ樮¨ /Òb¦«g» ºU.+Ab±%.Þ
+i}£XBrè¯0yå^×ee±·©
_¥±`
+!»Æ¼{;yÖLØ«²^]Ù6ܳk¦ ÝÄаþ|&ä9ßzsP4üyV5Æ
+îKþ¸kÖ©S ÕHÚßw³6%ƦáJblîGm¨4öàÖº(*e¯%ß\YßÔºFVðÄpUN}ýX¤¬PµÄ:r´Sê´Ñb\³uÛNDç*¯o[©«`D[r®åZ±8±îÒ~·¢$ÉÿåT£=&àíéÃ<^xAÄ]0ðØkFQ@À÷Áv×Èð3¶)ÏùuU«¬°-WáÂ3Ðq9C³Úp©
+¶õb5O5å#5IYvÅ5.r°V¢÷Æbäf*±YÀøèq³~TÙON9¿8WåÑcÝn¼wW§X2Ëe<¢x:yãÄæ'øÀ¸phj̾£
AɯKÊ¿£1 d¾lt=æÁUTT <ÊÊ</£qdz³½Á ?òý{ga¤YZY×Q×9ÍZkj$Êj¼×BÃíD&xQ`«ªXb¦Í
+gK6ff×BÏÜðð
p©6cyáöͱ}sbyLsUãgä¾ö~o0
+«ºP{"SÔÙ>Êk´ë±ïÁyGçeT²Â há,/22xóæÅÂ6ßúCú
;"c²¸LG¯9úvbúÈ¡.®hIaíPÑó¾©èÃj`SáBh]?£À°rq(5Ð8ª+;UpìT½ß0ÜÁ)ÙI{Ë!Qo
AËð.7¡àÆò¹Ón>> MwÃKYaw¨åµÁæ`×=GSÁe8R·Û³A~ñÞÅå`°!¸â\Ñ9)D*:8@kóð¬k%Ô»¦zkÅ2x7eÖMðö(«ï;Ph¼×Xôà\0,eSàHcW~¿H h̸0Ô+ ÆB>Ë`²8ãp åsý°í°½òéÐi3CÛ ë0¦4ÿÍgÆyâ£3[a¢V7Ä6Z¾ÃðÍàezÐpXL0ð¶ÆøãÙYÉ@î^S TD|ï¨Û¤+<RÆ4P×x$¥ ÍàË°5ùkDìpQÞ7yË$<ú³MQùS{SùΧð®y4¬Ö×7éð=\*m0çYôz=`èþ°Ü»³×;l Dæòm·8¾ÀCo£]»%2+õmA¤âØ©Ä`F^«ÙpAvZk?RÐ:#Û^Cçy¼áC£jæg+ÝLYµ[
Ã5h2æe2lXêEÎÂöfdîm|«¢ÝíèÑMBø<pYz!
+* Ùزª/ÁÃ<aYÝ+R5á¤vib
+1²Þ±p"H³ØÆ=îkJȺà¨HÎ[²QÌ%$WfyçÆÓÒÈJΧ| 1îÑ>èá1Ë|õ°)´ÀýB"öV¦FAZcð¦BÖç:¬cÿä¸Va ¦Ûí £³rÇ\81ËGp2S;FØUbsæX"á3-«TØÃx£ÙÞó$Q
+åÆã"Ib¥¸àà|D `ê
®ÒÝ0yR 9µâADÉÅL8×8VÁÕÂUp¶7#å¥e
+ê]ã©FY%
+L.OP(¢(E7³uõa¥V
+çïÆàÚF¬ûÜdlâ¦Z`á\
,!R©Ö©k¨wmcäs5µ/ªI+([ËNyM$rã#ÒùþO¢1Âg¬Ñ«²d$|É·OiJ´ip~PÆ;Ùq¼qN«8(à2±ívTVV³Ý\'4°+Ü Àxc Gä:ýK å678íÀ²HÁkQS¾²uVvJÆÿ¬¦ðU¼°Àæȼ5Õ¶X³lsÁ°¥25ɧ³ÊEd6Ô¬hÆZÈP1°Û¹äÇåpTyMUÌ«[
+ïʪ*|q¥Áù2Ë6
+ñ¼Æ¤?¤Ù¦!wŬiy$¶OuÀpÎêU½[zQJJIöôÃkcïÚCÂ~Q1 $8ÎjæwRì/U¨)ìÍóz1ñ§§lGúÒ(hïRâ&²Éô"eõ`8¬A¯Ò
+#èbWS@B 8à¦)Ðu^v¢±
ã½þÐæ>$®6L>X;%5Ïö§¦6F©ÍaÖiDZY *
+¦À!ãHaâ²u½{MzºpáJS4ÍVp£@wS¸æ8y2°Û@#ÍKµËIóR$B`Ìû6ÎFÌkpHL¶ö*"UY6z\üJUéhãxm}½\cåCÕÙάLI vÞR?r¼2t
÷É|O&TÖpxiëzÁ8ÀÚ-sö¦~ûæ Hb!ÜÇ[ÉûØ6ò¨mVùÐ\Tcð-{Dgf<.ðøNLRýòDc(-$cÑÄ^p£¿¿W¾¾É*9ðV¤º=ô
0¢F8Á[?áÈ«b8*çÓ¢
&'|\ÏÄ0:BKeÌrÃá
+ÒÉ 9R"/ëHã¯~G
ñaqÌÇk*|àØ6¨ä ¶uöÛ¤>MÀ7f±£ü ©(¸¢D%a4xèÊFÚ;¸S2f$cHUÿ
+Ìñq¹ ÿ×c®û(c«^ý¨Æ´3Î)§C#@ÍÑJS^1®Øù:fänæëú¸ï$p¨ÀsÛª`Ü.Îiý:zLìí½è6T0"ÉGÎrÌCð6IÞLôÈÛûÌl¤ý(+h·=rbW\æYÔØå׬۸8i£cÐNá`aêO~îo£<ùî½_|ËíÖ*©VP겨¥Ð8ÚìXlsÔåÂBG¿:µVÆ»¢]ß@*£«§ÁÐËì°9nØJÅòX²\p43ÒÂÚznk[ÿü<±5²x6÷GEFÈdW/£D¶Z83/«
+QStÕ{>DØZ 8¡ÆÀ¤Ô.Ìä1ìrÈ ò÷ ¾oà°ÞÁØ pæ¾?)U'×uÓp 1}}Ñ@93éJW®Ë¼âíX´INúÆ£të1ßÛÚãP»ÆÔ;Q>ó".HcqS£Q×UMÁQI&¸*áiÌíSãï
+¶ÖuõO>øè/<ûÂ)àå·Ý}¤,e6I¼ Ü
õ2F»ªÀ$AÛëh_h(Uc[á×4ÇY
+·hV¸¦|Æûunðé¦1Ø#ʱæ^0´ã°ùV;!é" Àã<âµÂÜ6fÆä5®ú[^a S²I#Ùk§iöÀhÅ¿6/*US0tceHçÌU¦ÊË" ªíu¦^Ø×öwd#:¥LKéUMùÒ1?hèS9ø²¡P4|¡¢e=xh;y:Üìí8kw[ÃQv|)++6ßBëaN^?µ7|ð6Èί¼aL]8ÑI£öQFùvbj¤,
±Hböä3¿0ðP6!j<Êa~¹:®+EºÛ}ò6BOà¸áЮmdKë¥ê¥ZmÒ4x8Æç $>/G®ÊªZTÄ+ËWû8ùèø¬Þ¶_ ´¯°l3ú>ÖXà HѲFy}®ÿĶΠ#(ÐHËVª;íZÜ£¤UI,ç4Å&à¿ì(®²hNB©ª¢ÈqÁ
+óvõ Ñ)-Ö¡åÁ\aâö!Ó5ã}¤ðut<%0W©®"c¶HkàPÙUsÛØ9Eç+AÁnMãÎLgcmóÅËýÍv¤êE0fø?j¥Ð
+¦÷è^Îp0àñHc(ÙZÀm´;:Ë¢µ<gLYWMòéðºýò% (%ìÐp^7Å:ìçn
+b±É4/æÿE]äYÒb¤xSÃÝW
+´þ(n"àè&ÊÇ©ÌÇn}ä:|<)M4ô«**¦mS¦ºé3ÝTÐÀsu'UÎFh%f`еyIú=9LAÛy4ßKA8
+á`Ú>.1zLa²·«¦ qÞ£BiAn>ÎÔdsüO5
+ªª2eeÇ9Ý£¥aü¬(²VmÓVûݱ(LFK4U¯AÃÙ\Û|þ
åw´EôGÄ\h²á[hS Gcb¸ZÉ0©ObsÓsë%c>7ßKÛÜÌ
ÃÆÔ_¼2D0£¤¨* õ²víV©&¥I8¦cg×_qÙ= Ww/.84Ã`ãÃA=ár¯xF®|¢»t^¢32rjæ˸ØGA ð¬pãÍ$ìTó)ÜÄáöåi êaD÷d hJÌ(+?'ÌH&n·¢¼,6û.ÓÇ
+¤¶£F? ¼äincZy9V¡
+}È°¤ÁüJ
+0Æ&t(\6dµ/øÃFtè»6UL©¿¢öÎzçó4Ó
+,ì¶ØSk¯-Q'¨cU3ÖZÀÉø.Ò¢7ÛÝX>ýÌ©«¯ØÕµW6°<ûöPrmà%P¹
Ñ>#<Ì©»ÑHòvKîÙÝúJæ4%VS!>ûáª
+j
+ Ïb_éÂÓ榨]íÞ}÷«Ñ_4qíN&ÙT^ÇIáQ²dñ¸àÆBD´?®Ñ^¯²6BÖtpËýK4ûg0&qTáÓ,*ǨÌ[Fi*³¶¼ñëàè(Âé¦çÍb@À߶õÊÞÙ×*
Ò[!£Ö,Ùk1c¢F'"º¶ðëdÜZþÅ°EM± Å× 5uUã1ÆÚÓTÃ$ÝY
fë ²5íðQ/D¯"*Æä\¥#o¦FiÐ:`;ÌX%ã4¿¶
+×d6®Ö7F;çZùÆF{jÊÌõÉX(É-É2¸g
+¹R±ø4ÂMá8VÂÈ* n³é"å;¸R{l,MôKäh¶`´Ù¨'QUðÜbt|Æ~Þ g²4ë´Ùd>ÖB(<¯öGÅ VSTØ£óÝMò½ÏÊF¦3,¼Æ»×rÊÈ>Sùçc©ä¯0a}/ ±ÝÝ8Ïüg¼´¯ndjWR¨Va»OwäIàBÕH-¢´ÆbݦSøÒ2Á¤T'H6 ¶h÷B¼0£4ös at .ÃZcúA[P.SÁ´{è§^:v
+¸)¢7ßy£µæùOleµ'ß·{~×ÎÙk®8Ði¥ÀË'VÖáÓ-oôÇI¬/½xçÕ_´saf°9è¶ôÁý=¸©AÅN,eÀûiã+Ãï>wbiu󥨸¥óE»ço>rhÿ¾IL.ôÃÊqÄVÖûø'pfÿÞÅk¯ºôØÕÕÍã§Öà÷ì\s]²WcK) ïÙÙv0wètÕú³/?µCË®3¿pÏEá¼ì´ÔÂBúû¿ôío>åU¦ï~ß;aà{æéN]>yâä}»wïÛqùáK/¾h'(ä±qR§aô1
ûÒçîágà1å
»çÞ;/»âàñ£ÇN?¹¾¼|äúï>è&1Æ{yieyùر¥þêJá÷íܳgÇî=gµI}ù¥úà_WUÿ¾õ¶ëÞø¦[ýkøÕüé>õÒ'ýÛ+¯ºôÞ·½îÏÿì3Ó-oºûÖWßzÝYG¯`Æ$cívú_çÜ\ï\ÿu?Q)ºm'èãë0`m=SJµ;iÚJ9QÀfãÌdp6NÖÂLEÀv#Rë$A½Ôe@²¢
+ÇFcû\V
+Gn×ì¤E<©UÛÍaIYd
+jÜs/xèÛO1¬Æ õw¾ûòS«[Ç5`#×\ú?p÷w>öá=xrycëõ/Ìuï¾óºwßóªaV]Î.Úv53É©å|e5ÿ«Ï~ý+}çÔÊf]Û³nü¯>÷õ÷¾ëu0`×*æªÒecsìXÿ³÷?
+ÏÁùË_{biµ_ùgB¤ÕÕW\|ïoÙ¹87ÎrxVÝNTÁ°|èѧ{q ö9°oÇ=w^ç°:QÀóÿöÃO~þ30r}ùÅcËK+ëÓÁ×ÎÝ;ÞóÞõÖ{o·4º*yâñï~é_ö»]rÙ/ßÿµ/}á+Cx¬Îý³ÿå7¯ºör;ÉïÆüãOÂYúÒ»åûôì\÷{îøø¶n·=ݾcçü`0þÂç¿êß~ëá'/¹dïe÷Ãë/Ýÿÿï?~4§ _þMh8ò¯î÷;ÃÜ|ËÕÞjÊã=þÑ|Á¿¾ñ¦«Ò49××ó)jÁ"-;mí[Lc at UG)~¢¤ /Vv8ªNΩ¢äUá4í$êvâ4â¦Ìóñ¤Gó.ol+`¹þÈGUmòT۪Ļ¹9Ñ1J³«mæûÎó@Á»}þÅaö½×yriã+ßxú¯=ÙÿO=zöøγ_ºD(²
}l\ÿðÇûÔ}߯Àű^ëÍδ±úÓñO>}ô²wïZ«©¼Û»´´þÅ¿ý1Íp1ÖAå ²O.?ûüÝ;çf»¶6Z `·û¿öÄÆæöéuÓÛn8¨Ñ?êuR©Ü÷íÅç2zF«+kyu£áèÛÜ\äªB7uiafòͯ~óÅç_òû8zò/¿}í7:| ö±'WþÅïþÁg?õåÑh|ÖØÅ/£ì±Gyö¯;r¸ÓiùíJÉC<üðëë}x;úýÑkn¿aiiõÿü´¼¼îÿ<~é}o~×»_/z½ö}_øçú²2w¿ù6áñ7õgþ̳Ͼìß¾ç=wßxÓçúO; qþidFÿEÍÏÆ .6Fõú¯Ñ 8&I+
+:M^Ô΢ÌeYTT5!¹uúÖ¡£¹Q8[s÷G<«¢±]©óÒQ3{¢Sëð5¾ÙÏ
<#;ôöî\*yüÉV7ýöµõ£Ô½Ë.ÞuÉþðú'^ZZÁO@?uß÷ÝtE¤":b31îÙ£÷õ;âÌnºîà{ßuÇÜlW+½¾1|ü;/~èã÷gy1ç¾ï¡ë¯¹D0a,z
+Òq§ùÙÎ]óíV²¶1<¹´6!XZûÔºhï½v<gg»=1ìôyVUÙJTBÏe^sFpG¸hÏE{²8úÂÑS'NaÖFQ~ê÷]qåÁë^uc¹lÌPÃÒ©åï÷ËÃ(û?ôé¯~åÛÓ¸dß}»adzñÅÏ?w4Çyû¯|û?ÿ§¿üþçhÝüî?°û×ÿÛwýîïü/A_ä0<·ç&ÜzÍ5ßÿþ·úììï½âÊKúúãt%k?öìwÝìw*ú»/ú× ©A>ë¿èç%#ûc©ó\\85¢j´ÊrWÚpJeè¹Vf÷ãQ5dRq-jÇuãlulæûÕ9+GTÈÑÕ~9ÈënK
+2SjÇl¼o^ÍtÔ¬^ \ïýòëßtç$á_þÛÇÿïßÿË)ýÕ÷¼öo¼a¦Û&úâÿËÛ|züäÚòÚæ¥íγjc³sò»Ïùïý:î¾óCïk¬,Û»{nq~æ>óèw/;±6ænJNôV
+µ5sìÊûÞûöÛfgº\j8ѳ/øðÇ¿=÷Ò¯~ãÉ×ß~í¨*É£$F!(±Ïg:ã*hã·<Ìèã·ÞÿªÛ_£ã´?¯.~ê£~à_&gógú«+®¾Ü(ôqsöûü¦öíßsåÕ¾øÚëû>òí§þúMd#m%ø÷¾þM·¥ºÚò3zàÿù7â9÷3~àk¾ííwNøº;oþÆCO|üc÷1
+ÿþ¿ÿó¢(ýGIý_½w~afúöî7¿v¦¶2õ׿þØ[:E³À¡Ë wë¿èç%#{ø¾yó³I¤ÅòzÁW.Ëm¤1ãMÀÜÛ 2Z«`®\ÜiÅIzbq¹Z%£1¹®cDX:}\vKVÔï:¸h§nm)gxõï}ãMi¢5¾{Õ
+/¾hdz/4J·Þxù/Ü{kDy0ÜrãAËÏ<fYyjyõÊÃ{óq¹Ñoyã7¾æo.7\}à&ï/Z}æùß}æØó/5Ç\Ûns³ª°Y×[Ø0 ¼çm·íÝ5Í'`éÞ;^}õ_}æk¾þð>}ÛMqér8nuZ7CLbêuYäÕVë;ïzû»ß0ÃÃXãÒNëî·¿å§9yü|úÒGyòé+o8RQúßz½æu·üÒ¯¾÷ðá=¦r³]¬bþô§F~{ßq×ßúºHëÍ©íL'yû;ïúÖ·üüç0^¼üÑ|áõoxõ4à zù~àí=ö×ÅÃáxz®·ÜsÇíwܸõìGn¸baaveO<þ,Ô¦zòùñ¸Ã¬î>×Ë
+Î*êvõ·[z¶ìÛÕ^fRÙ¥pGQسX;Ââ(Ju,tD~jÖRSQ,=Ʋ:k_ó3¹n¬¥e6®Ü(é$Ç.Ôý~Õï×//U/Ú«¥jØ
+ýê.WZUèï½N<ýôæ#Ð/Ôb®.Q¯\z`Çôâ±ÀÕIÊ¢VT.M{ûì¼ýs=ý'ýÿý÷>ôÏÿÿò»ÿêÃô¡/üí7x4)SlcÕjaô|4>áݵػþê0k-ù¼¹ë¯¾xn¶ãwXYë÷#4¦XíÖÇØëµ%¦3SW`oþ0â$¾ëM·¢ºEÍ¥fæænºõéõ<úè3X#»3Øs¿ùïÞ½{èÞ7J\ß=ñØ3~$ßx÷ÔjûÒæÎsßþ»¢¨iX
+zÖǧػwç?ù~yë¢à²û©§ñ
+={o¸± ¿ôâñgÆ ·×ËÎÊÁ8·85òq,âÀ ´ZÙ(Y=,ÊÚ¦À¹B'N¦e)ïÖmÎEJ-Ä Ûk¬3EVæ(ëVÚmu!Ù¸¨ÖÐ@ÃNB¬I]´wSÜYãP1±ÀO\´óÉê+ªíéO=8u;ò)k1ºo?ñü?þà#ß9ZlõàÜ(˼h~®½²Þ~²o÷üâ|dìh8Æ<aWsg;CoØ,«ÍÁxçL
+.ËiÔ¡Q\Sµ±³5M³¿B,aLiJYVhµÌ#73;3=ï±cKZ
+ã;#òðUÜ¿6´
amêbÅ¿|:b07×Ã,7ü%À0éÌä˼haqöÄqCý®®¬_|ñÏàÖ[¯{Ý7OS)à©þÒ{ï¦>ëQÁoó
+o|õ}_ø°0Èí¯}õÑoºjccðôÓÍÚã÷ºüÀ¹þû
+8Í»qù.ÂÔ®µÍjch6FÈÅ@Ö\õ¦o§
ͨÑ}\Ý°åXëÇ°xL>£ñåºÆÂëj}ÜçK«e1î´£;DÚÞºx
v?ª1 B²µgT«cØvÄÕl«ô½é¨BÙÝÿÀÿî?éâ¦75Ókïß»pÅå{ûÎËO<
ót H¥´¥DEªÝVÓSÎôR8a·onoý¦D¿¾9ÄAôäjàu+áðÇY5.²zbiDîF£w
+Oô>lªF9}#+Ëkýa®"é+§Û/½ü²i·uÙÇjr,BØÑc'§V;¢Ä §Ò´®ßhç4ý>0,-õëÞXæ=ý$}êɪ·³42àÚk8°ûùçÁëÇxùů®4ù7ßrõYZ; àÜâadFSo&xGNKÇk¹sÙÆ°2%Øv¸ ¹9'|wQlôTS©1º|BËÞ;3ã`:F)(i×æsÛ©¬rÎ&)z$#,L9à Á÷þ`¥Hï¦qúSÎ0níðzF£áÿõS:Þ¹Ð}Õ·9tèÒ]½nG§ê_ý¿02[{³±3¾Rîô OôÑZÇ!(±òÏN¯)Ô
N 6ìt~1Æ1FØÏÉÛÏ{¡]5Î]·ÍãFµh§Ë«bxÇî¹s¹3îu÷òfu <éÂÆ5ïÝ»«ÕJ<)onûýAonëK¨*°B§P¾²²±ºÚfÆûìÞúþýÐ>ôºuãç?÷·w½þï
+AÌ/ÌÜvûÏÈÏ<ýðøO<çSâ$zÍkë?Û3pá0òVìO"ÁºI±60ùÔ°ÐxJ56éÔÆ@¬7ãäVfåè»ÆmUbüsM=R³ê¹$R6a§Xq+!ç+[ä:¦=oa,¯}3¨£'WhæòóÝßù§ï¹öò6ÔET£»PQ®¡PµZÙTÓ6&§66ãV6×XÞ«66GÓtGóÝ9m0å7¾ ¯ 'ÌÓtOàØË'_q2Glq1³c/^ÏÂ
Q^w"_ksú`ÍzÍò¼.JÕr×»v-xì÷pðùExæq$Íò²N´xú»/'yÜvk~îtðÐ×ÿË}ñ¬ZÓÑ(ûÃ?øÈ¡C¦¹S¼öµ7}ü£÷ÁÁèG¾ûØ£Oûí!d°
+q~¯ìýÌôâý{:ìiϦBÔÕpPÀ컬PS<dGc,ZµO/ÕvKÌõÔÅhq!Ù»§»{ÏLoda ÿ½s%ml41¢<>jáYCýª§ÝIrv§JBåÜÐôÙãüÔÊf9)´»ôÀîíKë¶ðheÁN.m>ýÜé·êZ\½Üi¼¼ñÙûbÕi-,Ìt:IUå÷=øÈ´JeÏÎÙùÙV9ªÝNO×°q´
ã
+ôÅÄ> ½ïÓ_<uj¥ª¼'vä{é
¿õõo6· ÔeÂy
ëüÌ! x|4¦Y¸¦Úëµo~U£dá÷ñÝWGTéÞðÙØ|üc_ôE1Ë.Û·°8;=àÚê&0ï4UãÆ®*hPÍüä¾×àðÀýÙÏ|å»Lä²Ø¸052#Ý'\I¢Úëù©Õ²¨LnRGô2yqàc4ôö ´/Ì·öì9êr2_×Òká·@*1þà;ãM?jºR)ß%
lerûls¯Ó²)ÙxîÅßxìØí×íNµ2){ìéSøÁûNZßrkhg'}¬Oбÿún¿ùò^§=\~â?ôÈsþÓH«×Þr8Ö*µåVLľ1®?2GpË0¨Ù¬öü3Ïÿþ¿þÃ_úw_}ÝEe^=ýÄÓÿåþbÐøO/¿òòÂÍ ñÆêÌyð*ʬÓRDs4[\¼õw=øåo?Ü|éÙ¸¸ûÞ;¯»æËÐå§?ñùoë) ¼ÿͯ½sw·;WÀ§ÿø¼ï¹g_þWÿ×F×ç>ü§¾áÆ+¯½öÐÖ«ðÑ¿ùF9p[7ë?Ò³qÁ2ò Ûi{~6:¹R,oTÜÔµÄ,e-X¡Ó5d¢fD¨Xm=¡9D
+m09Að-ó
+ßCD 8jñ7夦];½vfP{ê§aààÅ;wí9~iwu}ð;¿÷çî_Ü¿{&+ªyempÆ-Që¯ge³ò?~ðþÄWgºéêúÞN?ºåúËn»åJ)Ðà_Çç`u}¬uJÌòN0XrÒ|òñ§þÅÿö{ó³@|ëý©mµZoº÷-IRWçÓצ°¾¬ðg:b0.êÚIÅ.:°ïß÷æû¯ÿzÛ¾þèÃß||v®§µ^]ݨ&B÷¿ÿÓô5F*8׫`ß÷Ë÷\sÍÁC|í«ýÍ¿ÎHAð¿þõÿúÏë¬ãÛn?òÁþõÚ¤abÜï°pÁF-¦ t¼ÛöïJî÷ÌNÌÑÊÍ#Ç2!0D+)à+È?èCQk;¿FDd,Û²°GɾgÍöí3æF1úöN¼uò¦hw,ÌüÚûîh¥
+ll~ì
îÛýÒ@ǬýG8¯Çкßrº0
+0ýAöòñµ)Ãtᵯ¾òýÊv-η[-Rßzú¨34U2â+ß:eòôZmÚWUuêÄòÚÊúçæçÞõþ_ºôò¬i*hëÎx8®YKÐ-kű?VÁ{Þ~ׯn1Â!aeãäå)ÃG°Ã/¼çMÓÉ`0úÃ?øÈUßö¶×qtÍ>£TïÁþ̧8ëoàÀÝg çk®=Ôë
EÀ¶Ã
¯§H4~M֫Ÿĩ?¶75i^nÈ{|YzÙÒJóo=ÝlkÒÎ@Ë°)©KéÖl
+Z»£d:ê*uæõðI¦
Ùݯ»>Nâ~ò¡'9>]Çk§ÑåîzÝmW=òäÑ¿yð F¦9O<uìúë/A¥ìÎXÙ»õæCw¼ú}ô+/¼¼ì Àãs÷¼ãw¾ùæDiÌtnç¦*Üé\<\®gºçEï pI¿úxâǾõÐ7Ç£¦@®ÕJ_uè®{î¾øÐåÞ¶G@Æ5l¹CJKÁ´?Ë*ÇâHæ¥"K$IòßÿÖ{o½íú¿øÏ?ò§úçb¸à¹¹ÐÅïþ
7\äð4}Îòû¢7©`äùßý£_²0°3èåÿï>LæÃú[^uÍÖôdüÀ¿åxûÛoàÁ9`ûáÄÈûv&ZÚ¨6Çدc¬µúÝKE
+©}~1)eFòÊ ý»ûõG®½r?Ð(ðø®]=Üê°9ðÅ=ðéUûiÙMÎÏ÷¦}
+à÷¼áÈuWî÷<AÂjxhý®[¯¼ùºKzöä±@P_whñàE"¯¿îÒ¯»Ìó]W:Gm9¶ I½áknºþâ'>±´´¹Ñ]uhï%vìÝ3=j½ð+ØzJû7ÝÜp©V&º*mÒÇN(uú¸»w¾ûÚ÷Ýzçk__]]\\¸ñC»÷î]^+à8M3mß³[_{ûõG.wYi/;|e»ºve
¦}£¬®
+Î%*!b)y/»êÐÒÕ^8Y7©'atËwíßêÉhñK÷ýÓöþm§Ó¾ñ¦«¦·¾ówíÜ9oÎÎÀUW_/ÿÛ³gñkë¿ÄïW#ûs=ÝIÕÊf±¼YfØÌÝâÃÌiÊ®Y¦óYÆÙ>k ú_¶ÿ+öûõ:N?¾IY0 cøÔ
+tXL±£
+Ä`ÙµWì¿úðþ©èÆÆ"»ç ÊÇ÷Ýn|ãu_}øâí¾yH\f<x`qßîE,üjäbfÙê¼æ[ïÜñêËá°ØöNU
¼Ù#²*ó#W_Tìµ*¨3KíviÍÑ6z"è±~Ñ(%÷ؿZc&÷sðîW©bYÿcö
+\ç%_ÚÒv:nÁCc×+s²¬S-MÍõÒY®vìÜ1»0·ÐàdKåb/âlõ
+}û7ü_ëÌl÷-÷Üþ½Û£HÃ-|öÓ®N"0ÌÏÏ°íW#O̳s>±|j½ÜYS¨ãhaÏga¨þBÐ:.åù÷¶)f¤ ·æ¹57òÜ$FÕq5²§ $}ÂI|Ïfÿm$PòZGÎcl:ÛAΣªöX²iýxû=yG>úÑð/½Àk¬ø
+Ò>aÆF
+x`\D,?ÊÂ¥Ib/ßR!b¡ÓâÃsÊÆuMÐÔÕþ1aJ,=ái½hAG~V®âX·¬Ø¨£4naêÚÿËüGù/+³tjÍ×(¶Ûé=o½#,¶'.ü½ÐbݺxWº£DRÕØ~GÆUu;f¸\Oú´*0F\SLÙÇmáuYùPFs(GUÑÞQ#4ÒYʲð,C¤¯}'=OÇÈ\÷¬=Ò1AÆ,ªfídoR¢qì,ÿK?øø°/#ôëM>×|Ä<¦@t¶X GSJÙ˧¥þμð=ò.uª¤ª?*TôE7äïÁ'L§Ó.ì'J(^¢½§k·¦9Y}r§¶UØa at QK(c?;`Ùô'N_.H¾éîÛ®9s/ `û૧Ð_¼»ÆåòFµÚ/° )bÏwõHñqÁlfýHÔ
+útÎQàÊ&ÄáóÒÚd Ö¢ç_ÆÉÅÂùÂeVÉrjÏÜ@|%²k¨²²Ø6Ta¿Q,Òct¢ÓIxgä6fRNÄMµÛÍÒ"§K
K0Ôl4í*FJa)"®¿II[0Â`ò>¬³íXãiìm,ZYrú'yl±ókF&D+Ç
+,Îx
#/í$"+°¢/¤T|FJ
+
+µÀÚöï
+YüÌ~ÑZÝrË5øõw~¯ýE@À6AøÓl°s.궵pý«ùòXÇIåd§-"ÍA¨ZÏ´ç¦òV`ð¡¡Z¢9 ºnòç`òμ #4äXnµøué#Ô¤|½ 3A¥9KV,7,¥8·ÈÇé½ÿñ7ïµäG·o÷¼j{ZçD;±ÿ!7¢NÁÒ4jµÓN ÓQk¸U.p¼©ÝwÝqýW¥Ýì3³34AAÔÈ\ÃÇYQJz^c6!Ö'rßH+!ËÒ`Y'm¢g³\Ì´°5ÈàÊØXÊ©Ñ
î×X$"ÛûÝÌííï¸óÈ
+ýëÙÙÞ®h·Ósý·ðqõ¢þû<g'W²²fi»½{1^eñf\k§$Y?L¿eþÛ0mñäë³)¸rfz̲<àRaíyw] üA±
6Ó°
±Í¬±Ññ 5²¢ÚÂi±IÝdRO¥>ÙÙº&üÝXJijeaÃjcsêµÝé)×ÖE ^
+Çós1Ýg[E&<[Nà øÿÛûh;®ëºÛ¦¼ú+ðÑ E¢H¤z¨bY¢dɶâ(¶g%˱³R;Yò²Ó#kÅrmQ-«KT£H±;E½ Ú¯¯L¹-çÜ;óðMI Ày·@èýWæÍ¿gϹçìm#ÁK`g ^Â4ËCÈXiµn$I3
=¡ÒÈ|÷1¸d²]&×FÔmã©g0 §Û1êlàèÃsÃéæó¦V:Fþ; *Ø86R¾÷©lØÏZ+X²j
Ìö¨tknÄ-Ç@Â/S·ôGLm<íoUøT¯¬uE£U8©+=\ë® 68ÖV(.¬¯Zc¹6"<Â}0®Á\c²ñEd_aÕ<·ÖU´nÅw÷nÖr#b%J[`gû¥u
¹f¬E©
+o`J\3'| FJµ:3T=ÁHØwwbÇq°ª¤IÄËBE8¡¤·sÙ¸G ÌKiâçn`Å·7#? WO`Ö®}ýÙÙÅ¢Hó¢±y&N27Àñ³H$uúØsÃw5âº%Íu'TC%ÖT
câzæ8ÞᯪÒ@©£Kß,áºB§¾¹òõWöÊÓ®óÖð%lR.ª:2©÷ÐIõª·Ú·ßtàï& ÷
)Ñ Ù
+Ah]iáD¦b8,}ºbUæ4évÇ<+Jê½ÑÄÔø Ål(ÆÌ9R3AÏëêÀcÏR,ks¼PÓØa6^Ìü 8Ù/=½ûØG
+©ÑÙbÃéÏÏ Í]õ@¸ko[ÁF]RëþªÅÂs®õåæz=кuÄêYÕM"ûÿmÄd¬Ïof®ÑØoº£x¿`Hü9ÀÕ»}0t»:[ým\w©íÝ\ÕwÞhv^ö0¶&ð~Z§qñÑùòð¡å˽(6òBq ¤<½¾ÄAtC#|9jG3f©7h¤1ÅÉC²ÐWYa;¢_¨¼´iÇ\E¨Ê
+
+ºÐÙ`x_YÀ§¶êÇßÈ
+A`äÎéxo^Ó Vï=Ø 7¥îN§d>CeJ]¯w\ìkÚ5 ûú¯øU¾µu/+JÇÂXÛÕN´²§9}VÕ%]c%äïÆBÕºØ8ÁÎ|pÔ1jæ´Ú kMs' ÿ2×
+/-'qUÈ.Y%o¤#ƸqÝx¦ïU
+cûðu®ûäLGèVQ©;
+¶ËnÏðä|¦Ü7äYTÐ@ðF)c[²`´ÄÚSýÅRF~&LEÆ6fÍû üÖN°»A»ZábqÖu\Äsup¼åZOCk7o×I«yãíR[1»ðfnÐÙ¯øéÚÈ··^NcWª®9ËÖäÎØ1o9ëGH8¶âÙÑÀÇû3<Ý·%Ò¥Ô±¿Qaeî±J.8¶¦Yç\á¹îq-&1w½z¶öÃC³il¡sîEB×Áì?/ºùã%A¾mb8¦ørtz$¬é¼ÈùG`Õxâ¶KCËÄ8oÄ/ÙLKCæÖÍ4POqÄê¦Ô*á<§¾GíØ}cLFª
+²¶Ãksb[uMÀFà%yÏl%d²~=½eª§uãÎ
+8hªÓï;FYm«¶e.Q¶ël#EÂT§M\2ÔÄZgy¹f¦¦I"cÚÄÔT
+ÄF,è¡lÑ,)LXL*7¬í6 §ÝnâÒe1HгbAqÊm^ߪÒwré&Ô,,<¥Ó䱨v5B¥oæ$ìè©ôTç§/ê½g©±xËÚ´Vsæý
+(xUvDò´o+&®¡a'2gÕPDJý¯Bø.wdUúÔ¯z9Í+F+zõ
+ÅÆÇGaÇç~D®.7׫þµ¶ÖÎ~¢Ñ¿cÊì|6LYb'°¦Tªßë=rtavA+Åy[ðb´56FÃÜ~§ýÒ8¼Wp®a³Ì*:H%ZQæÚB0+
+HÛ%RÞÆhZÆÿJ5=Fð
ÀÈÏ
+«'Ó
+«ÛFå³GææPã?¦;øo.vÊ$å¨Ý5¾Ó´*;`A¸NäºÃ&²bp_årä> Ú{(x¡È®Ý×·î© ¦²Ë öXÂpu>°U;Rdqa)ϳ$ÒË,@ÁE+%¤ÓisW¥v.@QXa ejLÐÙSÞ ]"¸2Ǽés#Ø+/dr\ÌÍp±Z·Ä)ìefØuáNÆû
+ÁÊõrÒ6âð2àEPµx¶Ø0òd÷áá#óQ4ÑâIA¦d>¯XÒ³0ñÁ"g:
+WÆégíZ2ÜÜàÕJ G÷Z¯ÕÔ"W+«
+q¥óÊS_@Zd®×ÂÏàyáì'°}S¥ÇN¸ÕÒ!yBàR"ì@«XÕãt||¼T¤]¦ú6Ø24ªgÑnÀÚÉ_Ê0ÊÚØÁ0'ØCÝUF¹^O5®åxªY)]ù«ÏÞ¼~ýÌùçn
Å¢×3>¥¶
+ÎX)sfÊBxFÖÚ\{ÓC_þÖ8±½ë-/{ÿ».8ÕÿNòB~ì²oïÿûþÎõkÆü
+<ßäÙ3ºe]{ºi©²~fJWðí$U
+5 ÑJ,#|ÂV
c¯[ã¨ë¨ÏL5¾Aël²,¬UFrØlf]£!«'qÏ>ÍÚKf6z_RyÔYrÌÃ4d|¢=>ÞÆ껳Óññ±8Þ×¾I®VíHZa\)£k@±mÚ&qÇ _'ý¯[ØÓNÊççû0סLÿÎ(Yaw`ÂZJ_ßpä?îæï|ì¹~q@Ç¿öÿf©êA§Réo^sßÜÂàTïHÀ³BÐÈÏmÙÐégja®ÿ¤àͨÑmrЮiknT>m£
+®¬ÁöKhgAiGÞl¤Já³8]m]Zkíy\Me¸BcQT3·ÚéÜ#bZidr¬jÏ|lÏáÛïÚõÐ#¶nYýºWq涵«¦[.úcØÏ»«³{î{â«î|ÙÙ[V¯ÛyÏcï}×
/ݶE²ñ×ß_ìÿÂϾ%Ëk¿{÷ôTó½ï¼ØpéX¯ºvç£=Å#þ¶·^ðæ×lE+³ã¡ýß¹n'ºs껹øuQH,]äòÿ}í¶÷ïeÎÆy÷
¥iÿ{üÓ_¼õÞ÷¿ê-çµþö»ÿéߧ ã}âªÕÓm[0ä½èG¸Îß÷ðË>yÝC»Â)!q_êU±Ü°µî|621Öüìw̬êþÒϾ֧j¦¾âª»¯¾[.yãÙï}ûy38|òs7¿ú§ÃóRýÌO]ðïÜ;?óS¯eqý@ÀÖþö«w|÷ÖGà#¶÷û
+¾î¢ðÖ×lèCï»øÂsO½Äï ú^¶ñÃxu§
«û.üÞeWNO´_}áé ù7¬ø½^î_µ{ïÑË.¿^)óö7
+ÿ»4~ã¿ãÆÛwõúù'>uýãOý¥{íË^²Î¿d©ßxÛ£<r NW¯¹èô7¿æ%þ³øó3ïº`Çýûöí«·¾î,¿Û£sÖ¶5ï{Çùý¥ÛF|ïþ¹¿øÛí-¶É/¼ÿ¿ùGþBýÀC½üà¼ó-/ûÂ7¾wd¶÷OÿÁ×Õöù3_¹þ<mN!3@ðßýÝß=ÕûðfÊTò,7'k'±a íêm%«®,±É«n¦uÑÙ÷QTÍjÞõyõýs¾þ#Ôh¯L´\HT]äßuÚu¹UsÕíÞý_¿ýÁ²TOîûÂw\xþæµÓgL+%L«aîù
¼(åáÙÁ57Üýä£só½,+¯¹áóÏÙ¼zª
+OúîM_{ã½{ö¹ùöAùíµmc#Ò¿ùâ,lX?59=vç]yÚd3Kv?qä±=\à·½óîÇ·¾æs7[LÑ2_½òÎo\sO·Ý}صçp7ÍLtÉ¿ó±+¾þ{&Æ[÷>´ÿoß}÷ýOþü¥%± ƹî¦[ÍdróñÇ7®|æ/®ÙwÜ·ï©CRêÓ6LÁ=ÖMÂáÆÝ÷ïûìWï¼ÿ×ßüðõÁ#K/Ùºfµ[óÁwoyäÌ33ÓÈð-}æº}æ¿ðõïwä¥üÒ7îº}ç÷ïûÒ7wóò
+¯<ãö(ã»÷±·ì³~íß¿ÁÇ8rèhoq)»ñÖG/yÓ9 þc"_ýöNØ4ŦÈ]î_d
+¬úõ«ïùü׿Wbð6¹ùǹ~úÁYúW¿óYàÄV3û?{Ågm]sû¤ðä¿úüpôö?µ oúé/Üò73ÞmÂC{öýôo;2×SË¿¹cnqà??87ݱa®þì¯o<û̵[ÝìØÇ?y]·.ö2xáç¿ö½N;}Û0Ïå?þÏ/Ï/RAÃ>À zæ/hù¡¾þG¦'ÛË|º[¾÷8|´¹ùA£ãN$wìÜóÿýKpÉ5ÌÊAVÀé¡ÝÂèþ¨÷úIAÐÈÏ
+À_«&âù©ôÀ¬ßÏgbmÊ
+Ýâ³ÔÓØü(kûQ±á¥Àvôº<T~Ä=d&àùnb×ÁÆ¢j2Å7x|3÷¨sñ8©Õé4à×~ÇÝ{_ºmï¾ð{ÝÒè½iµVñ.8ã§Þ~ñç¾|ã¿ÿÜvúßþ¯Ú~Û繦)â¿ÿ×Þ¾c×êé±ß»fVi¼(0 w{b÷ÞÿñëvÇZq]sí-þüMÿæW/å1{ÓÎyëÎòLÿÿúßÑìÓF¶ßþçU'g>÷µ;/¼ðÌÍ3]{Á/ó_ýß_ßØíG;tøèR»À'¥öëî{ýÅÛ~ñg_ó,¿¬Më'?öÛüÔçoÙ~Ç®?ý½¸ü! í}ô#8cËêßp
+üÿ·ßz?Søúù?ßx×[ν ú+Wîüøÿ
?ù«®úîsÙ?ùägoÓÆ3ìßì0üó7_¾ýõ¯ÜÙo>øúwïoý³ßü4pÓ{.y9|êÏíNá~1 ×}ÏE ÍAà}ðѧ~çß¼gÃÚ , A ?ÂW^wßôTûSøAäUnÙ4½|OÞ÷Î.}ÇyGçúïÿÇ4öwÂa:¼ú7°öò³~fü#ÿêÝøã¿üK8«ÁÁ°ó{ùÀ^u|í·ïúÄå×Ã.ÁÝpë#·~ïqï~î>g/ØÎ<8Ë5|Òåç÷ÿôê_ûå7Ã{wUç~ì_üíM¿øÁWÿòÏ¿ööêÓ_¸ÍïÀÉùõ? uäç±C_YÊCs¥4¤R7-\gGÄßgÆîZY¼â'ø«WY[ d22¦¨9ÚÛÞ[gdá¤5_{*yÒû;¸ïWÜñ?úÅÝOà¯Þ<'èMF_;ÅiÐAÖ
+õùap2³zsë5Oì=G1Ïcñ®K.î:qUfÂü^-.
+à9X¶ùÖS{÷ÏÇÄkgM¯AfÜ1Ì3TØÍú|¬Ûð¾ÕÏܺ¦,°äj¯UáWìͯ}Éóç>æg¸,ðKrDg ÍúCØö?ëÅë4ÖÎuZ)ÜxæíÃÖ@D.·7ozò©ùa&GO¦&ÚðÖ°@IpDç^ÃÏ}éú¬'1â¡#èèÈ|ïÞ½ç¹Î×àïKÞxö¶ÍÇ_á»ØºyËí¢¸a^V_»ý!
+àǧí<øRá쿸|ñï»mó*8T[;Úë´Ñ2À¹/Ý ~TÌ÷jàñåçlyã«Ïô_â
ïb÷¾£»ÉÿØn'qòBÓ/´Ïsr0ÙM§'do LGr;Õ¤[+cuùØ·9xêÓ#Nz¹*×õbÁªLUüÏÕ¡YíIojR®C<£Ñ;3Ôõ-Z;|z¾óÞ'.yËËë_¿·Õwï>ôäþ9oñì»8ü»3rYdmqe
+Ûª 0ìSæðª'½þâ3Ae[ih-ÃÑQÈyØSº}ÍÌäx·õä¹3¶ÎhÙ¿uÇÞuZ»:7; "¹+×`o²2jÕTã§/9oÓé^¾y|¼!(=ºû4'KõÈãÎ;uhd¡ï{çùIÍ#X;ppáËWî¸ø¼ÍðK{b¿YSãënzèÝo;.2xä)ÑñMÁÖVOuvÞ·÷õ¯:£,Õ5Û:ÿ決3\¸Àå#à#¿÷í$¾÷íçmÙ8ýÊó·L7åÙ$\æÿÂû_ üçÈk¶?økÎ=ký3¼´öìüàïÃg±´óÇ>ñí
¥ìßÒ°åRªïÞúèáÙèçnþÁ¾ä*Hïïí÷î}â[×Þ÷«¿ø&ØÃv¨áÛ\~p¾pµð:ÿlÞµûÈâÒÍ%Ôp.J;ßË@rl7j´*8°ºjá,+õI{U×pM©Ü%wàd¶Ëôóôí¹Ø;ÌÁ3ÓÄn6dXV^ ¤N ¡u1VYʹɧþöí·>|ý:¼xèÈâ]÷ìÙºefãªüê-&{ªßÏ]Ê(aúðcOÎÍõ^øìnêýùK_½vMg0,þàÏ®ºëÝûÌÞq×£wܵëô-3ívKpÞEQÊ?¹üª[nàÊë<:7üGÿàÉv)mi3ÐÈW^³sýIø½ÅÈì̪±?øÓ«/ûËkoºýÑ«¿{ÿ]÷í{åùÆ;úûèÇ¿ýÍkîñ·/{K½üO?}Ãm;vü×l¼ôçûçÿ0íýï?ûοµã¡]w>°ïkWß37?ðuäË?wóg¿z磻Ãå9Ü4á«Ò@ý ?úñ+¿~õ½úÂwìÜ
+Wî§mºùÎÇà"¶, ÛþÆÞsï¹ä¼¶°µ5«º¿ûû_ûÆÕ÷ÀÖv=qä·~ý«¦:þÑ»xØ
+Î1ÿçϾ_å¯ý£·øÏÌt÷ýñUðç×ÜxÛ£W^?<íl§÷\øÏ¿ÿõ»îÝ;ÌÊë'ÿÇ~Ëß~ÍE[Abï¼ïþùµ×ßüðe_¿ïÀÜß}a»ä
üè] BÎa µ?qùõþ6pßæÓ7ÜòÈå»^róK©·ß¾>ÑÁ9ãôxþè6èY88p®»ùáÏ]q'\qû¿ûï;<1Ö|äñÃùè¿råÎn{ôÛ×?à
ÿèPÀ÷¿þøê·¾î,xßÑÁY~¨ïº÷ûÏ.ñgt´öÁ6Ï<}æ»ùkWÝóÅoÞÕä{÷Ïù8ÕpÂëfÍQ&6lÚ<Ãb^õÿÖ9Fëé
+OÍ^DuÍ@{{ 7¼gle)E¸ö=J¡Ï
+hÉ̱\ÍFûê³wïU÷
gj*bw=~ðÞû÷¶iúÂóO»ëî'vï9üªWlÝrÚjïRÜà'ÃaAg,M\ñÛvÜûø¯þÊ»ïØùðç¶nºsÖ¶ñóÙg¾r[?£îÓ(ÁØÅ9>ÖáÛ×ã;ï~ ñÖÓ×ëÜ~Ög<i%Q«Rþ»ß¾ümo:ïC^;qéõ×n ä9ìöôê©÷¼ùL¯á$\?ðð ò×^´uy=ÔwÃÕîôT{Ôðð½³sýÑ=Û¶¬öð;¿k÷áÑý¯½xëòË| Jßf7Ú]{ß|Çc~«§;pÛß8|´÷#[>7ï{hÿ÷_àþ/¿q)Ç·¾þ¬Më-TÓÁ'
+xÕ/ÛôÒ3ÖÀÁ;áÔ91Þzõ+¶|çÆýíw½õe P´Þò?8¯å~¥Ki_DÛ^zë]»ýíw¾åeÀ¡p|¶ßþè`X¾ñUg »ù;9:8pXànûCçkWÝ}ÖkAÿÖûâ§ÿèlÞ8µü#®¼3Ú NxáÛßtöÓ¾µï?ÔËöÓ¾µÑ¦÷ÍÏÚ¶æ_|ä3òÑÃÁIýå>ù81ÈÌ=..ͪéöæµb¢U]Øæ5óG«nTN@ÒñµvþAÖÙcRgoo)ñ86mª éþ_8~Iú
k¡{q®8ÂjGPe2rþ¬ÛF
SM Û_X4Ì+eq`'wß¿ç²?ÿúì|ï>ô÷>ðþ×e½A*è¶-Ýý{ç2Â@¿HØ 5Ú÷p¦ÖäÝv2=5þÄ%ø$I$¤*
+£Ûoypû-Dë
+úÙúÍ{ŹëqüÏX½Û,*¤?
4V·NõWzR4ô~øî7~õíϼ¶¢ tñ¥oíøöõ÷Ã5ÊÜÂðC^üá¼ê$ÇÜyÏñíE©öì}ókÎüÍ_gü
+N|á|8¢?<?,ËxfÝ5AȨ\;r¨z-&3á ©$¨»
¼¬ëÚdWU5{ÿÞ|yM»¾Âª&?½íçAHÍòÖ»Á©eQÙ#JvÝÍÌåû)MÎæ}Y*
+ê
+3ÉøXë§ßq1ÜØ´i5®åXDJE±2èMoÝ8µW1oÒ¿zõøOõ¥Í4R¥D§Nk6`bK0ø
¹ðåׯÂj¹«ËP¥B1{q Ö¯zÑeß¾þeGÄÛ]ÚÿD`ÓºÉ×_¼
+Äû+Îñ¾öäïÀÔxëuo¦_ùû«_uÁßÂüAÐÈÇÝûî^ê4M[ºë'¹È¹ÊqáǤò{ £
!íëÈzµëÁðë~äº9 Ú×Ü0@$ÉLù4²²Õ÷-¢µ#>ZzÒÁ ©=½«ñu;R<#!Ù`^*4¥ØLÕªÙZÎiÑÏ';ñÄXrx¾x47G7PÙBp$tr¬9·8è
+t·Û1J8ëç4bÔ±ñöÌe»)1Ãñ<fà]ËR¶ÑmÚ§úËXxA^N2@5Bª,
+ëûGm]Ì
+TÃwUW©xäÐ6ÑࣤԺÐaj»"GmHоïÍgKßaê¸,æüBâ«;Rûû]2VÄ ç eÂÒª¹0Ê8wN£±àqĵ1nqÎh#ÑLyS$lj£µÍ^¿_È[í¦Ë R.CÏ¢·q,QøÉëHààµÛg´««N ô}{ÓãÉ©þ&V
+#?8f2¸ÑÒUÕÛºVk¼ÿÃ^ëkVq_Óà»}°[f<äÝâµ®ÆC|7ÚÅa)¡*ºÐlüDµËuÏ«
+z¬í_á±µÝ68õ§XðFÈØÀ¾ghâ8©°µ§q¬PT!Q°*N"%õì|¯ÙjÆQ$Ë¢
+ÚCÉíÊÜk
n6ÔbcsuQæ&Í SãíèYò8#?ÈMõúHÔÄÕy[ùªÌ9ëå/KGʼþÑó¤tì$xE¬n\óÈðnDi¸j¿+nP_&Æ
+¬öýÅ´J®H¹È¤Þ¦µF&¬jzÃX&ÔÄnMÐûa YjÇXì`M8y¡TYQihê_ ÏÐF¥
+c]\êÅØPѳRí¦)@DcªÅʺֶÑÚ-꫽)¼éÜ|rì2üpBùøá@Ö&íhõ^Õ
yI}]Ôí0qqÎZoJ+wyRU|½B»)-Óújv¡ÔÔ»Z{í<*ñ)Þ´¾"e¿ÏþLÑ$Zi£14c([®°Â:'7xBqqdEÏV#QZÂÍF\ä9ì»36
+x,0ãð1Jc}ZJ
+/Úx8,lå³6ILIg&_tkzÏÐkqüÐXeSå³N=r{,/ÎÍ ír
Çúü#£7VÕ+cmª4<à2Ì(m±wØÖöÇÞòÍ{áûÈT?í=á96ìç5)«%3ªuM{&ËJCcx=Æ,q"pÐÙåý£ºæÄ4x©_A4w[)06p÷äX·(²,/ºýþÇJ¯V:O|o&b4pù¸?TXzvR)ÜT^¨±NÌC²^@À2üc:7VF^¨:²c#ÔÄ+"BbZu\ØúNRóÊ
+¹r4fµQ°-HÃÝ.̱Zѵ-k!¸5ZmEj·9º|9Ñ¢ õyÝ(I o$~Âò°F¡fk-±",XáÂ¥º?lX»Jˢ׶'&{ý>¼+ÎêhéßÛÅ©Jx#5ì§R4NhÁQ îE,ØÑùl²?ë#ð¢@`äãG)á¦ËvD«\Q¸Î!*·#Nôðí¤Æ®i
+©/++øö ´ÈÊiV`9Á+u¬t]vnpmí¨ÌªwLö9~ð|äHâDÄIª8N,ÀgÑJbsÅD±*d«û
+D¥ÖäÙpÃÚé2,õîÄp0(7az¹dÎãÌG WëXÓp]"@Ъ?,;$>^¿*#?
+©³ÂD¶è0©\a!r]À®¹æn at .ª-/FhuOı<R·a J \&È°©ãÜa[¦¬j+ö<&\órZâ:>¶¸G}ÃÕ]#sD¢ÆiF¤ZP±
+ÅãÈF0yY`þS»aEºn¤bóÆUKs¤ÝÍ"Ï>qȾ|¬A¨F»b± º¼´
+£mGsjÍT¨ <¡|ÐÚr&ü´u©øÈ]>SÎÝ:Þ4N;ûõ9yÌtùhµYvVôU`d à8%hWI2
C"h½ìÝ|cþðÚÛ'øÙQ¶ì2|.!º.c]ø¢ò/·ÞÜÞº)BmÂ4VÃáìY¶8²¸VOhíÝw¸´<iµ²Ì3×*ââ.ð³9ß}V]$
+H{;:¸6ÀéFÛ¥~99&Nîäm@ÀO#/(T#a®èNÉ6ÝOÃé±zEUN ´ÅµùqïìÛ@w;9Ìhb騵@Cáê©ÛÚª=·jrîlÝí¬|vO#¥£6Ø5~Ýÿ=¬F+)¥ubiè¾ÛîªRçÃáúu°Q cîq³çEYê²Wy©¼³ËâJÙVY=A
+³^&QÍv8]Û6¼p̺N #'úÚtÇ{0%ºTè5,"ÃÚxn"£)
+¶¬Y;åV¥cd«,¾±i¹Bpa]hOª¶UÓ1<U9s½dBµ«ÐÚÎ+ÎÞÏ4,wáOnÍÐ8=i1p(%ºaã/@]æÍ4M¡e9=Õìõó¹
ÚQeý\)àbjrn¥äô º%nE ¶ÓfCäAqªÝR÷åU/.S¡gPG>N+4¡ÀÈUíRÈÒº\³jÕt<ªWË1ª^¿ìfH3!ciåna_DeLá+ÊÑù,O¾Þà· «>BªfäÊþMTOó»Û±ÀÙ$ý[ëÁiëÜ°§8neRYÊù¥§,:.ÄÞeK½àWU^ óU²LSr»Õj¥ÆENýª4q$£Zá,u½ÀÈÇRB±NìK¹´hFÝL>6*MFmgËþZq´p>Odå0²`d¬YõÉ
+Üñ¡|~ÑÏ5lc¼Ê«Öµ»vËñÊ:±ê$ IÝa«ÞdâHÙ/º¾4\.dY㽦ÌÌäuÿ÷JADËXÛ_*Ê'[ÐgËÅèµì¬è|¬;ívY*Ñ8òb`UÚ¤)[\,zY¹au0
+ø¡UãUÐÅÝv"*Þ,§Ã¬¦@ £ª±Ï¥6µ¶#×eËz¾ê`U,QÉ6blg½³è¬7|í[&ledQÏLÊÃG:Q±jGÜq:
+âÊÇÌ/ŹõFEdʤx& Õ¼,ÜèUS"»Dýa®¤y+µ¡Nxã_næZðØR1*PrÉ6ã,Ë8§ià¹Àâ4d&ÍÆP¯xF|<XêçF½1ÅÂ&@j¹²qñwÊO¢ö
+SYú9
$yL×t®;C cUIÝÈ5½iBFA|~þGS½
{¿nèc¢¨3¥ðÞ=C¹Êh£ÁâYê¢Fjýî53K¥=´$ãTû¹3ÇD
+o2m°)¡Æz¤c4 è{¤¼FEQXlÎÆgs}9Ñ¡^ðÌù¸@EQªéIlëIohg&¦1½VäXÅhùº^^ûþø'À3r,C·2Õt±Onù¸z´Ï+%×ɪU¢¦yßtLêÙkê¬?Zuhøéopal5[hKºU Íg&; sK½ÁDê¶.õâÑ>çq)µ2¾N¢Ø°mM
+¼6À¨ ÅÜjÇËáÐ4[Q§-õúenX$'ÆdMS¡ÀÈǼ4T`ß× ·Ã*%Ñ4såRJ¥;¨£êÄÈìÍå9»ò±¢¶D¹¤; »©.éÄÕj^¡pØ9Ô`1ñNó8ðF¹¯{ªMú$'[;<@íR__®£Fü°XAÆ·L ðþ\ôeYR4à%óÃ(
sªÀ¦8&ÌnZN,.XV¨áínTK¶h$ ïÆÆÚ
¼ÙNZÍdn!Ý8Ó<Õ_Z@ÀO #?g(mµ±i®ÉrÛmGqGè±dS{oÒeEdïú¦\W²rä&Â=M-4µµq=®àÕ¦Õ}´*YÚI²jlø·ãÕø¶hEDØî ü þmq´ÏRm|ÅÊÛ
áb-K31tÊETöUµi¼(píqvi˲gLCDl¬K©çæÍV,8ÍRk³ymû$G±ü"0òs
+Ð`ÌÑ¥¾(ÑóW+
+Ùº7Ìsb#z,god*t,
+)
+¶02MiEX,èxdiHÕlmvYU2лä:á\ù]xC
+ÌìàÛ¥1¶F ¥umÇØPQù/÷M)DÌh>öúR±N7ÕJFÆ¡ý³ÏÌ'lkªÑ¼BFâ"¤mçV¡S8Íf\*5ä"·ÓTôjãêV$ÂrE@À³B`äç¥|3:Qt9£ÚxÞh=ý¡Jg$(k|B§IZ¸dNÒMK»'ålÌ+¦¦ux»úÚÞ¨P8½ÎóÌg'¡=`ÂèÈyN"¡c¿Zpx ÊÒhC¥2%jX¬_(cá¶Ç(âæÉÖÙ%YJ
+wQ´}Óp6}ìU»c3,O[ͤÑ`A¡2®n-
+ËuSÍ°ðìù9C¤¿8ây©}qG%
#_ãk¾ä=q-hÆ
O'i¸¹>ié8ZÖgãú
]£
®Ãôm*õ±âzYoóøÇÒÊéÍUݾآØÐBZ4ª¹¸T²,ö«%"æül¹&FØ>9ÙÉòr°4<é¯á$¡ËÈ
+þ¤üDt·eKÌB°4aŰȲ¢,Ùª©d®¯j¶áX@Às@ø
9DJÓ6\Ô½ÕXD¦>
+ÄÔEdã;ZµWbxòc»M:>87wT¨éø°>RYÑe&ô¬. <-1Kª2M*ÑæX/ëÃ4Òºh.Ù F !' öó×)ÆèÉ©1xËÁâ¢%¼ÀõD4M,âØVÕ4æV{i11jrÎx§XúyV°±n4ÌÕÌDc¼ì#Aò\»R WX)À54Î*ÛM_8ƦãeqJÚ¹¸£û¹»³§qIÐ[{§Máæ¼õo_³®MñcsÆY[¸ÓODÅ (øů,%fB»¾7äbìP.U 6A½å*â(Iàèa++Ì2ÓÓãÖò¥ù>å¢4
+ Ð`>VÆÜRJÇÛ-¥
|,µm·0fzaiDÜj¦ æW§c!a: à9#0òñ [)mY¨¤ó¹JãxjÂ%çq×êKÐY/ÖS¶²HbÒIìÔq/Gd!p®» =^Þqî«ò±5u
Ï
+ñÔﯮÌ%2²V
+ØØxßÌ©¦Hï
Uú1éG4m$ÙA¿®¡Û(NqÚhl\Ûw`V*¦ ¨fæ¬+àÍ';,HÃxÌ#.-»cífLææ³Ky»Ý`ÜL¶Ò©@ÇÇ
°~<h¦¶ÜL£¼(úbÁ÷ÌJi%°ò^Æu½¢ð¤£cǧX¨`8úA[Úó+xĺ
+ÝuÖ?n;uþ¥è:ÏÇ-g¸3/u^Ê¢(PèÅika(%
+?I)$½ñ¶aÃDÒQÌe%;rZ1*ÇǺóKn[hmC[=Ùêõ
ÁÄ&´V&²;ÖL"37?[ÊÓ$m\Õ Ç ©0{xýàD\4ß#«&ªìQ©*ÂV
+]â(2iD$qt¬M£v
+2¾vÙ @Á>´±jèúaFÚ5f9¶|ÀÉ@JA¬3¤á©
+ãí¬3À
+3è»E>z¶ÛNic8ÀìRt«°§¥éÎÌÌÍ/
+"þd
dc«ÚÃ^ovn`8XÌæ ÍòGãc(N[Ýh¤á_T@Àñ#üþ'bÁr©:MÒhÐy^,.#7HÝq!}»
¦XLpäDÕ56ÀY¬ZRШrq+_c×D¬ÜÏþû]ßvà)I=Ì0/ZgÿéÝ4Æ [?ÌG]0rÊTðȲA¿f ÑÖFd%lb¼Ûïeífs¡7_j2Ñj%ÊÞb_ëÈr è>RÔàíhÄâÐþüâpõtÎ[×µYøñù8&¼T¤Ý$qT*mÓ4^\Rûæ§oHYÕs£X²HX#橸ÅÎ÷ÇYhú@o¡é;+©Æó0:Ïå0I7ýFNÑè¶ñ¸u]vØE¡ªdüçÅ Òe³¦Ì*ÆtÄfGj²8XÂÓ
Õ%·Ip DV?<;zToÜLúÒZQz1ÎrjâF<Ñåi=uxinnizºzÚ@Ç' ÝgõÆâC³ O@Å6$ÊÕ
AÍÓ1,bh3T¶ÈÕpÈsgÄN#c¦ntÔ³Áª
+oÔ»GV"'Lç¥*½l´os©I#ãæ´ÖÜY»Mâf«ÙóGoÐgV»i at fqÀDh#Ûoõû¦H9²¨æ3.â1c$¢$Ic19ܽïRjfÍÄT;
+B'
+,ÄÜ®N¥öKkrñóóh¬ËüÄs^¢ñE#±Ígó2¡R1m)HinAAÛùÙhØN+ÚMfý+]«\Õì½ß(vÎÁCEa
b£c1s×[áKÎ$-ó#ÕJf#i6pfdÒ8°ÏÓº91jÑX§qôÈÒ|_eZ¥q×û´dN¼ t<³òÐÅN«!ZÓ׶1 * à!0ò@v3cñMeQ¦ÝÍ-7
+T»E¡Ëܶò¶ívß\å³YQH²·ãT´´Iq&QÌ#Å1:?¾î,Ñ,ß9T¸å>kjÿeK
K-E¬ñ¸J¥¬2·i«U÷³2ËJõWA&JkŨìY¿§z¹QÆ
+áà!Æ¢4æãcIòáPï?0;99ÖJÅÆV°
+8±ü㢠²~ß.Üh§¸öqáêZ*;~ä
+M{åb[5vBà<µ V íÅ]\¾"Ak7REL;7"Yç'¥.K×Ua*ã!üËÀöª»,Nß¹'FÍfÚî¤ZÛÅŬ,K7È¢ U@§V«ÛnE~tn;1ÖZ)e0 ÑH pq#G{<¢cV7;ÞZ? à"0ò @»!6Ì$³sRTÜL4´%*ÔYÚ`$i'$oòA¦¥pt&J1!%-e ¬×hD ÑU .8¹Í_çURãT2þHí#SVÅ©èj"Å;d`(KÓÔ1HïÅ
Q3Ä<Mâ8j÷÷úÃÞ°0ROµ±Ì%ºâyEÒNñ´Òí´d©çæûòNÌÖoÉLÏ#f\7I9åK¥r¨x³ôJh_¡"[XBÄiL³~9{h^Di³åõ,·Î¾1Ê8{r¸
q¢Ç$q|G9J\©4´¶(qMÖjì³8ú3ÒHÒ(Aê6¸ÕHdi¬l'4î¤s ò¬kË,Õ%\æmºá'c+ÚQÜiG}Ŷi&øj<¿|Â0Þ {¤XüµÐ+µ9ÉÊ?ç³$áét£3Ñ)Ì
"s!D Ic"0Äû2´ÑàQ䬵ïV6nܯ@W £|ü(º±ÈU.,p:Öj¤i##ÁK©9)Çpý¾ÎqòP&(0IÚÚÒèV2)t^ÈɱAVèØ5ÅB¬[Õì·çÎ#'àÄæ£òýÉV^¤EçÊ¥ÞB«©±æ5ããcQ.í½
JÒ4PwrÔ9sNâÔ®ÀbZ\Æ1Ëd)D»yOÐÆw [ß:ǨFpiPhËEY2+Jãè8:9c:¨j㲡péÏ2xóFL[ 7áÉ y¡¤Òk'Ý`RpÏ %dýtÔm¶ß?`"Z5ÕëÞl&raqȹÑfªÝãci. mED´Ôe¦ÆäÁÒ G¸Ðs½/%Nþ[
+ö»¹%<7B\ª*Ú^ `ÆVd¸ "$27Ãlh´"}(¼Û+[{³"npE;Û
+:½TîyÚv;v±7k'Ón°Ó8©ùù°ß󽤩À¦(
+¢äx7Z·v2I£¹
üð\Σ8E¶ÔÆGB$ G´Ù´SÙ3
+¢5ËP%+]
+I{ sÕðJÿóÆCèjØ
WceÍ+ÐnGífK#A at k£,
+ÀWmiuáTp
+ùùE.͹Å2Ï3×e9l¥ñÚµÓI/ôóÙy4&È9¥~Ön[8±® ¤Vh|¬½ß¦
+¹TKçØB[0ê˲@7NgtÏüh32½ÊnÄX"ZÔ°ÑVÚiGðVÊ7δx8u|2êÐ|yàhç%g25r¼wºmËØÜ|>*7gÇ82¢#$,IAõRÁ0Ï)/,0кÓÃf ¥ÛØbàS9«iàì5uîùÁkÑ÷;84ÞS¿nãêÆÇ; ÏÑÓãÉD7baÞ# àT#0òIÊ/æ{r~I2fµ1Íu[
+siàQ°³p´f¡?2ÇÅ>dam²¨±ËQÃße)ó"£nfÕµÆdw"عìàKç¤I>تñtõdB¬F>Ù0¦¢æ
^1;biÜHãV¦ó\»H¬7ÀH`XFùá`4ð²¢®|I)ËBEé--.áQøÛÅ å±ÁlÓ$)Ýj5Azf'»Q§óàG°òùÁùaìÏ-½òm5£F·4&öuaø(Uÿ'¶
+º£ë¦q©ªF!£·¶¸%ö:cj)¥kFãÝ8ÔV8#¯ ͶKµ°T²}@u¥aZ}S.÷ɺDS¼ß8à '¨ñÿ(ç,â´°±NB8Ìb"øÉ@`ä
+çRd±²ì¨Wâ¢zn¢=¦ÅÙ<Î|pǹ°.ð@`ä`°R9 `¥ 0r@@@ÀJA`äÀÈ+V
+#¬FX)°R9 `¥ 0r@@@ÀJA`äÀÈ+V
+#¬FX)°R9 `¥ 0r@@@ÀJA`äÀÈ+V
+#¬FX)°R9 `¥ 0r@@@ÀJA`äÀÈ+V
+#¬FX)°RðÿãzßÂÅ= IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_emsmdb_graph.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_emsmdb_graph.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_emsmdb_graph.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,325 @@
+PNG
+
+
+IHDR Ï 6ù"ò sBIT|d pHYs
+×
+×B(x tEXtSoftware www.inkscape.orgî< IDATxìwUõÇ?ß¡w²PzP`AAP ÒDAP°ó£ XD at PD@ª(]:HzMBhi$ÐB(9¿?μ³³ï»»IvÝä|g÷{ïܹ3o¹gN»23 $ílô.6³Oh'Þ0³Kå[Ùóíí¯ól
+
+<nfCÚѾðU``àànà2+.ÞÛì, Î6³É~öÖ^®4³ÇJõ»Ç9F ÷ÙÔYºà$é`$m
+ì<cf'Íéñ$Ig#iC`]`=8§Ç3£HZG_3³÷´YècfÔÏÏÑcÍlZúe^föj¹¼'pð8ðCàûøz° Ñ
+ø%`À
ò7¢|ööÕÆy¾ý
+mgûµ£ý'ÀÛñÞ3Km6&GùÔx ,õ}*õ Ûú¼¼U:Çñq͹åÖ°g|?oÓcÉ-·b(ýw·s; ï㣯SçôuÎà¸wÆTîǵÀb¥6ËÇ=-ê6.ÕÏLúwCJõk¯ú \,Ò#µÍÌìt3;ø|tzD!YH"é%ic«([VÒÀQµ|oE$-'iwI?ôI=+õóKÚAÒO%íÒS£¾}4¸Nw
ÅãFì#©o¼?)êÿKXw ÿúïáBÔ@à0 p²¤Ñf`A\P÷£Ú¤.úJZ4^ç4¸ü{´Jé;Võ4PÒVÔ»R¿HôÙCR¿è³Üǵøïuh?_´_(ö´|¥Ï¢Mèw-Iê´®¤EJec¤(ëû¯½tL³±$ó$oW¶Gçìpæ(+ãÂ/ßãóÙWJm®¶Àêÿ¬
+Ü,iá¨?$¶·ñ¹Î$íõ=ëGÇþø¼ÉÃÀáu$Ý1ñ~»èôéRýQö5àXZJ}E»f\"z§Òö)`¨¼X©lõÓ5¿Åþm´Cã??é÷)ghsHì?û7Æþɱ? tÌ JÿÇEÝÝsZÍkoÀâ»r0ºô}ß*~¼lW:fRå÷1æÚ¬÷¢üDàÃx?X%êiÍKç¹°Ôï¸Êàü(;+Ú°%°p{e<ÇïJ¥ßÎáÑϹ±*°c¼ÿ_iìûGÙ%sú³Ém¶ÿ
+
+Âý
+êÏÂÒöýoÆþ¹±ß8 (Þïé/£®Ð ü-~s¯ ëú¿
kÇÆwwÝRýMq¾[ñyê8 _©Íñ'øñ]¾6)æùßÃð§ö¡åßvk^¢²ÿWJsKü-~çóEÙ£QöãØû»Æþa±OsVúó0¤N£
+¢ÑÔGKõeaÙR§×ë'%!úz3ö«6îýs¢ý-Ôþúõ
ðpf¼ÿñGÖÆ°7µ?³ßDÙzÔþØ
+!å±ÿFìýžp_.õÿp©¯ÀâsúG[×Þ¨ Sñ?±¡¥ïÐ
ø×9Ø×jõcJõï¾?¥f».ê Ü ýFóKmnÇÿ×þewáæɧ)ð¥qq}¿ºã·8ðR
+öÅïs9ýÙä6Û
0 íQ¿
+þü6.@¿ïWú_P,¯Î¡&<ÂÇñ-þ«¯-ÿºhw>§ð< ¨¥ÔÿõÔÔò»E}1O~õ/Åù¬t
+ÅïèøÁM[¶óÝÇÿ6öýJm.²Óq¿
âw[);Qߢlà7ÀyqO?ÞÝêä3qq½KþH©~ºûmú R³ß÷ú}£l8.¾û+})¦OàÔÂÞr3!9µqc¥öçó×RùàRÿ+DÙî±?6öýÃb¿Wéß²Ô×wãæîH9Çx¹uÝpSìÿ0ö'ÇïaPì¿_:f]|âÿðßÒ÷wñ¨/b¿ÐMÅ'åFÂÇÀ¢QVü¡ÞûÅÛ¥q,Q:÷ÚQ¶[ì/µû"þ§Y\×Ê¥ºGùIñûþÿ#î1§?Üfûo¡Âþ¥6Åsñ}Ú½TW<|~¯TÖ#^ïóø]-ûï½£p¡w_|>+þãúB@øuìûçÆþ¿cÿìØ_¦t
+_¤ùd½'ð9jðKÛqk¸ÚüYÌ»Ú^ôsÄBë0ÖaIj½Ïïô >EK>
?µ7
+\X(¼!WsL[QÂÿ¨ÀÕüE]1èryÙ?¡U1 ¿ Ïâ
+´po´; øI©ú¥Ò9ÆëÊñúB嵨_¡4þ¢3;ßÌÂmD ë
÷l´ÅSñúz¼4÷4.¢`æ´4!s"þ»|²ÔÇ>ÇÄëøxí]§Mwñ§ò1VÚÜQz_ö
+[9nRÝ(\ð Pª;wú°þç}Õñ²Næâß÷b;»Tw!@âÿÝHZÚwõ΢qïÑ]Qöfì/ ô§gpÀWKÇ,^é£è¿ècéxí¯#âÜðä¥÷ÿÄKÄþ ©·¤ÃqÝföAT¿R97¸ÓbQ÷*>¯Ûõã,"ÍlõÅç¶Ë¿ôÀÿhö´zi at M¸â÷Qô>9¯&é+Q^u¯HÚFR½~ÿQýFÒf¸´nS1j7ÿI GÆþk¾1Ø ®nä)©?þº&®Vz!®÷ Iž,.i;àÛ±aåuICpµ.øÓÔ«6tp¼nDÍIj_¢$ijHq£ r7üOó3û6îÔoÃcáô¢½ÓJûEí%- leOVÚL)½«yösíûO;%âOV÷ã§ÙëQ¿5sɹ1û13û ´¿Å'¸7ñ ÷Ø8`5ázÛ¢±¤^¾ï¯UÊ¿;ë?bfýqÿÔ§Q#ãõá»Í
Ñ¥ã>ϡŶu´(îûð-ÜOi3{·Ôä¡x].
ûPx0æ·âácÝxÝ ¨s,Ytff¯àÀÚ
JâpüæþW%¾*©-.§¹}}4ÍMâÚ¢ÍYQ^uRÜNV÷aÀÔìÅö
+¶A%ÌWÕLÃ7«£Ù¨ÒWy[+Ú¨Ô]FsÕÓß*õ£KǵNß¿Ój»ÜºöFÍÄpBì*úb`ñýUpaâcÜité;7 Ú&Whî¼Ô721¼ cÞÖ6
á°Êø¿CMûWO¶ú¨©;{Q³ý~§ÔÇú¥1Þ1§?ÜæØo¡01LõÃÅöߨß:êFM¸À4Â_÷º/¿³þuÍÂñ(´â;·þ i¸íOøT|¯×c
+C1æñëc=jNÁããwTü3bðGà/¸Öâw
+îIáWaø¼<>¶²¹¿'QS3ìRº/ÄûOGýi¸cåx¸dÊnO 3;AÒ¿p§À1f6f¶s¨ËàªÕðÐÀ§¢þ]`P.GMåø5üá¥hw¤Uq%ãC~Àb¤fö¢¤õñ?¸Ä½fV¨(SÁÛÑþ"IÃð§BíRf$M££B[ñi"Q=Rºv~ 鯸ö. Ü
+¸T¶:®²ÛÆ$s>)§ñ'é"YÉ[Ô4VÙ(Iã¶ØpGÝBW
+¾ûÿÉ^åOF/TÚ¿ÇìÿfÏ5³aQ÷ü÷roù 3;_ÒÀÎøïþ%à3aïãÎO6³$}ZJR3ffKÿþÎiã~%s//á*ô*ÃB°/îû3#iO\½¯¤;ÌìIãqgÙñ§÷BõBôý\ìO+ë#3&éûøwÿ3øÄü=üÁ·ø¿7'¿³qÑÇ föDh²ýG1OÞàæíáøï¥è{¸¦Á=y¹Á=yô~Üx\»øàçV3\ï+áÑÇY¡)¸×¬??;yþ¹ðÎLd.AÒ{¸ ºU
zí7ÇQf63¾E3M"7äÆëX;$Ý
+Iáý|À~¸Vc<0Ðܯ[ѳí&I$Æ>¸ó9`¿nÎqÔ|÷À5{wGá jñI$³0Côµùã¤;!_Ï`=\Õÿ2ð}ÜúQ]$I$iA£0$I$IæaR at H$I¤) $I$IÒ$I$iA
+I$I´ $I$IZB$I$-貤ë%1§Ç$I$ó"]9ÕòøBI$IÌfº¬!IÙ¤
%}FÒÂsz,I27#i=IÏéq´$_êýþxM¤óXØmN¢=¤$I$³¤9=¶H!I$I¤$I$³b å.¯AèÊQ³
+I cWc¼f¹v$IÒñty!5ÎÀuïÿ ¶kë@I};whI$É\D·yèL
+Ó<ofÌÈAÆIn1³ë:aI$I÷§ÛRàÀÍ
+
+´¢¤ÏI\*n>VÅ5Ã?HºJRï¤~©H$Iº) 8MÀç%= é
+I´WQ)é4`$p,ðoIçFÕ `¬½mfOÙÀ§¨*ÚDR/I¿ô:ð"0VÒm6é¸ËK$IºÝF&g pp1.,4 HÚø.°²åKÇ)wdfïI:ü5Úï
+ìÌ\bfÓâ?_ ¶4³g$õv N¶è«M$I6HÁi.7³GG+u_þU föJé¸z¦w
$
+N FúHZ
+ø °®=}O.tc¹Ã0Y|\,$IîG·Ñ ¤ÁiÍa`R+Ç©S¾"0.Þÿ8ÇÌÎ6³ÛC©>¼`fOU;0³w $
+ô ð&0FÒEIËIú¤ÞÖ´`k$Itº¼0ÏkB¥¿$p¤oâþà!3{w<ܲÁáMÀãþúâá¢uß<,$i~<'÷è6x)pðE`uàJIÏÙåÀ¦ÀIÀëÀ`eI?6³«c,?ë[¸ <fIÁïOaé ô0³gµï$I¹næøØ 8SØw67 ,+é>I{Hú¡¤Q7 è-iYIËÄÄy9ð>pN´y6&ÙÜѯÑÀ$ ¬gfïÙCÀ-À×£I°°½mk,
+vÃ}+vÖKZ¹Ôÿ§%]*éNI'JZ¤ÎTΫýÝô*5Ûø@ÒIHºFÒé5º¶$IyÔ Ì*v¾¼\Ù^ÆÙdzÒØô§¢ (ÕOôi`gà3ÀÛÀä¨OÖûÅþàZ`?3{7Ê®ötÐ÷9¸4ên N´¢½Xçô+àQãJec5â}àßf61öÆ&àl3;@ÒÒ¸ÖáIë ·â¾?ñlm·Ns½%é3ûi´|ZÒ+xäÅ `ð¥8çØ>¨sMI$ó2ÝFÐå\%'>Y~Ø5Þ/L4ÂC!@¼lfoÍê Ìl2]±Zþív~8þÿLù(ÃÌFFå-~ ßÄ5úÙ{ÑßWÿÄû&àÒ¹Æó2+
-\Pª¬ïÂ#*þafS$=L´:ðFã÷ÀY¸@°¤ùpÍÁdà[¸fd·Ç+!ÈÃÍÄ8z<$Iæaºb¯
_8ä ×bûL¼ zJzÂCl³¬
hcüïßÔø¤
`fJz8Øxø/0ÞÌô0p¡¤pmÅJÀyqxPÎÚØ×0 ,
U(÷ãÂÄýá71ÿâ.k&'Æ{¤ÇµÌì{E§±E?IÛÄùÆÙQÝxRÒæ!-mfÃÛu$Iæ>R@è,B
?,¶Hê?A× ÊZO$£± ÑQZZ©»¸°Aõ6À¯puÿxàföRÔUÃ,¨ MÀ¸Â°Nýà
+3;<a~¿^õ6©,÷Q.ëü(Þ7IºßÌv4³qþ"i7àfàªz¤«p3Æ·fö»p$Ý `®\S$Iw"MsÜûêµ´Í
öj!^ªìw"ÄjPýõ8Á¸¸ð3¢Ò¾¬a8ø¤[Íìa3ûHÒëfö¤ñ¸ÏE=ê 3ÍìïEAÙ±èØÏ1qýºAßËãQûষ$ûu¼;|.%i[3{>γ*°wÔ,éÿ$IW&5]ù{&¶¢?-MqÛû@\%_ÖBT
ÓBÔÿ³ýkKïon¯r5Ëix2§k%MÆMwâù?#%ý8'iz¤«Oð-FUÉîNÇó@4¢)Ú}7L3HgûÇÇv´
+ð.½¯K{ wK:øý3 |ÚÌ®(TRö& ,_6³>)I$í 5s1i¼Ûj!6×&k!ê
+t²/D\Ï¿Kï
+hè©á½!Gâãá/ã÷á/ºûð|IjÂ}'¦aº¸_Ëb,ùÛCln, ýñÓç$
k.ÞÖöG ÿ5³=£ýhÜ´VÖÀMÅuþ{àáJz8ÐÌnº>À`\YÆ>
G´* DôÍ^föRÙbq#:û³N¤Ë¹YÐBlG+¬@MÑ("£Ó´q
+¯Õ){h±üµ]#én`[<±î(ù3àD`Iùò×Â׸ wÜ× <,éE&\*XÏSqA¼ï,NÍ1ssàç¥öÏàÒyaFi*½EÒFxƶÀ½ñúIÍì
+àz\Sò"p´¤ópÌQÀÂ5³+«BãÉÀö¥²}¿áQJbf÷Ö¹IÌݤ!qfA1Z·iE`6h!`º_Ä¿KECJ×Ò×(|Bm2¿"Æ5ZÒïñ'ÿÂ~åIóe\¸VÖ~è
+Ì_Ú_ëY;]ý%Êû{áÑ1 ëá¦-%=
k/Lñ}ýqgΥ븾[ÌlX»p:°£Ý(éÀExJîv¦ài»GÊ kÙÍ
+N¤+aIûib>|r+3ª
(òBLnq½iîpQ¥þÄVx¬Ôv²¤CËÂ`(>9?hfCñO_T$Ú¯rîpÿñRAø>ûã¬÷gt
+ªX£/pCcvÆÃVöFY± ×Ào%
çùظ¤4Ø¿vǯ#JåogKZ9ÍIÒH!u¦?#Zrhg{µ
oÄØ95Ñ+eGÅ!x¦Æ ÔÌ¿ÂÕþCqé5kvô7\Ý¿
+µØãÌìàzc´>Ñ,éó!\5·5ºy*ë»KÅà)²ÙÔ8×ÀAÀ3\jfçE+áàÏðÓ3{7\mE$éÚ¤!½Ì ¢*@´G1ݹ²³µU̬n*ìH$µ*nìIóu/ÄóGü
+¸HÏu'wH:÷EøXÕÌî´¤Mc.ôðYÜ\²,Íýª¬g,kPÓ\ÿA|OÀý(Iº,Æ{G!¿ÎñüMÒb¥DT ÿ¾A
+IÒH
+BÒ5-D5±T{´ÕÈÙ¦
0_Aò¾³å·Íì`b?¢"^º§$}×Ü"®ÇWÎ<M¾(ÕxFÊÅðI\±h+Cz7Ué§Á.Ø_(mde¢¤cãÜÅ1¯'öÚG/Á;¸à$I×'5I÷#z¡
¨±9no¤
hÚÙIZiÀs*«ëADï½ë4Ý׬;MZÒQ?0_¼Ì4wOXµxiÿ+À£¥pÎ>À1þë*9$~j~ɧn¶¦¹0w¶L¤ûdî!´¯ÄV7D/¼ëå
Ø×Nô§¥¢^n13RÙÌ~<ãWU·Oð¤QwÖ©»XÒ%ÀʸCgñE¯Ê+t\)é|"ÿîX]ÿƯgIºÁÌÞ/µ+n6z
+¾¦â¾eð¶$éúdC2obfo3óZ=âý"Ô´KÍv_xÂÕ¨NÒE¸Så)Qv£¤½ïâûYËáïxFËíÍìCIâN¿Âs.\bfßé!¤á¯¡Èñ9<u$]41$I=fQ±E¼µ
+fBÑAìR.0³KKê´ý09|)À×Ýø¥¤ñü;úø%_áskàæÇ}~ØÁ×$Iç$QfR1 QÖB¡± ñR«£Çÿ<ƺ=m'Tö_öÝ5ö;j~ãyêj4$ér¤!I:ÔBÑ
ÑÌU5 ð.µ¼´]Ó£2ö¶³#Jd&H
+BÌ fBQ Ú£
(²Sv¸¢|GDü]ÒÀ_+QIt-ºÍï3ddµÕÜíÑB}#:EafvÁ£¶^t2png-î$I$é®Ì¢ QȨj!9WÎÂÌÆJÚOæ4 ÷Q8AÒ¿ð-²P&I2ÇÈ0Ç$Û©h!êZzÙ)ÛÒBÔËNÙPaf÷H:ø5Æ=oKzø#py)Z"I¤UR at HN$4OÅÖÐB4ÑRø,5óÆÂÀÇ¥ìuC;Íì/6vÄÓ=÷Ól ü8]ÒiÀ-$Éì'5I´MhI¾.¡¥ 1"ì
â|á©iøzàD}c;8\ÒÀ̬áÊIt
+é¤$IÇ#Û«
ØÏÐèé¤XHj;à+ÞþIóÕ&$é|R$IçbfHz
+Oδ35ÍAÃCðå¦çÃú¾bg$O$=DZæëñ¤zª¦á+=öú ñÕ.Á#3ÃÌl¤ÏáË['I ) $I·FÒð¥Â} ^Ç~Vlföúd$eR$Iç"iWà[À6 >3;&I2BtSÌìRàÒ9=$Ifn£AhË)I$I£Û9¦$I$³Ô $I$I241$I2g4_d_L$iR at H¹ IËJ:HÒ<×ÁszLIÔ¥Ûh2!Iº8,ffoH üXx8ÖÌÆà¿åã{/Ù¨95Þ$IæR$]IóK¯¿´ðp¤
»ÀéÀRÀÍ0³W«S8H.Mj$i?N~
+ܧ=>ø2ð-3{TÒîÙqÌøêÛãÙ_ÃO¤ýdc$ÍÔSÒÉ^ô±¤+%õêÅqóÀ.±ã³ÀP3{´Ôflѽ¯Á°q
+V-$ɬÒå5) $Éìãx`°°¾ÒIQ7kfÃJíÓ\#ð0XÒü¥²E¨ýÑÇzN¤ëÒmL) $ÉL iuIt¤Ý%MgÂÖØø#î+°.>¡SRxÿ^¥}U#p¾ ÓÁzKú4ðiàÆRûUfåº$I
+R at H:Hêùvt¸¤-KuKÿà ®vÆ[cAàïÀðE^ö~BX(h¦0³ïâ
kã̬X¦ù3Û|&/9IÙC·Ñ ¤b2Ï#i0wÜØxÈÄM¾LÒ3»ø:ðÇÅÕÿkàNx¸ÉÌ~S:·ð?ãuEà
¨¬\îÀÌî´îð¶}Xª6ãW$IRþøþT¾ð:>I0³m $}
+|è+6³ îÁ[9ÏñÀE^ÁCâ9
+ö7³§%],Tjÿu´fö 0iæ.µ%æúwTI´Jjdv#©°9>¹¬üO&ôQ+Ç5óÙÔèk8Í'ák#JíÔ§h;®ÑÚøÌìjI»àBÁwÀN²Ø, IDAT¯Ììé¨ÿv¥½Ñ!QGa0~_V/½_
+wLdöBt4¡ß
+Øü+&ê¸#ßýÀùÀÕx^¾ÀÏ[ér8n2Z)\Úè'iYàNÜ¡ðWNvÀýÊíëbf7Rs*ìpâÞ &
¦hö nÒPæNí¬q%I2n!¤;r°=p!°'ð}I[ÙI/OÙY Þ.ôë Pf8°¤föq©lÇ¢},éy`
+3»#Ö<8ø1nV8øIÇ_j}"ÔqÍ5«GY[á\K1¸=^GÏUï
¤ÏÍ'I&$i/âiY5Ô¯Úv
+Ü3(éhÜ1pà<|b_´7³ÿFdÀ`àÉz}Ù«¦«â(ÑÏêª~[pmfö$bXëXàåÒ¾ð(b»ÂÌnhó4¿ÞeiiX=úîÿÙ¼ã¾8;Þ0³±õúL$i) $³
+IâÎpÏÙ³±.ð1þ]\NÒÍìñVºYhfÌì=I §& 'î¾À@[þ#ñI¼F'½ñÌìgë9xØØøbÿ÷
x)Æ3×6<Ýà¾ôëª'Ë6OÁ3+.qÀïe«BU$]Ô $ó&æ/ûrÙ@àZ þ;_x*°«vãþ_iå¯}b¢÷£l5µúpà IÛáªÿCðú6¾0¦Ø §Æ߶qÌ+xXâ?½"=2À«÷ @Òâ±øRÕ7`ej¿ÅñøÄÿp15Aà¥&#I¤ÓI!AÒnxß»# Ч®½ÇoOÒ» ;I ifWE³ñU,GÙ3E2"`ü ~yI½Z:g"Ü8=4Ssü¼ýý_»`§¶&W3{¢½×[:æâjY®$©ê°:SÿóøÄ5ß%!#I¹Ô $ÝÏàOówã¶í3å«$õhgc<tïOxFÁo ÇKº·Æ¡ÿÃOîoâawÃê´ÅÌ>ô=<À®ø¤û6ð×h2XøNIÃP½EiîðµåP¯
¨oXZÈàëÔ¯¡¦
+]rLdÞ$¤[0øZ¼ ¤=«?3³»$Ãc÷ë%ç89&ðËñE6Ç.OâÍ´°ðY33IëGÕ4 ÌìªÈ~ø<¹Ñ=
ÀÌÞ
+
+Æ /¤íq¿7©ùÜLcß áRÕ$°:µÄB £qAà&jBÀ3ë°dFIÌ5tSa
+ÝI_Âãû/ÒþÎÀ±úÙíøDyXTõÅ'Ý«Ë#ÿ?x¬ü9Ã÷йìÖÔÀwã}Jçï¼â!éUàpàÚH8ç«çëq1îïPå&3»¾Z(i~IëÑR;88ÕÁxÈàÕ>$I&¤sÔ_+àsøZmµ?8ÑÌ
+g½MqoÿB at XYR_3»XÒÞ@pßJ÷Ï}%õ/
Ö
+§6Ñܱûâ&gÍì¨ðØ×\ì
Ûæ§4¸^¸ùaDkëÙÿ5¨ZºoÀ
+øÕpÇø¹å,j¾2$É<E
+ݸß/ ·IÚO¼6þd~ý;Ú7ëSóæF<ÑÙ&âjù'ñ ²Í§ø3ûHÒ(Ü4Pöúâ ýÛ¸)â
+ન»Ï|ØI½¨ù ¬OàÏßÇÍ-ãÁjZájÈà<4²2X×o!I¤H
+BÒyHZ¸_Ñï¸ý6\ ø>>n\'év3@ó'zpap),q>?m·¯saà¥È*ÕoÆ'a ÌìE|}ö2-ú{¸7£Lwì´õ}Væfãp
+À£À¿¨ /gÈ`$sö!{_ÇUðï¿OofïJZN4³û¢üàȸ=8hJ¼?À¿Xêf"îm¿rôSà÷ÇIÚÿ<«áÿ#iI3{½Îðw.5 3u#Úø`%|âÿª¤²0P~H-dðr; ¶pL$Ãtæ Öƽàï)TÚõ þ/Ó:Þÿ f6-V\(OÇïÇÍëÅ!÷ GÁ¸-8¾>}ôsàøwäHüI|=àãi!È´ÐNÔó
+XÏd2XLþWQs|aVÎ$I2H
+¼JØÂìGÜ G|Xè-is3{8 ÷êÿüLxÃñ0Á=ÌìÔC|3{RÒ£ÀyîöÅÍ kà·Çùögã ÊÔ]Ë =Ö&¨ú¬,ÍÁÀ
+Ô2$É\Bjº+¾,bf§µ³}_`#à=3{,ÊÀй.À¼w.6|'ã^üëÍàÓðp\ )è¬#ià¸câR¥ú}qÆ@`wÜc
+ñ,!iÜÙ±ê0æ!EöÀ[© ÏgÈ`$s9é¤ØøÐL@Ä<ðÄFÙܾÿ °¶¤ûÝÌìõXfxíZêãMà®p2p¤Àd\«0#T5GáK ?G>UTÙ«¸ b´-Mi2ø2>ñß
gg,|ÆuÄ$IÎ#<
+Zì}üRÜþ~=~Ïöt½[Ùc`$°+ÍÙ)3æê¥øSu?Ü1ðJIÇÇ?µ2Ö?KÙx\¸)óR»¯¼B%d°*,ÍÞ§2x.5ßL$iIjº¾¯ÐÑ_YRÈxþ®xÅo
{é÷ô]ÜÖÿ!°. §e6¿áøªgÄþ*¸ð®]'é4`¤ðP½q
ºÙ;Àgöº$-I}ßh28x_½°0dÈ`$ÉBWGÒ2¸&à`\88ãªú/m2×OøÃñÁ§/FÝpÜ7¡Ìpà®Á'Ú£ý¤3ðy×è£Ûk³UW¦þCKD³ñ¸Ö¤ì$!I$³N·y ç`k`\xí#éwÀ÷pïþ'i°ÐWÀfvCQ(i%Ü8¾¸QḠq2°!0ÄÌî,7Ât³BxÿïB-£àjø
+£PY!«Á4DóÁò*2$IÒù¤¡Ð00³%=H-iÐøBCÿ,ÚHêefoHúpV¬^X/Îl¯p^å\Ãñ þ®ª`ÐXøhe<EòeøþG¸3àÚv¦¹0°lú ð>ñ_OÍ7`DDGI$IçnÄãÀÆ
+'?ðIö£xð¤qaa °(°$é^Üï ðÜÔPd<¹r®ñ{ ®ehkÖÂÃ$Áù£ÙdjÿÍÔ|2d0I¤ë®DD, 0³'Â)ðTI'âõ£`èÕXhè»ÀâÀCø|qü}D&ömÀÔ4*ÆÕú¾ËS| øïÄmÀx$IîBF1t%$
+À7«ì/ès7®X¥¨üI³8>¸À*Àö±®@!ùÞ§¦
+8æ«Ö]9I$éV¤¡+§ þ Ø Ú=÷ìV)~¥Ú®ç\úë
+¬H-dp,>ñ?D-dpðJ&I̤aN é³ÀÀ¶Ô>ÙsÔO<d° °x4JmÁ"qÒHÜ,ðNG#I$évtÀ¹F@pÀð7Æ)^/3³óg¢ÏE¨ï°*µ$Hñp%5mÀ2$I4 5MØö÷Â5+ãQà×ö1®Îß¿ã{P[e°*!S¼0ÂÌÞèØ+J$IæbRÐÙÄÓýÀ!ÔÔúP³óKh;Ù;úÑ|Áb[æ!Åäÿ_jÏÙG$I$IÇ&B~glt
+< ü."àÈ4j«Þ§G.|2d0I$éL2̱£´ð-üWBjq.ÜMM3ð\&I$s41t¾¬?ý÷Ã÷'Ù»0¼$I$º¼aF&ÛÙÍüøÊWàÂÔL3®ÀS6ìÀ±%I$ÉÌ`
+ð?àÿð(ðdC+âÙWÅ[î[:¦p$,zƱC%É$I9L× teåp0´^}d.\±²Ä ®)é/ôEI{Ù¤½%I$I§N³3'+z¨^}â8IÇÙ˳eI$IÒÍèöB[´%@$I$Él¤Ûhº²b$IÌmt¸$Idö$I$I¦$I$I$I$I¦NI$It_R at H$IÙGj$I$龤$I$³Ô $I$IÒæf$Í/©Ë¸I$I2³¤0s| i´¤»%ý[Ò1szPI$I§ÛhæúÅ:À1ÀÅñ¾ è×ÖAö¾ ¼</aý }ÔyCM$I'£ ef£QIêafÓJEëSµ?}%íefOtæ$I.A·Ñ ¤aæ ¬!é³VÔ·¨´¤³%½¼-éIk{ØÌ.6³_Ù&ÀÕÀUzµçÄúJ:XÒt©¤:ú$IyÔ Ì Ö6ǵ Mö6³+uͧ
+Oâð&àúJÇ?¶®s|øð
+p©½å=[pÉó×ÀàSÀ¯%-mfguÆ5'I$F·Ñ ¤0ã×=Íì¢PÎ|ÀÀ¾födT=R9vL¹33*i"°xôs°;p08TÒ¦f6ø).d¬kfïF#%] ìÈL$I:
n# ¤aÆ ¼^ ÌÌÅEû«ÅÓÿ2T`1<*b)àP`3;Ú̶ÁµûE»íâÜÙÈ8ÏF®t¿¤?JZ´4%%Í?s$IÌK¤0ã4á¾kKZ¬R÷6ð>îXe9ü~7$,Ü|xÅÌî-5yX-Þ¯-ê"iEà6àQà@`uà¿¥&ÿ Nô°¤±Ô'í#iOI=$
+´t£óÌ/"I¤©Ayx¸-é}IÏIdfN4$Ø?Ç5þ âöef6ÿÂ,P9ßRÀ;ñþ=ZÿÌöÙ1f67Ul"iýÒ6v6ÂC.·º³q?s'$ý¬Ü¹¤
+$!éI«´q
+~$év¶M$Iº]ÞAÒÅÀkø÷ØÒëX3{{vÇÌ®®+¯>ñ¾õKzø îx#î°0MÒ8`0?°4p)PLÄJÚÐ̧ø¯;GýÃÀVÀ¿o]JNfövø7,EM¸Äèû=¥c¾À1f6TÒÀÀ©Ñv/àDàßÀ4àIC
+m¤%qdI\ëq5nnÙ hfI$é6®. ¸¼úãªûþ±5IFEh ¥ 1Î̦vÖ Íì=àÙJÙéÀé²~aXøxÓ̦Útp¯¤ÛÏÿ¡<BâIwÿ23Á¢Í{Ô(ÃÀËá±4iz\P¿ÇCCó 0X<ü"ÞÀ
½Íìè{p8ðµÐ&<BwâBÍʸÀ³5ÐCÒ¶ÀÍföãò}q-$Iy
f3³KUJZðÐ?Þ¯?eeËJLÛÄk¤F½ ¼ÙJý_%]/nfOêôeà¯À%½,\k5®N
+ÂÀÀf6\ÒòÀÔ²¿_OÞ/Õ-?>ÖNt ðjÔ¯mî3³¯I¢$=mf4ðGÜ%é,Üäq·};|3¶ÇµWÙ³uM$énXÛMº]]@h3L5j#©nÇ/âu£JÙ¢ñTܪ afouÖõÙDà¦uCÃü°®!y+ê.´nÖXwhÜ-m¢eE¹¬ øúïÙäxÊ
+lýöÇ.ïÏVÀqÂÖôsD¤G¦¸ ¸¹£¤]p!èb<óä½v3³Û$í üx8Tî
+ÌrÀd3{¿ÞýK$ä¡«ÕØkÔNRo|Ò«
+kË"×AUx¨'H|P=GGbf¯á¾Õòã"Â|5Æ ¿¨4ÿ£¿Æ² Õ_¸ ñ6°OKAC¸Ù¤õjý(àÔ0ø3ð33»@Ò+1öÛ%m;Çý>þF_ ÆãWgƱë;Ù/§VZ7Å<ÂX«HÚ ØÏÌ~ÔF»ÞÀÚföh[}&Ituæz¡½DÂK±5DÒB47iôÇmZ*[NÒ{Ôq¬¬M0³Oªçèk«æËe¯P²MK»ÑÜp2pQ´{?Ú/ô=\ÐZ8ÅÌî$ü$]÷±Lo\¸hDp[I»°:îTy¤ýqF¯8xÖÉóÌìl IãBûÑæɸ¹hÿw`'ÜgbsIÇÙ Q·:°
+®\&¡5Á\CÁÏñWÓIÛáþwg%I2ï¹3{[]â)xIZ
+ë_)-.imföFg]OAåýÇ(i\Ìì6IðôÒKã¢ú0<b¤¤ëf6$êFGHº¸§ Q5môÄ87Ã(sÆQ¿¾ÈUÁ(\RhªÂôý0]|XÉÌÞ sÄ.ÅïõuxØé#ÀÆÀ®þôtð¨Y½¡ØX§Tö<å?ÀÉ~lfgVM$é¤Ð ÄÓðÄخҶý¬Q$ÊNM©0Æ
Ñ©v÷0ÜV§|¤
+ñÆKÕ[{ßÇÃ4ë öÅMß4³¿Q3s|HM >
+óÄ|¸ðR>¦,0ÁD-iL¿û>îqM¢J*éñötÜ£GgÆIßÂ
¥® .t}Ü éHú ®Õékf¿)Õýøo«$Iºñ_©AHZ#&ªÿ* e´F|r,ÊúKJëEØgÔL\Ë4üÉûJù$ÜgàÔK);d¬M±p¹¤ïàÂCp¦ÝÜ |'æûáÎ
ä'¡Yx-49Û§D÷K wàY+ûãnÝßÑñÄÿ|Dmf
Ñk?^¨wá»måwÄ#;
+ÍÆP</Ä:Fà~¿3³£Ìl|uÎ#ñü¯Ä½ofgD_àB×ÜÓ$Iº>) $³Nh!a¯
+k_*-%é
+Ú$&5:èPÌìª:e÷ĹÆ99ãHà<<$sR÷)þ(®!8ø¦ºÐ Ö2³kåI§âI®´V m9ZnÿÊÂÑFøÊEhk3"éE\ ØAÒÆxäÉn¸éæP<ÿÅ¥ NÁ+«ðl) $IÒi¤0¾
+oÐúz
+óáNÕhÍ*eFÖÇVðÉèkùº¯¿ì"I¡ªû²`W<Âá àBÜìQhh~üOÒÿ³pGÎ¥ÍìI[/Æa¾kÆâ-"FJ,çÑ(;.óÇùûõàiIã>ûG/\¸8¦tì47«<¬'i©öDa$IÒ%I
+BÒµI¬ðnÔNR_Z4ð¤Iå°Ï¢¿¶²YV}fõ:
+íF9Ùæé·ËNê&ÄÓúÎxÔÉ'ÔmÃ)qéw¡xØRÒ£
+ÂW'SËHY¦ì¯°5ÓáùËTI¿Ç̬pÂ\×ý2&ÓCVC0§ïN!IºÝ"YR
+I]b"|!¶È®
+ð4ÑEÙ2Þ¢mAbâLd³|RXa[ÆãÜØÊå¿t,°
+¾¢æäRõQ¸?À³°©º÷xÜï¡Ì4üjzL_¨ë(\`X¸Ô®w¼ÎOÍ,±>Í?ÁW-L$Ý#5ÉÜNdq|¶³Y.MKAbJÙ"ÆÓvªé·ýµ¯e
+¾ÐTµü1|¥ÌFǽ(i´¤õÍìñ(þ3p_D ,/å½)@dÁ¼8½_ÒEáï0 ÿóXZ4ÆWpâø¸æ¨¿Ú®I8~GQ&ed.$$§æñ±5|ÚLýi)H¬U.£$Tã:;e
ñÈ
ÇÌìiùRß;ãþþ!HôÀó8üËÌþ élÜ'a0Ü-éûøú«;εðPR9·þ1[ã¹0 _ijt¶* HÚ,^´æë$IW$MI2#´T§7#²YV£5VÄ8eËIz¶ªsáÌr>°Eåz¯MÃCË;^.+{âËjOÀw¯$²ú:µÄQsËóá3:ÉÿwVí1æ÷¿5³g:vIÒa¤!I:ð#[]JÙ,«Äúø*EÙâ&Òv6ËVÖcB»z&¯ç=<t³ØØTR/k¾ád¹°Wµp,ý¸3ò\Ì&àZº~(ƵákñäTÓðÏv'3»3L8ßÂùÚÓÌ®oï Â|³&î(ú MJ¤!Iæl7ja
ËÒ2Zãs4Ö(²Y¶&HíÈlUá 8øa¨©À!ð]$aêF4ÅëÈHVÜÛ¯¹èR\KðwÜ7aw|õÏ>xXi0ë5<µuOàn(çôÔ·j~
+òÀ¾x"ó$ÝG×)I 5IÒI¸=Ù,ûÑÒ7b 5GËb®h[?Où_hÀ*ÂÁíõG/Ãk»Va 0Ô̶TmuÕ&3û@Òºx¯AfV8gÞ
+ iÅد&³ºÏ}± ð¤oáþ}"QÕÌìÞh{¨j]3{9úí
'£Zæ%ɬ$[3@{²Y.AKAbmàË¥²%%½ND¤©®£Õ?óE¨¾çØ÷øDÒYÀßÌlt{¯y0}á.k¹ºêx4C½ÈÀ[u´7
oÉVÂâܯ
+z¤þñÙZ1û!´lÿ¹ßß@Ã$í!Ãd^#|^§íl
Y£,HlAóhðÔËm ÍnÍìyIß ®Ä# Àó8üDÒ£øSñ5]P«0æ+{y_6»ÕAÖÁÃF_~ ÜkfE¸è%|NÒóxvÑ;
+L¾òçÿp'ÊÀ IÛÙÓQÿ7à8<
+ã}àÒÙª<éÖ¤$Is"j¢XM²!宫Ä4$>¢~Æðõ(æ§i3|â&éLºVaàÀX¬«¸?#Ì×¾ w88ÅÌ>Ô;4
+¨ÜË'= ONeªÙBb¸ðÕÚZ-«~#c§Ø?7W|)ÌO k âÚâQ5Äõl/}¾5îÌz~5)X>¼{Tn¿ð¤
+oï1I¡[) $I%7¢HͲ1XæëTZ
ð ypk
+{¦1³KN£MøÄ?Ô½#ikàL|ÌïãËoí¯þùî3°'¾ôøÑý<: IUqMÏÛQ¼ÐHXÚøN1GB§ïG]á\y=õïÖÊX
+w~ü-ðW|iðñLHú,p°R5³³KcíGßô-Rþ×Z¤Ð=I
+B$K)åôI? ö¡í?!Ã1ûKtÆÛKkN£föð©xbïYʨy5®ößè
@þ¸¸d~¹ ¸GÒ¡ø:¿ n)¾%ÝO¸Ó}¢¼G<é/
+>¤öØ,`.LúÌìøès "LUÒR¸¦çÐó:¸oÄfö ¤M¢ÞðÏw
+I_Ä µ"4ó¿
+ü3®Ij$½ÄøÀ.¸Ê<¯À»¸°Ðwü{O&ôTlkâ6ø%mAÍ¿aêl½vN
åý[iCbfÃ$}×ì.5ù1p½¤eñå´
+7ÇNÁS×Fû=ðû. ¼X9åRÔLMÀ奺wñ
+ð¤WSqo}ü¾ßlc¼¸ÀÌ ´ùwàøbcSÓ
+MGÒãÜÃð%Éoû°®aɼ9Cj$=ÄÓèµøºÓð§Ø§ñìËT
+ IDATq<üqT½±$ê÷&àçÔ²Q¾CãÅµ× 3±ÈÖlÇÌâ¡õêFFjìðµ/zàBÔ?£ÉQÀùR¹<
+±uÔ5s´ Í×Ò¨:QöÇÓ/l6ÿÌv¤f&zRÒj¸äÏ¥q¾çX bZø2Ø
+Oõ<pìûÀ qm$=§øþ(ú]_nüq3kä0Ì:Å$Éì!÷µ?ɤMÃÌl³è³Q6Ê
+¯öôc»úÚa²8'¶jÝá«1×*ldfÏFu?¯zÚ¼g¾ôx±_6ô§&<4³Ã«ç´>ÔK;Ý× ´&õÇW&ýbô·"¾HØföHø6Üì
+\$iK\À,-éb`3ÇbfoÄ~àý0qÍ~:Õ|¡²ÖÚÍg7 [\K
+I2'wp3²²?ð
ò~´kO6Ê)y
=ç¨ÿºR4wJ,¬;i®Ah¢uqp¤3pSƸÂí¸Ãä4\ Js£&d4¢ ÏQ°ùðc¼6.þ;H~wÄù4×ûÐÜGã7¸`tB´ùð]Ü1ö¿ÀÉVZç$Â{ûT×Ç8~ÛƵ/éV3» ÔßòÑßómÛUI
+B$s73²*D¬ |¦T¶\D(´µÈÖëE¶:x¾$ÞîRæ0ÜMÓÆ/ñpÔgÌì6àuIG7K:_{Dfv1®yX¨'ë&àÙÒþ¸£ãõøý^\Év5bM3{/2q®ÇöÞ®äÜXZ6ËÝpçPÜã` ðãÐTÜGôôðµ8ßfÀÖF´.Óôy\Ù'ö{âÏ.Àk^ÆÓqO®Û
I
+B$IA8>KóI«¤åÚëâ{EÙò5'Zõ(Ôá]ªJÞÌÆãf¡zmOtf¹9>\Xtý°ÎáUßgp'ÍÛªI²"µÑ<ÄÔ4eGAÿRÙÀ©À%fö¤ûpçÏýðUS?çZwÔ|I;\Þ;_V9
+7má¾x.Á1Þ+qägum¤½ñïÒà43{!ÊûËÙKÞ¤!IdFÓp§ÊºÄSdÙ¬Q[ÊT[d«l¶ÈVGcf÷àNå²)ÀΡú_²zLLvÓ|Rÿþ>LÒ©xɵñ\
+¯âÖêÀ3hêxx(xôË;¥þ{ácä)¨×ú=£n
+Ð7îÿóÀ/$í\dfEÑÃìpT²Îu¬
kn)ï\Q$øt)¾ÆÏ$¬nfÿiÐß!Ñöÿgï<Ãí(«6|? ½HBHÐ{"M¥(Ò»
+"¨ ¢¢¢"4é MéU ½HM¡$@HBBõýXk²çì³÷i95Y÷uíëygæM8ï3«[áÖ
+CHδºU5óê Ò$IÒÄðÛÔ/ÍÌö¯éü&[Bäåc[ºjIÚOÜw¼©¬J:¸7ÄÃñXâû}¬J'Ìñ·ÿÑxÚå<~án¨Tkß%iw<ädI?4³kBäõ§é¢_ÁKdYóãbäÇ¥1ïSIó|¸[ÒûföpO\Ï3·Tlf7Ås>g\Õ9ÅÝ×71§ö"-I$]EXZÒd«ã#&[ÅvÑd«^\Ä`´y?nIÄ+Üj~÷X_ÌO¥
öQ=rx¸vÞ¡ érà^1³f6URÊ=
+|%ì%][>m&»eUJÀ8þ÷×(b'~)×ûÙëòEðe!Æë®uÞF¼£B¦9&IôÂÄü>-o²U_ a¶FÑd«nÊ'.$>®¾GWâá¦øß.?HÒ¸µà]\<÷¦xZÒ`qàIgàe±â©Ãâ©T:nÖc
+@kV¹ÎÄÖxjf1Ïë%ýͬpO¬×w(3¾_5÷ðÜ )$IZ5l²õT½qª4Ùª¶HlTú}Yy&EîÖèô¶ÒYBÀÌ6¯+í
+.éHܵ1¹@NÁëfì¨õ&H!é6àQ3;µÆT&ýJÛoã}Jû¾§is_·|§,L¤mDI\à¢eñóhoÒ$I2·a-o²µ$ã#ÖÄ+4Û}#-°©Ï1À{íYH(Ìï+ã®Ö7JÈbß]x7ÎZã×´%Y{ñ`Ébü4IWWÙ/k}.¤åñ?ÅëGü84No°øKZÏù}é~µDDGAI$ImÂ÷>/]pkô§qËï-ª¶ zsÕ,'WߣùuJ©e3{wCÔ:ö¬¤ù$
+6³7b÷ñÔÊ1ÀQO¢/pp¦]"é_À0IÙSÀ}À©>gÞøëÛ¸ùOé[1
+@Z$I¶nÂjPHk¬ñCe·Fq½¦\cÍlZG<Où5¬ø¸Õ| lofE`å¶2³%<,i8°°WUJã¶x,EG.$I¤ãEn
+{B4BÒ4«ác±¯¿¤h¾å»Ñ!*G¶d\ÓQÞw+Þ_¢Ø>NÒ_ð/Ù,¤ÍðÔÍÚcÞs)$Iæ¢ã4Ìk@IêGã ËM«ö-©ÍU³lT§¡+K#Ëû"(óLàëçiAH$Iza0.>ÏÔE¥±kc]¦}Í·ÛIs=úI!I$i5± 7z¯FÒâ4«àõíe$M¢ùjïXÓ-®Ûú,ã[{^¤Tnü£u-Ò$IÌÝDa¢Ix¡¤¿ã#6¦a*èÆÓ|5ËNéìhfC%w¼8ÛÌêö)ÚÁSkR $I$]J;ÏÿêÆPh±Vy_ÄQ4)"p·F{4e:·"ì#é
+àt¼³eSMÀÒ$I$íA¤8¾ºD¤j1/Tì[FÒG4_Ír|Sn
+3M°^¢"VÎÎt5nU¨®u.$I$él¢ Ô0*}n¾4Ø/
+]l/)é¯f¹ð$^±èq0Þûuܪp}TÚì¤@H$Iæ:ÂñN|«7NÒ¼¸[£:>â4ïÿ° Ð+N7>ëâ
+«ÎteOB$IôT¢ Ó[ñ©¤hºMôÂñóðøy¤éÀuݬrå,z5?$I$IzHú>ðO¼
+uy] LÏ4¼×mÀà_ÀýÝU@Z$I¤MûáBà \ |»&áÕ*ų2^ ^ÞDªæfÖd®&B$I´Iý¿Ë OáBàÅÎ:I$I22ع
+«2Í1I$IæDÌ죮CGAI$IÒ¹ôB
+$I$I!I$#4¯¤ë$-ÕÕs©"-I$IÒÑHOÒ¡.ô+Iì"Gÿ.êÚÖ$B$It0ç¿ÄS
+wî^ ç¢-sw¡G¤9¦@H$Iºô-IûKZ¼
ç,·ZÞÁÌζ6¾ Þm GtдÛBº$I¤VôçÒv_¼ûâ!¯sî IWJZXè7]ÂÌ>nv-r+°¡¤:äaæPR $I$]Á7JÛǯ Ûk §HÚQÒÛÖ±¿ &F-¢ÁÒµn¶(6Ìì}¼Êáfíÿm"-I$ɤ$
+jãé» ¶76³iQð
+`7IÙ]ÀO{%}Ø85βu`
+°DÕý¦Ò½Ö¼I$ÉËÏÝ ©Þ:³10ª´=V»ñH[ÙÀ÷ëkÍllì<ìY:·7ðYÕýfÐ}»Ë<$B$IÒV kÇHZ²|PÒ]¸¥ ½ð
¼à`V`b´A~è_óFìû¦¤Jû¯ öÔ'ÉÀcU÷ <ײÇj?$-"ésöôkI×Ç\Öìì¹´ìÅ$I´IÙÔÒ®!Àáñûp«ÀWcì¼ÀÖx+äZ0_iûàIG õæ-ù
+p0ø§¤=ÌìA<Ka'àmàe`9à¥ydfÃZõÀ-$R*ákT}Æ°ÀH`8îîh®ãc!I$©¤c'3õ$ö5³§¡ÀZ1ô·ÀKv3³õ±f6¾Î¥ÂÄ˱}'pðyàñ¨~¸ð|Ìc+|ÁÝÅ̦IÚø¤o
»a'IÆ9
¢`CàÂvø. V£±XX8MÆEÀ0àÁø9xÕÌ>ëÄc'º5)$Iæ$Í,ffïµpüRf6!~?ØX ¸ÄÌ®a{áßüãë%/KIêcfïK:8_ÒÝxÆ@µ¿Ìõx&Ãù fö¤? wJº·D<
+ü/ƯZ,üfö P`fOÖºÝg6´Iý©m
+Xwn[>þ¿3³Ñ-½Ow'B$ÉÃ÷ðô¾½ê
+!08X_ÒÊÀOpýÏ%³%M5³áVÙqþð`ÁÍì>I#p+ÂÍì.IOÅuVÆøz\üRÒjfö
+çoüF´8v~[¾&¾ycµ@1xÿ¾®ÃáQo¡ô4ÇI$scM$ÁýÄÌ&Vù:"øs3ÛQÒ¸
`k3{NÒüx,Á@!'ÙTI/áë}xÂZÀcÈ1TO¯7Q3{GÒ$mS· ·´ù¨"'7 at Y¬Le
+/üÏ×Rq¼;I$IûûÎxýS½ñ¿+¨*3ØÈÌ.íÅE%Ó½
+Ü_ÿ«²;â÷Y f6FÒ©x@áM=ý#b¾6©m
+èÃ>^ÃþQÃÌlKHsL$IÒM4 ÷Ó÷î0³§b*êÙÀBÀÂföMI»Ììµ:J%>ÀÆMÀf6£jü`Aà¯Îù,ÇlTuÎXà×j}¿¹1¥ÒÊÕB`U<v<
+²Xüo£08Â̦·ô^@Z$IúDÜf¸9{tiÿç»p÷àvIÙÍx¬ÁÀk,ÂÃð7ú¦ÂÅ}"éJà(à^`´¤ñ¸cðÚà
£qAñ%3û0οïuPÌ{í×æ¨ÎXËPTmóܤá¸5àݶ޷IB$IâHê]^Ì%í¿ùî¿Á¯!éF3;&ü8%:"iðkàf<
ðÙ:oèCqpkcàiß*ÁÑxËä>Ãë\L7³#Íì-xÔ45(bê¥.Ã꥾V¤ö`Ò$IÒ ÿö¸|ѺÔÌÎnæ¼ÞÀ/ñÎ%=ìÅãûÙµñÖ<DÒ©föð9à9IgkãÅ>3ûx¾-îN´}R>hfS"`Bìûø®¤Ã¥BECñÅû®&¿,¿V¹ä1úQ;Hp0ÁQøÂÿ(
+SÇ4w¿Jf1$IôdB\/h¿Â£óû_)Y¯"ø<pï43{ÎÌfH:"Æ¿ ßü_t{ã=0³·%=çÿ_¥«âe÷Ã-À
+N1³7cßêf6sÿ®¤7bÿÕ"Xõ¡ ýExÊ_½ïiê§å§âÝÁÂ20Ü̦ԻöJº$Iz8_Ã#ìW¦@ào»OÆÜ
+| x@ÒFf6/YQ
+ð<¼Uñ_ðűúMò%*ÿ{·XÌ%m¼bf·H:uæÁmgfÛ4õP- ¬_Ü ê§%ÇųSoÖ°LÌͤ!I¤+HÿoãØò¸_{þ~u¡Hñë¼Pê7°'pkITßc
+\,©r·KÚ88ïNyXKR/3û8ʯ
Wã#Æ-~?Ïx#ââ®
½Ììè Ѹ¸mÂj²µEã¤iÀë4NÞ)=!R $I2§2ðG¼ªß¥øâº"î÷ÿ²¤¯ÙgÅ «àouóIÚÉÌÅ 5¿$0¥jQ¼<_ðËåGáøñ@À" °,0³m$mǼjfåöÈDó¡65
+×HÁÕ¨¤N b¸ÑZ+DÒ´ $IÌÑ_`|!-6³;ëú& /YQåïIáÞ®x´ýOñ?ÖëÙdIÂãÖÁÅÁ¯>7ÂÏ_,ÔKPùã?·&s2IEâ<°ÜTè±xÖòsÝ&:ÖryÎÀ»)çP lQO¤Õ¤!I¤XxOï{¸_x_)àhüͽ7p\¢ÊßíÅØ· »áaKàß%7ÂÀQár¸o+¼}P¤~Q5ð!¼§Àÿá
]q¾Ð._âx$.0³3Ê× ÁVóÁU©2¸hûÆ)ÃqËÄ4Î&-I$³ÉàSàfÖ¨;`øÌÿ:xÊ[y¹q©øú?ÁËðÁßðúáÅ®t½½ñÂB ã ßÅáë?Ù!.fãÍìñV>ùYûR?e°7M§vûöÂsæ$I2»Dºà+¸%à±°¬ÌVíuñRÃÕ¦Û!À>5.;?ÐH:-Îÿm÷þ^ð
+IãðÞÏá©Dá¦ùIuÊ^k}õ2¸µ
@6· Ç-*ElÀ+saÊ`O$]I$íÄÜ2nÆÿÿ,WÖ«õG·E49ÚÏí/bô=àIw?þ^FµÁ=ãí}a`bH}3{¿z_SHZÚ"`*)c©¤^GÃ.=bIê$Iv`(nFßx»jqÔ§Æ"=X,õ>Âý.¼ \ HÚ8_ n¬@ÔøoUÿè³°µ
À21l»}>lÍýCw)$é ¬NóÂîßHú%^wàÀCQp2þ>)8¸¦,2Ìl<^)±MHZú)Æ°"ep
+SGfÊà\IZ$IÚ!¸`è>Ø÷ÓÏcfC%í×:xR|x8Îý"0*DÀl!iYj[£28· ÜKÃÁ µ®Ìdb$I;ñ*0×&÷,øMô Ø<Òý¦We
+´ª@d)¬Jc!°:IR± ü§ôûk2Ì)¤@H¤Ã4_{,f6MÒqxÿ!xIßFí~[ÓXÒÒÔ¶¬H%eð-¦±2ÌiAHdîDÒÃðÆDoµÇ5ÍìÏmGá¨%aEÊà0§Öí`$³A)&I2÷û»âM6ö0³v-¸÷bÔO/Á- /Ð0epT¦&]@Z$©¤-G{úâ>ûpa°Rì¾ÐÌnhçûïÊXKaÓðx
ax¦rÁLLº=âÿùIÒÁÄÂ6øÀÌ&ýð9àì®×ì
~~Wøþï5¼/B[¯»X-VaïÑ0e°è1)IO!-I27#im¼øÍÀ¢7³Büø¤ûÍì¥.d+T¿cïóã}»·Äw/i µËã<§Sé2XN)I'$áb¼Öÿ÷ð|üÛ$=dfÏEã?§;uá[¤5ãpwQ)\æ3{±tÎ|x@-!P¤N¢R=°2øz¦&I×!Ij éѨØÞ_ ®N6³Ïê»^°g¬wX½ïô0n?<ß ü¡Nàn¤-áݧSûïÆt¼%ó§N£"V¢2ø&¾ð?\B¥Ð¸~$éf¤!Iz">|9¶7Çsà&¿>N
+ÂóÌlz½k^è
kñÅ 3%éàëÀåüh-&â&vÆ?»Dm«øß-
+h2XÄdÊ`ô0R $IcvÁkö|¸ÑÌ®Y)uçHú#^Vw'`[I{¿N5³©¦ão
+eýKxÉ`²FKwèµy$}1ËáÕ¡¾0(|
+ÜÞÙI2Ò#,½ºzIÒHú©¤o·ñôpsyÁ <}®àf``Ëx+ÞãÂñ"azã*íëQ÷Å|þ üÐò¿óÄ5®ô×h©$ImR $I2°Y½¶´uÃ}pzÁTÞ¤1³IÀsÀú±ý)ÞxE`,
+-s÷ {¶ÆÙÇ¥}½ñ@½®¤WáEnÁÓ Ë9Û3q±4Æð¾<+ij$Aº9¡À ö4³óJÇ
+ü®óËnáÀ!UÇ
+X´´½Þ#`$p¤¯
88TÒ¹ÀÀ¸o¾ÌÆÀ±-y¨Ù!ÕkBT<˵fö`óÇk9?«ÅÏ¥¨ñûx
+çfva<Pô\z!BÒc@ºÞÀ¸[àuà3/ÖkÆÐ'g$Ýmf¯EêÝx4}-&ân
û?KZ=º÷ó88OÓ»¸[ÒWÍl¼¤m_á(=ÃÀûfövÛ¿HêKÃÅ¿ø}0á3|øcë
äÕøÔº_SâdIÛÿ$Iz)¤õðÃ'JûîÆã¦þë#¯ ß³E%õ7³×%W,Ü £Ìì½:·»ï)p%½$éßÀ)~lûbü··ÌìëwðÀEÉfö<°[{M§±u¢%ßÇ<TU>1¬XØá©Eáf6¹êzÛ¶v-óá1I8iAHI[Ù7/°pþV¾(p'î÷îô´½gì,cfHºxCÒ¦fö¤¤WãZãñ·ö$í¿ÝÖ³ \/i!3û¾¿iÄ[af¯Ä±ñ4H ";á¶|-Ù(`TßÇâÔ«PÉ,x_ü_n¤"FYXN%eÁ£$éa¤@H:
ñ:ÔT² éR*.³ñ.|ç·Ù/b̹À¸`(0ÚÌ>0³1n¶ÄÝkÙ4IGà
+îª7Q3&éj\ ûÞ¶7w+×û7³ñ³ñ½®¨-aÓqÊp<¡¨68¬ª¿C$Ý´ $s7Ñtç³H÷ÛX5ÞêÇàî¯Uò:p
+ЧXô$}¸LÒ·ðÅ~U`I½qÐGÒ¼¥ª½©¤ì
+¥Ý/é`?àÍLÿXàiI×ÙS¥kLoÕP"¾êàÀ¢ QøÅÿn®Y¹1IG
+dîDÒÀoñ·_ µ¿ãn]ÌlhSãk¼</ø7ãUùfH÷ظ",ëààâ°ªký¯[Ðds$3îæ
+5"Õ²,ÿQI¥ìðýxÝá¸5`¶¬I$íE
+¤MHú)Þ®xY¼@Ð>aâ_û!p©¤^f63ô5ñ
¾Ci¼ ß»N*Ý{I¼
+|ÕÿVÄ#ÝCï©q¯-Û[â7³Aw1ù¨¤V"eðc*¥/¢b
+xµp$I2W¤girñ¬ãðb9WÙ¿ãøáÀ7ðt¹3ðæ;_ö1³Këã&ÿ¼,.iR \
++áõ
+¶6³7%
+ÃË¿|jf³ÜÑühV¤h"´/°g+¾¥©-V¤2ø6.ÄØvK]L$élR ÌHZXOk{ÐÌ&´àyp»#&øi{Ûá± cñüý5K%éóÖÃcÿB¸ù¼/[ÕSÀc
+Æžç¢"ßx ãÀñ¥ú¡ÀêfvssÏ[6~[â£^ÊàR1ì*)ÿ b
+nfµàÞI$iAH:I«âµó{ãi{Kâ>öUJcæÁÀ§fVö»¿ïÃû\*éP3»_øVÇÛ?¿ÁC¤Û IDATg\ç÷ÿ4/Ò»á&õçßW¥\(é'qÓkÏ9f6ï X!¸£%¼¬!©Z¬gL·i.§.7ºCÊ`$s)AÒ¢ÀCÀifvfißÒïÛàßÖô °[Dÿ¬efÇØwñ¾»pSÿÌ8¯à!¼$ðÕxàL3; jN½áâáo® ¦â4³ ø·.^°\ã 3»´5ß52¸<µbX28)Ã3e0IN Ñß¾îH
+.DÒ2¸/{üÌ[¼¶/0±, Ììݸv/üýd3;/Rì^Æû£aGÁ[s%ÍEFâ¹ùoÄñ¡T|÷gÿôîw_Ù͵pîx¸¶4¿GñÙ"g5j§Ï5 :e°ÍéI$³IºÚHZl/XàézkK:ÆÌþ^»1æ7_XOÓýZ¸9¿Ëã7ì´½sñ¿ÓñVb3+i
+nn/Ükáî(ÙÓ¾îKðÙ[¸ûa¶4ÚÖ婤¾s~ /¬T ¾ÓsH$IÐNDÃÕðEôÅ&rý1³$M/×IÚ¸QÒP3{LÒx½ÿÓñÅï|ÜoG¼Pã«Ï¢°DKÜúÅïCqkB¡øâ[Cp÷BñOà³M¤®Bm!°Xû)Åï2$IO#-s:Ãú¬û½/¬¦ý¶Ä«å=n¢ð,`f·Jº8 :ü^fø×qW'$wá;¨¨1P=73'ix\£hk¼"ºÿC$Í_*y|?:çQú÷af'´úK*!i)*Y¬Z.åÁá2$IÒ¹¤@=&ÛG ×D
+`$í¿y¿Âíê7ô»ð®ÄØYc4 Þ/ªãøûõ~bf¿NÄûSpÄ.q±NÆ£÷?}?/Ý«^ªbD âÔ¶,Ã>Áã!Ó8eðã¶Ü7I¤9¨8X 8Xïø=3»ºêðjûé'Qiû°IÕñ% ÙÇön´°n}ó»^Ò8<=±7°Y9ÕÑÌ~Óçz¶Å¨ÝW`U*)ãñ
Y73e0I¹sCí"¦`-¼`ÑgföM`3Üpmóâ9ùöÀë<pÞvø+fv·¤ýùÀA3»7J| ?3³{ÙÃÀÃmy°H\Ún¢ö@2Y¤±ÃÌì¶Ü7Id'ÓçâÑüÓâ÷ñ"; 3ë72J(éËøb =-¯ôîÒؼðÙàdzó ¤vÊàê4L¬î28LL$iiAL2³k{_`÷Ãî Z4³ñÞÅ /pÝZ5³%]7 PemhQw¡5`*)#ñ
¿:eðݶÞ7I$i at Zæ$-R]?jü8CÒø»;ð|¾Oã{8ØÌ^¨uÈ2ø´Ö±j"c¢^Êàâ1lrÌe8nñ(wlÑ}$I6As ¯á~øÂP,ÆÍì3;GÒ³À×p+ÀOÌì¿ fö½¶ÞTRê§Þ¦2xkÀèZ×L$I:s:f6#2NÅÝ
+Cñzÿ+yx¤µ×ÁÁÔEÏ
©4î28LL$鮤¡»%hï¢;f¶þìê¥ÎÃÆáuÊà[2$IÒãHBw at Rà(àÀ]4áýjYÆ°ÏpÅ0à6*"`X¶ÈI$IÏ$-]¤UðÀCðÃÏutÝ~IP?epáö>ÅÿÒï#2e0Id® -]¤Mß òáЦ(µáý©2Ø$oаËàp2e0Idn'-¤ñB[áæzáõÍfvQ®7/°2µ
À1¬HFÃÁ×2e0I$©A¦9væö~:.Lôóââ`<µ{¯±$µEÀÊTRGáÿS4LÓ¾O$I̤@è(¢Òwãx@høLö0³¢Ëá`j~1~*Þe°H,,ÃÍlJG>O$I2×. ZýõÂ
@瑱<+é¯xà`9e°Üe°oÎN)ã$I$i!iAh/$g$|ÍÍ]x4L)I$IÒ#^D»½@´ð+àóøÚ«
§^_à}à7é"H$IºÝÞÐÒŶ+XØo-¼/³¥Ê«ð¤uÛwzI$IÒ&2a6
+<g'Æã³*Þh*±3ñÞ4GÏFxZÒ1fv~ÇO=I$Iê.vÀÌl0¢ÖÁÈL(âS- zóô%à»f6±c§$I$uIBGMFÅçáêãM3$lfouÒT$I¤ -]Ms"I$IºnoAèÎAI$I2'Ò#,)$I¤óIB$I$
+èi)$I$iD
+$I$é\Ò$I$I#2H1I$I¤!I$I¤!I$II
+$I$é\Ò$I$IÏ$B$It.iAH$I¤æ$I$IMÒ$I$IÒÅ$I$IÏ$B$It.=Â0OWO '"©/p+ð60ºôó¿föVWÎ-I$IÚ´ ´å
+k7þÀ.ÀZÍ(iIëJZ´Cg$ItWÒ03cf×·æ$Iów/}%Mþdfï´ÿ4$InHiAh÷$-\ë ¤å%'é~I7JÚµt-Íl ðuà3à%I«¶äÆaø¥¤ïHZ¿%I$I¡mVÞ4QÒË.´ð °8pð7àóqÞ@àC3`f#Ìì1þäò
+äÌ_ãÞ_ÃÝWJzBÒ&íûxI$I9ÀÅf¶dü¾pvÛXø¶ÝnfwÙ qlÌXÍø¤_Sqa
X¡4vp}ÏÌÖ ÿ×Ï$I$)ÚÈ <s3bf¯ÙÿâØFÀ-f6Æy©-fHÚ8Ø4Æ¿
+\Wuï1¥íáqOâü
+$m$i)I×±B$I$]G° dbÛH|¬YçX=ºÀËñûÞÀfö"¤3¡1³qqïµ%} \PºÖÁÀfÀ2À8`%I_)¤y½ñÀ
+fö^³O$IÌU¤¡m,\&i¤¤ÿJºVÒaqìZ`SI{#{jX$-ìÜ»)
+)¬Iê/üË?Áã®1³ßÆ V3³Í?æñ_à8`~`௵PÒ¾v´½¤HZ®t,ÿÝ$I´´ ´Vúâë83ÞÅSÂÌV´ ¾àqì¾üNÒi at oà à|ñWÒ¾Àô8ïP`pN\~< Yðu`2ð&.zGÙXI[÷H:£&YÄG.Ûãã÷ýqQ0È̦BýN¸%b8.X´.648¡ê)i0°ðxZ%$I$B;°pþÖ¼´¤ ø[õ\44úÙ}¼êc××uà33û8¬lÿã ÜV>Î4OüpÍ4ãã>Hºø>pR?[ÎGÀÌ°>l»/¦æ:³Î#0³ý`P»Ø¸
+ظ]Ò³föº¤=KÇ5$]lbf_ïáL<pÓâzËïÙGuîß,Ö Þ5³ m½F$IÐ#Ú=w{`fTØÆÏe/÷IZ_$ë\H´yqjáÜ?¨Ú¾ªç\/i&ð]<pñ2àOqx >ïò¢þw\Peh±7ðT´pú߶÷Fáÿ°7 ^¾,émà|à`3»NÒR¸ÕaX»°s!qAq
+¤Õñl·ÙË4Ï«Ë$éàn3{¤×L$éhÒÅÐÞÙ|
+<Uo¤©²Ø¨¼_Òg4#"±föY=RMÌìFàÆþþËÜ»ÖÞÁ3"¾"iaà@à1öAàgúÙøf¦±l\·`UÜr±U?g Ä}ÿó é9 x³HÃÌâú£Âuq¿ñð ¤CÌì¶8Xÿ÷ú p
+°#°6þßqm`¤M©~I[੧§Äv/àç¸ kfg6ó]$IÌuô(ÐRÂ^Óü_&Lße1÷ÿ±´¯D®%ÊûÞ«zCnwÌìC*ÙžÏây6Á-'ß¾SîdfÆð+ãÙ^t-nMø=_¾f|/ÑpQ¬bfÇUÏKÒ.x¨²F%Óc(QÞw6ð33»(®÷*p"îÊ8:Æ_~WßKá.M+RW/<Ãã¸çÛÀ!¸[æSàÞ
+QÖ$!dÖÆ]?×E¤Å#Ó$I¤)$0G
+.¨ZtËÄ"ÓÆBâóUûTíÖ¨1¹£?üiÕc?@Ò¸à#`hë,
+¼Rµàÿø®¤?çâôÚfv?d9XÒ¢f69ªI~·xgL|X\(\K£#;b%ศ1·F,ÃÀ«RÎ4³áÀoãàèÈ&¾ÓM~fvGißqÀ_Í춸ÎÅÀ¾À¦Õa9<̼ é,3;5,®Wg.I$eÒÅÐÓ ÿ¸ø<So\$@c!±ny$£ K|¯Uh©9&·´àF#8þþf^Þ÷¶¤ÍðôÊpõû(p¿½$éfàIᥠËC%õ7ÑÑÀD3ûDRñop[\Uß]±¨
/¾/Ç=~jf£cÌäf׸[µÈ¯Ü[3 X7KZÃÌ&IZøpTrµË+;$ýÑÌ>3³Q¦IZ¿Ú"$IRE)ÎMÙ§xëç7o×Õ±«àže$M¢ùøwÊn
+3{ÒØÞÙêuÞØ_dÀߦ³ø|DÜÇèÒ±·ðÇýÍì¸{¶tÏqë©Ào«p1Q¯*eMûKÛ«ãîçJû&Å>ÌìII·¿tÞyóø:Y1£>xPè¨ØwnH$Is¤!iH,xRðoDdô¥±Ø;/ö-õ£ãJX<®ù÷Â΢õGÀ×åÝ''âıöþ%ioÜ*±Ýðpð73{OÒcTÞâ§Äub
+
+ÿ'ÿw_¸O6 ¡¨;ïoñ
+<>ãÊêÆóÜnf£JÞÃ
^$IS¤!iax'>ÏÕel²X«¼/ÒC²Vö``zu}*ÓûèÒþ§".bó÷»x=
yâù Ñ48<N,ÁÙù5æ1 S((I-F%ÃbG*i¤à"â<èòªìËcÕ%Sñx$I¦È4Ǥc ·âSISÅÏ-¨>¢ KÜQ¯¸RÁ8ÜmÒÚgy¨Æ¡£êÿ87}7õ×âJqf6DÒ+À©¾gru6ú ÷àµ%v´GU¥ÈxüÅ«ÀvQ,«ÌÂô7$IæH0_O]"¯:Èràk¥}}$½KÓñ£#°CÇ{r-p¤^%Qó-Üðº»MËÀíÀ=fv²¤ÿàý6î1²^â|3ûMûm
×iH$i´ $=p L ^¨7&²úÓXHlKÃlùi>ÈrL·ðvÃÌÞô îøxì{ØPÒ¼UiýñrÐ×Ǹ$Ý\þ/3=?°¤?Æs<UTgÈÖDf$I3¤@Hæ,¢àP9¡&¥je!1_¬}$}B3AÀø¸5êÍ÷À:û?«Únúif6·ÅÓ!ÅüWÂcòÍûÏÙ³$mFÒ
+Àxëèrß$è®ÈIÐjKÒXH¬|¥´oiIïÑ|ªò0ÌJñQçÂe}µ£î?±;ðKÜ5PÒǸXø½Û¥3Kö%-IÒ±¨O¤ùjýi,$¶¢a¶Æx\ASAc:àtyà'föj;_wnd p ©oì{¿©¢çÆïñÝáÀÀ£Ý-IÚHZ¤=÷ÂØø4WͲV®ÏÑPHL£ KÜÑ\
b~Ãh¢®EÒ*á
³ «AËA4çê7³¢_Èj±ïÏxc±cK%VÕnIÕjø$@)&Igu,#
+³ªYVY®l_ÚׯN®ê"TM¾Ùv6¶n+5¨êIôk*±./Ùa!º
+د1XÒÙfvv÷ý3®óI»7HZÝÌÞlÁ½´jÜó.¼gÇö}¼$E
+$énªYÖjT4¨fY-$6§a¶Æ¢¸e£© Ë1øfú ¾^,é|k²NF7cÞó#¼à×ñÅúB¼/Ʋ@3û4þ-[:¯Aà¬Ý$éI¼çI 6Å}\±%å{ï»(vþ'iãÈ|Iö$]IÒS©ªfù¿zãJÕ,«
Äú43i¾Õ¸Ù}ë7³ö^Âk+é ààºMºÒ=]cÈÎÀ9EÅÏøoTÀ5Îy(¤%iOà¯xkðþ¸ ørôàX oþFd´.iW\ ¼ç/L¨ÎI6$iE5ËEh±*°Mi_ÿhÒÕ]]ºÆ&IúðînØØøLÒ_Ììí¦®ÑEôÃ{eÔÛâx¿ZjúP§¿2³³ "Câgxß1fL[oîUr¼¸+ÃÂx_oýFú /Ù;$ImÒ$Ñô-©f¹4
Ä&À®T,jÒ5_d÷Æ?-?ÆWg w¶µÆD0(~î/i·C
+Å㮫qn£î±Èo+i ^^üêÒJç<±'«â5¯ªºÇÊÀx¿JnfWIZ¸X/ʵª¤ë4û ¼ÛCcDö#-I´h-ýÍW³\ÆBbíª}¦ ½âôâçv¸ðøDÒy½
ÏãÏ1ø9p%^áIËáe´WNÇÿõ¥$¢¾Æ¹¸PºX"ÏOSt:×ìØÏzùðH)'bM~ofãqnû«^
WÐ,efE´~uóIàI{ÙòQæ|ÿçCf%»çlÒ$IûooSߤ£?PÕ,Jû><8û³l=Ñ¿ãMFÒx?m·"æ¢/0xHÒ8üïÚ²xÀæÎf65*vÄÀ
!²Á
¸@x«(%ip¤«Ìlr»m
+Þ¤Òlgà¸">!b=ÆV?C©újx|Ã$IËOãÂ^þ.ér3++7 NÅ],àADÔÅys;%Ý´ $IÒ¹Äâw>îbX°êð<¿7.F ÏÓéºÙ(¼gFyßh`ñèZºþÙ¤Òtpc+®wåüCHIpÙ#^öþÇ{©Ôiø*ºMÅGé÷¿,²K$
Û7 /J:o?~/ÅqpðÓSø³mñ¬âükC"Qá¶Zwk´¨^¤Ûý«N*iC`H;¶[È:It.ѲúvÜ0³^Yx¯ððB¹6¤mñÅf¤ë¨ìke^íB¸>nâø¿%-§ª~<àB©úÜËñŸH£<KÒÏqÍæx3/ðøÏãî¦2³r,Êñ$G©Ä]nñ¢]'àÆ+bfYºVú { ûÅöþÀY¸ð[^Òà[föI¸a¾c¾üËÌ^
+wÇWi ÙIïf£Ò¾
+ð6ò¯÷uç¬.&]ItÖÁß4
+8»}ÃkM×Ìáå£xxb»h²U·uüþN7
+f×ØVá ¯
[` pð(¾(~ìRZè
+Ü"iuàV`93;³Æ5X*yïÿ¡Oò^Ar\ðóü@Ò
+r=eñtÙy°£=,i>ÜírPìÿSÜûÜ2òcàÿÿâÿî`Ñcª]a¥º øq!$íßÙMxÜÈcö(°¤!iAH¤ÓxÓÌ6ÝTScÂ÷]]Öz<+ ÜdkÍ 3û`vçܸ@Ò Ürr)pi±JÚ#ßúE¸j ã®ÛÍì%<¸ï4*ÙHZ©hhµ([¾»ö´%¸
+âøÀ±fv;
+ùº/ÞÁtrçØwãÜóZwý`f×E¦Æ¸åÑ:ßEñLÛàÂv0×q.pQ)@t?\ô4géIôÑ!Iæ"®³î5 DóÕ(ûÑPD¾@Ã"RQ©FYOHtDÖ0/¾xÕÅÌ^ÃÖ¦xÆ};Ãk8t3^ca¤ý
+·\,ic<Eöüͳãð@Ó¨¥ã[ñïzyÜ*ñ|ÿy\ûyà$3{<öÄSKï¾_ÃÓ:¶ ÄÙXIo[ã%¬
+¼TôÅ÷Fß°ÀLÀÅÈKxÐçßã~×[µæ$ iAHdn%LËããÓT5ÊùhX²ø¹!
+
ÄtéÔ¿i¶»ßÛ̾ÛN×iô=Ùx`IëáÁãÝ(1³;#
+õNàS<ëbRñv¯ßÊÕñ+âØËxêëõÄ]/éà <xófv-5jJ á÷eÜU° ÓQ[dºYÒøÂXÿEXM
+^b^GQ×Hê7Ê Å$Iæ0³iøÛyoèQ ZD¬ùûªlÕkùÝíÒÍìjÔ¿0³ßJ:521¶¾R:ügü
+üG¸)ÿ|"½ÒÌîtðrdJÁ»&FÈ_cáÞ K⢮) ¡u¡.Ê,@¸'¢õmxÝ5ÇÌìu®½
+¥kf6CÒPÜuS«HVÒA¤@H¤G.&[kÇÛm_ÇGlVÞ±1æ
DݬΤè× )Uì¿<>µÎÛ[Ò×ð¬5ðìqÿFà«ãYà_Ô×¼Ýv£¹H*²cÊ,Vü1*â._oàîïׯ¤àT9
´ $It&±`M¶«7N&[ÕñëÑÐa41Î:¯ÓXàÆÖAÕ·
{aU`rÄÜIºÒÌ~KcÆÓ0öáqà2ï\º#ðQX*¾ïp²xuvKdE-#P¶Ì4¼ÖÄB)&ItG¬íM¶âtÛP±R,#o²ÕxovSþÌìAÚ©Òe,ÒÃkì`üy§ÿ7ùwÄøG¢ÏÇ!À÷ÍlJXu.ÃX<é×ìÚ
+×ÅñÍÊ®J¬EìNZ$Iz*Ö&[± .Eãø«ö-.i<ͧ}vZ6Êlpmð{(g½=°'nÙÑÌþcÿYØ=Æý ¸4ª5.dÆ,§Tß([
+ÆçÒ$I2§V¢ÉÖóõÆ
½Ú±,þv\èMóÙc"¸³K0³!ÎԻȲÌÔûW௥íû%JNÃ31â
¢úKz8ÄÌîSvî5³³HB$I2«ÉVKP-Lã ËÁxb{¤h^HtX5K3»l6ν¥´ùâR3«É±½^¥rǶޫAI$IëÌWãSèP±^Ĩ}$½KóÙÝ¢erÀäËͬQ¬DÒñ¤@H$éD- 4Ñ3Üýi±%+E«ªXY-$ZÓÓc¶1³S"ÆcN#-I$I×n¢Cd]$-Hc1¯PnÒ5æ³5Æ·g5ËlöÔu¤@H$ËR̯ŧ.Xd¹.^ݱܤë=ÏÖx¿C¦g$IdÎ!õ÷)u¬&²0úÓ8>b«òvX-ÆмhúØ]÷Ç`3Ùìà¤@H$Iæ.½P,ðO×'ieÏZÄ´ nIDATÑ0>bÍgk
+wJ§e§·t9ðàföigÏ££H$It:ð8">u´EÄÀö¥}}[Ò¤v¨fYã9þ.i3àjàcIg7y$I$"ó¼}uM¢~Bµ[cY`óª}HjI®ÖV³<ïã±pp°¤áx÷Ê{ªU!B$IÒ£ú cãóL½q槱÷(7é*ê14%$ÆÕ,Ílº¤¯ã±ýðÒâ$/«Â¹fVt"MB$ItâM~d|êíª«ã#VÅTt}@CqÞSbþ¸Ô¢ñó0àI¯ z·×3u$)$I¤Dt7&Ü}i("6zÕ>o|6 .ÁÂÖ6³º®®¦Ö$I$IÒf6ÓÌÆÙ³fv¾èïZÌÀ»U¾ö.
++iÃNpHB$I´Ióû óáàc\,¼Ã~ïöù"p8°±}·+æÜRR $I$IÔø'°%ð!. Å
ÀËQ¥²ú¼db$IÌyDÅÍì.R»!I$IZI\º±§Ó,¤$I$O
+$I$IÐ#ZX§@H$IÎ%]I$IôLR $I$Iç$I$Iz&)$INGRhXÔA¤!I$Iª´2ð¤Eºz.]H
+$IdîCR?I¿ô¤Û%ý>: bf¯7 gwí,»LsL$IæZ®ÆÛ!|8ºtüT`;I_ì¹uº½!K-'I$
+4M+m_à?þhf£Zp}ÌìÝÒ5NNÎ0³O%]Üßóï®HZX
+XXº§Ó,)$IYHúÞ¦øw±}0p>¾¸o<+iM3{OÒÀL3{3Æ~ØÅÌv-``hÕ¾wI×Ì>ë¨gêl$-¬QõYXå࣮]ËI$Iùð³ÒöQÀQfvpº¤Gãø-?IÚ ìQ}Áhü`§ªCÏ Kà®1íü¤yqÑSK,æ¯ ÃËâçp`/`ûNr«I$I2æü3Ílb+Ï[Øxº´{m`|iû:àHàGfv¤O»ÛçÍìѾ ¸Ì̯Ú?£5óë
+$õ¡¶XÊ:_øÅc/ÅçèúX}ÍotüÌgI$s{ÿªuPÒzÀH3\uhyàS3^Ú÷
+ò[3%õ7³ñfvCøÖ/q¯p¿û>ÕÇÌÌ$Ð¥î
¨É0ÚB o¼/ü7RÃÍlR[n;{³îxR $IÌyÁát p¯´(n!èSçÜêFoã¾ó)ñsq*
õûßIif÷ŽVÎ v´6°¤]Ç× ÕWèâÙW§±X?M ²øß[#̬½,="Í1B$IFÒJøúfö~쬿ø
+°lo1³ZArÓ
ª öÄ¡" ¦ÇýßÆ]«×KÚßÌî~,<áOî·pK».¢¶5``Äþ»?BÀÌÞkÏù45ÕNºOI$IÒôð/Üܾ°´=cøÏ¡¶6³ÍÇê\zðpoì»
+8RÒ:föh8ÞÌFÄñ_ ÙX`¬¤Ý%Ýü _|_1³OkÜïcàÒ6|HZ FÕB`5<àC*û¨X^+§qviAH$IZ¤þÀ:fv¤Uóp+Íìl`n ØÈ̦Hú
+¸1þ¦¾&Mô#à<IáÝ`fOK:xNÒÀD<A¼ßGEL`f ÄæËM=«]ÞÂï£^Ê`/|±}_ø.ß
héô^)$IºXhïþü
+¸ZÒbßYÀ×ðEñQIÿ3³%
+ÃÝ
+ELÀ¹ÀñÅÈ7³Ifv¤oã)Ç61s%ýÎÌÞ0³$]
+¬HÉú7´ÃóϬLm!°DBÃÁÂ2ðJé;èI¤@H$Û´>°+î¿ÞÌ*7÷åïëÙI_ÀûÆç}ñ7å¡44U¿/:}Íl¤7q+BZxð0ÍÌ^«7W3{]Ò¸5âk¥ýÃñE¹ÍDe-°2
+SÑ0ep8uR{(=â9R $IÔAÒçðkàQûïÿ5³Kczá¦îð`ÀWK÷0ïGó¿,ZçvC f6!¶{>ÐQ©Q08JÒ/Ã^deLÇÌìUIãÅ}ÄÌ.Ô_ÒÖéãûLm!Ð/52øakî×IB$If°°²g$íif
ÿA|_/|,^%o_IKãcs3{¶{
+¥\ðþ7z3åË}p°8p¤pÁù¥L¿áV
2ý)Å4
ÚÔñhÕ\2¸
+Sߣb¸
Ù)=´ $It%·.¾-/À/ ·´°¸Íp`&°@ðÃ
@xø:0(]¼.é4Ü
+ àùÿoïÌ£íª4þû!F@À Ì
+¢
+È`K«8`´¨iµF#vÛ-¢¤é
B+¨¢
+È"QÆ÷ Dhê?jÜ!çMäM7ù~kÝs÷Ùg»ëTÕWÕkuÓ"V׺8SÒd==wo-ã G{ .o:|°èÿ ë4wTìI=I7-C^ î%7þ+HÕB$øør
+{1f9ì]DƶÿLôÙ©ÉÐx²WÀndá¸3"Iº¬)p¤=]Ó®Ñ
+ìXÉø"â/®*×½Ü@×!ðôF7Ú G×"2\P
7æ9
+DÄÉ}̽4&vªÛ´dpKê%/-ò¼dp&#/ìD¬b0ÆÁ¦<ÑnûÞLiMçLƽ@£aίÈ/ìãÉ'ô$í9t°ðgÒQÑ
+L4¶Ém>¦¬ïI Ó(
+J¢Þj5Õg 3[-£ãåÕBD,4ÜÈ{mtÏ _ô
+I{°¼!ÐÉà#½]Ã1f04¬æ·
+ù$ÝMö¸¸mÜ6dÞq[7yLQOJ' Iý¸"»\ÒîduÀcÊãÉ. Ç×JÚµÄû»WûV¿ÛI}.t@»S9Öb ä¼vøû ¹¡7«Ñ³dpÝ2ìYòé&.dpÑ ×`^ö cÌ °)° جù:da[2Jè64¡î-¤ëÿÕäÓÜÂ6-ýÀîåç.à=Mt éx¬AðÒ-Ù,ø¤Édøb1ðÇÊrÏãýaT½6V/ÃæÑGûI;øìm c:nà-½$½}ô,lÓÖ¡ð>ào¤ápcu°x'¿gã%msÊuh<áuSÚúLîôéø®¤ÀIᢦyªë=\5Ð.ÁWQï
+Ø°{dð"¹3jº5Ñ=Æ3tÛHzé¾ß¾¼;H)âñíbD,-÷v4v%¿ÿîùntÙÞ÷Ýd¡ È
+÷²ò2ïc¥øQ¥Ùï¶Ê{1 $£gÉàKÊ°J28VÉàý«¸d°±Ác.`màsd¡ ëï¥w!³ô{*°³¬³a©!ð6àoFDÕ®ø#ÀOɼ§Iwüw s$kßÛ»ht
+ì"»l7¶)çTÜKz ª.UàusÅcYQJéáG#â×5Cn eË5
º©¶^Kºãl*tDéLøzIë϶'êõõ_kºîÔK·¦U2Xy ®kúyvSì¼Xæh1HU:¸Î@8¸YÒeÀoÈD½µ w·öVÊw
}$m@½7`2)\ÊòÁ*7ÀA3ê±`éº]$íMë<µ'Ú,,´.ð{JÁRⸯ2ǵÉàæÔ{Ö+áµË`å
+eÉ é{1fé"ëlZ~î"½Ã²o¾d°.IpÁHÀi>hÉ ñûbÁ3$HÚØ;"Îù"âàXÏRPh΢¾Ë %f0±Á³j!iK²záhÎë#ÕI×*Ã¥U2Xõ¸/"÷Í*CÆUI»ýö#¿ü>]Cx½Ô{6¥U28VÉàLKéÆBÒ¾¤a°;YPHÀÏ#âA{M²·B]àø2ìIÕ%s,4£{1+'%»ÿ Ò0Ø|ZüÒG"È|èY28þ
ÜøI£Ðü)1+
+cL¿ôR² ÒQdëã*»ù»äñd͹«Qo4K«|³~¾'"þ6Ø÷cÌa1få@Ò+ÈJ
!K!¿à¿äGw|:ÉàeìCäÆß,%fÕ #~Çm ÓD)µ{PD:Òk
+H|ø8iôô±ìað¯À±åØsd¡,/\ávÇÆt8ö 3)®òÝÈø³#â1XVóÿÝFÄGt#¤ÞO&öõ]!²ëàO_Ðè2hÉ 1Ëã1£I N n'ß(é1½9.éƸ9R¼AÒÙdA¡þ|O¬88ìªxc:1#½ cVIHÚh §°GDì{qóï-{3â>àà³»ÒQÍØòçAdÂ`st)°ô$ôFðYà%<aYð Ø@0¤ÉlúûxI×·ó$ý°Ó;w¤OKgFÄ]MoßBfä7ósà I£þ?ñAÒ궴¤/!Û '½="ó
+Î&»>D«±Ðn@vnô᡾cÌÐàé$>F&ÂU|,»¹Áÿ
+øð½²1íI/ÁØÜÞSsÛ]O>Ioܵܤué¹ Qõÿÿ¯@Kûáò9Í-¯kælBÖ)h~mIv?ÜT;üDÒ>ä¿Ã3xkÆt2áA°`Ik K#bIç=¤PñVàôX ,ôà02\pp p±¤Ï¶«YÏ^ÀÛ×4ç%=M&ÞjÊfý*êë¼¢[Ì!/¦UQ° |×÷÷ý0 ÆiûJºÈFc ÆÔrp$pí@NôràõÀMצÕÕ}!p´¤#âaIû[3"b^ÛãVÁíôsVò¢§&D!³Fq¡Ëi-;üb²ED¼@/1fôcÁ73ÉÒ¼µ¤ï§FÄmoUvî4ýGÄݬÖ÷pñ|ø`gIãÛZö~¸>"~Q³átw¤Mè¹ ´¾8FÙá¿÷z1Æcj袸ú%ý¸5"N.9wd/çª<öN+çWýÆ5?8L»RÒ;"â)Iï>Pd}Û¯
+Ëy; ³"¢%6?X&D[Rßè¥eXsÙáßÒðÌrÙacÌPcÁ*eÞÜȾ¼l®stIRë&þ¸^Òñ0°pWÉlO×ÀÿcWç5yÖ.Ççµì¼ô <O>i_-émÀÀ¤vÿ:à;eÍ{¾øO")%ë'ÓPUeo΢a<ä½1+%ö I;ï$ÙGDHº|ò½ø%Ùñﻤ
+¡1·K:88xðûºkpÁ%ÀûhwHúYùozDÜ[Þ
+ü{Q1 &éeÅ8¼zâ´*&zûV#3÷ëÂëaϳÈÿ\\vØ3ʱ`úDÒȧò#7EÄÞþ|*ßø³¤#âAÒKðHDTÎüQÒçÉÚüëKZ?"'åÝö
+szYÊ9Ài¾K"b©¤wÇ¡[iô ">Þ>AD<Õ{
5Ã:ô,\½{Üøï"!à²ÃÆ
+{LgP×ìE§~&ù4=8´ä
+ì³Ëþ"
+çª#â6Is"âjIsÈ<#âÿ$}446!ýÔRνô[Í'Û
+E28zo@°¸Üø/¥aÌ(Kcéfh(In;O´Éb7Ýqó æX8x;ð¤K"âó5Cg TïIz#iï'i;r³_T@µÍ±.}_½¿-Eþ?4Ø 9îÃÈ2¾?îþÞk;ÆQ/ÜdðII¿¦U2ø|ûÆÓO:"·ÈBç2
ÅKÆáß .éµÕÆY6ï§ÈAûó/EÄ=eËû;DÄ#=)&7ôf÷øÓ¤R` pi4»ä»$}88ü1½éýÍÛ®q Ðgf~D,ô:àÙ¾ÆÂ2É`]X`SÒ_
+<@nü×¹7`~®a1Ä!3¤Ì"7è#âÈ~À _"å{÷ _ þúí@nðû ÛWR¾^bäÝÀ[ª¿DD¤¤,ð[åÚcFÄyeüRp<éYØ?")¾\
+éPÎ]øpzn¼=R¼)S¨/Ã)Ã2dÒ,\1Æl vÞAndëölସªmìêd8aQDÜ
+bù·¡«O4Ú
+|x]QܼTÜTÆü¥Ëífù2ÅIÚ¸¯¬ïjÒcp?i |DÁfã`õ²«I/BHÚ%U7ÂyäÆÿàG4-4ÆìA0½²ùÔ<¬Ö·4.45"Îôwd(à>`{IWOã/®ú·$ÃýHoÁnMרԹ1Kú%°3¹/ >@jï{c&0AÒx¬Ìu»¤ÍËõ^ n«E]0ÜÌïïmâ"_Ü´2$uÀzå´çHcjp>Á~I1f±°²#iCòéyÛ¦×:±c§v/Ý!éYàä¢
+öý[DQjñÏ&õ¾M "7úÙdái4Z÷v%Mʱõ¿FÄIÿ
+SÝF6-º7"~Ö¼ÐxVÒ[h«PêôÔàçôÒË (!*#`
+
+ÉàcäÆßE¶_nª> Æ3 :ÂiaÅF ú¹]DnÌË´3¹©¿ï-c6)
{µù?NvæÒºK $ð;À{I¡x2"+×9¸IÒýq*i4,%#ÉÒ¾{õÇJz¨Â Ó×ÝdDÜTw¼'"â«J&Sï
+ب]BzGfí%O`1+'ö ¬tó#âк7%í
+\FÊ ¿¬WØgå·#KìYȧÔD#?`qÓÒháÛ
+l&é%ñ·x@ÒÁÀån,a9d££»H«õÛqMÓõúª(Ø'Ö¦gÉàZeØBÁ«h³-4ƬbØ°Ðl)ilñO"7ý;J{á#È2ÄGñ«ÿyI³ÉD{í5
+ÿ>²dðIå½ÍȺ¬È'ôÛ"â7¾HæÜ^Ö÷û8DÒD꽯,ëÁHUBå
+¦GÆÓ8Iq¡X,%¼9§AÊ
+çEnèáÜe
++$íL |8EÒƤÇáp`_Xð(ÇOm[ß6ý½"9Üå
+aÏÒþ7àK1fåÀÂ
+R
+÷Ì~QSë.ðúNïªÞ´5p ÓpxD<Zæ?GÒCdGÂÅÀ.ÑÕtýµÚ uÞÍhH&7þ?û«¹cÌÆU.`lÎ&¥ç ¿%Â÷óɧû£$- ]óW{DÄÍDÄ
+ôì
èR¼h60VÒ4Z
+õË°Å4$Ò*ìWc#c1ÆÂ*BÕ[ IãÉMø¸¢4#ºLØ{T @o&K÷Yf¸'$½zoÀ2rÝ*IðbÀ}cÌ°ÒXCðI×óxróý$Y@è4IßVæ.OÐZù°GòaõÀÆeØ4$Ó*||EoÒcÌ aÂ*Âõ¤w è¹íÊSzOêÖ"vC`+`í2ì)Þkh.nÓc̨ÂÑDÇ LsîInØYÏÆÔ{&Ñ*Iæ.|7àáA[¼1ÆáÆI£òD~ðEò¥¯Èyí5È<:ÉàËË°E4$gÑ*ìWKcc1
+BÒzdyã#uI÷þ±p®µ>¿ÙØVÉàLàOÀ¹4,4ÆUøÎ_éRÉðà_Èû«îñ¾ó%kÔ
&a9äÆÁA7L1Æt,ö ^M"U¥¿ÞÏy*b»!0
¬ð8$ÁKi÷Z2h1¦ìAJâ/o'±4ÜúKgEÄÒ¦sDö¨óL,Ã*ÉàLà×´JÚ»2ƳcÂPP6øýÈ~;=
+DÃkP18ØMR»dp\ó4
+oÀu´JÃc\ìAl*à`Òc°ºíAE ß*Î%
+ßgÒðÌÊ5c15Ø0R¾@**ÆÖ4,´³Ï9IÐcÌ(¡#ê éôÁZN ËXüPûóÁVã>\'i³![¥1ÆÓ:"Ä0
+òÁ§édH`>X¤´ðù^漸SÒC³Tc1f@zÂh107"«JC6'¼ªéÏ-Êk"1LJ<_Òß»J¡1Æ¢#<£Ù@¨¥È*¯Úß/
+
+i5 &U
+§uÞ,éÀ¸sXm1Æ´bÂpSÊ?R^7×´°±$¹Ì±1Æa¦#W:¡?DDe@c1¦Ñ¤h1ƬtÁ1Æ3¼tDhÛ1Æ3üØ`1ÆìA0ÆcL-ö c1¦')c1¦3±`1Æ/ö c1f9¤h1ÆZìA0ÆcL1c1¦3±`1Æ/ö c1¦3±`1Æ/ö c1¦3ÍÂãÀ#½cVóËÆ¡¥#<èz
+ÆcÌJ¤MÝ#â^Koü? x³d IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_001.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_001.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_001.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,35 @@
+PNG
+
+
+IHDR ó w Y©1 sRGB ®Îé bKGD ÿ ÿ ÿ ½§ pHYs tIMEØ6ÆR tEXtComment Created with GIMPW àIDATxÚíÝyåÇñoõ1÷ÁJ¸ÅD0ȯUL®Y}6n²Odññ@£ÆÅh6Ý51ÆÄ ²
+GÆÁP9<ð æ¤gºkÿ¨éîîêkººù}î®îª·Þê_½o¯±~ÍJÉJóæ_çèÇ«$DDD²ÐÂ
ð lX[«ÉRà©ç=ÖõªFÈã®=ÑóqçäFÇÖ{#?î|w×c#döB?îúâ®È{,câËkëûâïHeÌ|G*ÓdÖSÒËØm¾ã©væ;Ê÷%<ßñÔ};ë)Ë6¯ÚfµÍjuü6:©0!ïÃÎÇ.íÏäHË\DDDÒï)å O[]]ÍîY¦0É´DÎU[ºlEn·Ì?ëgzCÒ·íµÛ;úúÍl}uaçóÑ3oql9¬ù˵ T;7áÏxë©+:w±¶6,Ñ#Ì6ÿ±óz¼¹áà (;òröðs ʺÜA>lÊõìXe=?ìøè¡þÉwôxmÄ ØÞä#O¼ØöêmV¨Ï¼ØòìcNº5%óÿÁó7öxíèÓïìuº÷»gÝ£Z,"Å*«¦°~ÍJ[¯Gõ¸ÆMùÆÂuyÆ<Á >ýF¾6ý'|múO¬ýv[Óy£SäãO»ñ§ÝÉøÓ¬ßð·«v$aïx<b˼{ GÃÆ{ü{Ë|ßûý½å|ö®·ºjs%{Ö=ÀÀc P÷Þýaï<ñªÎÇ;×Üö·¡Ç^Àï·@+&_×£
~èÔë;V{WG=±`ÜöÚmüúÍÏ·¾²Ñ3oéÑ2ÿ¨&¼Ûýj«%¿é¥Ã^÷Ûã_Á+¬Þ
ʲzÖýÕZ¾ gÞÝùµÏZ]ëÏîÙB_ýÌÕaÏ=gQçãw-ûÛ9DÚ'çpüyjIc WVMt»A5ÌÇ^FÓ&«»½±#ÈKÇýGÖyP}G÷EkVö¬ë
+`° Ýk±kí"W]Í® 2éjB¯Õûê]+¨9îÚÎ`ÿâí»Ã=ØÍÔÕÍØu}Ánö `7{¨^¶}̬
a×B|ìÉ·c°ñÅØøâMyÊOS^:»ÙîAníMúæ}À»Ë¯æÝÿ»ãÎYÄ;ˬ§ÉçÞ¼ýôÞzúJ¦|+<ÐW)ÈEDú<Ðã
+ò-ó±ó:»ÚKÇÍK8-s¹¿;W[¡>tÒ5Y½b6½tSÖÎ{gÏ])¾ÑôÔ½=éyh w»áTZ
¶Î¾Z}og7{6
+¶Ì;Ûì
+Eä¡ÇÏã tÇÝnHÕÕÝìIÁKÓÇÌED¤o¼{¨'Ý2·«|üÔ¿ÿ`ØIpý+#ÀÀ ¨{ï~v7xâU`arèèf7`è±×òÕ»÷×ý¸ C§ÞÀUwE=nø 7òÉwðÉá§/MÇnå£o
+; îêÛ{òmlzéæÝìÝuê|ðü¼ÿ÷ðËÓ>ýN0*ϸõ+n`ý_¯ïñÝμ÷».ê pfßËêg®aõò®£cÏYw®uÜüíà¦Ìy GÌÔ¹Yõä|j^¡ãæ""iõO7»a¦¹amZÑ
+´!Ö|k m³ÚfµÍV.Rðàjjj:oç:!ïÃÎ×t;W>ëÖ¬Pô¡êêê¦Â\DD¤Eõ,YÏ\DD$Ëu¶ÌW-ýHÂÌ(EÒO-s
¹(ÌEDDDa.""¢0
¹(ÌEDDDa.""¢0
¹(ÌEDDÄYaîr5SVþJ\DD$ÅúdToþ§û}\®46T±éûÈÏ÷ªôEDD²¡ení;ìÛ´ùö()¥ùËsÛUú"""ÙæÝCKxÝn ©S·RûÎ<±Yk at DDÄÉaîr5âv-Ç0ÁpN³k¼Áþ×û|¶c¿ÖSü_ù#´ù ßË jÁD[30}'LÛÌبµ ""âÔ0w»àqC~¾8 |äãq[¿fþk,}úSvïnv\ÁTVM;¨+F´åOw¹8½ÜÓ5©úܽÞê7!¾åé«eR½Ìâ0P¾@;x ¯¸hZFü!гNù¦oåwK¶d¼BþËäÄÁPésyûòÇ1õ6Û¶D>#ei
¾ßõkV²~ÍÊ^¿?êS#ߦKÓüxÜO` ¬Ô
+x1[xýe'¾¨ Ï.0L.ûa-ÿð(.úîH.éóB
+ÌÁÇäyçsZ½Õ6ÛËëÀIÛJ:æ#-aÞ¯ôÚ[ EÅüqI. &àÓOà°Ã௯㬳?åñùóÓó£Lpl!´ð£½è´Á×Ö¯YVáb½7ïöZ÷ùëþ½íEƧÞÊ!Òü§ºÜí¼Ö}~ì³Ýe³³<N®·ñÔÃdêB_m½D¦±óY¡Ëú÷í.RÝ´Sñ¬¿XËf7hbýv$2Ô£x×g<ÛL¤uïòFÎδ s/¿ÆpCqÕ*¿à "ÆÑÁ
+ùùÝò6Üî:0aÁ¿¯äâËÆrÑc)+-päިﴽE´ï±¾½½fw/5Òt©(«Xßh¹Ç»Üvhìs¢ë'ÖòdºÞ&Z~v^·[éÚ&â]Ñæ#ßdZÑêh<¡ÑÛ6k#N¬xÊ?Ùzdw}î<ÙmÐØYÉLÊÞyÿâ_á÷AQ!P^u¬¼
+(£A4cÒ¸÷K J@ÝNfµª_næ'Gqé%GfEwM*Þ#©/w'ÎSæ;Óó¡s%¹nÙtu%ÛémÈt½°ó9vZÖÑÞß[+=Ñõªuò0÷úÿDÀ¢«Uô+ò²¯¹?>ÀÍá-À`$;Á^ô×Þvß;ÂQóDVP:[]3§·³;?¹|.×_®-[¢ÝåÞ JÕoe2ËlY%:}*×YJÏf//XB¯B7xËÁôÎ<%@aA Ã\yL;¡ð>(Lû¸ðüM¸g²ì6¯
+j{ª[é}±lj¥gnÙÒ²}âÝýçÂïC¬iíôD$òÝkçµÿÓùEðzaÿ>(¿ÝĨ¨N^Þ̹×ê}gTàqíæ_ú&?¾ssÏEAAc÷À{;a!Zå4m¤¯ì~O<óíózÛÙPí|§ÝË)÷XËïFm÷ø[÷eK´ÜPo-¿xË«¯¶ »ËÕ[=MÅ|¥j=%³ÝÄ»MF
+µÐçñG¼ÛA<¿v!ë/]¿1ñ2LÓ47¬MúÇ¢,o ®Ö)Ì¥P ìoÁ°öPuÊ(Î5Æúx¾v94 íÀáÐÜuuøL8aÎ%|sö,ÎãücçÛ-]&(¢íÔé.[AMMMêZæÞ¶Ç0<ùnhl Ð+aÜPI[¿GóáÚ±þoÚÅýhûª¼þðýóßeÑ£#9ó1zT[ED$-Ù\cæ¥ÞgñØÛÂ|ðûÁ×f]VÞ
IÇøøåï_á´êϬóâüXo°nåê)*àÀnøÑ
ïá
+|Æ/mÑÚÑs·Íл×I
+üȿØ
+ò<p@kÕ*t´ÀM|¼ ìaÌáû÷±þùÚ¡µ£ÿ@v üëJy|;©5$""î0/ó<K[k^äÛVË»½£Þ Ó«öÏÇ?¬;^ýÞzÈ+$¯8á{g¯#ßý1{~[ίxï®fw:'Ì{ª§sÊügó2çêvr°Í«ê¤<ÌÛþ ù^pAs+´VP[àpleCúµ2ppÀ@-æ Í µ ¥J¿·Çþ´¿? §4ÎC<dãH.]2£zeÎA_ÒQ&ã`P]¹ãoý
+¯Å¥%`V»ÐCºÚóKý<öÀjÈÃ
+ó@H·»ê ¯o¿bü{àï¦åc^øÇÇ9Yð>Þz¯ÍU:Î'Ù^¿T)©ÓÅîÅ¢BFi45Yr #dw¡Øz>ë;{¬.v7ÖìÁ»4ù aTÃØ·¼pí%¯sÇosêÉ#p¹´Z÷çñèMø£íñÆ3C¼gwƺo±ÝR9ï½}V¤!࡯uVNÔ/»ßë¦NDÅî´½µ<%rÈÔ`<ñ.k<xdzàqH²_kù_\ í~hnéjmA^«^ÈãøïÍ«¨`ÃÛq`Ý8&´;~çNQ«¸ê9ÿÔxàñYöÜF¾uvß_wÌ v>'ßÊAÝ+g0xË"ôÅ .Ôt|·:YT¢ì@4ñÖ¯l§·zìï@¦¾yaëoi7Àë£ ¯£UÞÌ®ÿðÏW{
+6~1~fpçCÛ¬VºÙñàêöBy|uÍ
+óO_Ç`öéGàõºQh±î@ÌXÙ~BY2="NûÜLi¦îO©yÖ ,é;ÖêÛJ
yëhkÚÇÅùøººÌóÕúþè` A]}ïðoëjèõõ0äÜEyøë|\>wþ~¯¾¾gv\Ù9ÝÎûp ÷zS1ÚR¬Ö|²åÉ2ÍÖõy0-oª-Õe`ç°Ê- WÔöwümà2Áíîè^Ç°.Ks
ü3ÈÙÓ>ßåâÑ%1c¿ÕÅnÐõÞà´íí°o/nÓàJûÁ7¦lgÉS[²bÃÍtRèF«k2Òª}=ßé:ñ.ÕËôlgµÒÓ7¶}¶×
+ICË<кv?ø|°¯ÛÄÄèÚ5X» .
+Zaùo¾ä§GÒØÚ@Ó=ãU|?ÐÑ ïx?&ûñµCÀEí0ùÈ<õ«Ñlٺѣúg4PÒõþXïKdÀx¿/Ö^·3 F<F$3L¬rêËA]ÒQSõÝND%h<%åÎÁxìl{ÌÝm<Ú:K÷6 Ih òÙÿùãx=àqãFm.x¼0¸îMÍPß ¦3;ën@¿rsý^^3«æù³+µÖDÄLdZRÔΣ´ÿFìºz.Ó´úÜ»ßߥã8ûÌ÷FH+>ä½`½¿À>ÿy2/¼5þeÍhÍtðÙì
+bÕÖøßÿyÖfGjº1ßíqùñµ{ØöyÊ[8®j3fÔGP«\r"̦NÃðáÃX·~gÇùoFxNÝ2Ûìö7¢<7C&0ý{9nÒ¡¹4MDD$gÂà!Erò¤H¸T"""
+sQÂ\DDDa."""
+sQÂ\DDDa."""
+sQÂ\DDDa."""
+sQÂ\DD$gyT"©QY5M
`Óú5+U"
+sg2MS
Cuu5555*
¹³mX[«B`é²*4Ñ1s
¹(ÌEDDDa.""¢0¬VY5ó_÷×c=짳ÙEr$ÈC¯Ýîþ¼·×ED-sqPuSH-r¹Â\Dr(ðEDa."""
+sé+ºÝEDa."j»ÇÑE$7èlvôhÇÇïÓñs
¹84Ðí¼® É=êfQÂ\DDDæ"""+ 'bKP!Â\$[UWW«DDa.ÍjjjT"¢0ÉVº~[D2E'À(ÌEDDDa."""
+s
¹(ÌEDDDa."""
+s
¹(ÌEDDDa."""¶x.\¨RÉæ0×(O"""Ùíÿ¿áÓ|Å IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_001_fix.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_001_fix.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_001_fix.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,43 @@
+PNG
+
+
+IHDR X í úm2 sRGB ®Îé bKGD ÿ ÿ ÿ ½§ pHYs tIMEØ
+,i+/Y tEXtComment Created with GIMPW ÖIDATxÚíÝ$e}ÇñïP[þÑDJ£b´ÄtÛ9vÃíVp§+r$¡!ÜÁÁarÀYÃ$¢îåůrºÊF.pÖ§è ÜÉ©h󣢩P¿'ÌÎ\OO?ý<O÷óôô÷«
+vo¶§<Ýýï<=ótÝn· àD£ÑV«%ÍfSFDDØG« c#Ý_N}¸óKM¤Öù_à§ÔjQÓ·2aç§HmåÁÁéL¿^Öó
+Og³©ÚÄ|½öÍ6ÚîÄm¢~^oY{{{Ý帲êUúþ}¯1 ๪ڰúÕ;33#»e $×¢Ê_Áþì;ÕûýØ57e¶Üýßøxîg9:èöÿþá.9ò¸MÿïOî×¼ójù;EDä·Ç¶uþi%\ßvz]j"òÓ=
+yûttоüO<ö÷Ý\ºû.xìpÄÆ&¦DDdyÿ^£Ç+Øß¼</G·¹÷ï_k×kF·®Ïñïý¸¿§p}ï¥÷÷mc 7ðbyÿ^±©^Ú«¶à×/ß)G¿Y~uèο
+ØW^ÚÑ÷÷£Ç·Ê¸MDD^wâuòËo×ÔyKý?¸¥oÚ7®ÞÖûýßûLßßÞ<u£üüûýUæ[Oë¯D¶§!Ç^ïýû[
+ö÷gF
+ñã§;Ë=óÓF\º^DDN8kNDD~ôä_öM?qνß_üúu½ßßuÞm½ß_xüÚ¾çòÁNí[¸z`ù§~øp?ûØà»Ó/º[DDö<rEßãÓ|Þúàyê¾Kûþ}ÖÇÿVDD¼÷ODDäì+'î¹DÎùó/ÈßßýyÿÈ×ï¼HDDλj,~î¾y}àÇDDä«·XDDf·~Y¾rÛùò¡ë¾ÂYÂlð1Ó:òà¿^ ×ßzÇUʼ²Ü ××p¼vÕµrôª}ÿåû(ñÃN0ýî»þBÞpr'´þãù¹píü<fòz9fòyóÔ
+}áúS·Ë[NÝ.""ÿüì_÷-ãmpív¼}Z®voC»·ËO¹QÛH/=ÙyXuößÈøÙ·Èø9ý/'ûY9i¥öwxÛO^»¬^¿CV Ó>Ï}µ¿;eêCwÈ»Ïï¼3øÞ6÷
ë{6Ü%ïÙpWßô{vuÂuÍÅ÷ÊÜ+""?®\ïÝnÝng¸¬÷ØÓ÷wÂõÌ˵{HDD¾ùù?í{Þ÷\btð,ÞÑ ×õW?*ë·<*""_ÛqAß4·ÏBlÒp`<nüæåùN¸¿9ÕûË×x?T¬óoû>³R½ÞYÁ;ϸY~üôrð©ÃË;k.UH¸uåÛüYìßÿè£÷
+ôÁ>óÀe}}°OÝ÷QåóϾâá^Ût«ØoÜuqïïçmÞÕ×5ôøç6(ç5»õ˽{E¬^ÝNº:n³¾lãÝNÙÖ«bEDþuï§{]EóÂb'\W¯ß!Ryþk×8÷ïüÖJDÈv_<v?¸qàïg^þÐÀ·iZõ£ß¦J®Á>XÛÍÝ7¹ÞtÊõrÌäõ/7Ø;zf§^þæ62yÿ_èý~îæ]4*®á uRÁú±käåòß/ÝÞ{ìèñÓ¾þ¤OÈ/~xkß
®îE®`õz¸ &¿÷îåçß¿Yþå{êýí§}2²ò:vÍMòÓoߤ½Èuh÷öÞïºiðÇsòÒÛäGO¾Ð¼Èåäu·Ë×ÊóÛU®§]0/Ï>¶I¾ûè;ý¢{dÏ®+ºfBº¢>¢õ¾ËZMäÊÓ÷_:ÐEнÐecÝU_Å;.è"øàÊ
. ¨TUªmAÝn·ØÇ`/9p£´O0ØǽøìeÃêW'þ&W«Õê}UvÕ«õë
+W| Lë/¼kDgº¯½&AÀæÐi̼ðgffÆË| X §
++-Æ OzìsÐÀеC?QdT° @À ` @ÀW|«ÄFÇ'K³-Iâ Xx×2
Ò¦-Ûd~ç;åØ"VEá )SeWozzZ6mÙ&Íf³'já2çV[Ôª(Xý²+{× ]Õ<ËòÎ涨;µ[ýp`¢è<Çpt»>` ,tïÙýÏçr?¶À¡Qeø^îÿùâsÞ¨VAPéͪ"Ê¢ª£²lðãQûn_Õó~ü¹Þ®<nùÇSeÖ®W
+N¥RËû÷ö¸Áû½÷c÷߶ûW5½¯c$ÏÇ_ëµïÊp¬V:`u;Ru"Ǫ?¸¬¨é\mGTÐè¶[·nI¶Y7ÑÅüMöGp¦ Çí>ÒÍßä[¦¯ªSµ>Áõ6Ýnó1jßáè^ô+YÁüÁTJq¡Õ«µIØiuhZIúxûT¦w"¶ÇíqiS©'Y,Û!ê\KºÎI·¡øë©{
NÚ¿Byxí+øòÐ÷äû O[½fÝEZǬÏÓùÇíó2^ÿq}¤}ûn2½ë@S]Irâ»Z7¡£z[ªêz<üéUÔ*¹ëWÔø^ÿ´óÏâÝY!Ö¦
+qu±$Ä´+ ut½¸yÅõ%yLÕãj»Qç½êÖµïõ×Í¿JÄG\îPÝãº5Þ¶zò±m¾¦ªU$Ôm×içoZÙ_\\_5
+Ù¤Ë6ÙnWí\Öc»Ön·Û&ßm.òw ¤ÕjI³Ù¬Ä÷¸Ëø}õî>¬ê
U;|\t×izz¯Êõz ØGÀ/Ú>XFN/î«gû aíó
+öTñdEñÌ®[+³ëÖr,bè/ô6è" OX ` ° @À ` @Ào#ÃXè0îµe¼%ì0µhë7ÚÌ캵Vê.Q·Ì»w½náçÜ~<ȶ£ì 0W¯×9Ú¯Æl ÕMÒT!©ººIå©ê
+0§júðtªmN£Ñ S_oÉ£îÚ9Û8l/êáS @ÀU´| @ML
+ïSºFQÁi2nYÁþÔàE.WËnvkÁ&«.~©æ¡ª^M·,Óå@i» Í°2¦Ò@À@ML° àë5 ° @À@±ås°¶#Ou$ ìP´Z-£éæwα °¶Í¦v2U®>ÆI`ìwí(âæsÓáy¹7ØÌO aßz&ïa@
+ÕàçÃØ&ËWW¡/l¡p°OÞ÷iÐäx%`KóvOUaw}ë*[WE½½;9uó2ã~7¿é(iª¶×-;j?%]?v¯TªÖ'êß6·&" Ø\
in=£ªtlçeR)l«ÉúÚTkIoã¢;CõB Û×6m&ÜüFw[ʷøõª²M:]ÚçêÉõºEUt®÷y*m¼¸Ê6Ét>_|toóóþÂ[´+øT¬åÂ7¹VVE¬ÂÛªÛv×Õ¬ï6v=ÿ¨þx_Ç
+Õ,lî#/·Q¦/ïß«Îv½L×צͲ¸µÉ2TÓ¤Yg]¹Øö¨yp»¢ò©µÛívÜùGÇ'>ì¿°¸¤ýjëÂâÌ®[k<OÛupýÞg }¦d¹.V+ö¦ÁiRÁÖëu tø÷¯¿rë .p <XX\"`E_õ}·(WÇ&¦2[W®¬£(ZV9>k{åµÈ¬<PJçñôt!!¬ÙlãcZ|½°8'zö
+(©²è&·¨*Á¸jXW%Ç}o>ü<ÓÁhâBª¥$yL²IÛÚÅ+ªu°=.ã¶^MtÍ(i¿køÃ(%î q£{%mSÛ¶6Ù·q_nN1fÓ<léè|_e:PÉð
iö
«}j³ª
+T5½®-k×
+§Aç²"Fu_¤R\¶µË¡
+³~>ò¥ÐÓÊrà
+ÛõV7Gæµßòö"äk¸H¤QÁæ.d£ÞÅ='nzAB¢NÛÀp0y(%êÂj4/ÁO\µµÉ2UÇÒÖÂ`/å3Á^¼w1 ?:ØK)>¸xO¸.À!B¾1 ° @À X ` tnEÀ£ã, øª`½|Ñ Ñhк *ÏyÀÖëuZ |,¼ @}° @À ` @À lø¸×üØÄ÷°
+#×å{~Ýwo÷ܽ^åªæ
+Í%ßwUÍßÅr¹Û)PÎÇ"XX\RþmvÝZë.ª2>¶¼oïgxºªR·pØuÿ^¦îqÝv¤GT Çí êõz!Ç9ñÕQLHQáWñE=W7OÇu§j½lædãÚ(¢":âkÆi^mT!ëúíô0ú:³X&#%ؤ¢Þv§
+Rݲ²×¨j@9åö"îm+K T°§êBMÔEðô6gÔ²Ì38½Éò£æo².Áy§Ùn î"°ýîQÜßÒÌS5U×
n¹&ëb; X , ° X ¨ ¡|Öv´§¢¤V«e4ÝüÎ9ö ÖV³ÙÔN´rÕ
+cX56_óEu1οrÛ[«Õ¬ªÖ·ýáÛÚ ¨pÀÚ+ ÐE¦ív;q¸êîn ú»ÉmYâî¢^UIÆÝÞÆä2á·ö¦·´Ñu¤¹iûÙÎ_·]6í¤ÛO¦ó§É; õ1ݾ4DZÉ-PÂ
+l0\¡ë[ÜíWâÝv~q/Q·QMo{KÝ6ÚÜǤ=Î?é-|¢æ·Ii:`zy&Ù6mÎ ïØpåê#\mª§pÕ`z²Úy^%YGß·øI&ÏË2`ân¾i²qÇq;Ö4kðIÃÏö]uKªò}4n²¬æTËj?±òÈÅE®n¨&©\»¤ê*yøÕÞæÕ?nZzóöÈÃÛм¿ÖcicÐEikT&9Qm.èk[ugsK$ËVµë[ü¤Ý?6Ûh;oÓéMÚ$nÚ$mgÚæIÛÉÔÚív;îÃü£ãVö_X\Ò~µuaqIf×5§í:øz[çë9y?Ø?yc)Y®K«Õýip¡T°õz£ ]>eà<~Rê¨|ÇÊá
+ *olb *X (/"h4´, Öõù+ x
+XnN ÏDÓ ° @À `-5à<`,e¨û
O
+T `Ç&¦zÿ©ß6[ ,+êñp¥÷{Ôº©*Euµi§¨yWmîùT»;ÜÑ êÅQwÅüQÓ+2;¾Æ-+É-¦ãæäþöIÚÉv©fl^ØÞ=Ö6ÜLÃU²Yt·-¼1@Àz ×ËÓUá[mn at yTö"ªRb·èQóKú¾ûBUÛF,ã
+6x.ïß;2áðÒ
ªÎdlÞZ'};®j#ÓuTµ©ÍzS%Ù¨µÛívÜ£ã
+A¦Rí
+ø¶°¸$VKæwÎM3Üe¥
+ ¥î"°}ëÚ(#¾É ,,.° àC«Õ"`Àf³é¾vaqàL½^/ìÍT½\äjµZ Rû8Te¶[¨¶4ç¦-Û
+¿ý# |´~N£Ñ(Ŷ° r]É" ªlV«Ä2ÊW[±@À&8QtâÔj5åúwÿüOµ}ªùÄM«ú{ÑÂ×t²
+ê$Ë)ò1áÉúk·Û¥h¸îvøئàüÊÔfyÚoÃGU%
+6A¸FUjQ ª¢óõüàz¶Ûm'Kp>ICÓv;TuÜïiÚ3jÛ/®Ôméöƽ[0Ù^ó Ú5Ѳ<tÄ0õ{FáOgú|ÕtáÇR}lGmKÚ>¶/é~×=·½.æa².Ó2ê6Ô\ªWyPHû|ÛêÓE«[¿àv
»âú
M¶;OíÉÛÏêÊ3Û-ûôÁª%íæùÁ,o!µ.Qa«Úaoê´«õðµ=ª6F¶ÝT°)B6m5éúù¦'«Ë*6«PêKî>fZM»èÎðð *_ÁFäQ}V&'Q8 tÏWM§zÌEn(Óm³¿i{ºÚàãqëlsÜÄÍWÕgj³n¶ëÖ{e>@m¦·ÚlK².I¦Iº^i·M·®®ÚΤÖ=Ïåqcò{ÒuK{£¼ØÇWeÀÑñI{¡Ò ü*ËÈXI*X7eÓ5
+/;¿s®²ÃèÏÖ¡z½ÎQ >Ê :ø ° @À X ` ° @À ` @À , X , ° X ` , ° @À X ` ° @À Ðú|±ÞyJ IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_002.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_002.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_error_002.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,41 @@
+PNG
+
+
+IHDR î r Ä2Ú sRGB ®Îé bKGD ÿ ÿ ÿ ½§ pHYs tIMEØ8¨p IDATxÚíÝyTåÆñïêªê½Ù Å@ÜÅ'£G'dÆdæq!Fc{ÔÄcrr23&Nrmµ!ÑxH¢pCÁA@(4ÐûRUóGUuWU×r×êºÝÏç>]˽·î}ß÷¾¿û¾wyÍ×Å_0âñ¸·ÜtÓMT¼öÊz¥OT Ì?ÿimp00Ò^÷¿ø0¯ûf7ò¼NLûurêþ
¦½#íMæëþî{]l=snoÖ¶[ϯ³¶·Øzö/:ÿ¶[OÓyä0_ræÅ|ªé[l=ͤu±õ´º½vË}ú6ÚÍ<²/éÛë°n²¾9ÒÚJ]/óÿ¦¯êþÂuæß cµ¸EDDÄ×`{ÞÅóïw4)pëÉÖÍ÷ûÏ¿ïõ!ó¯q¼¼ÏÜÜ÷zÚÉ׳ý/7õ½~êe÷- Zv§íelxô
+ æ·B{HÊÜm[@íKLØòæý Ô~)ßø!
+G\ZA{âqßÆ0`÷ÄûIÇçàï>wëϦ,¼ÏÜÀÔ®vü5ħrðv2æR ý×øìÓKn/:ß««¯àÈ¥w¨øÌìy ؼq©Ï³å¼8õeí-÷g¼¯?âÒAÚv¤öä¿Ë' ;½ÅÔüÓO½ÑµV÷O&ö¬3ocÖ·ñé%·ðÚ®Q©ÂR9¨í-îìà];óZ¶ühÀwÙ-îý¯ßñýÈÙÓ¼9ÑÝ:jÎìÛt/£ç,`ï«÷dL;öÈoö½Þ³ñ®ïÆèþýû-Ë Ç^= å}Èüo÷½o}¢Õ:iÁwl%êgnfêÉ×÷½ßþ~Ê
+¼ýç3ZÜÛÖÞ1ßÅú[O_ñùá§ÏzÆ®Ið9Mô"lz"±}sÏþAß4¯¬¾
+yçly¿¼êÊ÷Ç{wßëg|wÜ?ÝsÖ7^ÀóïÓ&"ârð=oAFð6´sî_§íDyk2h×ÍüÆVwÊdÐ1ë²÷òìÛÔRA{ÌÜå`|üÊÝ|ôÊÝw%%ö¸£®$ýþ½_J¥OsU_ÿà
dïTWyJ¢«ÜÈX+R]å)©®òtÛÖ&÷§Ýq/_*hÏ<í0`Ë®ãͧ¾k+xsäÒ;rnæË'öÑÿHÓV]Éÿ÷M9÷n^lJ(û¹D^¼ðØrôÁ{ý#püù÷ahñ,x[ Úy[ܵ3.éë.¯y 8¨ºGÍI\ðd\ÆïÊhmûÕ§¯óíºoHÚ""âì®rÛ-îôàí ÑjYz«;ÑÒ¾Ó×Á;Õâ÷#""C#h§ï6¼ËêÉiãæ]ì*Áº,u[DD¼ÚÙÜvÛ¬Yqàõû2.P9ûòÓ»½¯ÞÃÇi¨=ò`mèï*ôU|øÒ¨e_rÈükؽáö¼§M>áZÞ}îVÞý[æùæÔí`V¶èF¶½i¨ÍX|33N»·¾~@Wyö9î#θ7¼×ÿ¹^r;³ÏºÍk®aÓï¿=à·ç.ý¯®¾:ïÅiG-»¿Ò.PK]vÌ?&Îs¿ðXÿj¹.N;þ¼¬ärÖ7^¦ÓDD\¯Um¶«Üؼq]\hÓù34È)²½d$Ïþuÿ
Ç5Ø~rÚÚµkûy:7ü&MkôÈS¯å{|©
+Ü"""Z¼x±«ËSàñPöè^Ni<n© ØÐø%¥%ñ"ïE¼¡··(p(p·(p(p·(p(p·(p(p·(p(pfÏ[`ésq®ÙÓØMçrÊBe¨Øzsùjûò6ÜÓNì«Ô£@;µu9xàIJØ7o\Wô³Á\)Mk¾û©Lä
+2N×=µÌôå¤VêôÉþ½byçvzKÞÇzj°÷ÅAÜ¡È.q1@-óxë»DB>2¬
+J0µ¥¬àÊ=íBÞªA1[ÜÑËÄI§§"P[·^¾ÌOÜÆ9gOñÕfúwf>7û}®yòÍgf=ÍQjmä[f®é³ÿi©Iw;ëR¬ug'ïÒ[fÓ¾PÅhµLXI¿\yaf[ìOVöìuúÿbeÐʶÛ'Ì7³ieg?rc?Î÷ü6S¦ìÖfê+éVh?2[WX©kÜ>àÀ=jÌtt@õ p°ùó·óý;VÒÒz>~áSe}´ V?·ÒÅfuBÓ
+V×ßnEdõ(>ײ¬l§í0Û]]h¹v~§iì¤\I¿|¯½Þì'å©Ø¤ýªX°ËU±:¨°R'8ÝïÍíô g%ÀYÌÌo7¯ÜÚÍî{^ìG%Ü@+ÁÀ*8Á1ÀI¾µüo,]6gÒ!õ¾é:*å|å²þfZË^v!]o/Ò9×2í´T³äûíÁ¼ÎÃlzØ-sv>½8`qc{¼(Kfc¦Åoúbo·êrÞ§|¸G4<@O7ÔÕ0õ`¡§½
Nülå×Mäª+óEF)xå\ýz¾ÊÌz;É«¿m§[Ñus3ýìvÿú¹,z»r3¦ßÏrýK~;X0° D"@ð&¡"øþ[?Cãc»øøãv¿¶¾ãJ^¿´\RùËwþ¿ÖÉÏpö¹ú¡P/×L½á÷ýÊëõ/i{TÃ
+b½P]áj è Z1"ã mNÿ;§¸_®|+¾1§¤GKVos(´³ê:Íw(ß47®³<Oö4
ί¹YYå[¦)ß<f×ÛìüÅÒÞÎoÛÝ67ÒÚôóâÂ4»Ûâö²
+«µ»*7¹*óì þÞJzX-KNÊE¾:ÒiþÙ?×<NÖÃJ½e§~v±yãºxiBcq£N&1nlªGïÜϳsÒJ`tmHÕMòåÿø
+¿:±ckwèý²\ñý 4ðFcÓÒu¨{ÞÎ5a ºß¬¨qòY1#Æ{»È(¢`é9»3k+?¶]{*õ§oÿ)Y{lÝ`ìè 4À0Z Õ̤/.òËUû¡õ]ÀãNáË_ÿ«N£¾®R9%""Ã^ÉZÜ#k~J´ÂA ¡Ä¹í zÆ £hmP;²¥;7{+=²S9%""TÀþÕA t0¢:T¥qè`PP_ýâ<üÈ»léTNà·Á'¼ü]
+ÈPéæçx4@ÒnØîÊôt·SP}
+ÄúìÓÃÀ(ª*k³à@èÚ±ôî.x1£wòø;}[°ÊáÖRWééë§@í®i+HæÚGJ¹m©«¡ý~¾ýÚÏ+~ßÏo÷þx "Õ
+ÁÁýÐ }¾_¯1aÂdÂá8åæD:û r õ9¾sÛ4Î;waÏÖÓÏhÓº»ñpáF¤î`e(ð4p×WÒÓÙKU"UUÐÓ
+Q¨Iâ@>9Öï3inZÞV¨ìúÑ°w/-{û¶ßý~çîðdj¡ûñ8bå!ùNð0³.VÖÇ´µ;hÜZ¶A]¬.Ëi¹2ó¼q«iZ¬\ÙÝf;eÐî -vòÊ2+øiëë\hz3Ë·Ú»RªRÊ6pz~AW BkÄV8r6Ì`Â!Ó3âÁĵj½$þ·íô|¸ðH¸ø¸ûÁ©}ÖaTWyÛI`÷áòV"(¶,«¿me:7?±º:r·f·Ùé²ãÖ²ì+«¬g;Ýf»e°Ðïy×`)·ê
+2´H)ÛÀ]ZM´Pªj#BwOâ³`<5§üê/<tß{kÖ¢@hiTTWÒõq'ÿyÑ«Üû³ãùÓÓo³léÌ!Õ¥Rè©<VÄof¹^ÎçE+Ý«å[`£Ër#Oìå»5°×yïÕ~ëe*´o{± ÅüvøyÏwut½T
!XU Ö¶Îq8öø8¿yjº?ñY,ù×Ý#Gc4ï0,ÿ·uÜóà$~váY -å V²Ùé5ø;˶s¤íÅö:OûôNï`
+¢RJSz~ Å«Êë+VÓÓÙB( ÕµÐÑhQ÷&[Ö-pâ¼f"¼ÃäI½Ðü<¦ù «×¡þåMDïð'w±ðHßê@1<¨ïBϽvRþÊ¡b÷[ Õ )ø®Ü·\Hñ¤Å]Õó_Dã A°¶Ú;¡7ù6¾óÜGÏî`ÜNF%
+Ku´wAgOÏÖ]Ô¯ÿ2üv*g>
`0ày[ÙÌ®av§©X-ô¹º-Ûén,ÛÎ@nnråv½ðÑìïyQÀSª2å$¿ÍL£Rü3@S®?ò´>°pÛm0rl-FC!¸X!kÅ¢3÷õ_Oöô Õa8t:ì~èÁ68â¯òµ?ÃÓ§""¥oÉèö>Qy<MkÜoqW¶ÝI4ÕUºJhkËlmÌ5÷¾°/ÑMLÜ©sámÝв&LÄØ¿BpÕWåÖOæÓ¦xz®[DDÊ3X²u[\ío®cÝ=ÔTBoÚ;ú/:%s-lx*1z$FMÃçN!ºÄåqúÏuÇ={ j8 ñÕwhzbJ°H©µ-åPÓú¦ÀíPUçÿ0 £2lmÓî:0ÿ|E
+ÐbË£¸îûS¡Ì Ð
½ÍÐ0î.¨
+,ÙÄC»è骷l¢§m7Aj*#hÝÕ¬ûþ:aÛ-ÀhxkN¦"tRfO¿=ìÀVî
KÏÛÀ~Ä_Ý©t¨èùÚ""e¸«{þH´q]ä[ÁiXvâ ÷?
+ðàÊ,\x0ñ¬rþiSóööÂþfq®n¨9n'+}[Á³ÄØîº
+V×ÝÓDDÊk§Å:_¦7
+ÝÝppP0N£ÿÐ 8LPÙ «~þw¾·b*-´í>
sþî÷!KÞ8Ä1¶Òݱ(T÷±ïæÑNçííÍL6rØg¤Î=*]DDÛxÅ::·ÑÛ]Ýq8ôßÕÌ@E®þ×´µÃ®÷ xùâÉFx°j+^xæÉÔTÆØôÚn×·Ù{#
+xPl ìhú<naõ~ÆbÛ_ìÑf¥ÛW(ÍÍ,3ßz]·bó»5½6D¤$û@Õ%ÔÜB×ÁçÙ{ @ OôDz£v¢5m°çcÀxr¸Ö:OÓW »;À>§ÆÈúvêk+]ÚvÐ/°¹9xÖÛl¡ØoZiÕZ`ÀÊö9Ms§^x1HÓ´nGZFÝÏíÛøÿþío³ÎÕ7
+N]ÒÝ[Á÷GR_ÓÁ1óƱpáÐ|Ö{Qñ{9DÕí³f^/g¨_£ "C8pÌ?ö0&OȦÍ{צ19ãYßç}<mxêÇu¡PpHfgL§áÒr¬Á
+Üú]µ°EdÐ7À'ÆUóÓ¦(u=
+Jf8·¯iïæoªÛ\DJ¸ýÚÂ;@ÈÉÃãÍ<ð?×o{ñ»fz)ïÅoÙ=PqöNIpß"2ü¸>Ȩ$""ÞhlZãÍxÜ"""â
+n¨µ-""
+Ü"""¢À-""¢À-"""
+Ü"""
+Ü"""¢À-"""
+Ü"""
+Ü"""¢À-""".Ó #"Îãlë "jqøR<V-R¦¨Å-âo¯½²~XlgcÓe¶ZÜ"""¢À-""¢À-"""
+Ü"""¢À-2TÌ· ï/ûóBïEÄtU¹ÈÚé÷Lg¿/ö¹¨Å-"´!ñà\-mmnñipnQà§ru·IP6{Þ[DüIW±àï|vj:ïQà2Þf>WÐñ?u(p··ø
.N)Ʀ5JQàñÅ+DD[Ä/Ö®]«Dn?Ð}Ó"â6]&""¢À-"""
+Ü"""
+Ü"""⺿TDDÄG[·ªøÇÿBLú'
+í IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_hook_life.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_hook_life.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_hook_life.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,122 @@
+PNG
+
+
+IHDR ¾ ¡û¬¯ sBIT|d pHYs
+×
+×B(x tEXtSoftware www.inkscape.orgî< IDATxíÝwxUÅÖÇñïJ½#E"("6^,Ø+*Þ+b¯\¯½]¯]ÀÞûµì]»"(Eé%zM÷Ùñ@zö9Éïó<y²ËÌìu!gefölsÎ!RY -ì8$®mvÎ-;ªv "áhô
+;KãUa!R¥H-Õ88ì $.Í@ÉÔt a """±EÉ¢ä@DDD
+Qr """
(9¨ 3ÛÞÌÚonfÇEí'ÙñEêô3³ãͬu°ßÀÌzT_Ô[2³Fa^_DDb;xÝÌ:ûW ÏF?xÒÌ 0³ànü"Ù@à¢jwf¼ÖõED$¶èVÆÊ18ÓÌî:ó¢Î
+
+
+tνmf3!ø§1³cSDàvà8 =Üð P?¨ò2°èî{ÆÌ8çÙe@ÀÀà qÀF »=Üé[^Ñ7DDDâz*ÇTüïáÀͬ)î´2³zÁ©íÍì6üû+[i³.°Á9wÿ@¿ Îoê éA¹úõ̬#°SPw>á8ø
+¸Ø9÷ð0Å9w¥QrPyÆwá{
+´7³á@;àäàx&ðpsîým´9!ø¾Ð¸ØXìÿ/øïi H ¾ïÔ¹2Ø^¼doÙ¹ez""Rã)9¨<¯7;çÖF ìç;ø?ü_í s3sy%´|?ôð0ø?Ñè`fm¢®5?ñ2ð¾£=0¸8
+ØÔ1³vfV\H-¥ä â~&8çÖ8çFÇqÎm pÎÃ')øùhø®ýhSIAÝåÀÀå@sî{`$p ÁPsn%ðpððspýð½ÿ
+®_0Dqðç¾5((£»ÊåÑ£azÝê½æÈaè~{fxôê½¾ÔT¦§2Æ¿àåιwÂ¥ª=sÓ+¡Ð1ro¹nì{,ücN%6Z»/ÍáÖ«áýv0îS¸·Kõ]¿¶z
+£§2J¦aðYØAT¥`¦-4³fÖßÌHM`fYߨýÌ줨ýÃÌį̀ýÿ3³GÌìV3ëûµ«ÞÈ#Ìl'3kÖõkÝÊX8çÖCupν¬1·F-FáçeüìËßV¥wÓ0hùdüfÐ`8\ù¤í?0 V\læO®{ÛÍ6ÖíÙûÀÞ'ÁI!wBÝßaÍQ»¤üýnká½ö0á¸ãÌHùÁ@«wáÂï*çu ÐX|^|¼ÿ/df#sÙÀnøУÍì,à `0¿ Q3k ¬:8çþz [:çGiä )ι3k¿Ý;ßÌZôÐÿ÷[;çFÕíÿ¿e|vÎ-Ü·§öQÏÄçÜø»>rñs'º × +Íl´üRª¼Îñoèr+ôü¬9Ft÷çßßoCÎÕGKÔÍi+¯¦ÀéÂ>¶~Üö°â*h=ö?òëûwúsÒ w§"å;BVý-Û©°If¶>QUpÐ̺à?ôßÁ¯·R`£sî/`:Ðv+m¾9ÀÌúà'EÿËÌîÚÜ¿ÓëË Î£Dæ>
+5³3Û¿¸Ü¹fö¿ î£A¬ín@/àr¿ò7õT#33ü_ Eö·õUÚ²a¶Y×~ø7¿}³Ið6äÙ&üºwß;çrJüG*¤Éëpæï~{Ú×°è `2,<R¿Ë¡'`ʱ
ë¦+?*ÝuÒ¾¿öÛKÃ!ãê²Å*Ra¯âï`j_åàø¹ÀPàüDçÄáB3;X|ÿ .ÊÛssÍl~âõFà`Xð$àè ìÌmÄvð°ØÏ̶Zá'n¿íË4³ïÙιËúÂeKqÙnøä~ø鲺+á+¿e*òUÚoÈÖÿMð=uÖ@süQeL¶ÙN\9Íýv^¨3!rî¨?`JáºKô¨ëì7f&ÂäfeU¤Âm¹@%Y`×g O;çTöûlÁ9çæÛ
+ðk´ln²ñw^¹ þæ \>éHÒ߬îÁ¯{~xñ
+3»ÿ{¡2~Oqàé/ÄßzWæ'§[4âZ~_9²À:üÿrü-ï¿TÍ¿uÒRØ´kdÿ£]Ør®¤5,¢ljkìn¾îËafLjR M6d$Cnç
+.RðÚw½¼ã» ü¤Cà,ü|Y=ï=è_Nþk3ÿÝ\p+ð7À
+f6¿øõ]ÎÞ:¿àoã¿<ë÷¥f¶É9W0D!å¯É@nm'Abð~¹èLüÂøUÇ8ç2«>v£`ÆËðH_Øa
+̺ÈUåu <v$´ùæ_éïC³\h¶>ü^9º}ϤpB$RY.ÇÿN]
+<÷å|ûCT¹ñÿ÷&Þá?¨£][°á{×̾Á?¬îóऻù9@ï ÜËf6#¸ö¡Á$ã/Ílp0Î9·Ö̾:ãÄ=ßS(ÏÉÔ2fÖ
+ø
+ÿh~ÔwB´ä¡ÞÆÈ~úBÈYç·Ï
+eÀ²,hù,,OºA·hêLH/úKr>ËO%;CÊÏpòàȹÎ7Â_ÿñ'@ÃaàC௶´Åà-ëmäÊÿz¥6sÎM.²¿È²ìÑdzñÏe)®YÅRdþ¯ÿècÌleÔ±ikþÿ|tÛEÛ_! Y/àzç\¿°cêÜÆt,0Ñ9·¤mUÁ"HåuókÐømøÏÛ%Ø E¤æSÏÄ
w èÓqâù½!¿gVtÿ£úc)R
+¯7>YrÙ¢
+ùÅÌh¸v¹Úè1Ù"SJf*¬¹(GrpË=HÒ
+"""R)DÃ
+""! epwØqHè»9ì ÊCÉHxZëÂD*]ü
+qIÉHxeι¯ÃD*Wð¬¸M4ç@D$<é9"ÕCÉHxPr 1HÉHxñ)JDD£aIJDj¬ñá¯"û
'ûC=ÔXY·Cd?¯
+äÔ
+/)z$&éVF6¦,l
+À/Aê*ø¤çûóÏö]gBï~ÿ£6°¬;)´¥,4!QbzDªÅ¢xäXø²EÙêMÝf=½vEwÀ]OGÎϽ~ëÙv üuiåÄ,Õ@Ã
+Ôs R-ÚdCÚjó|þ$Ï6£àÔ P¿¿ó:BÞpì"~?¼4É÷\0¾zb*¤aIJDJÍ¥Á»*ÖFòDÈé¹=`Ö?à°
+#GAu[ÖIë® y¬è(9J$&)9)6 Ù·³¾q°áÀÖCÂJßÐáûâ Xd? Ì;¹9[¯â1J5Ò°Ä$%"¥Ò2®}bmÜw&d÷Ô¯¡Ñ'Ð÷3è¼±äzùÛû ß\\röfús©aUà¿¿þpHØJ!1H%&)9©ÉÐñ{¸öÕ²×Mü~|&OÍGBÚhø?×j4Ì~
+í¹!ayåÆ-ULÃ
+T9Ðvùê&.c.
ûBê0ðûȹÆÃà«¡í#Ðx=,.º?DÊv2Êÿ¤
+hXAb¸Ð{%ô]ü¹îë¡ûÇQùoÍrßÑpÆ´*OÊK=´ÎHL« )E>Ô¿k
+7 '©dI¨ç@bzDbÚ
ßß> ®Y(áHeK²ÂB¤(õGÃ
+G%&)9 z$&)9 A¤ä@D$<V¨!ÌìX3kXBþf7(9 jLà³%f68Õ9É ð¨ç æ t~0³FÑ'Äà9`+Å%""áQÏA
+á˾ v~ êÃßÁ#øg%"R<½?|¶ßÙ ^ên<Ñ^î#:E 4!±f l v ÚãºÀBçÜÂc+%"Ró¯é»ûí?9§Wíõn½>i]º²sNYÇTm<¦a
eþß4ØèOòwB«Ìâb֤Ĩúkl:V½,®úkU
++Ô Î¹f6èJáÏ×µÀ»áDU>JD¤ÞæÝ®.4QøÜ'Ãæ6póÃOÍûk ³áò3ü£«oÍ^Ìs ¯
+Ôù .¿åÂV0önÈíæÛLýN=ÖÁC ¿Ly
+~ËÀÀÐ=`ö!§$¬ÀUïùúùi0øÈÚÒ¿ÞÿÃVãV%5ÏHà 9êX20.pÊGÃ
+"µÎüT¸m~^Ø6ò÷Àç-aÎóÐä%èw<ä6ÜÝ"ç³CNÐåÿò Ó ÷ÎwAªóçr;Ãò ë-°Ë@ØÔèÏ¥äÂÁU½¡WÈkï_éÏ]r$,®Ã
'ÀyÁmaÆ0¨û-pq24iýÐäèÛòÂø³*ôÖU>
++Ô<àçDû!^na, ¸5?µüuzÞ} f¾·-ÄyPwôz^^|Ä9ðßá~¿Éðü9[¹A~ø¹3ì< ÎþµðéoÂSýö½oÀêS§ýµÈ·:ân26ïãË5Ë$ç@»àI¿þÿj<*þïá`ø·`áuÀ}¥xª&$Ö<?Søï
+À°b)·xMþ;p$8Èo ÿû½
+y;ø¯ìaôµðíp8á>ß-»$OìwÞèâñm ³[ë@ý×à¦Ç#çÎÚþV¶ôÛ_51ïBÊ$Hã\ý¿ÖúËÖϧEÅÛ`¹)V¨asÎÌ>þYp8º
±@\&ιlñ{Ú¢O&ôÙ©bmÌJß¼°æA£OáÐ1[&RÂÆC#ûSëB^ûâ˶Ìë_^7ºÂ¯¯ÃÐïàÜIþünÀO~;swHæ;ËÏ
+<Èïß}!dõj8ò#»Éa}ß²½ö¢a
i$p4PÈtÎ- 92Ëä@D*b~*»
+R'B§kàô饫×ëcøøz¸÷lØów)þ¯¢b<q04YGÏÄ<°hÕÝ¿¦?ù°æ4ht»¦,5ûÀ7Í`j7XûÏÂí¦N9ÇÃÙÐy)ì9
+¾ºî¼öaEÓ-1bzj¦Oñÿ¶r,å¢ä@¤Öi·ÜUöz}2aæ¹0÷zøâTh8
+uVúóiñ÷sY
+á÷Ëá×æ<ZÞ }£iö,̾òZAÝáüñcGÁ¨vðÉpßÑænXvB¤ÞnÃôaÊ°ìy¸ôKXÞþ¸>ïïïVhù8ð+¤ÍäUºõ6BòÏeÝU* õÔ8ιUf¶hGÝÂXÀÛJâ/RCYè
J-uÝ$Øã8å°#)§9sË*Ú}Üàû¾âqI,1³³Tç\Üõ©ç@D$<V¨¹^ÚÅcb dfÉ%J¯?,"£ó@è¹ øsãCu~A¤ZAk®oðãRÔk Ý5¶°M®ÈWÁ1+î¸+\¨ïYÀ¢,`EUG,»ÎßƸÿûÃ`ÖÕpÆ´©QÔsPC9?fÿqØqW4uÐ/±ä¢µÝßI+,Ý·båV'|EZIbO®8Ûr7Áüw:m[ÚNÃ
+4!±Ô,zcÃ0®ÓïQPr "
hXAbz*G1½ÇÔc "[¥ä@bR&/ïÏD-úl/ÿXÖ°ýýA_dØ èlÐá "µ$&Åè°Â¼ãýã^ Yp$-&UÞ5uYÇÃ-åxB[±ôE%à
+'""ÓÄR0KIR£6Ñä ¨=î
Êmsy{ÿ¬÷r?¾ÕÀJ{`QÛPx¸ADD=¥Ó°ô©õ¤ø(?ääàéýaeÈO
úÓáø/¡ãæ-Ëe¶ä, jmö1à×Ãýcdë̳>÷m
+?翯
+kw:³á¢÷ =ß?vUo ìïë´gâ¸Ñíeí=P^ "
hÎA©uD-ñµiÎA®Á Çá¯×aÃËÎ
O{_~Á90ÿÄÈþ³½àËOaÕÛݽí6ðÇñ <ô,½²w¥À}·úó+ëCÎàaÝþkuër¼rÌ=ùI!õ<z"l>ºö<ß|ÒPÌ$sÔy'òÌ÷Áðððú9pÃ3²Éóà¶Kýö}§Cæmqüó/Xô,ÚÜXöøËÝ{ ,AD¢iXAbRHÉÁC iZáÄ ©Óù?ßòÚCÝ©¾áïºS`ã
Ëvy'²ÝyO,~hýæ;ô-aîÄì
+""MHRr×R~)_Ýü÷ÕÇÃê"ÿ©çÞ?jNd»ÅZÿ=«f¼§÷@"5®@õ(9Rr´²z\®8MÃ\`»àÒ/ËåSyƱ÷@DªÆzÐ}}5_t»TvÎ3 [$\!õq7ûòvÇÌ3Ø sÒJ®{Ìl?$±ô\\?r<3 >oYú:ÿ®>|Ù¢l±G+:ùp[ß*ðÕþpÃr§_8mSÿsÎm®ÈWUÇ'R!õ\ö)Üö,|nIÓ!§;t¼þýý¶ëÖÏägàIðÖ8<w7hô?8ìÅÒÅpäû5ù>Ãu/UàE¢÷@DJѦ¯nXû¬?fô[Cb¤M
ô¸tÙÇAö.°ÿ/|~y??4ü'ìû½Ø¹#ü~t/|{)dïeÇ ·AϵvîóÀ7C£\§Ý«Á¦=¨;.zÞxàdpIPo!,9 \Ü~AU¾!®s0è9æw÷/ºùpúoþÜî¯À¦¨^]ÔìÈþÉÂ~GÁ{úö¸ ZÝ
+§Îðç÷ù|"Q óZè4 ö\9vÇÙðKø¥´\R¾×QÖ¹"²uÉÓaÅYP¡Ïð \*¸¶ßr»Á.°äÿûC¤¨a]`áãÐäNhõ!¬ß6·¿ç<XuÔy}áëÑPçPè «Ã¦þðYWHÍ_3aÁðùdèùZ¤9çúøF¹°.®4|,V
+í·]â˯߲zÁÊ\hø¤/®êw#äEúÏfmyüy
÷ÌܲLl¸p0nËs=ÖAñ
5Ë
ÆoY¶çZèùSi#.AT2P\" ä@dÛn½ªbõç§ÂÓï!i¤Ìvo©ýh"[3ûhH×½²å¹ÉõaÕ5ÐøA¸þ
àà{pÃ×ðí@èsO¤l£pmT?¿«Oä`J=È:Ú^æ÷íç{¾è
+eøc/MiïÁðÇà?ü±¼¶pROا"`K-NOuÅ}è»èS©o
+Á~ÁþB2èð)L¹n
+>>Þ+ý¹;«Ùá¨ÖÖBvçÂítýªðþN#aÒ@ÙÉÿA<¦/Ø85P¿¾$dÀøÓ Ðٰ߯´3$É«+1 Ýt_¬ðfq«&HÕ¸úÿ)«3¦Âѽ!}<¬>ÞwÝonà¿'l¬ÈW½O ñ{
Û9nAáýSg@Òï~ø^:ïDûÏkU¸Ý,hô04êYO*r«~ÕRÏA¥QïH|;x9ü0ð°¸üø
+´óôùðeo·á°ê5rö]oKYG@ßWB¸
+w«ÔsP5¶Ñ{ "âiIõØñÄÁðQ¿½)òÒÁA
+~UÝÔ1ùox²¬þ°~mxy÷Ûîó>ä7_ð½çz½äÂÛü Éðè10³Ne¾Â²PÏA¥*±÷`+eD¤¶0³ÆÀáÀ±ÀDàñp#oe/÷,|»HĹÐîæH÷ÿ×À{C`îKp÷F ÉÏhs]Ém÷Z¦
+;, 3ï
_ÂÄàBÒóM¥¾Ä20hÕ$@ÍS0!ÚÎEmkÑ[JhµipQØ¡H\z
+³Ù9·¬4¥Þ=¾@ þ³sWWY5Yófð¯:UÿÈæE)0±´Y
+{Ùzñm¡Þ&80£rïù©Ìk
+íWTçäÃ-=ë7«áÅP#mëg%K+¢ÔpQ½ýï é@
+°xÔ9wMHáÉVµÉ6óJ.óÏ¿ªæúû¬7)Hrníª°gÅôìäà¬mð?çÜõÕ¡HÙhÎÔpÏô̽á¦G+»e3Û¸8(-X^¤x ô0³O¢OwÎUpñ'Ê¥ä@Dj¸Í k§ªhÙ97ÎÌrµÀAÀöøº[©RxÈúÐ;ÿ®ØD*BÉH8ç~~0³ÀaÀ?£ñ½ ©@Z°ÝxØÇ9·Ø̷ȶÄer`fizÔ©ÄçÜZàíà3ë¿eñd +´&ÙÞø¡Ý-&1'.üß½a!"²-ι©ÀTà>3«p,ð-pñû{¸åãÔÑJ³ÕbµÅÝ¥Õî4³ÇsÂGD¤4së÷/̬p ê9(
«á«YZ¸6»ä Ïp"~òÏèpC)çÜ3Ûh½8çrÜ°ã¨MâñÙ
+gßO 5
+ËE=â19Ø/ø~h¨QT&$JL«äÀ̺ùdfÃGD¤òÏá]©áâ*9Àß;\ðä&Àñ!Æ"#Æ6õ¯wõ²RPÏĤxKú985ÄXDbÄô`á-aGñ×ð×?Â"N(97É5Z9ÜÎÌêH%ÐDIñ4Öu8~Rð+b$àã?ø0¬ D*ßðá÷¡ñûy $,6OÁÅ_ûóóSáÅÁ°ù0H
+?(\ÿÆ`»ÿÁÒ¸ëâ¯~ -!¿)4xn|Ò` d7ðûSêÁð·àÚ¾Ð(>2O¼N`k ݸè[_Ö¥À;aó!6özú.¬ä7ª&PÏĤ¸é9 Nêáj¶ÿàFhhAjÍé½?¬ß?Z¼óÜài/ÿrv=OîUç®»d;~§mý:Y Ûû\
+ÿkÏOðç³CÎvQq%ùò¹ÀÔº1º
+{ö#@ëy²O?ÁñÇ~.çÃ
Fv;®§÷+¹l\ÒDIqÏJ?X¬Æ/?º8*ÄÐDªÁáÁ!Ëà<ÞÕÚp"4
+ýgÁù?C½÷·¬ÞüU8{
+쳺äKµ| úÍ
u>'\'ÙùÞ%»Àäúpðr8!*9Hþ®~z¯öÃaÓA%· >éx¨Üò,Ü0&¾9-áÂq¥«wÔsPCÙqföJØqW¼d¬»ã~¸sîg3Ã9÷£ |af]s3BQ¤%døÖ¿÷WÀ°iä7¶Ó"çêOõEîÜé4¹ô×Ú!ºßay)þJï¼:
+yð;àíÏ`ïûá¸þ|JTMWk¾íöÛæÜÎú½d!{/¸á«Ò¾-¹ºòSùëWç\¾ÅÅiRf@JØAW¼$½>ι_¢ ¡ø
H- Ë`ÁnÀ_þØÚ]·,_ú6gï
+,òÛëºCâR¿²6uû¥[ázÿ
+UüS#øð6øùb8îÒ_·h[ãO/ν!¿ä7² ñÐñòµ[ ±Öå)xI^Z²
AZÝc& w pIDAT§î(X~¼ö'lhúxZ]ƹ0bd¶ÇÁv·úã»
/Á³½ u#,¼ Rçö0·|h[$/. ½VA¯GGaSßæõÕ§Ãê?d¤&rffÎ9=qPbF\$[KJ{^$¾Ô])?>òÔ
+æ\ð0<SÄù°Ýý°ò°¨²ã¡nVé¯×r(L¹òC£gàÊüñ#ÀïC`Þµ@6´}¦E~md¯Ü¶Ò¿~/úã©ó(4^o3$±[?=ÎLòûóS·Y<¾Ì;Ð
$fX<&«f6Ã9×%ì8$>Yè
JÈæ§ÂÿfÂi»BuaG?ælvÎ-«ÖÌl-ÐÜ9WNbõNqÎÅåCã¢ç@DÊë0q+K5©zcÐBHsÔhóÀ#·<nÿÀ«?.¢Û%æ(9©ÑúÍ
~·nýüã«-Ù-$1G÷×H1î?Æ´
+;ZB=sH1V·+¹T%sK%æ(9 z$æ(9 &$JÌQr ".õHÌQr ".%sK%æ(9 z$æ(9 &$JÌQr ªWw
_;
+ z$æ(9 Uväµ;
+ 9êÊ)µö6K`iX¶+l?NáÏMßì)ÿü>Ðaá÷ßÜ æî;þÿ);¥|q(Ô_ª¾×$1@%æ¨ç@¤Ôæ\ cC`Ãî0ù=xôî÷60ÿ¾"å¯
©{úí»ÿìæ°¹üvV¤«#Â}á¯Ap˳Õñj$fhÎÄý@MÜuß|`,¹ø¸äjë6÷Â%_oy.¿t=Îþ¦×
~ñ= Ý×/Ä_ÀØÞpÀ÷ÐsmùÚj¤a9ê9):ßE¶{|ùỦ%×kô&,x?Oö\KÈô@×
+°ÆïZúr
+^Ù
+n7
+ß@NC%qCÉÄõú?üBOp$._?²}íkðùg0áxXxÜz:Ü~?g\$òKø¿¯÷
gBîàêùë[$ý
+ëw!»ãÄ®IÕGs$æ(9)MûCî#äà·!aô^ VÃDø°-ô]è¿çuªà'&ö¼ý9üø!¬«ÀBËèú#üÔòB~>¸à¨3b¯³Î4è4¿bmH)©ç@b²ÉAAÒ,È:Ú^æ§çC÷á»á0aätÄ¿"ÕnûR'@â*Øt Ô
+õó*ÊÑáè[üvF2¼µ,;²{¦`ðàµ/ÕD%æÄëdc3û
+p1òEÄ ×[ü×ïιrNì+NÐz*,Ù:<\øvÄÁ·ÀÈN°dG8ð{ø}{èÜÆxÐ0£ä§@¯Wàð¥þøÞ3 áÂ×èr
+tW¶¸Zæ¿öû£[ûwÔs 1'^Ýüg²ðK¯#¡½n*19`mÅë?å·{Duí¹ÄÕ}=tTøØÙS*ãÑ+ÞT%sâ29pÎ-;©Rf@åaG!5&$JÌËä@$î;©Ôs 1GëK%æ(9 z$æ(9 9JDDÂ¥ sT3ÛÃÌîÚßÅÌÚO7³Ì,=êØÁ±Óͬ¾µ0³Óª;v z$æ(9¨<Ìì`ÿBà¨óÿ öþuì@ü}ø-[ÆÀÑIE}3ÛÁÌêÇÚYBTf¶{P6ÑÌY«òQåþ®gfIfÖ$(×0ªLu7³ÆQÇYò¾1"²M(1G?k0ÀÌ&à?èF;8xx-8ç[¬öxýVÚ<¸øôFÌö0³ÿ ³ÀÀOÀøÇoofÏ9ç>5³Å@73»X¼v1³[ÀÐ ®OÙ5@ uΨØ[$"Eä ÷Ùma"*ø ì ÊKÉAåZ ´Æ'ïÿ0³ÀjçÜ3[efssf6ÈîÝF»ß9çn6³ðÝÓðÞ§à?ð³±Î¹_ͬ
+°Â9wµ53³Y at NÐÆ^ÀéÀÓÀlçÜͬÐÿøøÒÌñ½â{.ÊHå(1¨*øüð(9¨|ï ] à`» hìæ8çN)¨hf;o¥Íø4Ö«qÀbçÜL3cfÙÀãÀÆ |
+¤GÛÔ ¶ß×
+sÙ@|Òqpþù«r·ú]RqÎåâ'%Ä%o4ÐÛ9mfÇÿçË
+Æü¿ºöËê#à| þ¿ ¡HÂ÷&tÊu1³+]ι©fÖÉÌÎÄ'[0³=]ðÏèå[kf?û SÀå[DDâ9çJ.%%
+ºðSs£íAð¡íû-êx7ü¼]s¿DOÚ;çfDk´»8Ø7üDÆt`,Pø?`ð#Ð
+ÿþËÀRçÜQõú Ss+Í,
+ØÞ9÷§Õ ê-öÃY|ëÛÔÝ èwÎô6Ä-3kÓࢰC¸ô0g³ñ"5Æ̶®uÎ]v,±JÉT©ù4¬PÃ8çJDD¤Ü´ÎH-¬ÒÏÌE;ÖÌZFíÿ_Ð3Y°¿OPg`Ø3;°z#ª¢ä@DDÒsáïùR¯ {û©À³^å"·}»¯â*¦a¿3 üÂjÑk<gf)ιìàøhçÜÒ` ø¢
+wg}_æS 8?¡úiàà üªks×ÙøÛ«#soY༠١ι¯[ÃWÍsÙõÀö@}àßÀvÀ%ÁþxçÜÐ
+¾Gµ)0ÙÌöÆ/é>-êøiøõYãQÁñk̬ þî¦ì`t!{ msyfö¾w"¿ðÛ ps®`=.À ü-Õo× 'á×]yøÛõ!À`$¾÷âpàçÜ 3»xX<cfÃs+ðþÔJDD¤À«ø%Õïv0³v@/üÒïð«þ$ïâo^»6 ¦øµX®OrÎÍ5³×§Ílsîrü.ssÎÌ6Ï©ã+XÛ¥^P±s.38»¸ÅÌá{?zâ{!0h(9(%""snqðO¬ðz6psn½mfs³JHÀ/sn
MÃ/÷;°S0áñ7ü³cÞ2³Dü3 Î3³ñ@sn- æw3K
+®u%ð(мäà×}ÙÈ,ý»Q»)9lüDsïÙ·ø9-L8¸?ì0X_¤çìçoDíO2ðÃéÀÍAC&~¨àÄàÀ¥ø Gd×x-8wxPççÜ3»¿ý¤Þ h$©u´TAªJfösã¨ít+£Ä%±AÉ¢ä@DDD
+Qr """
(9BÔZow;
+=JDj¥7Àì}ÃBDbA©µv½Úé^}ÙP=Øöú
+¦w{BÝYÐÿ3h
+ÏöåûBêRø÷[P?Ï×YÃ÷
{@^Hý>N"í>q04Yy 0ÿ HÈÝ>cEÊd¶ôÍÀ±Lí+{BÊ28î]èºÁY>8ú¾ÙÛé8N·_ìPgõ!4Ë
uðì Ðöw03*¾ !Ný^èݾ£GÎg$Ãk'Àîcá°JÛEd4¬ \àó»`î}µ#,yw^sî¬`ÙðàÝzÃ÷
y g;ÈkWÁcüwÅÃÔ[à·aÝVß~#;EÊD+ÄòÙý0ÿ~Èm +nWGÁ¬t_fv#_fÄ0ÿnÈkÂK=à³OaåÅÓ2îÞññÔÏÍÛäWáû&¾'ûÀ¼ y4Ê
'ÃE«v$,»
+Ú]WDªzDBçêÀMøÒ%Cê¸ý`Hrpÿi°üvȸ ZæÀ)?B£##õg¥Ãsãáݵ¯Fçì Çì}2aQ
+<ñ&L¹ú_°õXòÀÅ@»,{?|ø<nx¶p¹ëðì 7¾IÓàò³||_Þ
+cÆÂÈóá¦ÇáêÇáÎ}áãaÝõ0ïahô àë7Ü
+³îô~déQ½"RÔs ºFïG:ÿì¿7þÈ' ~`BË |.¼×î·Ý¯_ +aSçÂí&ÿäðÃu¿ìý¶KÝ/|b pÀ
+ßÆ"u|Iæ§BnhðO YÉ?ÂÆ ^z>~9äv¯>ä_áÚ§#í1,Þ=Îï¿×²{C§èëH5Rr ºó"Û-nô&QÇ®óß³Rü÷ÿ
+ã¾
+{AÂfH
+¶òn7uFáý«sÒ¶K"uRg@~óÂÇ:þÙÖ0h6µH½©ß2²ß'R~ü¦ÐrX$ñ?7¡Þ0Xyßr*$M3¦m=N©JJDâÎÒ³!í#¸ýB¸ùA¸öµ-?À6ï^xMw°ÕÐqóÖÛ^Ó½H= qIác ùí½ù°¬gz=!qadÿ¡!ëH nÌ?(°ç»«¿°¡?4y ¸°
+°Èþ£GA~Û-ËåôL@ß6io»í
+G>¸GîèÛh°:Ír!e,¬;¾k꽺+äìõz£v;¡ù ¸þZH?ä'A8z1¤~ <
+.Åß}!"aÑD¸ÓþUù*Üøßw
+ åë-Ë¥}GÁ¯SüäÄèýÀ¶ÛNýÞû>þ²÷oà_#·]g!0ñ%ø`þ
+röÔÏàü×ý´Oà7}ù/ÏFÃýáç"í´zæ¾u_*|[¦T7%"¡IrÐi ì5¶ÞiCpìÏȱn«`Ö è¬pþD¹'||0¤l>`FKÈ/Ò6¼~Û^
ÃÆý¿óÐnqá:mFA£gaþPïI8ëG?¡ {&, »Y8éÁ.GÃûÀÆÐä^#ÀøúÐaòk¤üa°áDÈlV¸FA»]^/ñ*eιKÔ fÖ:¦ÁE%[7½u?(]ù\çÂN'ÿ~¬Òе.î{,nñ§9sZ]Rj,õHÈ ËøÉv4"¢ä@¤Úÿh\qû${{-*¹le;èXò=· ú¯-"ÅQr R#½¸ä2Eõ]ùqÆ^k5á\[D£[EDD¤%"""R)Ds¤Z
+|vVHÓ:RëøuØÆÃDJ¤u¤Fû£«AáÇ IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_overview.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_overview.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_overview.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,190 @@
+PNG
+
+
+IHDR H ÞÿÐ sBIT|d pHYs
+×
+×B(x tEXtSoftware www.inkscape.orgî< IDATxìy¸%Uuèkï]Uç{îÜ#Ì
+*2¨
8¡ó|qÓSã£/&ãD¢/Î 8%È " JÝôxÇ3WÕÞ{½?νÐ4Í^Îïû껧ªvíZ§Nuïµ×^¨*0`À¥`À0`ÀÒ1P0`ÀÁÁ0`ÀG0n©°ã!"ÏÞ¸Õ¡w«ê϶Ónتú«;éëãÀÁ»]U}æ-ï©ßêÐZUýý}ìk`·ýJU[÷G¾ Dä(nOªzÉ}ìg8t«C7¨êÍ÷W¾î28ྰ3p,ðY`0µõIù2p$°ç¡0z'}]Ì /äöõC·°U¾
=FE/B ôP¼ûǾÀO·Ú?x+TgÏV k ÿ¨ª³Ûôõ*à[í
+üúÁ{À#ïqÛÿq¿f+
NDDÒ»h¿>¡·â<Û¿ïï>ôà=`@D¸·ÈSÕK·s~p5ðKàEÀªÞ2¸xÍÏTÕú òý"*.Â]V©2a1ÀEp
+b@
+(ýý
+ýÿôçCä#ÌZ1B¾´ßfÇBD.Þ¨ªØæÜñôá-À¯þ>X ܦª·Óç_UÕ«2XYØú¨U "
*Å`²òÀ "sÀOUõyÛ9w&ð8àb`3ðhà ôªê»·sÍ>ÀuÀ»Tu xÐX<¬TÕ "OFX{E$e³],
=kuÆ#©`@p²0ÀZ(UTúJá¤Dg( n¤"s~ k¥³ßug#ð
+à+ªZ Hÿ7ø(ð×À߯^:ñ\T"0VÂrvÊûZa$ñ $8ÀôßÅ̦)
ö'&ÝBiÊʦnÎìí-ýî7¯ÜvR""+wÈ?©jciD0 1obaðp ¨jüØRJ°¨îh¨"ÓMöØÒâà×U&,ͨZÑZOÄ,X,ËÂ
+¥@EÀ!°°ô-}ÅÐ
+XÖ*Æseù\Écm`ýå·©eËR}↓K¶9Dä£Àëé[cv,NVæ»ì®ÕsilÖ·:E¥BDÕÈbÀ
+$U`$¥Âª {C)QÖU,7$¹%û¢¶gVÕM"rðçôÝc®ø6`ÀV8ÐGe÷]öK-ÌûKÓåüàOZn®£f9hº#äj·IRqIÀyé =
+u
`Û_FúÊ,lþ@¯ßdá¯fB¥x`¢TöhzyÉzÂoR˶¾nîmú¿ÅüRò@#¶ëD£'«§Ú<ºÙeKub9ÕRp-%IqýQð@pÙÂd¥ ÿþY §?qÉè+Æs!õ ;uJõ#l±Êº,avÁê=à~²`Á>¾;ÃK,ÎýA«ÊÿYëxJo©
pÿð[ÉùÁR±Ã iõtåõðs²ORdl£S° HÈql
+hGð(a>1TÀ¾Ò_[Ä 5úÊIüØuaß i"g©Eíå¿r5þMÞ7^AÿÙþh©y tý¬´±!ya¨Õ$Å%ÛîA%¡(¼`êôýW±}Vkn¬,NR"ýIBÿ\dÁßuq³
+à {äg{l¨%\W±¬ÿC?"r$ý é>¯ÓÐq_DV,µX>q¨ª¥M7en0cbb(!"&¶IÁYr#28)Rö/0¿`uQ=19×_®(tIÀ
+ôþ5þ ,ôa# 5a¸L!8+Ù=nÈ,kK{éÖ
<ø ýe·SXû
Ô¶ÌéëgâÞs³ºð¤Nü²å¤ÁcId`cÀ¤ úkÍùD¨%}¥C¶ÿ~Vé¿,ZÛ
+3ã,¼@űÔ\dzS\LW·~äü{Æ©ÜF+/RÕÓPûÃ;Á5Xø28à
*f®wÚ0Ã!S-»zåhU{1$©ëôÄÔHFÕVÅU"âUiÒ®DÁ
+êÁ;èõúr»ÚOwô}çµouQnS7±Z¥¡S*ÞÝϵC)7°Cúbþ¡½ïÒ_>IUwHEeq²²fc|âìÑ$«F;d$ت1b!ò1ó
+d¸´ûÖik¨ÊZgXi!UhEÐ êû~³ôßúôÀÅÉQèJ?àkñý\¬¸TM|ÈÚûW¸p0Y¹ÇDßr{}Ëà·D䫪ú²¥ë¾1ÆÙ_¬(îøxÎÌñÔ×ÁTInÞäí°{;·Ã¢1ÜklϬºè¸Ò{ªPdJ!A¬*bèYp"ªèú9H24Ë ÙFÇj@@UÜéDb¤©0m at K
q
Bn?Øn¦lE0
¡,Î{nLV×%æÒ=Á."²pý%ù§©ê5K,Ò}bëÉÊLÛ¬VC,Jg|ç6º2)º3ÆF#2:JR¯÷'+X¬¯Ê|TÚVX¡¡§ ¢ Æ~$±}?ÖNV,ú*Ìémï¢ç¶J ¯hÀ¤P ©hyLVîªzíÂÇKSEäûÀÉ"òaU½j E0àËÄ>¸¼àôÃRõܸx¼ÁñD6¬ãÒ³¶n?ÏÑGYöÞPç¿¿÷¬,øÞ! GæëW
+Uí÷ó¬C-mâï±ßÉ4cÿ2Êyow\N3ùá:ÿú¡ïÓ ¨t%p½s¼CZ
+Ü7B ]³¾}ðý¯µ£#\³áóè£fijQ
+[¦£
+V¨t+&V»)¬Q¤1RDÒ+ñæµÕicÄyEª±Ñ¼'=ɸ%Q¨YL&ô¥2lûíÂ@¬C:£bbÐ D
]%Yè¼Kü8RÈ*úàpÜör_î¨Þ´É?~ãîÔ/ò¶:!T«ÎUq·UÊBɬô4Dr A(¬!u@/*zÓ,¸jj¡ï»0ê*D¦eBÏ`¹é+*·MV\dûlYM0Þ1ÚSRÒ(Ù¿j¸(u ? §Ò·>(;Ô&.øö¡_ÿ[So-7¸ÑõYÏeߺm÷¬,¹à9ßüðíûøÎã<W| ²öI%?~Ë4#5xÎA %?{CÁw¼7B*ãM@p¾KÖ}£ÍvãðÞ×ëìx^«·LåN7Êý²ËÆÄ?j9Å«mwUÕ°jE
ñQñ¡ej8>.jM_ÄN¯bÑÓØlF3× tÚ49õ´*Õ@ðÞ%åæÍÖ¯ÕbýzÂÌ<.QfM¤ÝÍ º[¤2W
»Ú÷3·1öB4|¿g,6qT¢p@î[êgúPADÓWwWÕ/±H÷H¿®}ðuÝ«U+£#¢z*yÐ2øPdIÊPÍ
¢~ãzõ³Ó¦æqs³±=½E;3314£'ø@/@(ßåÍ7QÜpåô,e·Ky¡dºÒ lîR£Ø!Ð^¤7 _x'} ïç»iãǨ¡ÒòÑ.xÔR?ËÉ
¿´Rí._)§\%7yáSêåJkõÖíz|ñe_Ì<»Åvóµ·õÞ0Á÷Ì°ê%?;xÇÝ 4ÏSY··0²ylã`ØóËîÅâ~ð\ñç?Ä7 9ÔåMyÖ5=¾rL¿Y´\üÏáësöÈzc\ô?guøðÊÔ.U7rþêì¸çÈK}vW¼oaJU?ùÅÍ~}]ói%©¶Ú¬Ù¸rÔ±ßj Î8<Ð.5éæ"YAz¾nÕ !Í$EË ÍĵÊÍg
B2ßÌÆJÆ*ëÊH£(I³
+eÕ (2#óMìP
Æ:
1ÔJ%S!äDÑe6enTQUjª$Æ¡ÁC Oèttz´"Cq·áaÊBíës=¶W{G`¾Vݼ¹8<ª¬
+UüÄ+GÆí57ßA
+ϨÉScÅ8'¡ÛÍ2ÁPAÕÈÌ,¥µõ:=UÕ+%Y·Ñ×z9¡QÚØ#ªjmr|µêy ñÓ)qÖÐZÑU_H¡¿Äl¦ ïa
ÄBðé{W9ßøte"R^
+|MUÛ[?~¹ýwxÀ%åÁ>#ç¶xÍq k_`Ùç?·mÙôÂ?ú¦aâÌÿ:éÎoοËrd ÓRrÁ?*ÉȺÃ;¼÷°mÛx.þ Ì°Û«rÎø2·[tÕo(øÎÊ?ÙáPföêñÕÏͲÏKæÎ YdËÞÊæÝ®48éÈGÏÏl° SdgÍqä1w'÷;ðRà½Û*ú¹Ì÷ßð"Fuë6vìå~x§eI¾ï.8ZñåÊQ¼÷1Þ2]Æu3õsʦ¹¨½nÌ+Nbhf ±R!«TŦ1I!%$¤ SSÝØéaUÑñ!ZãÃkÌZ!YÆÆ*ØPóï µ0TÁ@hF\³$35ÄvAí;`OD²DÍ
9¬
+f2ÙÈoL|¤ò\ú5«À9"¢Ûl%ïnñA³[¶ôe?>buÓtoØäu®
+µ|×qz»-£Üy
0\;1BÊèÛ0^°|Ì
ËlÁÔ Õ
+¾( ÝÚà5yÌÞ®³Ë*«W¡{îJ}ÏU´Çêô±àGªx+øó°n[L;hG
¾ -Oðд0#.͵Ø"b³ê|Wt©ïC~
+÷¹ND.5ôKuÿKU×,©p©e8ä¼·ôøÜyJoÿ
+õó¯ºõü<Ç=¤7ÌׯmòÿÊ9óJ÷Eß@¥\5ËÞ/S»D¦^ä8üÍw%HãQæåü¼Ûú=>9Yûæï=¶Æ{7G6Øv;×ó«
êq²Âëß:Ä?®çÉ?÷üæUÀWSN8£ÇN`í§ Ú¼eCÃþ±
ûþ¿Å{XöûdÂÑ¿»;YÜU}ÖRËàV¯úÝÌÖoiíf¿vc'L7ìµzHh¬ÎuÕ¨Ñ^¡("¡ðÄÂßZ²«¨lT(b FñB@éÈøxZU(B¡ÐIÀ[Ñá½µ!¨8$h5á*Ai$_^¥>_ S$=¯âë HÏB ukH¼'d)+=WϸüâãRàýwqþ!m5íæaøÆuÇN5üªGí4Rì´Ì©÷1Ì5iLÍgÚÎÒÖhH ÂlR!-¼@Å/ÔýQ©¤ÐBsÞSäÁ$:\£gd6:A!²¤íÐÓ²RRÔ¢F¨!7BÛ
+IÅPmÂ2\Ãá)멤 Ìù~
ÌZV2YÞ,ô±UÇõ©Gr9à©ÀqÀÞôÓü\|øªnZBÙÇñNQò*¼æAygf9ðù5/®ò7l1à.Á~xééNÞýjòï
+ÕÛEy~u0ôëÏ\°Þ©kðô£n[bÕLé,Æn¨ñÚãj¼÷%y¶&pÝBíÂ{¢ä¾/`º|øó]]ÃHÿseÏÍàÖ.©8°¦äûl¯!NYóÎsÌÂÐ/G|i³/çòïÞYÁ|OD
+àÕªzÖݶÞ"òÀáÀrÀUë7·÷˽®\µjRº½"¶;=Ê27Y£Cµ¨¨÷
eáJðâ¢÷*y©cDÅ
+ÁûzÀ+)QB"PÎD æ&IàEm÷½ ô¾S«eÎ8²²¤¦ÄP"uAìBÁº àLAk,¥ZQÍgÛRé1"C)&*¶fïFêÆ£`A«Ô+ò[#·Ë÷pã "Ò~«ª¨êeÀe÷´9~·#ïrýs[¿¥µ³MRfæó²ç½<jE
MmWUj/W4KÄ«CÄ A@iÖª! 2þrnÌûÙ¦«CVó=©dJEð®8J0BLúK©*IÑ£4UHâ2È=%e x£ÌN$Ôg÷(-J1õ©ZbP%Ô`Ë@LYÑÍ5:û¬<JD^L«êwJ»°Ý-ɬ|pD\z
+~ømÐ;Õ="ëÿªÂk¾÷`Ü[ßYé>1²©ú`ô¿#s©e+O¬{[
×Þn©´äìª2¼PûyÉù¯ÜFÏ'?ëï§7M°þ'}ê3J±×=moX>Òå'nÜâ{luÌl¥d¤a!AÿL°ùïÎ<¥Í»VòϵydzîM´ó#¹ÕþÕ÷£¯¾¿ðù0z¹Þ0ÕÝ·(Êdx8»¬¡Í} O§ê«IÆJµ¶×¼Wh¥VÁGѾ÷ö¦²é[Æ@h""¡? ãÄ^Oµ>$ª;Ò
+ Ý.¾Z£KZgéG´bD¢*i´¬ÊÆ!¢WNï=>MÌà*B¯ ç#ÆZ±
+ãÍ>z´*Çú¦9ppÔÂöyàâûØׯ]ø|Kd9TÅLÏõvíæa§=w_C£åi¶b¼YÑz¢J^3B0!Ç¥ÑXÓ_WU1FúêDDDPH¬ar²¦R8$x° Ò+çK1¬s ã>¤^L?fÄ-=ÍÁÖvæRÉz
ÒÔÁÖ,R±A0*¤b¥Þ)801ñÆ,1gáÍôBÞü~¾ËûÂn}@ÿ}Fg»}`{gRNøõZw£Öùäs¾õ£:º9ç+ÃÇ[¼ñx¡rù$ÍW,ëòáemÞuþÖíî
+UÞõ³&ö¡vÿßu>ý5ÏÅu¥gBî(Û¿]WpæºÇ½µÊ[>rÒ\9Ì/¼«ûñ[z:Üä¤OØÙP ünb¯_Yeóy-^7«4V½#áØ3ùæ³ìÁBU¯æþ)[÷õFvGÅݲ©½ÿæéVZ©¤az¾Ôv7hµæÄ!Il at 5j¢Öh飩Ö*EÔ& ÝVá*¡ðIÙ¢bH¾§¢VP#h4 .! ÂÆ]¾¬&I'8¶Ú0×R2
Xò2Múuì¤ôF¢Q$qØ t5RÖ¶4a¨Û3½ÜK*¤H&´RE©¯=çd¤ëÊZ&«e'Uý-°ûÔ×G<}Ýz¹¾ycóÀn^J¯ô;-«êÎËkÚìÝ@»0&4MѬV¼#Ñ3V¯j³«DEc$Þ:¢bHbìç\ðÛ(h»âpÝÄØo#ÌÎF¼µh¨;¡%Mú©hD1*bÁä͹q²¶£6Ú)r *R±T(P ïÃe )K©£W$V ªUõñß]°zïþ@ôõPF°óÛ¦©{ éòÑI¥kª¼nZ¿Óü
+¶Çg'ïnå²àµOTxãFËî÷(0ªÇ'Ç-ûõÞ½;YÞ¸§éîr¾2¬tM
W>
;¬Û³Býjç´ùêuÇPý92»e¿/m}]¿2L|«Ç¿"LLCÛU¡kñ;<ø´2N|±2õäÏýï.ÿ÷³k'û×T)
Ï¿ÆKa<Vù»+Åd¿ûÖ,ûý pÍ ý6+ºBíÖÙ
aE.T/íCÿ¶à¬×vxÿÙ¬äìwN3úÓ6o:Õ²ç§ëzSÿ{öV)Ê}x® UùFoÕùÞNõzF¢(}Ш Æ%NU£!"¨sj}Hçæ;_
+¡4Î(!"A±V¢õªªªs$1Fdd¤fÚ÷àõ
+C5X6¶Z^fçKé¶c³d½H%FÔbô¨¢BPOÌ=v¶¥¥ê£Gæ{¸¡g-.sØècRªì·¦«ð$*nýæö¾·´&Ë@hu7mêè;2ß.Ä5ê
+ªQ*TjFqlÞÜJ©f(h?9eT$D5!ªñD#^ FÅúR EθysW[íR¾ÕoÙ¡^
N;Rz¹hòÔbê
²$vsbbQ`fsb&4R³Â«tzÄVÑOP]±´Dðªäõi"ÖGY¶ÄÀDî;EòiFNÝöÜ4cÂ]ÜàÄ[aù{§°¿ió¶_wx÷¥Ó,»bÕoÛöz¥ë¦ÿçv¹²Ãû.Â^1ËþwaÕÛ§H.hpüµ]þå¢Yö¸~¡¯7yùÞÛ¶Â]2òÌşHÚâ
+ÏsÜ5ÓÔÿ£ËïðîÏsÔÑS$µyÛ¯ç8äêiê_nó7«§pÍ°êWfÙûeS$6yÙU-^uåÉsö'÷ôyÞ2ÆO?=(+³ã³XVFUß²Ô²,1ª»î¦¹Ãg[ù>㣵ª½Ü«1ÎתNHjUk Æ*bç\!jÄ«E¯«S«1ÛõTuV1Öôxc¿Êk°råÆ* ¨4*Ü´¾CYÖjNÄ$B¬"ÆA§ *>JbÂPFG©æ¹RÏRH
+4÷¥NòV¢éåÎRÿîÈæéÎ×ÜÔ<ÂZD±ÑYÑz¨ibÕY1&kоÙOuQLÿý"*ív,µ&I+Ú)g-ÆH.¶ÑßWãÀ{%ÁYUBPÕFPkéÿØ°¹¤ÝS®;\fe}¿B-~acFÄGèåÊHE
+g³m[ Qýp]ÌDµï
+[F¡[hÄHO¢®«WdíÝ?©eDä>ë
+S5Bzõ$½»
+4a·WGnþ;ÃnïàÆÏ̲×_nø a§à\ëæ8ø»Jñaì=~ÖGn9Xiï1ÉüúýíòÈ-o²+ ÙhxÔwÙÝ#O°"åyÏáô+ï?MõtaìçUWóªÌ âGø¯£Ss«¥{
+¹ßA6ìôaxSä¦ç+íc
áÿ¤qkng<®àG§A²Ö²×'éÀu'(¡ØOüLýÝmrL~H9Y=òçÆòÀÚC±¯åÀ×så÷öwXdPnÀâÕ^Çq&uçH£vi|0¦ID"`
¾QDò¢0Qg&¨u5ÜË-Z¬¨Ñ)
+ÝDQQÄCª"±¢¡ÄDQT3- Ib` :9²fmCò¢Ô¢WÑ¡-kJÂe²&h44["ïiÔht`r®Fª!¢eèg¶)X¡%J%
+¡Ù{NÔíwÿÄü¡iä+DÓ!Q¯½Ü±#D#*ëÔ 1ãlCFU©
+kð¹Æ²w¯1ß-<D¯UIA,ê}AU
ÌÑÑn·KZ£b¿
+ºl"¡µ¾#¦¼Ôr¸ø®!K-=1àK$sÐíEõAð1Nn\e縼¤l%Hj0¢U$ïyÒÜËÎeÐéÁdåRì=Må;Û;7Âw_´¸´:Î5aùÿ¶Ás~VkÞ#T/çÊO,^3Ï¿J)³µÒ¸À·/ArË$ÍWÞvýS~^ò?ß*9ïEÀÿwN0sâbÎåË×ÒæÍ/LyÎnßo¹gÆ9Ì·WF¿=Mõt¥ù'=>7º¸´[rþ[AÊ!>øü*oZhûiÆOQý¶î±Á³VfN6¬øÌþa«S_"¹ pÍß®ý¾e¿û×óNûØÑ!fÝ^1ÜézmDÐ(4uªei|D¼"ª*ÖÆô]¯ÒÒ$Á:+eÒíéõ¼$©J}©F_ä¬zEEQ¢"U4²j&ÆZ¡d"Ív!k×w¸æwL«X1bcbL(Ù IDATF³Ë鮶۾I^Ó
+h½&èØP%
+IèAÖm*%/|¯â´_®$%&V\´k,.u$ÖÚÒkm©·'Fµ^\ÕÚ¨¢£©ª³b}1 TMâD+¦©V("ívÏøàÅ:§Î&Y
+ɦÙBÚͦYVG¬E1*ek¤PÅؾ¯CPÌP½&ø\í[ü¤ÓS&F3%%·4dýú6é¢7×P×ÍÕ£Ñt¼nP¨10×´7^'·BVxb§$HtVªNç°®9áH ÛØþ¶U+ªZãÞfºà.øÞ§Á4ª¼ã[û*[vjs¿tOîn9èË[ïñÏäÐÛuÛû+]éð
+?d§<IÛRFwX**n¥.»î
+ýnJçHaøG[) $ùÛöéùù³©ðÊ/l{ΰì«:üý÷ä{ßËà
+!ªcC§Û³!ÄÐhYªµD¬£XcUÄŨ2ø" B¨Æ$NP5 hÄ!RKÕA6LõIu¸bµ[ªørÁ¾u
¨8QET+¨ef¶Ã\£)`uj¦aëºÓª16nÓOЮH5KV+ºa+&WaËtd¸nÔ¤D(KQGìª5µ²$ïåà* "©¼
+&Ø)t§Q'%D$/¬(%6T¨U
+¢Æ~ø/ïXUSzI«e@¼/qÖ¨«e BQ¬âÄ¥03ßcÙxF§DÝ~ÉïUMßACcD¼ï§ ^iöJZ¯V×Ô£K#Vç[9S¥IRu¨ê¢sfQ°i®Jh´¼4ªE®K:U:#.÷ZÁ&±½"®ªuKýXdÍ$íïIÛ*=Spú_÷M ÇOÞ6àC)w²«îipeßÛeq<¾ ·ÂícÌqȳ<W½Êí([ùvÒÿdwx§
±5°ez Ë?îX¡vã¶m]WðÛSº{ Úá#ßèÜ!þ-®Ú¸þòÜsÊà
+ij»©ÜØÂÖËÒ8µÖª(K5.ÒíùèÁYC@ê1"VPM¡VseVCàÁbZõ¶J³ÄÄñÇ,ÆÐOô«DUèåg
+FDC¤?ZzÁZ'½<Ba§wtz¾C©dYÊ\¬,4pÌΫx2i¥±SÉLµÕ%®¨#¡ôj«©ØvÎd'×æÃ-ºxFUÄØØË{6/JÍ2fT¬A@¢#ÎE©V+¡ð*A#ÚÏt5àl¿:°K
+"0Ĩj-bÑ<¦²yÎSMÑѪ£S¨ø(*"ýȤ "FDËØnÞÒ Ñê± yÙ4ÕjUkc´k£ãivº%IYÑw6qbÈè© ¯ Q¥êtÃëè°3m÷4¸¨
<Ö1(#Qu!HÀ»&pý?+[¶SÿZmßÚxÏíµ½]ÛÏ9Èsù§ô*ïwì}ÆËnûy¾í¯¬ÞB5Ü&ó¶t·ÓgÌ@a§¯ÜYCï"Øïã^2î¯5¬»u½¾Å«w/8ýåýÎåüͲïæ.lø§û+à}¥Å«wÏùú;|g¼J7Â/½³ö
+v£_z<HiÙõÆîaÒé'<6åÄ5þ²0Ë~¦45ÁûÆbä¢1.:¶?cpO0"ÅÈp6Ýì
U1!*iƹ6Y&Ä|¤(˪¿±IT¹÷hTrkè$j%ÕÄ9Q±NpN b5#[f
+O¦:×EA±ÆhQDqÎ"ê*ÑØnÚé1ƪÆÈülKGjT
+ã#Fgæ}ò«Ë¯:úÜ.{Ñ=ûIÿõ´'ø£á!yOi5¼Ô&&QcV¡L¦ÚqN2ðRt¤à!1½"¬¬en >D0F|j¥'*ã ±,zß[¬%ª³zÖZg±¶¥îïû3jÚëOVªU§e©ûCf>z!ä¥8Z
2ôDDÈ5kúgE\âbÅÒw!®ÕHºlîikô¼$óMÍ+U##FZ-^YR«8¢5Zä1¯f¦ÚîIhvÑá
+1DU@³Dl£££½B×2ïç»d§<)²áÂÈP®
+ÜðÞ&/ºxëoBºFÉ÷Rº²ß}ÆsÉSAãÈò_,ïòÑI÷)
@w¯ïò±Riß¡Fɹ{n{L¨]¯tÍxñ÷ï,ÕÞÁ½ölzAdë[üå ¢¾ý²ÈÌ7pô/Oz@óÇÝ[
+ÎxaòâeäI(9÷½wÖV5³ìýåȦ§:þeß®û«i&?tOîUò¿-øÆV?lY
²~ÿ¾AXqÿ®ä8Ó[9Q½~(µ1â³Öµ£õªÉ\b²ÄÚ²,M»[ÚNÇv»g»y4}ç}5Ö1ÖH^xÓjÒî¨ÌÍ2×èJ¯Péõ¢t{UEEÀ¥LÍdRDû©e@±FCTÊ "Z«bV¬#NAQ%hÔ¹¹&ÝB%ËjéÄh
D$
¼Ð¸i:éÙ\+Uk
v'`f¹2¼D¯j
+¢¨w¡ÚÉà ÕÌCÑlýPÍ,5Æ9SfB4Na4F1"¦ÝÎM«]ºV§´yLHQº=/í¶ùfi¶Ìôdãætº¼T|P1Öm"ÓóQ(~ùð¸4lÔHéU¢¿<99bªÄ "bÐ¥ÓîJ³UØ*£U ^Ón·°o~Ïþõ®úãéÙhR«1MUñT3«6Át<âíVRlPh¢Á
+ÁLéæau,õo2à¡K(9ÿàÖÖùÂßTyË@Ú9ß>µäì[«ç@X=ÇáÏyàîî«ý¾ë·ËØå{´¼}gãQ¨ÿHiýQ?¿ÕïP5_·m{Ëþç ôøÜk·=÷@r
±ïüà$àÃ
+62w0|kÔN`Íren
¨Ï>¸ä Æ.à¦Ï6xÎAßíÑD6SåÍèñ©W+ÅrÃò_qùW
ª]mñÚ#[)ûæ(?¾`ý_Ùød!ËxÙç8e]¿þàÌ BçêV/SòåJ¹ëËß© Ö~rëï3Ç'*~r¹?YUä|åâ&qag6Â/áQ¯©òúÓ>gØýg<ÿ¿K.ÚK)ö(¹è3,ÿÓgÞÁ;ÏÑGy~û $<á[J¥+strdêp!ÝRåͧVù©m¯oðüÇx~ù´QÎùôýz8#ÖkÉÌ®«¯¾äê-;ÛÄYk+fN'5ÆV'ç«Úî&ø@âj2<dC"Ýn<Z²âQ#ªÞ+C51¼Uç¬UÈÍMÝuuZQµ¦Î£(Î:ÒDt|¬bZ"Î5
+
+Q1HÈôLË\9ZfÎc8à¼Ç´÷ÿI»Ç¨¯Õ«ÚË¡ðPK
`H»£¥KÄåAµ"©bL1ÞQe'ó¡®\6tý|³kû]«ëÒÄç¬eIâl¯ÛÓ FñAûÃH%%ºÄ© UC´ôBB§Û%M-õ¡*Fk
$E4K«2æJ¥´zh@D$"ªE$Nt¨fdÕÊasÓÚVô¡¿¶BÔF³CjCÊÊei¾ysË
NWc£å¥,KV¬¨ÑËiç¢ÕETR¡]¨ÔD%1u&BP-Y·õÔ}¡ø3ì´Ýhý/å'¿èn¼ë)ÏznÆZðVÁÞâ¹ø
+NúûIfß0Ì×>5ÏÓ¸êvÞÝqȹùÀU(3L°y»ÕNî
+Ë^F6½¾äìÌñøOYöZ[rÞ -/û
+ò§§ä|ýد^rö@6§l~:Èâø~«us?ÍØéÊô˧vta¯5+k«l>~Þ ÷G¸Ê ã ï\ðO
+iðÜc
Ú¯ÀÞª=GÖ¨´vþ»Á3+8ûó?ã8ô«
+øÝ>k>`?Ýqè×jló®ïÆβìóÀoeïeÜò±&¯<Yß?å¸L@°°hãþSdý!]>~z±OM8êÒÈ
+;ùyà÷{Ú:ÿaèy"2,ÿÞÖæå-^ç£K#¸úl`
+@ÙøìÀ5¤üѵ˦«Î·ìuMÂS7{οµïy=²ä¢[öú³¿Ðä¥/æ«×ͲÇ;¹£,},²æ6ï=-åù¼µÂ7Ï.ùÕ{*¼ä5Eðî!®\V»ñ1{M^xóæÎcQ!¨&ÆhÄèUkµ4Z)4btj¶g{
3£Y±qr¬.Ív`j¦ÿýëg½yv¾µjÕk¦fçw`ï=vºÎYSÞ¸nó!F³÷î«~÷£>óàýÏÌ4½üð§Wwékk·{õN·¨=öÑ»_vâ O:m¸5ÏûÅå/<û¼«:>V_×n÷Æa]Wþö¸§>î[;o]úÛßsÚ÷/zÉ>ýqß|Òaûsýµ×=öþÚk¯Z¾ÑèZÍöðÁìÿë§<ý¨ÿ\¹òæßþúêþñ¥o¼aÙòåjCY{&·ü¯WøÙ믾áÿøâ£×Ý|Ëê²(d×]W^ô1ûöxðYy^T?ùñ¯tíÚ
+û¾ñM'¿éÊ+®?òoÿä5Ï}Þ
+pÆ·Ïù«¿|ÅóÞôÑyݵ7öÿûï}ÕkNúÛ#ð-ñÏ»ÃSIm{Õ²Úïç[síN¡fpÖÅZÕHÔC´b¬DU¥[xQUu¶*C5B8íåH¯SRcD3êK¯ÞGFSTÑD$ADTcýæ&»®®Y+=oDDÔQï ¼°Ö멬ZQõ:â\Uæ[=WÊ
+
+W¯ïý뼪?Y)c%K)r%ÍRõªª)ý¬èNO,.JéE5YÈm$Xc$/â²z
2ø#¬lxóöÏI ~1Ëÿ[iÿa×á{¿Y<;Æ/Ïaùç#S¯å1çså Oé
+ñÏÏîðîEÖ¿©`ý[úòÂÄWï£\ð³v:%²ñ
+KþÝs ÜñgóoÞ>éógñÈæ¿ ;e=7ã¥_èò¯ ÙíBã\ý9øÛȺ7"·ê¦!~;·¸×ÜGËàdC¨ý¦Áó \ýÇ¡_ñ\¹]Í´äÂW&ÿk>³ph«ú©f~©÷ ÌqÈñ ~-ïçØNÉù>í]ÀvÙXáõ·mGÖ¿Üqð{ǸäGÀYÓTmóÎgsõi9_7¬¼a3¯hpbü¾}ç>Å*¡~þ¶G
lÒ]uWÏ¢Æ7v9¥iÙãÚÅþ»üýç=ý
aù×ǹö ÓLì_rÖÉÀ{"_ð´-X9<ErQ??f_ü ÉKNÜüï~I¿ÛrWr¸ºëê¡«FÓé5ëÛL7ÊÝ«µ$Xctl$%z´ANÕGbq¾YÐhäfh(+Ç3¿çêÄÔ«b¦f;Û°eU+F¦÷¬'ùß¹àß;ûâgï¼j|ý{Ôiß9ëâã¿ý_&®\½ò¨¯ÌÍNíõ/õÚ·¼ú¹>`ÿÝ.j.Ûû?ÿe#ÿøC°aScÙÍ·lÙ+q¦óä#<sótc×wÙK*/8áÈSgíÑnÙ¼÷æ©éñÄÚ2W¿qÍÚ}|ðÙ>ÿ¯6Zäk_øÚ[¯¸ôªÃÞöþ7¿±ÕêÖýMûüþúöYµzÅ-»í¶êèûßóÉ÷mÙ<³ây/:þûì¹úÂo|õûo½ð_ÿ¹/¼ÿÉecöÛ÷KÎøö9õ¾wêÖÿgï¼ãí(ÊÇý¼3»{êí7½B Aô
+¨t¤H+ò³±!ö
++Ø¥HTz==!¹ý¾;óþþØsC¡Ðó|>7wËìÌÜ9s²ï¼ójǤI½<h·ÝvÛý{?üÐâW]rñÕïÚ}÷m/½þo·öÀ·»ÅÆÿ|öaoñl4+u´eVݾ`൥jc|±h¥VqÞ«zãä9²Þ1ZjÐ?X×áRb{;":.e|§ô7x¼¯ª_<ç×_Z¹j`ƸÞÇ_=4 XÈÆ÷v¬ztÑãLÔ½ìÓü¿ÙÓ;ú2ÖËw~vݯºþ×Ö&j=?yb÷²ÏìĶ²#]uë1ç_týÉ
|f¸Rm´©ªi+æþï´£ß:urÏhR÷ô+ßtØîßÙw×yßyÛÃ;áÓgÏçJÕj ªEQý«ß9óíÝ&,¼ùï·íñ/óùi3¦>V)W
+sænôÀY_8íc=¸hög>yî§/[9Õ{5lTyýë÷üÑûO?á}Þ«ù̧Îýåßo¼ýàoóÑ}úú&âÿιð=ï;îôí¶sÍO<ãÎÓ?x⩾߹·Þrï¾ïßþzÒÉ|ömo?âöÓmñ\èÅ?§0(Ý,ü!ðÃõß[}&ð$m_ÓrvJÌM*_ÛD°>âKRâØsKÏÎY·¾´_=ÚÎòoÔùõëüj£]Wí¶qÁ¶O}^×ãØ]Ü!páº×Û¸à!൯
+±Ë Bç³&¹ný øALvÜ=Á0«/Çÿ[ñ\=¨§Øö»¸p~áü[6eîïw¿M©ÍmçOó¾ÆTÃ[×wgíq¡IBî®±óÇß¾'á®0ÇÎL½Äû¯î§ø³QÞ8'-L8ð®'jÌݧQx[?ÑretòºWÚd!¿|}OfoyÄ
+ÖôÑÐ}¯ÒæpÖ|3ÖÇBö>e`Òعã±÷fÿ %>DD;Ú¢³§ç·çÕª³µ³6lâÔ$±1adMYÉg±"¨R©<¶¬Ü·¨¢]¡"#"è!ìxÅî;lö¯7¼f»+EÐw|Ð÷÷ÛsÞ_=p? ,YÑ7Ó®q÷SNñÎg/»rþÑß¿à÷,]Ù7-°Æ%íçm<-f^¿ßî[ÿr«93o¸ù÷+«ùj5U\rYu4ê©wÀÞûí|õûîôçwÛé&O\øÐÎY¹héf>Í<K¯ûÙ:îà5®\Ñ7i§]¶¹éØãùÑ^ûì|É?|ò)}}C/¿üú^óÚ]~1oëÍnxì±e[JÎ÷~Â{Ã0hl½õìÆëZzï=浪rë÷îcqÅbþ?ólÆçnÜqÓ¸ÎìÂj58N$ LgGÎär¡Ôê AC$iÈãý%¹ëR80T×éã³QÑcðª&
+mòÑ÷ù¥Y3'=R*×õz#{ú)o8ûÇíó³e+¦\7ÿÞÊ
+ËÊ}³®¸æC÷ßcë+Ïùâ)'}ùoy÷Èh¥ýïÿºo÷¦}+ ªØ#^·ówØgûUkõ⮽õ¡á¸æÿzq\l¨T*u¨Õë¹SN{Ûßô¶7}5_È|û«?üh¥TÆæçEK7òÞÙMfÏ|@A¯ºòV,|ÊëÝÿקøm<iÜc]ø÷ö÷
+M2Füi8þ´z½ûÒ~tÞ·¾qÁ·¶ÚjÓ¿vø¾çn´ñ´{DDo¼áön¿mÁ^ ÝÝ-G ìRoç¢{Ûøíýkÿ.)µséÝëÆ|!(U)qêÇßëtÜö!0£9Þ{ÍÓ=[àKËÛ¹âö"ç,ùO °a°êá½Ä;÷ïüL¬í\|O5ûý3{ïdzì¸þ{köÇ1t-Sª[×ùÙ<°}óâîëfÕg»Y²aÜß\ñá´T°¢ÁÖ<£T¶Ú"¼ÚkàV°5L½Î³úPÏ5®Þi¢ëÒ~Ûþ
+@W8iD¥1{jJýiê{V¬é£g`YáøQ0å
+ßòþW·zg9ñXÇÓØæÀ§ë{g&·Óõ·èüMwÁ>ªêm±-ººC[Ì
¶XÈ0Hhkk3ù|ÞD0,Ö£Å+ª
+XLڻ̶+Ö&Ó§[êFù\¶iº|A¸å®G·=ò]ßûþ_w¢KâÂÞùR AÅX%K§ÉFÓÇõ81êµ»#¿ºRGF+Ýê½ ´3+ähøæWTÄuvÒÙÑ;®w¹ªÊ£F32ÇÜçÞÒÑë1ºtYßDÍçn|©'¾cM§ßY(äF/Z±9@
µ3'ßÐÖ?¡g @6©¼ãGý_¹\í¸ëÎw»÷GvÚu·W='¯ú϶håÖ³»®;£x-/ÊÐy±jL bl.²ù¶¼éìÈÛ¼i/fl>kìªÕÕÌÃË4(2bqg~ôwÛa³=t×>ñÿýü>»Ï»ú¨w¾`ÉòÕ3ÃöÎ|íc>³hÉã³Oýð¹|ð3ç}d´Ò¹héªiaæ÷xûöþÉ~»nõýw÷×îõªßøÏ{Þ008Ò;88, Ým¬Ôkéü;èà}.Û÷5;]µÓn;ýñÍï~Û§|à¹ÜyßΪéýÞîÇtþ;ò¸C~:4\î¸âò^÷ÆcüÍ[Þyôw8h·ß~óîÍfÊ?ÿùeT¸;åÝGä±Çm±zõÀoýýÃ0h#~Ûíæ^sËÍ÷î÷ඹòN*rÃûì»ãÚ¶kÑâ¥D25ν¡üEýt¹öï8õoJcKË&gf9eè¥îÓ¿gÐ0ÉõÒØóÙÊ
ìu^??ÀäQËlÝTÿ>"?¼z]>ÖOÏç,ÓnJ¸ÿ}Iç0ãÞ
B× gx3¡í> ËÔóîúØ ó²ÊmÀ·ùæS¼ûhºuлdlvNn¾lq²ÉùÍ
+q&á÷z~ÙÎ¥w§ïøën;umGǺÿpÛÉl9>ÃQOÒìð¿;ȬUJSFö8þ¨´Î ç%\æ¯ú¶cñ`GÛøÕíê,ïZjtl
/ÿr-3]Üsɳ÷Ó!"U CjΣëü¬{íÙÎÿSe^gþ¤ªßXûo7F|>n>£ø·þÑx³l>²ah}6´&²ªªÇ^]¸áDJµl5¶hSlDa:\¦áÞ ±½éûvwÞÛ¾ùÖ÷yÍëqdB«6J¬ê0wÖ$®ÇWÍh+dÆwû[PÞ«x¾«y7.+Ë.ßXD|Gï¸ÇL\éÀ9Pyé׳àÛîÛæð£øEâÉßqÇ-J¥JÇìÙ3n¸õ{÷½âòëO.óCÃ#¥ýð¢3OÿàI§ì²ë«þØÑÑÖ÷«_^ñ!U5{ïóêß=Íú1йÎø¿ãúüËíeªú¯õÝcÐ{¤½ö?²¬²}©áge3"Æ«ãxçñÄ!xpÁÁÑ(Ãó;ÖU0bÒÉÏGUU
+µùÿÆÀw?´ãξècùáývßò¶y×Ï~sÝA "F2éz¸½+ç3F*UÕ0bçÕÖëqÖç£aLd¤½ q3bî|±ÒQ0&m³°Rèì( L9íDÃ2±28Tj¯ÕêÙ|!_2Æze³þ °q¹T]ôwù²Uc+¤Z¢(¬xàn?»õ{÷ýÇü;\½zpÊn»osYggÛS´6"²5#ýÎýð¿ÚZ¤ªÿöû¥ÅóÃ0ÉY6ûgÕP
+z.
+Øý¢v.ºwCôéyi?
+ØfÕS¯ÏºZhIçÜî| KîåØ£c®92ᶣ
+Ýw¦
+oq¿#³Æ#'`ûF¯Ráóov,ÞòéwÇÃä=ï,Sþ^äëèâ±±Í
+Çâ=h ϧËihyIÀÖBR&Ç©G6øãÞJß4ÖAÈi7«ß2Ä;í.8`Û3;ÿ·±2í\sÁ(®v,Ú=`Þo<+çl» _ÿ¸Ìé»xÌó,¿3ýûûtpõ¿F8ð ·¸¾©>ÐÍà)÷ IDATò¯
+²Å£Å{
+¹¾tøÚ×0ù[).ÏY+!<¦ÆY;·áóEUsMÑeìËÿlǪìkÑÓAƳگuÎß°teuÅýµÃ(2ímÆ¡\`¬iïÌx#ÅMÅA+`Ц6]1Å»¤ùRHbÌ®;Ìþçßæß¿Û§|ïûãzôMh$I4m
+w?»ðú~óùG×êq¶XÈñ¾#Îèíé¨
+yX±ªJìf/ç?þþÊc¯ºâ¯{¯F½òÆýÚ̦/xè{wPï©Ö¡5ê¼q'½åÐÿâç8ñÐßùWcmR¯Õs¯{ý?zã1|Ã9\pþ?ÉDþø3;\ýsÞ/úl±zÇ)Gý_[{aðÞðùoý˯O:áá§ßÙçù=Óñ}ÞüóèÅè ógDÐ|.3³xݪÁúâýy±7]&l¡º ÈX4eq.0oX¬1ñÍùiÒ´#XÒÎø×ívvÞÛãÙñÃÜéâ;XºY©\-F¡¡Í4÷F®¸æ×¾õè=è.ÞußÂݧMê~xò¸UQFixE14¿Ü{çíúú»ÕÅáü¿Ýxh¾P8}úÝ£«g Ö:©×czz{Wl9o³;¯¿ö_{m´ÉÌ{gÌùË×½µTªtì±çv¿x|eÿô+.¿þä¹[ÌúG©TéüÂç~øãO|ê
+
ÜÈ®»osÙ´i¼òÞ,"zÈaû~ïiöCÀ,,ðó"¿u¿Øm?ű²ÅK~üvC÷cç-vñÈÏÖw½]=vÜη¯}¯_= |îÉ×~{?ð¤~YÞ3å=OÒê¤uÏ¿¸nýíÞ~%ðmàºZ´ß\Zàç¯[n!§]Üs)péúî[f&Üq90æ¹ó÷±{!»Ô;ùǵÀµë{¶éX²^ç.îý=ðûu¯w³ôì±ã<ZçSg¯[æù¢c{6ÿãXkS
+wQ-^²º±]©D1|X+Jú2WüVsf.<±kU.k½
+q=Å¡Wo»ém¹\éé.ï¼Ãìn6kòCa{í:çÆ|>Sùý·ÐÝ)¿ýØ=~qñïܯËTQÃ_·Ã%+8õ/ÞfîôªU¥³=óøVsfÜÔÓÕ¾<ñ*ÙÈ*Àö»¼ú*Aµ422îõG¼îç§m|§ªl±}p»¶¾qúÆ3î÷ªÆ«N<ùðm¿ÃV7_yù
+Ûo?ç×°Ëù <²t«\.SzÏûûS§Nxx¿ýwúÕ.Üvåʾ££å®¶¶Âà{mñ·Ïþå×wÙeëË ×7ªºAcþ·&<.÷ÀîÌ#KWV·XÒ_ßÞ{Âb!Ò(²ÏYÖz#¨¦q*¢`ð©MáÔÅO,VÔ!;n»ÉWßxï^?ùÝßßø§¿Ý³÷Â%}Scç8qOm wÜ·hÞμà{ówÞ|éãÇ¿·³£±@ß@ѺL®V\5õÇþ¿_x¯&nÄÑÑ'÷ Æ-X½j&ª"& $êTÜ~¯ÙõOßúÚO>|Æ¿úÍ(F<eü#{ì¹ýïsÁW¿òÓïf2Qå:å §òÙqþ?òSú¿b1?|Èaû|ol±²ÝvsÖk_¥ª/(\ÿK´Òѵøeò¸ì}ÝíáÒÊn.D¡EðµN>n¿ßFÎ*DÏüè§>xÄ·¼ s7òà'N?ê«a at C±Vt§ígÝ:ooU¯:©Ý°ÕV³ç%ÕÎ;ýSNÜï<1¨IOm+¼zë7O4ÆÞ 8aÉ>ì÷Q'½=yíl`Ä2}ãÞ}ú;?n@£ÐâÄ©ÆNeó-6½k³9Üå½óÙÈÞlM®iöì·þï?ll¦LðÈç¾pÚácç¿þÕNðǶëíí\~Èaû<Ö¥ÅÄØb¥³#Yµ²¿>g¤Ré|&É.°`DP^»Ï¶++
¶BÔ0!ÁÌi=Ë?r
¨XD
+ú¦#vÿí©½EöÞmιÑ;ï]¶ô]oðØc+Gzó¨ê
+© ¼ç¯=·^odkõFvÆÔqwØfúCq«Wû÷ÞöüSÆß_k8ò@vÜ}ç?wtv¬D]0}ÆÁÙ[ïp¹*Ò;nüC<è'¦LY'J.o(^sàîÏ9yñ·Ü·µsI8eRï?öÚkû úû&ÍÝbÖ?9tïïO:áá©S'<ü·öéL6ª4qÖ9oçÌÙèfñ½n÷<Ýb¥EÏ0ØâlÆl4)wcÇH²âÅ¥]Éæ;»²¾¦éÌ ñ!Ð4BâÑÔÃ(à(ÔÐó`fL¿p×WÏßÕQDÐæ»7Uã(äód#Q!C
+íí;ì¼íß{z»y@Uê:T,VÄÇNÈåÑj%\Æzçð vÙãscõª©Õj½pÖçßwÄ<û-^:Áb°r´L~xE}¯Z
+!ª"ÍÅ°÷¶2ébéÓzúN:z÷KêÞaàßtÄF!u#ºÝ¼î7w£;*U¯ÓºÛ4ÐÄ¡cI¶z»»ì0{~V;ͽ]z{Ƹ׼óÅD¾\®4+6°µ}_À®Ë´)ºbuËIn|øëɪ>ļGÊæsgÝ3}ã÷dBÕ|üÓ4+ã'ô,9ù->)lÈÉo=ì3cǧ¾ë¬ëx`ávªjkÆÆlѢţ%¶hÚÝ<üªMÛ]^Ýi ¿:·++jMÓÌ ¯¨I¼ªÇZjhPcH¼$
+Ñzëh6B*ô¥zà~¯úó!¯yÕTï0DñéÛ¼³#j@µ^
+¦M[ðO½÷
+ÓHj#Oê±±KÄ9Á;K<aÆR¯{xA$ñË<÷$îï=í¸õfh±Aж|°lIrí=îߨù)¾@*Üa¼¦>GHºhqJd-z´ië*¤A4ϱ¡áS£Âx6©{ÙØbE1ESçÄC!¬z¬d3Í·µ
+ì°ó¶8yÒc^UÂ0ÔÒhhÅ+&ñÆç mÄJ.cñ^U½¢¨>k6ß|ã[ÚÛ³6vW[{aðÅö-þ·àë\{nÀ^-ÒW8 ×eØûݪÚzÿ$N³w?<ºÿpi[Ínó5'ACCbmªÉÔ[Ô«â½Ç^1F¨*8+©¥£.F{Û`¸Z:¨T¢ô®NÅQMÊÃG½
+,º³Ú?Ta¨T×Ðf´§Ó Vû+¡7ViË:y|Öä"Ô©h&T,B¸L+hô+UìÊÆKV7vÙlfrèZ¼*Þ¼|*¾áÔã%µopÍk
+BTBhÑb¤¢Eé5çÀÔy$P^ ´\òZ®ªÔñqÜ`\W KR&£F½d³ê+u#a`¼§³-ЮμÊuÉf8/
¬ñªõî¶ÌMxx[<DdÈ
+eÞ?µÆùïò«d¬:ÿqÄo³äÙki±6crÃSâ¾dÖL9mC÷ãè#º.
+,
+ýd¯¨ðÉ ÿn]17eÙ÷Õÿ±ÎµxZ+µ-fÿÚcéÒÇci«*µàED1&5º7BâSí ^ ¼GCMM!"'ÝTHØÔË«G¼"I"Z*¥RBµÄ1Î)I¢UAÕA½s HcÄàTÀX+$N6^hW"¸I=ÑÝ¡øe·/(Bà1"¤ÓbF"QEE0*b0bÀ{ðXqLÓF!5@Á»¦&Ð¥¦4/âr9CgaddDâÄá©çUº§ËgQTåmÀ9!² ƪ%Õ¦¶ÎµÛZ<;#¾e³¯SW4:ÿ(çÏzVóçÝ6t_ɼ"·8IqC÷ãqã¸Ûa«oì>òïÖÔàÒ¾
+<%]Nÿ<Q`ªÛnÖ~Ùì{ÿ"·ÉåhxD ¼*N,â=Æ;TæZÓ<OÃ[k IâC õzªR´cG`M($U+û2þÕUêl&Z¢x1âe¤\¥4«ÅµPb<!Þ'XcT¼Ç1"/y Ó/ºÍfíXÙ_ßü¶£{l»yQ*âk, øÀSº5r3B¢JØ\+,®Ü ç °hâYÇ{ÄZT=xÎÖzÕ+TË5-j¸F¢¡(Å| #F:«ETHÄTÕË$.í4}`2¡Uò ¼Æ²Å++ÏÍló¶NnûóÚ÷J¼kÔ^òÌË
ç¬saqIì§ã¦½Ûñ@ PæSùö!vؿã>k?Wæcðñ~z>7ÂÁóÆ®±ËCì¸Ï 3ßÖO÷ÙýIÒý0{îÒOÏúé8gÙÇ>qGeßÜO÷Øyϱ«%Þ;m KËorB¯õÝdÓãG8h&~dqåMk²(UbýÒ¾¿ê AfXæýSxvîýt}}MßÔàüØõrZ?ß`ÜgJ¼÷)q=˶t,
+ÓãvMNHëÚâ°±5¾×9ÀÓÙgÇ~º¿<È&'Ô¹°ùOß®gq`ÒÇÇÕâ0u\ö¡Õ«FX56¿)&5¦¼1`,"1é;NÔ+FÚBÀ{¦öX¢Ö®Q¿Fó
+`ü¬ãÛè×µ&kSH÷üÔH¤ê=hÏY*7¨7P¥ÞHLSOC¨¡T_Êqkñâ3±'³`Z¯¹û%5ò!1` `פ"¦Í«¦óÐ+&I<Þyl Íù¨OÌѱ é.þAò9ËP(äÅ«à}ª´ªªÔ1p1±¼W@õ¨*ÞyÍD¦%¶xFA£ÔçA°¸¿_µîý"ß]Tä'¬{½Á¥
Aæ9À¸O0îÓÌ=bLfyrMNáàyu.hKßõ½g
+²ÙÑC¼zßAf§TbתA6}Óº²NÂ-Ñ [2ÀÿkÖsLÌ_rkÙ÷Õ1×e÷ôý>óíÿþ(½0·0XâóÊF¹)»±Ó÷ó,9ÝñÐAó.vÜwü >På[ÝU¾rdûæ^sõGÙâp Ï¢mný2øÀ2ë/1ÿøÊ('n0ÄöûÇÜôuCçý!{ý ÂúX?<G(qÁ²énùÜn^¤×0ù=¨ÔÛ*ñã'YñÚWAè~X软Îo~£Af~ܱàØ/r,Þ˱ð£ ÷M`âG<°l~)$û=¤a£«glw¾akmëgõ1Å´9_õ¬Ú5`«¡éÃìùÓtü=+NM¸íM[\æYµsSß~HÿL)`ûË^ý§çûµø÷èéo³yÇõ<2DµæµÑXD 2LhÀ Æ
þMÿÏÛ2³Q#H=F1G!}Ñúæ (%6Ëúh°NSë睊6b1ÆPêÕØ0Câhî]Q&ï¡Tµ³µò¶þ²ñÔÂÍåruáºThÒ~V@¬ÁT0c4Jt:Ç+ª""ºt±b«¦\÷¤ÅÊ '´ÑÕÓAÚ$>5UÒÆÓ_AºXñ¶H©8*Õt±'Nf¬&¤Þpÿ±üª-þ;º<H
+ܤçô<û0Âë·áÈ«¾êÙÍ3xãþo±õ¥>3~¬\Ìߺ|>á¦#K¼í7WFvõ¬zµgÅf¾4Â;=µþwq<üEÏÊMÆ®òæMØõrǽçx÷S÷v<øa^wEwÎ+çYfÓ6o=n~ê¸çá=¾]^àPýÛ</apC·Rê[vpõ:]w~D:rL>ÛÆÏÎèàºùYÞ}gàõ U¾zP¸9ϧá-wìpgÑ!cõ
+¹»ºYü½Nnþ«¡óÊë÷pÜ÷NÃóºxäçí\zw÷^üÄ3ûºYòNþy¡ç²[÷4àu¿ÿ8c÷LXÛ^Ï0þ².û'G9~gàuYÞùÉ®ýGW¦}x ð¬zkÄÁÉòÛs|òBÁòÆ9#²³OëâþtpÍ?;]Þ÷tãWá3ã²ú'ßç¬(ñÄ*_îMKhTà¬Oupïù¶2´@ÈÔÛ¹ò¶±ôx-^Æuf¶åí@¥ê4gôBÕPdL@Q/ÒLYþNµ¤ïWÂðgÖJàÓôvÚôÚlÔR9±jÁ»ÔË4·Ø<JÖÏFûç=ÆZAMSÏØO4Õâ¿#$Í,Þ¼dÙT½JSг4Rh
+Î6
AY;¿
+éoc
0æb¥¹RQó¾iç
+Dc V1bH#)=±XIScÙÐÓh$Hà55´UT!q^ª
+×-¡ãrаÌÇÿ<ÀøO³ÿ17eÖW6æ¦L?$ÉpÒ~½Ô_ÓÅûl}ÒSåë\÷Oÿ
öùÝ,ÛKcïNnÿH/|ÂG®[>áî£$Ç)Cªªó«oë8øu½4öîad·Wn\ó¿¸nÊðáYÞÉ¿mÞóòÑö»¸p~áü±-Ì1<Ë&
+Ñí ¾¾ÌhÌåMa+\qH9½÷¥åàÛ«|¹W)OWªs˼çÜ2ï97áæSÁ¬Ñò ŵ¨Üj¨Pâ©sÖ¹cígüj¨N f]ÙìʼѳzS at c®Y³lºV[ÁjÏ 5~Ø®«ÀWAÂGj|w"6¸ìcýi8ây|ª»Ã0é9
í¹qFZçÙ_«KÇ\;½ÙYÞ3`yÕjÅýÛN'-þ3T'tg®!>õþ5ZÒÁYÁ·&Ü©fÅG]º%<¦8\³gAsX ®{V÷¨5b@°Öé{
+QPc@¼fC/ÅêÇ{Åͤ¥÷ÞðoÛª¶xù3¾+óhW[°bÙªX³©0g°ÍÅÓsbD½¤¡0×,V ñ
+®éÄ4¶lh.Vd,Φ5¨Oç«V+R§FcI#´²f±¸DÀbEÉD&>$qc#¨5"ÙEU¥\u¦=õoÁkñ¢È>+t®Ç³ú1½xÝîé§íÇÃì¿ÃÚeK,$S¶ÿÄXú×±,bBáZeäµMÈRÂG»xàscïsËÌ$ÏùáÖÞêsaQ9P(\ãc} Ãìu4¶°ÌþüÒFÈi'ÿ¼FèüRÝuc7{r¶¿ß|L¦KG»!x0ØCõð^â{wëà
§/W%Ü8u:øbÄ¡+Óñ1ÚÔvÎäøpPX,DõP>þw<Q³¬we(î}^^´ ·¿%`˯ôÐÿñ6Î?\÷³=æû
+}P5~ÒÍÒ{ïZ ø×µvÿS-æ
Ju;ÇÂçd¸²ób ç÷¯]W3]ÝÓb\©Lñ]%±Ãi3 /<I¹b-ic6ZÍh¤Ä±B¥YFÆ<EÄ'¶âÄ@¹3\NH$L-ýMÚb`2U"+äs!¦éÖÜð:!¦ ¨UÄyQ=Ö1ú¤Þì£Ã
+5©¶Cê Ö
+2¦¬n.VuéxÒ¤5¹ìÒm\ÆÊC*®x|zÃ8/b!ÖZÒÅ
+j[Á &LàiV'MðUBS¡Eg!Ã¥ú?^仯²lþ¡ë ¥´Ì_/dËCÇÊz·T7ÈV¯ýa@?nºvýBñévô1lô;Ðb¼vìZ
3ÍY6Y·ÝóøÜô¨^\·MÁ÷Î^»n!w{ø2 ë÷¼¼oÚ¹èÞ~òw³ÛÙM.q,x«ÐõëCÊ5~ rwÊ×/r,x¡ç y>ò«ïó ã?aûWe¤]ÔÅ£?}¦ö,[/áæ¯
+0Ë&·{Ïîâá§Í/ äq<|ð;7÷½¤þLåhkê/ë\|nÌ´þ}À®D-%ßipé×óä%vÈpÄ%í\þ¯ºb«ï[¶<_)·Y¦/nçw®¯<g>^åÛVøìwêüú|¡sÀñà®ÎyÆ(ú9N(ó¡Ê 3ßnè^¼®'U(5Ò@ɺ±`ÑòÄ»´)VÕ¤>#hÄ$h{'Í+kló½wihUtM`_@%PæPZ£P÷ëiÄU«À(ªÔcð¯(EÔVÐ4¦TkÉè¤|ß¹/ÅpoS1Ý^s®Ñ´sM3Ñ4G7í }¥¹X MºX3S0ÍÝ\cÒÅËP(6
+;SgBDPÛ4FÀhÕy¬ ù\¨Þ{i4bM¦ãT62"@â$Î|6\¾áF®Å+,§e9åBàÂ[>9Â'z}Êqÿgê¥BN¡>ÀñÀg×_UºÖ¾"dW¯doÿy}G=\àY|Á"?ÿËX9¥:-msáG¾ÍJç¯
ëmsCð¼]±Û¹âÄQN:ɱp_Ãä?tpÃ/Çî á£-/p<øíÏîàú¿4·>_[áÇ'ÜyY°ý Ùÿx" X6»ªYNæ_7ÂoO¸åõ wi4?-³ù-PÎ=ñÌÛ=ý
+|ëì
+gæxpË¿V®¶l½À0ãâyÇ3lt©eÞ# ]<òó2₩Áeû
ôÉ:üÂ0³ å_b»íáYµ¡ûCû¶så±£¼ùÇ7Õ×ÜÖ=ù;Íêéñó¶IëZö!v8ıtXª ·
ìZUFaêyO|0[USÖä
Íóáãêün/OßFÏ÷3kñQÈD& Qnÿ6_¸®)iÚVyE
+0
+¬®¤×bð~L ÓüzÄ)Z®ä-*ª¸¤!j½îñ>ÑbD
+Î'êÀ¥û×Q êD¬Çt·gÞpÖâ¥"1%±ÁƵqMe_têU4u&QkÐz
+ènGo
+@3ç±oiÆTÚ"êåQ§jpDÙZï©Å
+êq(0¨º$»Dµ*ªX!
+
+¨z/Õj<0©·ÐZ¬´ø· ؾÑÅý?ê§ýĮ́ðéI©Z´
+ª®¶ Ùå9)xÛê½jBÇÁc*|rg0Rª;z~0oM^l!³J<Û'ÏY+[ëßÝ<oa0d¯Z7¾ÿt÷;¹ézàúu¯gyÏ`÷³îõ®ýÇÏÿróÚçÍ-ÔÛ\æª[\æò;Æ3SÊpÌzµ]Üûû'ßõ±ã'Ï£G]UçücÁåùôhæÜüà/¬C:¸îõnûÄñ÷
vqÏ%4Wcd9y$ËÉ?;8¤ÜÍ!?;ÏsÖÊ<gýz}WÄiÖiºÒT(¨WÄ
+Ʀ2"±¤1ÛrÙ4'±1`õ4´ÇÞéÖqj
6êÉXl Wê5±FãjB[Hx-fÖUkµTÚ4x#6
+ÿ!M¼ïé˶´aG®ÅK÷jÂ04h30cÒøÑ©ÂÅJ(©í_@¢Ù F©£Hs<>uDJ祤V'èÐhØPòQj7ÇuQTY«êrQl¦@=Qêõ$µu/"EãX%°J½á¤»#»hÃ\ÿ<-:¦tÚïW+ó];ùç5/´í.ùëq5~z$9@vûÝÚeûa5u.Ü#ÏY¿}¡m¾ÔüÇ2íUÈ>úªï¥Æ³ºXç·gÔ8û»Jejwø\CZüwÓ?ÜÚQÌH·mÞ
+±§ù¢t×:ðµ:ä³øöÑ Ýº¤/Ù0ÀYFãcÄ;$ñHA!żh'ª ¾úå
+ïIDATêsBÖh[.b¸æµ\IÔQ¯¤i$ı3I⥷3sÿ·/
+ë*À¥Z<µàÅiÔ{> µ{m8´3ÄÂ
+IÅ$ jêÕ,µC¡ioh&¯ªÆZë5r9+½]f¬j#a´\Ç©¤SD8@÷¦·+-ý:Ì®»¯}Áùaö;ÉBæÇ
+|þ°«n;k7o²ö3 ·DClsàói;UR
=åY}$DÚ¹äI=ÚøÍ¥>ìxèã#²ÕÚ÷!¶=à¹úlþckãW /ëqÏDÓÎï-º-^^¨bF+n£Éy_®¨ Û$óò3%mÐD¡£ã0\o¾h5yE=jS'mnÑzªz
0ZCÛòµFBM#ª8UCzAÉ¡#¸ÄI±$¾lìPZ¼øVJ¨)£Í½(ðµd,D$©PPÒ]eµ5¶¡.,T(NE+åç!¡-jÒhàO]CV$°õê1Íe#¢P4qÎùê"Zü Tv¹iß>ì¨>
+(õA0ýǼo¬lãGküèÔΩóó«üæVB<^©oN:ù®|>íÆÿγìCéñô3×½0/xý{üñ»
+.ûc?¹; ZqRß|Ò7f¾ÀxqxÙJ©-Z¼(Wî()ÖcÈDââ"îþÒô"ÔiDë)¡Ýt¨&XK,csÍôu¦ãCSïÏÔYÒû ż§¤YÕ(dh`ѱhà
+NTSrù@ÃÒ+"qìNèÎ>%ÿN¼'ùYÓ¦ä}¹Ø"Z0nاë¼.NmË ÃµÔ¡$Hm½1¸±XêR/b1M§ÀEU5D¨Zïh+xQ-ÇASÐïq ¡µF+ı3 ÙP+äÁ
+8l-^ùѶ5¾±§gÅvJ}2øÐõkC÷½Eν(dÿ'eZêàÚÔùõÞe>z2¼9Ä ZbwUÄAk0¶6Lúeöügj?Ë[~Sã¼ Çû.^_v.¾'æ¦ýJp´gp.4¦@´ÒÐ}cÈ^Ðbâ¾ar×ÿ-a°Eg PÌf)×¼/äÄböXf°£ª
+ÄbâÞ"ªé6Ø`MîbL3°´j·
+À{4HsÀJÃ+õX40ÐpVFÄX¢@ÕyQkUSCh&c±Æ"Z]2Q82y|¾%þQ©%Q&Ê' d"tÌ¡)õÿX£¹ö4ö0ZN+±G]ªR L¦®¡xn57M7Ù¡&]°T@ÌFJÆzFÊ¡jÒÿøªcQ«1d2ÔI¨Ö,í(f<Ûßբź4íêÿ üáY7iú÷ÌeÍpü×®<g>çÌg-²K½G~þLe\7˵®0Ø¢Å3 øJ"£éÖÓÅfAk^\¹täð±B%FÖâ
+$~Ìò´©Y;X¡µ¨÷P©zÔ=µzBî4FKtwD8ç´ÚHPD(AF¿RMòÙ :¹7÷²Ye¶xiÅ\ÖJßêäqâPOB´9?´ì°ÎkKíëD mHb QRç#iªRÍ7háÅÑ8Aã8¬Þ7ã\ÆøZì0VTðV+Ú "^ÊÕb>ni[´xyÒ[´x¢@Fë>CÓÒôÔÔr¯ÔÑÎ\êa\©cJÓPKS/TÕTm£¥ªR*ÕID¼7<Î9UM(òT@¼òö'ÎDÖjj±¢mÅ(iG{TÜ¿Ãi9<ýï!F ÑH3³Æ@Pi1ƸJÛÛ/'PÐb£º6
?h¦Nl&LôªV°¤ñ±ÔÒüÂÕj]cÐÛÑh4h4Þ Ôªj`ÆBJ5ÚQm\Wö
+7L-Z´x&ZÂ`Ï@62C£U×74R뢬붢¡¨U¨ÅÐ#øjÐ$Í`ÚüWM3èîð¨§ZS©Õm4¼S¼w$Þ©ób>¢\«K=nhG!0IÜð£Õä2YÅ{+|ÖJ¹¢Æåu·gy®±´Zü
2Z×4¶ ªª¦1¢ !h¬hÝE|¢ØZ!°BÕ»f\AêCß\¬x´^JåzCÔA¡êSïÚÚò+uÆm¾`Çd
+B«Qh¶bÆTÊ5ÍçÃÚÄÜÖÈKµÕ¢Eg¦%¶hñX#I[VîʺçòUé(æ½FJ±hµt¶Sm@¤¡gâ$N±C¬Ái _)yê
+§sÚh¨xà], ù¬Á%^jõªõ¡«
+ÉFU1íÅU«GÐ[X=¡;÷СBÖöUênùh©2qLá<¦`©WSªÁ¸|êE\©c¬ ¥Ajeà!Oilú3ZV©7MÇ;Ñ$ÅùD=J[[¤#åÄqC#«Ä
+Sª6M¨¹%v÷*½=³jõ°Nì-.ÔÛ£-Z¼Ü yÝa<Môí¯(äÙ´x¾rvY{!X:R®MyàÌUÔÑ2¶Ró®·Ý0<êd¤d4SÏáBkÎcêIjÍ#µ:'¶\©«s8Õ¹Å+-d3J^T0" Á'Psµ*0®HGuÖôÎ
pÅ|ÄL 2±7P öUjÂj*qø<pÎa\âÓÅ1¸m.VF=ÕºWçÑFÃsx× DòY&bã¤æ/¹l¨åj(0*ÖJ=VÂÀtwE<¾j ½
Õ-A°EWð¥'¼EgbÆÌ¿âØíÓ?ìÚï124Xdr¾>8h¹ØárÀd2APÈQc TQcÊÕXFS tAU
+Å4ÎÔFFlƨ±Vp ^8«ÅHÅkį·ioËQ¤Å
+9»ló
ënY0¼çýd¸¢ØjU5Uâþaá`#Ä5FÅ£XÍDÆg3ÈpI®Ûr%Qxw$±ª* ÚÙZ#6R)1¢dBÑ®¶Õµ±ªÒÛÔ1:Z·Ù|Ü
+c[Ð-Z´xù¨ê
+Ý-^îX#µYSò×X[Ûe¤Ïç3Çu7RÎ$
+©+L °Jï%[P2¢ÃCF#Á%¯çFÆPÈEÖëë.1Fjç(@Ämíy$ Ê]máýùl0´¡Ç¢ÅËl(ËÇuÃýî½TÉd-Õi¸¬)Uâ¤Ö¬ú¸Q7Æd2ä²ø(0 H#V©ÖºØã5µ
+¦ã|>¡RmØ$®'¹cMêåUlh¶C¼÷¦µ+gN*Üßÿû©ñûNáï
+Ý/eU éÊïÿ·wo»mAÿ].IQÛr¦Ò6-rGÈôú¦Ú´IÜ B²xÚéEìÛ¢ B¬ù`÷f÷ÿAbÇóOµÇøÅÛíøª9Lù¡9¤ï]!)éþxÿÕWUU¥× í»ã¦$¥çYEý h4ÏDÀjUÊõ*ÿíj~É<Û¡kþVLZløâíý!/òº¾KÕr9øc;FåðÞ¡Èä¨*Ö<-¤®{íÇ'¤êÊα*hJqòÌèûr\_ {ĤX/Ãù,»µ²røçûGÌ£ jaÐÿ@îýnxqó{óôÉõJß |´ÀjÄ;ÒFvCï½ú¡C ìX© Ï%jÒëâÝÕ"¼.Ío5ÿNLRÞ¼ëjSÞ6<¶Ò¤¤»6Á«¨JUzY_
+Zï#öMÿPV4¥¤Ä"Æ]?ô¾¬@`>/ðäªøÕÊ1?Æüý»fú:&a"÷Õf?®D at eîÅ9@ÐQûnÔ8M v48GÊdY︽Xf·V³Ð¯WùSïË|ÞDá6õø¼ëc~»9ü¸Ï\Ñ$N±\x%Q¶×iÁLCG UG Á{rY®O×åMQxÌKÿ¾Ì]{Òc> Æ|Bªpcån?¬cÂ,¸iÒ @¤åy¼ç±*\SYÍLrêuÇKD³ºnêþÛ»^¯w úñw
$ÇQÇqÂ0LqR8VïzÇe®ÿîË×eà]UºÙ¥aÌ#caÐcÎÄCY©Ûñ2&-ðqØÞÊ!UQÇ$ÌÊܵË*ÛZY1æñ³0h1ÆsÆøÔ0Æc1§caÐc1æY4Æc9cUæB¯Â IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_struct.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_struct.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mapiproxy_struct.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,149 @@
+PNG
+
+
+IHDR = a =B¤ sBIT|d pHYs
+×
+×B(x tEXtSoftware www.inkscape.orgî< IDATxígTUÒßÈ09*E0
+FT &T]sÎw]]×5§5£~ºæ,Ä,( DA¤ Ar\ß:íô4=3Ý·{pÞçé§ûö=¡ºgîí:u*ªâñx<mÔPÕÿV££NÀ»ªzUuÉáñGZuàñöØÿäJU]YÝòx<ÛÍ0¥§N5ËÑØÉR¯åðxÊ$¥ºðxÂü\[Ýx<5I"GûZ´É)ç|3£qjÇ"ÇSSðJÇãñÔ@Dd? «\ùCDÑ%SDÖDä}É
+¯Àz`½¼'"ÃÚ%""æ\ "Fȶ»ü le"rA?ºÇSiøíé)¾+°à¾@0AU7D´MvvV3Uu]Øù`'w83qïü¤ª¸6Ý9ÀUý=ë»c¦s ?ªj©½kºDU×õk¤«UõÏX¿§ÑûXì Ü/"KTõµö7¸ö í+D$)E¯=î"ÒEU7ÍMÀKî¹;v?-"Tõs§H}IÉõ¾x(Jú7àñ$UõôlÄnÏ?»×
+ÌZµëq^1%é²°6§
»[)*p;1ÆÛ@ý°1V¸÷ïrÇ)íCÙÀ ³Ü{ÏÓ(tïRÝß³øGék» 9îÿúÍ°vë(QvZ ©À\÷Þ{®M¿°ë§{¯!çÞ»64{®-pº Ë\'ܹsÂÆäÞ;8ì½Wªû»óÿ(ëá··< ùÀ+îxWà ©|ÝüV ?aÖ!"rdñ~>ÆÌìÿ2Ë
¢ôx²}VOÂ|}§TU'\»A"í^Ànü+bù<H+ùØ,ÀüÝ:ÎEiÿ¥ª.UÕ"ìúhà»
µ{UD3±ëìúè$"ßaVùØb§YÄÜs1ð{=³ y<5¯ôxÀ¶ öQÕsÝ{»¹çã)1c£ª7cæî\÷ÞeQÆ{è ªýUõ£°6ã1«Ò(à
+÷ÞYe9Cªj1p)Ëͯ»sÄ|[éæ §»sÝókª_Ág÷xj*ϽåØ"ä$`º;¥ýü°×
ç
+Â^-d>ts<Ltç^ö½~£d±Úý^«S±íd§Fã}z< #Ã^¯qÏ!E¤cع ª'"0vøùo:+LÐÊ°¶Z
+G0ÿéDÙ øÕm8µlUÝ("ÿ®.O\ /Déçñl+üÕ>SÕÇÝõíz
Éa¯§¨êÐôþt~?mÝÛCUuìì1ÖOa¯/A at 6O
+Ç[z< «Ã^G[öºMØëvQÎøµ1¾Îòø£¹®Ã-@Ìù(ítrïÜ
ý_OVÕ)g"d
+ýÛrm;ŪÞuOÈùFD _eõ-×æ7çÌ/)Y¤Ü-*ÇSxK§"¾ÆÌÙiÀ"ræÙÒÿ21F {c
+Ö(l»ê@àXU}«~!þfluÙó*
ªÎ1ÿ$ÿÅ ÇSyÛÒ=s¾sà?óµ ñ-0<ò'lë)Ü*sf9=³è´Å¶Ä^ÀYq1߻ضVv½ãæý@-ròà1Ìz» ¸øæiÍõxjRz³#!"1ôªz·{op0BUû¸÷nîckËà7ÀѪZ "§aÑX -UuiØ<õ1Gdzd%ûÿ¿©j;×nf͹[UoÎÜ@±°É@÷^Z-"rÌ2ÔBÃBê=Çãñ{°ª1aï½)(mQ©ê.ädJòô|OißXX:@©?ªºVDöά=ͱÄg3°è¬`JØ×oó)8BùØõëçÚÿ夬ª£Dd&Óç}¯ðx<'oéñlóH +^衪S«W*ÇãñÔ4¼¥Ç³=0¥ÒÄ+<ÇãWz<ÛC°mº8dz<ÇS
+¿½åñx<gÀçéñx<dzCàÇãñx<;^éñx<dzCàÇãñx<;^éñx<dzCàCÖ=gGD±Ìåe=ò±LëáßU5?ÚÏöY÷$É êó(~Ãn´¿
jfy<øT 'p¬{ìU>_õ
+½®´Ú=ï,æ#wTõW<í¯ôx!"iX
åc¾ÀnÀzì»Ö=Â_aU;`7Ü-8È=F«jq~gADZ`ÏĪæãUµ(ÀiÀ.ØuÙ«è¾+üª.LðO
+Á+=(¹éC7ÝïãQXD¤)¶Òìà}¡Ø
+wúNÙ¸8Ë:þð¹ª.¹RÃÓ±Ãs·0hY²çóxª¯ôxÊEDÒË0SøØM÷Uý3Ésµb7ÜFÀ»ÀÛªú}2çñx¶D¤-p¶ ¸¢ªyU8:pv=öîõ[Óm¯ôx¢âV|§ÿÁ¶ îÆVÕötróÄ¢oVÕaU1·ÇS¸m¬[ÓDZ"ºÕªhHkà>Ì
+tð·Äz¶E¼ÒãÙ
+éÜ
+lnQÕoªY#G?ëTuzuÊãñTÎ9ùvàràà>U]]½RFDzbkTõ»jÉã¯ôxþÂÝÐr[keÅý \üø¸MUWT«POF/[.p±ª.©fÊDD8¸Ü¤ª«W*'6|rB "r5ð>¶o¿gMRx TµHUÁrlfÈ.TÞãÙf®ÀDà{àø¬ð ¨ñ*v-Î&ºÇSãñÉöNRÕÕ+QlHGà¿@ìâjÉã ®RÕwª[ È1ÀËÀµªúfuËãñ·ôìÀ¸ô1XÒ²·
@Uç¨êqÀkÀxÙ»ºeòxbEÿ Gm«
+ª~Ü-"·W·<Oyx¥gEDzaæô¡ªzªn®n ª W ÈñÕ-Ç#/bywöSÕª[DQÕÀÀÑ"ò³ {<5¯ôì8úûÀùªú`uË(ª:KøÜPÝòx<å!"· { }UueuË,\ޮñß"Ò¸Eòx¶Âûôì`H`8p¤ªþ\Ýò$i}¶ÉÀªZXÍ"y<¥pGjºÃr"ÈÀqضù6iEölx¥gBDZã±ØϪ[Ê@D²×Ýáɾ§¦ "ûG«êÕ-Oe#"/ µTuPuËâñðJÏSÆ/ªêãÕ-Oeâ(À2HßZÝòx<.h`<p¥ª~TótÆBÉ[b¡ç<`QÄã§ÊÌôìüzÆ`u»®¬y<xðJÏ+)ñ>°TU/«ä¹êb7ÚðnðV½y1°DU*Y&Ø6×õªú^eÎåñda×Uõ¿0~7à÷Ȧb×Û°G&Ðhåwº£*ÿÈY¿ÎVÕÉßã¯ôì ÈýÀ>À±Éösq
+ÕÁÀ ¬*s6v]öHÅn´¡n3ìÆüðªÎN¦La²í|ôÞÞü<Û"r+°ªÄ13«4à=÷kM,i ôNÀ$Þ©ª£%§ç`à ç¶Ã³}âí9x ØKU×&qÜ®ÀÀÀrì;Ô
®VÔ7×=8ØY¢RÕeÉÑÍu6ð/ ª®IæØOEHsàg,4ý·$yV.æGànU1kc¿ OæBAD®À4ïØì©V¼Ò³ã¬0ûUõí$Ù¸SV ÞUÕ¹ ¹VQý\¬ÆCªº!AQÃÇè
{ÇfO!"Ï«UupÆj]M±b£3ÊéÀ¥X%õÏ°|I2sÍ[TõdçñÁçéÙ¾9»É$¬ðHÜÌĪ¯wVÕ{Ux Tõ÷£°æ4[D®p7àdpuúßIÏã©çkÓ¸+ c|¥dا2 U-PÕ'À2`;\¶IÏãoéÙNqÑZ³ª:1Á±r¡|
ªÎIåÍ·;¿ V,áºZ"ÒÛfØÓWöT"2Ûò}&ÁqNÎRÕ¯"\ìsmÿSUOÂxvSÕsËã ·ôl¿ÜN³¶ÂSÙ
+ªÎTÕ~óãÄd¬4Uu)ðp[¢cy<!"ÇaûÏ%8Î¥ÿÎUð ¸|^×È.D"<ôq¡õOã-=Û!NQùØ;«³¸|<¡ª%K¾8eUp¾MUÿ/Á±³±l¸¿&C>'"2xRU?H`ÞX¢ÍTuaÒ&K¶Y¤ª'8Ö5CóiIÎã¯ôlÈ#/Ï- Ñs¾MU_¯¨}e""WUõîǺ
+訪KpO"Òó}k¡ªùÇh
USòÛ¸¯P¾¡ÀÉ]¸ý\àø!3µ§f""uE$5ôËÝz""õÂk¹D[¡ãrúJDßLwÑëJ£ôvÑ7[D2¢õ2VºÔ ;®Ñ·¾H}Ó¢ôÍ;®WNßT·:
+gH°ã2¿÷Dpò
+¼À©À[À[Õð ¸-µÞÀÅ"èêð̼¾{âUû
+ÿI{ñ?OÛyÂÛ¦VQÛðëH¢´MIRÛ´rÚ¦Ó6-¼m2 Â¥px´¦(< .Ô¼?pÀ8ys÷ÉÍãúÁ9ºÏÌÆ¢{
+°lå!gûÕXrÝ&îøwlÛºV¾EÀ| ½;^eBoæÚQú¿Üñ:`ÐÜ/ÁæDéy¼ XåÄHÈBúØ\ %îMá}7«°z`éh2>6håÞìëÚïâW¸v
+Ýñ,P)ò{/>^¬:îw ìQUÝ7H7Æ}X$U
+ñù
+è¯\¤ª&\sué'¦B÷=~ }óìõÂTX%°·K9&z@nÝv^*ä tqmGdÀe´ã~ø;º¶_eÂáùªP$ðEFÙm?Í£]Û-c3 k;#
+Ò#ÚÆÙ"0.t?ôSÓ G¡}ÑÖmפÀô48ĵMaç$´=]ÛïÎSÕ-eþ*
+Ü´¾ØöÏ1ªzlr%K"Ò«!ÖGU
+8F:èULù¶k×Ð2Nt%7~Jqõáò%l 7
æ?×öÚ=ÜÿÒçµau:ZgÇ«^i
+×./éóh38ûOhè®ÉWëC|8Æå%ú.fdÃE«Kú<Ôn\Zr<¤ ô^»¹kìÃ:vÍp)<æ§Â'
+áÊrd¡!´ÛæÚñÈ,X syÚ¶ O7ëÃr¢=ÞNY -Ý}êíº]Çm²ãIðC\²ªìym¬=]¶ý³aS*\oÇKR`hc¸úÏÒÿ¥öðRhG¸kvt-øµ6_Îwödè·Ú¸{Â{9vÿö÷Ö-v m§PY úi %yX¬ª÷ìßxóªqÉüÄ¢Izõsp·9ÀªúC2åÛz®ÛQ¢{ªÍS<¹*gÀO@Ë ¥Vey¦PT賺s+°¤|$Dä& ª^LÙ¶çÖVPk[°Ýc· uÂZ£d!¶XÎÄ]ä»~¡gÅrªÖ
+ë³[µ[°
nha[-ü³Ëw£#´Îss
ÅØb¼<Ù7c´ÀÍ]ì\¡Å®{ì!Ùó¼á²o¢ÄX£.%ßY4Ù(1Dw£;.»PÆß{Þªq¤åééLù0à Ü
§Ö8
þ&yx%1rÇó%Çã8@m¹k/k²Âãxû5931aYÙ+_2J~ Áî±u"ÚÔ8ΦDáûñÏ
+;J+
+PúÇ×>#ì8ÒJC´yëP¢4É]+ì8%ÙkS¢4à^W${¥¹k=;Bö(²çPzþ΢É^ÒDûÎ"e/ëï=¤A
+|þmx¶mÁ¬<ótvûôu7*Uòy¨'"Ü0?À²JW2#kUÜÆS9ü.á>xUÄi@ d bÁW·'U¢JÀYw®î0?Ï8Çl«WÌõ× ÇqöºèT©Õ®=ñ<×(`ç¿á
+æ\x[MòãïFàHÇÛ8Æø
+X[ù7ÜE;¾§lêY#ªgiíE8áTàU
+äÏ!Ëá"r·Eä¹MDΤ¸3¨êwÀ,ÓrPaO+³VsгS§8Ú$µê¶'QÒ«+l#±¼:A褨êûÿ
rë-"ÿt7ÚsÝM¸}²¢i\TË\಩óúî~QQm4PUÊûÛNÀª§ÃR3FDñXÀ\à^Ì2:³ùüâ®ÍdXùoÆFî}ÄJ(=O f×ô$¡Äû?^JÜ{B,L60"R¸¸ÌyÀ
±µVÈ`Uý2¹7ßȪº1@ÿaXh¿ÏÒìIm@ÔÅRrÕËÛ~»þå`,V¸ô¬ÆÝ?IK¡ªDd"p¶e/F"Ò^UçÃã²SàHÏ"϶I+`
Ëþµ2ÿ頻¨ê?Tõ6U=[UUÕÖÀÀ"ò
AªÎÄ"eöNH¥@|Ã__ÕÆä,A¬ô G ?
+ +{ñ4êþnyUª:ÏeC>
+¸UDÎ$q Ð?ÎÉ9KQIÜï£'=ÆE)pöêÃN>«!nYe¶ê©êý_¨ê¹åØ\Zþ.õô
+2gᬆ
+÷à°e(Aþúª6º«ê¦*°-Á-{ßéèµÿ+ÎsÞU ôîr©*2è¸2NfXëæe·ñìôÊõ!ë5J'ÍDn¸£öxxNU¥±ªªêìûtM`îc%x!Ä_(ÙräåÞpËP¸÷Õ-É6N"XÖÕ
+L
+°ÓEzÞ@×+æûv B%+=O iø§¼ß
+éð?W§(5®
+Ûÿ°L8Ú^×_ç(9WCþ
+éਢgNÜ°Òë¡Õlè?ÝóRàésíõA¥ÄÅËÃìË!g
+üã^ÞÆßàöD¢
+ÂX^¦µ8tArÆL"7Ü@Ðdûb[ZÅÛWU§ÈÀG"rª.¯°ÓÖc,ù?Dý¿ çè#ËRk~nÂÔ"HÉíÌéz"R
Ñ*=#*l˱ðñ@¨êX¹KJÚ+à0¡-®ÑúÎÂòy<Ìô4x§*§Ñ¦4XÄíýpòT{=êLXíj°¬ÿRí°½áJG_Z1øãDÈkWz®ùÀ´¯àw at njɼ¦Æ¯ôä×ÂæPà+)¶»$ñÆþ]gÿ$¤-COIÎÅÀÏA°Û<ò£ÁoÖ×ce/Eɨê{"Ò³PaØ
+7Ò3JµôLδ XÑ·üt·´ }æ¸VðË^ÐíØ/Ì*0¼+,o
+yumÑn&fõ{ý @àèI0rOXÛºLÙùÝf<
+õ?ɯõ`B7ÈÚÝgÃ×@a1Ú¸ò_vMa×ù³÷CFÃ+a~]³/ljõÁ±¡a¦ÀÛ½LC~Ö`ZÞÒs¡ÅrX¸4[
+Gº-ÒÙõarWåä8·_¥
+ì3 YXÊÙ $béi)ïð?`°ôXâk`HÀ¹gEDfw.'[òèêbMÌkµ
+ ëÊjÄÃĬ48s#hdÊòPqª)=ós`ÍQö^©9ÎW#e#×)ÇÀ¡ÏlÝ®ù«Ðó|(,ºÖõ?Þ3c)/uU ¥ÚÍ(¹aÓi1¬}Úná|Ñ~ïd¡ãt8,,±ßëÛÇë÷=Ø66¾c Y.Ìj ÷t_K-xí`{=pÕýøvÓ
+3¡þ2Øÿgh»¾âÏSüÄù²1Và+-0g tîØ7ÄÀe"²WÀªËñ©Aì,"iÞ|Üf¶NZSNU'Àì×É,¥¿ÃaéY 0GaêÃpK/0ö ÐHÉâ,§0ë)¸Â}'Óî¶qæþÃèoy°âF8i*LÝæÜÙßÃq7À´6ðÓ½º~Øù;»>Kà¡ÓZ4Ös§À=AÓ õ³3L¼Ã>ó¥Ðï:8p1,Û¾ï¡wCîîÐñÈÞdóf,#O·¾K.Fð°ë8èRì²oW«°AÈ$¸r
åÙªª<%GA¶ÂñνADÖcÁQ>'¬aëTÀj£nØúýôðÏ'6ÿÈn0ñQÈø
+ºÎ«Æî£/ÍìO[Ù³áòÇ g´µ>Nì°á ø¡|ÒÏ~ìëDÙG^ë:=lï<ʶ¼"ÉØ =Ãì=ÀÚyg5»^Éÿ
ù×ï7Áè2§µi÷ÂÔ°ûn/À¼`ÞðéËðTXïî±>?_þ|dZÇKVQ}k7í^Ø_
+¼fc.¸
+¦> ÛgJÎ Lk-%Pã¥>V5XQÀ¸ýOafú Ì£¤*l¹bckÍ¡û
+ó-K.@Ëç ¥´Ýw0Üv8Ü×ö½ÉÎ/:wë1Ó×ÀÑç@½¦<ýpUù25fÀaBæ¯PØ>0oé-^î×CÛ%0ù¦ð4y?rÆAaá®»
Z3MaºûaSx|~
+ýfÚ¹üVðÁÞÖ~û]?÷¬Qzð+X´sÀ¾á¼ùÙáO ¤b·J u *7dÛ`ó^Û>ì±kåÈ´-°*>}ÖË¡°>¬:ÑÜ^¶MÒ`nZI%ôèøLݾ>Öé¡ñظév÷6
(k:3n½
+Á°}àkºÁ
+« ¤:ÎM÷¯´-²Ì9ÐýQh¿¦î[ß7Õý!íO8óBØC_
WÀ¸ñp`ØC
+ Ïy0î»(&öã¿u÷ÁÜ¿Cê*8üFk[»Võ
Ôu0ø$¨W £ãüAÝ>_#£½^4Hþ÷W
+ÌÆË îx"l]%ÿ)/ÇÛÑUDêÌ×Rzæè[#²,gd¼Ô §N!»À!í¸à³ .¹¶ì^ÒvÍNðèI°¹»mqXXvû>º½cÛ^¹ïÂè#!¯=¬/çæ².xjÁ¯aI;Ø°[ãáÚìõ´&vûºmuýñ!L9Ð#Bè;¼÷
+lêaV,¯íPù/Ù¼¶¦põ
+°}3'ED2Hã/(= ®ôÜYKªÊ®ªËDi¬ªqmèjlúªdÑVDéJÕÈ UÄ6å+½ay7h2Ã|WgÃ[ç
+xÙ¬øóêÁÇ'æ]ÍòZoViXí`òI¾z
+/å;ûÃ ¿¡×Z
+¿û»-Ï] Í8Xßí§Âñ# ¹³òÍ
+ܦÐj¬¹t,ï;MAÎ?±|{lÙ Ò×B§¯àÄ2¬ëv
¦¶î8ÒoÜ×í AØ5õ}K{bÉ¿¦|Þì%ÐjÌ8êÏ;ÙoýUOCf1<r)g@ÿW ógJ?Èm+aïá¶Í0¬Ìé
+
+æAÎJøõ(h=þV¡OY,CéÙ}.ÌR`×Çìd±»ø)
+FÂòA0çX,7J²¢ÐþIèµÖÅ Int¦ú¶o|É]t3 {IDATÆÄöY9åHÓàÝÿ¸7m`öî¥n¯ÚýóO¦ô¬Ù
+Z~ Ûï¤ü1 jÿ{ÁýÃ!ëh:úÄèoR<z"¦!jUØ"$À"òRÄû±¼N¦HAý¢½Î
+cS¼cÔHQ9mÊ£>ÐCDòÊiÏxa¯O;@d¹0ÛwCËø3¢ûÑ~½RW@»g fºÚM[""
+]HqAXh±£kùáPDI%Áë½n2¶¢ÎsíB?daýµb§ÔÖù
+ ±óÙ;ù}%¬?¾wÛÁ-Zy(p¿ìú@<'z®Ð[Dúèßè#"G9WÜôrIÃ÷CñlÅ"S!ð²,+§Myýµe+¯_+à¦æ-ç\Ç÷àBbgX?HË·×Á)S`iðú
+°òD9¾?ÖÍ^7
gjSxçE(ªg¿éÀ¦}0¥§°|ù¬/αyö;Þ~#ë
+÷Ì? ¿¬?><ë`iXÓVÅ®²çÚ£àv0øQó½}é(h
+3¶EKQCóee|Þ ¾yÚ~ó²¦ÃÆ}á»ãaÍ༯¶þº-oò °<x+4ÿ ù~¶zÊä©õ3lìãúÛç%`Å©°z
+ü^Û,Fé`Ãfå6 NèüÏ
Ðù1x«'üp¿)FY3`Õþ0âxXwý=¶³q×ü
º1D/?Ü(
+úäÆásÐv(Ìèj_èñÂðcJÔ¢Äo`ÁUpóUüåó³îPXöPf
+Ðø=èò4X{.ì8ü*B
+WQSëºr\EãÐsÂöÝ|N6`Erþ0¢'üq lÚæw÷ÚÂÍÅ&Z¯ÏT¿øKK5òúF ð÷ÚF_åι:Î~`þ?º1F
»
+¬.£_´9Ï`ñ±|æðãÏ°ÌÊ~±|×(=ïüeëF
þ0Ï%x¬µ ïþì¶ÓAF>L?Ãõe²ÐZð¹°Ë$XéÌUu#ª§)3»¯6ËM~+øò|X6æjç²]þÙõaÒ¿LÙjü¬8ÿ:_f²Ô-fÃ`Éy°bý@0{w^¢dÛW*xNôÜØ5ø|þ½°ÌåoF9ÜS1+i((a'`UÏgê9Ï(§MYýÀ¢@çÅÙÌ'i ð{9mþ2)]2¼~»®L=VÁwÁÂGLÈ»ÅéçÂ5ο vÙhnágÃ>7B¿)pï[¦}¾ô g<i}f×y-á»ÛL×:ÝR6Ã9çÂÌ60áqX×x>èeíS6¹gØg~îåÒóO¼ÈVÏÂÕ¯ÂÇ]`̳0ç* ÒÓr3´~k
+ÖÚ£`v>Ô?òJÆlý´Yµ>ê
+c9WRê~ZÔÀ$?õðUo·;Ì;
+³ûGs3ãR :Ý
+ç¯Óï®S«
+ÂnwÀ)£`uÅ
oX ·É)£aÅ[Pÿ·M ãÒ@í°UàƽíåCáÏKÞ¯½Üöò3É¢Ço®Öang8/dËi°Ó;ÃæÀOÍáûc¡ÃâØæï¼Æ+52Gæ«ìø#a¿ñpÆ×0ô@sÎÜÜ®âñÀÔGrJ²5µÕê\DV8ãÈoÀ±>7ÈØË'Cô.ØÒê©xê¹U^F¬´"²Øõ´ÄÒw°^UFÏ3ö1þÝÒg$<w¡m=ù¹ùÝ
¦ÃhwNÙ=(ìÔÕ°ê`XâBú3ÀI8÷¼ÆÞe«ÒÑý\¿ùÐ÷Q3a¿}«]/-k_»Ï3ÂMOºÏô!¼ò7[ÖýÚ«ðk(ës4PÕ¸-S"ò5¶Pø:¬Ì{ûbÏøx3È%X ñæ?xß"·ï@à=U
+PQÎصÃÅ ë?!ÃÝmó>~ ëÜà¨{ ËY7C÷÷æ_ò°OD
+ÔÕ6ØQa3XÞ
+ _óÏV¥ûlðsª?Þ¶~6Ô²
+;¯ìê]í|Ö,;=DVÜ]ìyñ%0ø÷ÚÖ\û(×Ùo¢áðé°ü@Ø´?¬éÃ'%'ÏÍ»è2V±°1ü^§ôg¿t¨ÛùÉãFÀcWEë÷GaÍánÇÄé¡àY·Áà0?Ýü]KË9¯ÄJcu|U+>ìB¸ñɲϯp¶/ÂaÅ/=ßBÐ|µkÜ|^Ú¶t3gá©Øþ?1(=§OÅoÚVÝèÿÑ.
+M
+ 0ÆT»º£Ì?í^3Íõ¿]kNÕE¶C7}ÄØYMpÑÀ+"£ªqgVÕ/\ÁAØju)prÂÙùÝBÉL¼Siþoä"ß# µÛîé5]9îï²ÛrXyU³Ý:¸åøx?¨µ#ÝÖmËÿ¦þ÷ÂÂ(Ðmìógé9êFD¦nk./÷±mßÃ'C÷7=øX5vÈïÔoì|Ý64ËM¦BXYº¾¼ýÝvôùÂáÚVZZ1tYe&íÍ{Báq|yX*ÌʼØ}J¡ªëâsV.ÈÅ¥3PfuGCJ[gãaWJ[jâ!|µé=9úþ»V°áÀãoÏ°×inKo}9ÊUj¯S¸[Ⱥtøõ³t¿ø {¶"×·nðdÚ«ì9/Ì/,7¹=u4}ZG¤%hå^ý{ØiV®KÃà®;a}oøsO`í6
¦oBë×úa~?¢åf¨?ÒG¯
+¶í¾z_[d(@ÊSÆZ=Íæl-Û_ßGÜùåÒ`×
+,
+òà åÑ6Z¯1Ðì7h°Î<º÷uáËFXoNx¦N-1÷º¶dA2Î),wß2LÛl;.Ow79¥:;ëR¯ïìF^ßÝȻϹ
+²Â¬7>ÞÙ /rVÁ!ÓK¶ßz^ej»¸1úþÃn
+·Þ3Z¨n¦Û>ëTø¹#lj
+³ìÀË
+aðªØÚÿÅrG0o0óü«ÇXUsNº@Gd°è
ûVâ
+wÐLQ*lw÷ÕöÑ8×ÂÌé[Pâ¨[çÄ(e
+"ç§q.²r?d° ì>§EÉõMö[J¿÷öþðÛ°¹dO>N¬t/V}§*ËPöFªïõvá|*=â,UàÐï/a Ô"Á(в»UÜì/þwæÛmÃþëFûmûì?¢Ã}°pí2¼<Î ; 3{Áêcáþh0Víaq+"?Õ¢)IuMáõÓLáCǼ-f=ºý<T§É7°¸#¬íeÀÙkay'Xß~¿õ³ZÂ×ÿgÖãìùPX6¸ä
+\°QãQðGXÛüêÆì:D3=÷ý,: SX¹£`åÉ°ò¨·Ä|îá½+·<^¨
+£ìY\0{®°G²Ú¶Ù mÂÎ[AV?o8}gJVÕö±ËFØ%Êx=øð¤Óx÷eö$r®®+'¡Jú~´&ª$_Ï[Xfâ@JO¢¸¨³=)íK»<ÇG
+¦mn§dý¤Bv~lís6Bí!3îÙ³rWØÔ
+#^©úù£ª¹"2
+8R¬13xFDvQÕ D8ø6`ë?È~Ý2èD]7>¥gÓ¾aîÇñK!¯£¥{¸ècý3|ú?øe0Le[=CÀÂó,ÏÖª =F°I.ìò¼õûw¨ýdO£:¬ýn©×@ÞÎPo,¤~gAB©N¼äux*³oµ÷R6C£O¢Ùlɲ©»æí4~Îu»8¿CjÃ"Æa·ÿÏðýÛ²J_R:ùè9Cà%ÕÇÁ;ܸë¡ÅÛÑFÞì H~OÒÑYªq[z°=õ¸©ç;Æ®Dd/àMUçîê
ìgÉèê¢^.®ÿ+;Â.A
+Èzfu>Ü÷ªÆ§%98CU5=Íðþz¨êäJÓÜï#TõÙ }û WÕ¸³ªH°TUëTØ8 ñûô$ÊPbÛ´)qܶ¤Âu¢ûÖÄÂçàÐyæg4©¼÷9Oïõw4¶¤]±ÀôÆZÖa£<òR`^}ÈKN«¢Å;f¬¤ÀÏ¡V!´_[6%iðJðáÙøK.·Ò£ªEäEà.,«ªéKÔ2ãVxí¨´UæôLóëöT=+ËöYeJæ̤T¶þL>ªôzWlô סkOp¶X
+¢í.}¢²+<`T£ºAÊ:óݨ;NpOÑÒ»3Y\ñgwÌXI/½ãN)48{hV2õ$B>ð\ >=`JÏ} Üpÿ
+Ìîª:¹¢ÆÉBD²+ñ+ýyD¤>0¡ZÄ[Â<:Vu
+Tu±,zc+j¥¾\
+ýFràvàqUÑ÷p+úïìH¡VÏ_ìûÌëùõ!c-ìô³å´ñ02+@Ⱥ§rÉ .¤1«ê.tû ÔÒroÄü
+ªÂK±ªZ~¹ôâu´¥Ò¬<O~Pzà¯hÈa"rTe_"ræOO¿ðþ9X"ijÐJUzîo+oøC¿(¾ÒI%
ézªOH ½ª¾
+ü
+¼QÒ¢RvÀ?0+SP ïìÛJ5ðVÔjcNÔª?H"õcù¯Væu访Ç3°òôà nÍt!ñ*ñåpsàÏÉQŞÇSsP`A"áÓ'EÉâgcá§%0F
HððU
+´B. at jNÈ0%¯h·G
Õt(Õ§ª9ÀE ¡Ày@àCi$ñþBD:#¨ê´@ð->ÎîñT)æÓã©9_öqÙPW§'0F³ç0yÄ)'IÅ_ÇËIvY!XyÀü¾I ´;C¶'Y4ЪÜààV#GSiT58ø«o·_²îÀ×ÀíªúbãdaÙmìßÈUUïÓã©¥úíG:p~¢Î7w%b^w½"´
+ûV¸å0,)Q`åÌXéqrìÕóxªþ ®Mp"U½¸
+øHDAÇ,y z¸ZU_®¨O\|ÃõÑÄA?OºÌ³2<'æ{gæíW7g: »¬²}1ød93Qÿ9øË t[Í«'P[UË©7U.ðe7üöqµae(ªQÛëD$hy¿PÕOnXÅôé"ò°³Ä´;ÙXEó®ªc¹2ÇlÜü3a!xªéQY¹=5Ö¦ÀtÁêmoJ^¯Ë
iù%Çóò`inÉñÄ|Èݽï\Öw~üWr<%6åFï»)×ÎçYÿÐñÔ|?Zß-0!¬ïÒ\;t<-ß>WèxtXߢ-0.¬ïò\Ö÷ç|XSƼÇ+rá°¾³ól¼Ðñ¸|/Zß5¹ðNí$üuoþ!" %üRã?À@¬ â9]Dâò;Dä%lKë&U½8 [ÿnM ÿÑÀ ÊPÜöqx@^.¾«¼¿²Þ'µírÚnÒ6Da¶¹å´]SÃÚ¾£îÅUXwk+Tu.0sÔOÆxªê
+ão1ðü."ÏÈßDäéáýDdÜ."c°hκ@U¤ªÉȶ}+P4ÐÖ³´öĶÙ*=/¬<ÛÏMDjV½nEîü; 8TÅÛEEä
ÂEé
+µm³¨jAXßüPÊò
+ú¦99cé+@P¡K×7%dMp{ÊèÖ7s
+ï[ú¡ïe¬È¾@QXß,`Kè»Ò7#@±Î
ªúïDÇ
+³ð/`wl
övC]*Vêþ;aQ=±g
+¼QÕõQWÓ&%_ :qV0ÇiÐ0l7¹ÜK/×Mip¹«3ößpÔzØÃ)ám_ÈÜÔ²Û>Я,i[¸úÂÉk¡M1¬ø_ÃqsõEKæ¼`54Tï×\B²g³-IØù[¶óçTø².\¿&zÛðÏÙvHËîzNîÖm'¥ÁØ:pÝÚ¶õ
+à̼èm¿Ëk\ôÐ9Ð$úä©Þ^?x"Ò³l©ªIÿqÝ0klW 1Ð+ºÿ
+mA%Í¿LDÚãÝÖ]ÃW¨ê¡É+ú<ÿÍïÂϵá¼0íøþæ¥#»n}ÖA{÷=
+sÆܵ7/
+>¯W®,{À¡û?3`ûß\byØnS:i
+VB3møíºÐ¸ p×ÐO0).,GögÂÁ`wç¸ÿq¶eRàV6RáýpͲÇx¥>tÈ
îz_æÖ³×Ýç±&pòjhíîGïåX2ÃãÜ=hf:|¬.{ç5.¤Ìé0ÐýN,O7ÃuaI
+jzî;{£´ÊCÜw6)3úß{ð¯ð÷³
+ "±Òó*gìiº/°v³MǨ`Ëí_×T5"q[Í
¸«ªcÑ¥ªý#<XÞÀ@¯íÅa׬¤ª$0Æ·À.MÇS%x¥g;GDÎÁÌÐÝUJ*-¯®Ìj.âÁªzBc<lVÕ¿'O2':"rpÐ3dÝVK1æý^çbµömiòx*Â+=; "ò0fþ>¶Cxtâ= ÁYDêbY÷TÕ Ù=¸ç¦À Ô«VDä0,·V/U]À8/ sUõÞ$æñÄYß19>>XÝ$4ÁBݯH dXÒ·^áñT1W`лª[ 8?7ÓTxcyÀþ/I¢y<1ã gÝ9è綻¶93øûÀ+ª8¡s²¾
+K½ïñT.°a V¢â¾ª(ó,\}õ£ã"འÐO"øíé®UÕ·ª[x籨l
+HàUÝ'iÂy<qà,﫱¨®GFD`9®IÂXÓ±íéÙÉÏãmf¥áIw9¸GDîL°>W ÆXæä³TxRÛ%Ç/ªº»Wã\eDDºß_$ªð8^ð
+§ºðJϪþìe#ZÍkËÅå3z8
+8ZU7&8ä%X»7ÍãIUÍWÕó× "²uËåâºÉ%(Mt¼ÃC;Ëã Wzv at Tupævì\Í"m
ì|ªêÒÇkÜ\¾FÎx¶?Tõ!LÿX¬¸oµ×TùðÐWU&aÌt`pMå}ñxÊÇ+=;(n¥y.fõøÞ¥±¯Û]bÕ¤'¸ùÉÈùó $±Ò²/{<APÕ±ÒµY"r$P,8ugf Þ_pj2¸øMUUc÷x
wdö "½°:ViÀuªúm5ÉÑ+q1¸HU?HÒ¸o»mëá<Û7"²;Z¢¶T%JXñÞ`°ª&ò¹ìåÖÚOUç'k\'^éñ Õ-ÜÕ
+¬ª¿VÑÜYÀuÀõXºþÿ¸-¸d9bþ[UßIÆOe#"GbN¿¼M¶ó¯óçëì
U
=T0Is4ì¶7$cÌãI¯ôxJáJI\Ü
©¾©LÎ.3ò@̺3¸EUç%q|>¨êeÉ×ã©
+ÜÿoOà4à,Úk(ð®ªþpÌVÀq@à`L!y¨Jjéw/ùüº#c{<AñJ'*n«élìfÛË<ø&Z9"Ò»áöÇ¢ÈFw%³ iØ\w½£Tµ Ùã{<U
SÄ ÿoÀ|¬¤Jèy)¶EÕ«ºz4z Ï/Uu}%ÊüPè<5¯ôx*Ä §°ÕÛ¯Ø6tã]R,\öäF¾éî):O°îÊJÌ&"»1gLùÕ³Ýà ÖÀ®@÷½n¬V+#?ß'sûª¯ÎòÑZWz<q!"-±È¶¾é¶ÄÌïÙXÊjJßpg`ÎÊ^õÈ>À§Àª:£2çòx<[ã"0úúvWz<IADRfÀÆÊ4Ç(Ë©À
+ìñx< ÿ%ybÊ IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mpm_cache_case_one.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mpm_cache_case_one.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mpm_cache_case_one.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,84 @@
+PNG
+
+
+IHDR ÷ ü jÅíP sBIT|d pHYs
+×
+×B(x tEXtSoftware www.inkscape.orgî< IDATxíÝw]Eýÿñ×; ¤H(лé"R©*" XùÙá( ¢b¥èW¿MPAPzIB=4 Hÿüþ9Ù³wïÖìîÝ=û~>çqïi³sËÞÏÌ93¬t$p20/oZØ5"&5.Wffý¤Q¥MDÄ^ÊOwÒèØb¬RZ£Q1k¤QÀÚ5w³yÀ¥õîäànf½a/àÿ
y}>°0±a92«0w3ë
+ÖßnTFÌ÷þíNà`{à5àQàÕæÈ̬¹xظ¸£±ÙérºþOÒYÀÄ8«Ñy1«GÒ§?6Ͷ7Ë[ÃIKú
+Ûè¼t×Üͬ7Ü
+¼üx¦¡92«0w3ëqñ"ðIÛ ÏFÄ
ÎY
+jtÌÌ̬{9¸U»YÅ8¸U;ÔUÇI!Ýb4'?ή·óK33ëqîÕ14Äç°¼-=o¶.isR¿ ÐV!¡ÍD{ÇFÄÜn~ýff9¸WÇ«ñ£®(iÍ=¯·o)`ùNW0TÊÆBR! W
+¤9]y¿ÌÌú:w#"ïä¥!$¦@g
+ÃáÀ²8o0TÒP0K7 :²/<L¤u3wër+^ÃäßÙÂE±,ÝcdrËI!HSPöZáÔQÌÖffàànVêç o6*ùEW
+CiºDÒ©Ik²Q¯Ñ
1ÀlIëÔî÷ÎYÁÁݬy¤àúV£ò i¼¼Qçù²mì{/°%°Mí¾ü7ËæÓý
6×}'Iÿ©»"bF£óÓHîfÖBr3óÒm$F[þ´;®.ËZ :u^'î$é±;K|'I×EÄIÓg$= \Sµ^7õkí´4°30Ø*"®ê±v¤÷ /æÉ*º+Ím)ñR'ÎYØ ¸="^鮼
+¹þí¼4D;w´w飵;IÚ<¯wtûÝ#åçýùN¸[ÒþÀ¿_§H
+ü5"ÄlC$Ý ¬< |°½$ î~<
+|èpptplD¼Ö¥§4N ®û[9dOà6 Û;p4ppuG´
+ðà,ÜBbÖ/õñ;I:Ò¯¢Þ$éÑÞ$=Z¸(wõN¸YÒÇ?å׿,ðCà8Io EÄÃ]I¿?|Xø^{KNùN`2ð¼o°0Ø&"®4x0@heG`{I/GÄ=5éo¼ lBºoûIIKÛ®¡Ì´lNãõü¼X?çe3`*ð`F)Ýa¤k|ã#b¾¤QÀñdémroéü÷fFļ9ï-åqàà~à®ÎÔöÍÌÊúð$é´¹LûZK§;I:ZH¸4¸×P`ɼ,#i.p#ð÷nzú!1YÒº<~$°0T;~¸&¯¯\ <Ltpp1©1Búw^îi<§ÞüIÀ_%mE*LÜ $éûù¼IÁzð0©a~>ïRà`R
+ûï>Ü,é;Àk$m%½8ØTX,-ét`çhµÔ.iï|î
+À¾<
+lMjÛ3çß̬ßêwt¤pñnR¡ Ö Òe¡ÀÀ¤K"ªÊ¸j.W%ýødDZYØ("æJÚx
+8="uÊôðË6j³WDÄùØÛ}"âuIßÃ$=\7òpiD×.¥÷%àC1SÒöÀñEIÅeëÃH/ïå^» +~[¾ |."tðùø¤«õ#âä6Î53³êÌ$¹óæ.¤@©ïÂëÀ¤Öç ×*_Ë«Ø¡û¯ßSêéy+©3Ù½îN§:Æ '¦.* Þhï¼2I«Ò/ t;)Ï91ÿݧH-[ÓvpßÔéÒÃmkff=(÷Q88ÔÊðð<MÁ|BmÁJj%twp_ÔÛ>°¾|_ÒgI×ô#õ|Ú^1]ÒÀáuncU'·DÄIëtàûpppmDÌÎ×>¬!é4ïTRÏýÀF¤Î
[¼õ²|ûäÙÀæ¤ò×ãÚº´ZUC$LTbIgçDĽ® .»°¤Oïöþw]&iBDü´d~
+\,é_¤Èq"©Äñ¶~ÑN§KºÔ<³0"NÉë®$}vtMIÒˤkóËösí¤6p^Nàøv73³18&"vûd_!R/ï¥mDÄ+Þ
+¼ÓîÝçõ"b¤¥u#âÁ¼}$ð~Òµ;"âÙRk kDÄí5io<³JÛ&ÕÌo·òö1ÀÆÀøüøxQ:ô.`zDLÏë#roç4fÒØ("nù{»:î=g%mß·ðå׺3pcñ¥4Þ÷TæBÙÄ8«§ÿÙâèÌ 6f½%ÿ^O±ÎKwQ
úXîÖ_8¸[_TÅà>¨ýCÌÌ̬?qp733«w33³éÁ]Ògrg7333ë¤îy¬öö{´#
+-[{Ü*Íù\gzF$
+ÍãÑ×û;Cò}Òk/offfýMÍV&iSÒï3r@ýIù³|HcÏ/
+,!éZÒ`0[ gKEº
m"p;°ðCIïF.éEàÛyÐ_ æ¤ÎÑG{~c`UI_ ¾ôTD|ª§Þ33³ÞÖS>ï´6piHÚ²H×|$§'_Góö¡Àñå¼~°gD¼&é(ÒD1gÇEÄü|ÌïHÜÜAfVD¼OÒî¤ÉnÖç$ýGÒ1©ß33³^ÓÁ}¤SµH3 íXç& çÒú W HÚ4Ý
y<हÏöôiRKÀXÒ|îÅóÅ<ìHõ#Ï=D¡ÏÁÝÌÌ*¡'ûQ¤Qã¾h1k¼<bÝHúp`-ûƼHóýÃå|òõ÷S÷FÄÛ~Mª±¢ô¼X¯Þ¬ff6`õdºYÀ¶~Dºæݤ%íG
+Â/Ó4Oð½À!v®='"Þ Õ¶&i+Iôþ`;I>Ò¯ÉÌ̬ÏëÉûùùñRs{½fï×ý½IcÄ/o?Ôn'I· ¿fÎ;4û¤ùy/Ê×ê?Iêiÿ*ð9jîÆÔpN)ëÖæ73³ïa¥çõîÞ¿©åö¢¡½ÌcËWÇ·þÂcË7^M0íéàY»,IËË óHJËËì:Ûº}¼cË÷dÍÝÌlÀË·7ªfZ/ÎgñãLRëh§Ï¹]|ÜͬRjio×LR?.NÍséfWj¦¦»5S5Ðè|Xÿ!iëËJ:¬c:`¤eÇà,^ÍômZÓ?×ÿ?Ö8¸[QÓÙøp7pAcsdm©L{»vZ/v4ø
+Ö.m{ÑÁók÷;Õáà>@IìNº«`G`Yà·áÀ^#ÜÁ³vGigj¦³iL;|þâSw¨3ëî¤ÑÀGI·'nN
+£Hdþ_i`ö©L{»fºhr¡l!wÍti.ï©u{ÅIZ8 ø,©)t(°TéÀ¿£%-Ccj¦õé\ïºim0íLÍtaGß_3³¾ÈÁ½ò}¬G' +Óö»#÷fÞ[ÚéÌN_®:u#÷
+ù~<OÉïC¤Zû\R3|ùî<RÏà"âÍÚ´Ì̬ÿqp¯¨<õí?òRL»°i¸ß5I÷ß6î´CDLoLÍ̬»ôäÄ1ÖDĸ%"MÓ§õ;%ÒÈ|Ùâsp "â¸>"¾jð_öÉÓçY?åfy "ÞþÕè|ÙâsÍÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜ«c¤å 33k¼!ÎuÛsx\óøðBD,hX.Í̬Ç9¸WDZ¤1ÀÀyÙ8 ?_EÒ\ZýEÕûÙ73³îâà^Añ
+ð
+po½ýFÐ<ø¯| x.iðÔþsúffÖG9¸@ñ60)/-H¬JóÀn4ÿ1Àk´^ûó{øeY+Ü
|M~r^n¯wL¾¶_þ[ ûæç«JOËZ¹ö?³_Ùåàn]ÓéÀýõöK¬Nó¦ÿíiªý ^¢õÚÿ´~ffäàn=""ÞÈK«Ð¼öÿA
++IAëÁÿù×Ã/Ã̬_rp·
À¼«w¤eiü7öÊÏW´xV
+ ñf¿3³>ÉÁÝú¬xxx Þ~ICiÙô¿
+MMÿKSi½ö?ÕMÿfVEîÖoEÄ੼´ IÀÊ4¯ýïHSA`¬¤·hôçÏç¿afÖ¯8¸[eåZùyPïI£hü7öÈÏW϶þgôðË03ë4wÐ"â
+ࡼ´ iI`57ýoISÓÿhàeZ¯ý¿ûõw³6DÄ\à¿yi!×ìW¢yíàSyÛÊfQÿɤá~g÷ðË0³ÆÁÝl1ä¦ÿ©y¹«Þ1¹c_9ø¯ìJSÓÿÒ]ukÿñZ¿3«w³oä¥IKû-7ý¦¦ÿåHs´ÖôÿboÎôÞ¸Òc
+õMîf
+ä³y©KÒ4¯ý¿øDÞ¶¤ÙԿݯ¨ý¿Óù}EÒºÀTIç gDÄݾ->w³~ "¦Ó{êí´ÍÿZÀN4Õþ¤i¦¿zÁÿÕNféTÒß¾,ið㸥éYpp7«<òuýòLk {ÒüW ^¥~í2ðBy¦¿I&
+$´;°¤7IÿOdÖ8îf@ÌEоÞ19Àkÿ[ûçm«JGËàÿ#àÀÒÀ¨¼
+üXÒeÀ/"¢nÃÌz»æ_î«·?ÏôWþk ëª9t©üx8p¤çìþ\Y=îfÖ!¹SÞãyAÒÀuÀ2(ïÛ8ø"ð$mt4³îáànf&éÀ¡À`yý5`©óߤ~ ODÄ;NkLÍ! v"ÝW»$ðOàþ0d¦¤Û"âqþö1¾§Òï4Íz¤ÁÀ/ÆܸtÿcÀÓ½yϽÕWÔÜ?ÜA*}ÿ X¸´Qêõ»z¢¤AÀe¤Ä9¥«é·¡Ëy6ëFgFıεn@D|/"®_oïDI_t¤[%·ÌÛÿ%éØ<©ôIIWIú¤mòö$#é"I»Ò¾PÒç$Ý"éFÒÿI7Jút+ù%éw¾-i¤$m&é·.´{>ôåókø©¤$Ó/iYà3¥t·tv9¯ôáÒ1t¤¡.Èù?KÒæÿHÌú®S3kÛ :Ûnjë$Ikåãö!
+CycÞu0Ø|7o?tìçý)yÈÍK³³%ßXØtíÞyû·súûfæªí¥éÒÂQÀÛÀ.À,àBà4RïJZø 0="öãa¤¦ÆWókz4H. ÝâspJ¾mèàÿþö7
À)±p&ðÖßM33³îÕ,¸K:Ïjç¼é¤[aN¶çóìX #HAn%àcùøåRÿ¬x4zÖ]qoD<ü´æ´ \E
+¶ú·ÿoù{ø]DÌ!
+Ô1#çåóÀLZox9"Î95}ö˯ù@àRá@øcUIëC#âÁ<èº~ߣ%m#¿fffÝfQoyI߶!hë¤xKÒ&¤ö%Ý|ÜSXÞ j'Ì/Ï+åçÒ4ïjÕäôÎ:åsk½X
+ÎÃH3vMÈëHoÔóB+Û/Ö¤ñl~þàPR¡æ|üÞ|84U裤Á=¦¶g33³n1@Ò7IµÓ/ËIZ>o#éÚ$IMï[ä²Fµ ÜJªíBj~ÿ¤¥%
+Ééßl/i#I«&Á¸ªüþ82¥yD_ãÀfÀ´Ü§àaRáa!ðF£=¶^Êi<F*t@ºèPRþ¼mà¹x
+ØxWójff¶ØfùH5ç?ÓÔK|°]óÆtð5 è9ûÒµîëHÁ}¼ý÷¤øà`ýKÁêDà·À·KuÆþVqÏ,¤Q®Få´§zø×Gº5X4æö!À×%M ];_.ï>ø¤_sHeãr3HýÍiüX&ï{¸ø{D
ó$Ýì_ßÛu^Y·S;-ðÖH:íõ0k¨<ͳáÁl¬ÏÈ}¢&FDeúFÕë-offfý»YÅ8¸UL·÷<Bܾ¹G}[ÇíÝþnIëuw¾ÌÌÌn
+îFw¸Y¢fßoJ#ÐAµÞ¬tï'>×Õ<,/é÷]=ßÌ̬¿ërp´¤H×"Ý.6 ¸4cTqìXÒtÛKzo)ávÉC¹þ ÜÏS~_Ik·%í#é}ùþ÷w;JÚNÒz´Acþ#¥óÖô®´ÖÉ-
+«Ölß*ߣ¿¤ò¶$mÕÉ·Íl@4LÒúvôY`[6³Ò¥ùÜ%}tÏùõÀéN"Ý[¾°
+iÈ×ûHÃÈBªÉv$Ý~WÞ~.ðtNã<@ÌÀˤ!p¯"·
+pBM>ö!
+uûw`WÒ½ï[îAß4Îûhà"Ò¨tã%ý4ÜT`¡¤e"â<~üH÷º"é¹øNV÷&Ò ;OgI:40ÍrÉcÓ
+(ùcE`VUI#J>OúÿL½ò©Fä×l éRp'à¯EÄm.~t °kDT>8"îô<pzD<SÚuZNci¼÷ùzü&ÀW#¢µábwþü¦nVÒeÀaE$½4 ÍF1_Ò¤9§¿÷_*ix8Xi6¸%OúqZ8&¡?Ø8">-i$©0ààn£4ãê´¼G
+âi
+à÷F
Lù5iFÓÐÍfÖCºÜ?@Óð¯÷jÕ]QÔàÖ)ï
.¤YÖ®®9ÿàÀãþJ!¯;K?2»»Jº6¯Þ%é9RÀTÒÏÒ9OOSóHtÆ2çqfîg`Ö¯äZ÷XÚ®uÏ¡©Æ],wÏ#âÞϹuDWûxRó÷x`SRoÏ,Ò,eíMPspYböIkgkgCóuÿsI×òþSçï'¹ X*"¾P>@ÒÁÀñ-IÃo¶Oëg}ZnUj«Ö=T-î À¥ùùy¾3ëºÜÿ8CÒ?IÓ°þ´çÜ üBÒøQ{çNm§Æ_¸§fV$JÞõMRþq1CÒ¹ùïVZÎ w-p¤ó{H=óEê3p²¤)¤æþéõAùÕÊ´¸W!ÍeP[ëGSûÞϹõ.-k·»7çùÕɽÞ'[9g5`¸UÒv¤æòȵµ#â!IkjÚSIÍý&¹·Np_Ôo>pSÑLü6%uè¬×»ðàáx Þ¤åÇ#âIÛGÄø|ÌÀx!¯ï
+ÆcËWKîÜÙV{8ð-w±¼Tû¿ÒWxlyëª8¶¼'© ÷þCÒ`ÒõìÖ÷JÀLZÜóLý»õEUî]m7³:$¦õÀ½:°$éÖÎrÀ¾©ô|j¸ÄmfÉÁݬò I«Ñzð^xæûIRÉÀóñvïçÜÌw³LÒr´]ëLº²¼ÿSz>͵n3ëÜm@´$m׺W ÝyQÜ×ÑTëÝû973ë<w«|§Fk{5@¤;'ÊÁû_4uR{¥Ù63ëîÖçåAÚº5l9Ò¸åÀýp5Mà Îéý5û &iT_BTR[¬,¤ùä#hªu{À!3³÷&>ôiÒD=Gzw÷ôßk«Ö=x
æû~à*jÝóZ¦lffqp $G/ÿ0ÒØû»£ì-F"
+ºÒÖä#óhY뾦Z÷ë33kÉÁ½Âò0¼{' #H3}7wàü´¸× M
[LùY,wçç/ÔNùiff=ÏÁ½$¾|4"Ú2y×;ÀqjümMù¹
+0µî;iªu7üz½µäà^!¶v!õÚ©oFKú/°-§ü\§ü43ë×Üû¹ÜamS®¥«S&{EÄ=733k÷þ¯è´öd~\
+IjR,MSÀ¬/i¿ÑûÙ53³æàÞÏEÄS&QòUÒÀú¤NtÛ cH JÚ#"jLÎÍ̬§8¸WP¾/üѼ\^lÏèÖ"ýM£$ý6"&5"ffÖ3ÜXü7/W78;ffÖC5:fffÖ½ÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁÝÌ̬bÜÍÌÌ*ÆÁ½ô)Ißô¤õ/3³þBÒÀÍÀòtq³Ô-4:¶XFï*¿?Së$-,K
+¼33äçïm\VºkîfÖ><
+L6mhÌ*̵<3ë
+1¥õ%³ÀÁ½{¸X×¼Þ¸ìõ;hÞWòÑÜû±Ðè|õWñFç¡'8¸Yo¸øEi}!ðBòbVyFçÁÌÌ̺{ËU»YÅ8¸U;Ô
+ >LÕîÆ&iG`àÎx¦±¹³ª«ýþ5:?fUæ{H:^Òì¼^³ïÒ¾jö\Ú÷}»öÍô¤G%ýPÒ°|Ìwò¾ºõ_X8.¯ïÜÅôZômIKÚ£»Ò´Ê¨ýþY%é]¶«³¬Ô
+i#é,IÛuG^{¤!vt°¤ý$m.©OVÜ»fi<â¡Àç$´3°uiߢ÷WÃKûËÛ
+òö%+{õÕüÝ%»éuüøiÒî²#ðIRÞÍ"¥³ ²IDATʾIú¾=ÒèX»~
+¯³tǸ{GÓ|^>OÒjÀcÀÀ_HMNoë¼Fqp_<¯ #Ïæõcy¤ \jí¬A_ûñü|:Ç-"bà´¼mfHÒhI¿ô¤ôþV?T{ß,;HÒç%Ý-éUI÷Júl)íC%MtjnQxVÒU¶ÏûÏ"wãò±Çå}'Jº]Òëô·¾&ë^ÊÍDIä°t ¤m%Ý¿7_,óÜ*5-÷×ì?$§÷³üý×Ë-8'}ßÖÌçù¼¤¿I*é:Ikçýcòþ{sËÖ=®ËûÞÏ"é¹ÜZ´NÞ·s>ï4RÒî´¤+óþÍKù¿$oÛ¦Gßüþgð?¥e¤ÁùwfTqP~GKZº|rÞ¶
¤ë%Ój1eÞ¾¤$.©YE)§;:¯j#ý5<çÔTª4VÒFJµåx`=à&àcyù ð|¿»rNsHÍö9Cò²¤¥ó¶¡¥ã÷sdÍù«+µª®Ù¾L>~°¤¡6%"¼tr¾p))X?¬
+Ìþü7ïߥtÎó¶óóóKûwËÛææõaÀeyÛ#yÛñyýVò5ôÏÀkÀ¹À¿CóþGËù®ÉëÍëÇæõ§H%÷'óúyÿ7òú|àÒ0Ü÷LÍÛ µ@E
+øóv©yöFuÉG o·åçsHÓ¹yÛ:ù#òwðçÀô¼ï¼ÿë¥ïÆC¤Z^fFí÷ïê¼>¸×ÎßåUJù|4Üò
¤ñyûÀùùÀ²9íó¶ gåç?Ëû¾×××Ìë/ ýùô
ø[~ON¯³o(©ÆÀA¤a¯ÿ׿Y¸¡ôùðµ¼ïº¼þ»üù6yÿhàs¶Êû/m?9çæjÒCò1cJßÁù;[³|>fü*ÿ/ÙÆ{RüÿÚÊ1Ûæ×R¤ùù÷5ï/¾«?&ýFMñäüÒq?ÎÛ~×w£)®0
+دt|ñ¿s"0XÐð/Q\JÆ%¤ÚzÑ#awRí~fÞ¶>°Q~þ°TéÃ+>¸©¤³býè|L{Á½¢UJÛ/|{Á½øGûé:ü yý¡¼¿îÓhºD04ÚXñó|ÌWJÿÓyÛu¤&û1þòBóà^ç7óúOòúßê|£ó÷ô«Àyÿ/ó¾"¸¿DÓàX÷åm'´òý+û_òú
+ù»¤ÉrpÿRÿ¿ÛKÛÉÛ*½Æ§ó÷3H?ôÅÿÁrùÿk0øVùµ{iöùÏÊ¿GŲIÞ¿aÞ7Tü¿¯üÛPÍ»#ó÷£¨dÁý-R+
+ÿ÷/M
+R» Φô»Góàþé÷êå¼þþ|LQ ¿¯ãJç,ÿÆë~y}°}+ïÉGKi¼M*¼|\ Ìß¹â7ô`ÿ¼¾ Ø6S÷ùÀå¤Q×!ßÌßGƺ`s`µ¼oðeRêMRh½nÜç Ns³üâ;ô%Ýw×9æ㤹¬gröÍç¤å5¬ o lw³;µòãcñâ¢#æ·wbn>*¶N%5=ý0¯¯Ssøí1?"æ ³I_ÆåÚHþrR©zGàb`ª¤[:Ðf=ïüX|_I3¦çÇ1 >Oªi\Mó륵ûÄÈ¿6¤xhú^µæ>xT8ØË.*=_ø[¥m÷EÄÀÿZ N+þ"â5RÍ~ð Òå)óÚÉç@ô6Í{ñN"Ul¾Gj>,ö¦ó
+àcñøuDü©&íó#âxR+!ÀN9í·kI&µ×k?#,¥|8?g_«9o[`UÒïð `üúrñORáöR¿§%µàlOú®¿I*àl^JsßäþoEÄ«H}I5»"âü7&ýo!½¿SI»®I÷ÇqhD|ÍÁ}1å?æÕÖ:VG®ÑüôaVsìüØ3"ö/EÄ-ÈÎóãÆÖ(6v$æ¾âõ `ÙÒRûOõNéùÂ}³òãðÒ¶yq é¹+p/)ÐïÖ^¾¬Çeñ9ÎÎkû©·kDlBª Õ³uézàùqJ;yx/ROì"¨¯c.òlÏåÇ÷¶mVÞ¯Ûô}üJRyÊÙ3óãñ¤Ö¶Û#âvò9][I¥}÷Ñô½y¦¾FEo&)µæ¾üX|çHÚÔÒr"©¶ZÌA0¢£i*S
+¤åÇÂèü8P÷ÍÏ'0õDÄõñ!Òïâ±yó>ÏÛ ö"Må4Ô$ucÍúòã!¤Nsjò:²î¬nm_nìÂß}ÔÓ¢#]þÙôOð~¦d]¸ØE©fwGj.ÝxXÒ?±¤Im©¹_®Nªm϶#ý8ØÆye×Þ¿+ioR+ÀZ>IªÎ'Jç®ÍZÿð4©¶þ]I¯{¶rÜhà1I3Iw©J[ötMIÀÖjüçzÞo+ié|
+R¹4f/&ÕÌ?G*T
+\ i¯HTü¯iZKc$mQZ9"^ʽ.!¯ À¤>7ß#5Ï#U`ô;RZ=×REÀ;4§ûçø¤cÏ´¿ÖÒ¸T«ý¤ÇiYs4?öÉ 6¤e &ï;Tºtiòé¼kH>§¸dér×|ÞF¤÷£lvÍúõ¤é¤À=ô¦î|`§\¡DÒÖ4UÈZ¤ë{×<K
+ÌDļQj÷Ï Õ
+nÎñ1)/·ÿGêÌô^Rп%/÷ßWogD,$Ýfr
+éHÍGOåCîÎçózQºþ5©Ôøécϼï¼Jùug·çmoçõKI×æo£©T?Tðù(é²ÄM¤ëü-zZ¯OÓwøîÊëE
+gR^6¯KºýgMR³ã7òþrMÒµÚHß»qÀ¥Ï¹ø3jÎ9ôÝzÔ sïü¿47sùàxÔ¬z!©01tyì}¹IwRÄq©Ðz>©æWn-*jï3IÍ«ÖÒ§ûKK$Ï"õúéwâ9àxI»FÄtRÇÙ ½Ç/î,úTÿæuùñHII¹Î:ô}:Ô1¸Ù]ñ(ðR¿¡'%ôéwsKêÛô=B*´^·ÿ%ÿþ?Dz_OKÓ|ÔDߪüÛ}.© 0
+¸("fæ}ÿ&ý_,Oº¤y»¤gHý¼Öj-MÏ
+gfMÒ×I?ôEÄÁ<çjà#¤»1zµæ,i)Òy¿&þ_oþý¾.·´mTg×í¤ÂÿѤÚèÏ#bn®Eî
+¼Tô´-é6ÞUI5Ý?GÄ!ÝRvEnAYÔéîõ8=û¡|î4RËÏá¤Ë3?4¦&ñDÄB¥Ñ·nsk*ÓH
+rË1I».%õ3 \SÖ÷d`wR_Ta\JÇíAº_¤9>§9KÒ¤~!EÄã5é¯ßWj÷çÛ÷öÞG
+òÓògq]DÌÉÿ£ßýÜÍl±õÃà¾Ôrù<©ø½ù÷gIÚtà`%RSÿƤlodÞz»-¶\ûZtMö±³)©2)"ÚêxÕírÍt©#]íõPëçrýR_H. NYV)ÿ4f äÏÝ IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mpm_cache_case_two.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mpm_cache_case_two.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mpm_cache_case_two.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,170 @@
+PNG
+
+
+IHDR ® !R sBIT|d pHYs
+×
+×B(x tEXtSoftware www.inkscape.orgî< IDATxìg\ÅÑW¤DQM2L2`À$cÂGlc¢1L´ 6Æ`ÀM9g0Yä @B" R}?ª¯öîhfwfvvgvUÏ9}fnè¾=ñ½Õ]]%3# + énàÏföX
õ~ìff;¶OÏ]ë,à]3»°½¯ÕUéVïAÔùY«¨70oûR¹Ù;èZ]õî@3V ¾fÖn6³±ÖÆwÙWéüu%/»Íì³\{³ [3÷´rí¾ÀÀBÀXà63û¾àyÍ×ÍìÙc âÿ÷Ùi7à'ÀÀdà!3{· îæÀ@àá2Þ¦ Æât»¤Çsåz÷)hn*øL/®wºóàR`°0ÐWÒÀ}ÀrÀÀK¤ówvú Û¯H@Rwà!àd`eà~`ή}4.<}§%Í;>/p°
+p¥¤²Ö~¬<'itø§ÀaÀÀÀPIkçêþ¸Üü¸÷©b$í.é©ÜïíiIs´Çµê5D,Wî¨w¢´ù3ZðÞSï>Eiöù¬[ï§ò!°E;_ó"à- at i{.à`ÅÜ9×g¨=plz¾#0è¶WIß³Ëè7ÓööÀT`´½ðY®íaÀ¹úG hûhÜ·§ó§í^ÀDà¨vxoO(ø½Ôû{Ö%
+`Æf. gn»#Faî³ôO¯üNRv|!Ü*BÒÜÀÁÀúÀ´B:o%àf6%m¿ |^ê¢û¤¶zó æNyÉÌFÙ{É¢$é`)`cIë¤sûˤv{ ¦vĿȽ¾7ÍlLj÷IOµö-ÂAGóqî¹áóBSrû¿NGà;ÙIÅEÜé^Ðvávsð9¦Ìì3I÷Ó\´'?%µìu¸
?>¼¹°'ð.°3nue},üm©A4Ì0x<æAçæààü3}³¾Ý ð?òÙÓY§ã·&Ñêü"W÷Y`ÝÜ<ÕjðÖÔw¹6Ö¸ÓG«ÙÀ«À²}|!×ÇûÍì3
+ü²àõ-&iáÔ¾¸#G{0æ×ðßÛ÷-Öè¤eq%¯¥pÓ¼wÚý=W«ÙiBö%3Û¨VíõÃÌvÔx?>Ód4p°<îå÷<|saf_HÚ¸JÒøïòøÎé¸SÃù6½ýÞËU¿Øx[Ò½øר×,é*àI/VÐÕ}$m<Ï}ì
+ü¸.y$®GvÝþ;\¬¼RÁuËÆÌ®Ký¸¸ÅÌ®më4jj.qÔ´í]pèD3;¡¦i®t
+rÂÕ¯Þ} #é( Õ×ZøÞÌFì·DzáÖÖsÙ<¤Åp¯Ágqë½½õ 6ÂÝá#Tìú+áÞã^ßÙúã/åÎ]xÑ̾MÛ}q¯Á¹q|ÂÌ&¥cýñ9®áÀH`q˹ÓKú)îÿ8þ_:ÑÌl[««;þF¿O8®Ü®=
+ ËbfoØ?¸¹Ä±øTB±c?Ð|ýV£@föMC|çö|RpîÛ_wh÷ÜÅ?ãÙãO¶Ô¯ 2ÊãÌefgµs EZµ¸ÒdãgAA#yAA«pAXA%ñ/rÎÖKuа4¢puKA4'பSëÝ¡ ´@y`U<`ïòøz«Oñÿº©ÌLN¡Håi3û¦ý*§
kàϸ~¯´ø¹ÃÿMÈñÛ%Kr¡
+ Öí쯡zò~'pR:óák²~/t^VÒxpßû:ªïAu9cM¹On÷AvJÏ7·ü3mà[3Û£þOüÖ»
2g©c)üK1¾£Lñ+,fö]u/7jH©Cþ/:¾Ø0[ÜiÝØõ© iV<TÓÙ¦ gCr|¢\k©"ûæ¤)÷ÍLE·ilúT>jåô²IIéZÃ¥¥ºÅLbxÃAIsá²÷¦¶¢ÙD<tÓSÒÇ#S%ýÎÌnkkÚR®p[\¥hÐ%M²¾ÃÇÄkB
+IÓþß×'=Φ\®SqÑ®Ö:»È S"i/àÜÂZ¦=æ¥Ìì.à®dÑ]Hafk} :Ê.3{¤½;ÒUIw_¦RÒ¼_/ZĹKKØÅ(7¬D§GZ¾³ât74³7ÚûföXmx)ð¤Íì½ÖêíO#:g<-ǧR3Ò8Kb8?Í-¼.6Ür¼Åo:ç4|ÌàH¸OY²®Õô{ßfö%ðKIC%íff÷vÔõâpÓHB1`£m!e°}Þ)&sáѺY³R|z
+ÕÏvé%6Þ2³÷ëÝZ ©p+wózYöfö7I/àiQ¶2³Èb\GB¸öfîOS³yÐ4lTj¨´Þ}¾Ç»úç$ýÏ]VB¤³æwoÄsTï3{BÒîÀÍÖ+×1¨=!\A§#9|MSz÷6ÓUXÙGÖþì#é<åÆåLÄÂW%Zé3YX5µõ=ððªUØÌîtp¤5ÍlL¥mm'+h×%3SÜc´½XÏÎÊqÀþ>®ÃElTòz
[/¬Rh¥¹Öí}Õð<^¯àë$Ü?$éM<ÃòåÌÙ)éímV/ݧÕÈId@îzDäÚSÆÞø¼áA¸CC!Åý¿-´«^rA¬Æôy øMrM/·ÞÞ¸`¿\ Ü[Ê]>Yc« àk¸N*9¹Dw÷Ù¹åÖ© íñÏðÚJ;Dä ÖXHZ8)x>½ÀXà^<ïÙ¼¤cñ4öY¨µrÊ\ÛÅæ{IJN3¹ç?Ã-%Kk©Zt°´p >Ôû33{¥÷p2)N¡¤yðaÕ%ý=ÔZýÄÁÀS¤H5ÃÌ®t%0BÒÛÀe¸½_ËëtVÂâ
+Ú°¸:I w_àÇmÀ-9H:
+ègfGÕ¸/åÌ~À¯'qÒéÄ«Êi&ó cpïÕrjJYëàq©Xæk<XÚÌv¬ø
+j½íøƺÀ¸Ñû©×rx
++NCëj§jæ
+%ýècfÛµpÎL¸ü8xÒ^¦ó8/³âsß ÇH:ÖDp4>wxîSx¼êô)fö¤-pËpi|.r)à$àdI#h±ÑÕ\£³Â]4tk½ûQ-ÉÂ8ؾ¥óÌl¤Éx$CÌì\»Íç¯ÁÅðÝü¹çãðÛ3½u(IUG¤IåP\ àÿÙÓÎÒÀÉxLÅ·ñCÚú^tB¸ h6 >2³gÊ8÷¯øhE¦E£ÉXMK
+.1³W[ª<GG[ZºeD£É\±¸¥y°Øÿõ¬éqYà/À9¸ÍDIÙå¿®
â-"i`c`öêôGà2I«·äònfßKºØÏí?Öæh4v.náïñù¯nÀ{¸E6ÆGm4jíF34«ãNq ð3Ð1³Kqì 2Nÿ7°{û;_Le>÷=îsðü½ÕÌúr¬Ï°¸ ¨;Éq5<qKçýØX¼Ìv× v³V°>ì0àIç·ädafÏK$i3{®Ì¶[ê·ða¿ßâ"5wpy¸x|Fv+F`)às3û¸óÖ 1³O[:IRwI§áÎ
+ïâ/Ã×´#éÊÀ·EÌìE<ÀïÆe¼q^$'µsq§f6ÐÌv7³ÿÎÈ¢aqAÐ,¼UÆyËà!Zã7øú§Íì³üIâ5JZ©
ûákªZâ5`Õ2úÖ³áÞ]v¨¯ÅA#Ð_dÛq(¤Ùc=EÀÌ&ÙîxÔùcʸæíÀz%²çy
+÷îkföuVËpAÐ+\hî¨PÙîe¤9ØOÒ-â~,ÖJ{¯ãk«v&+F ;å ×{´îñ=u{NJk [qÝçie0y9~%i`ím +Fà[Z·¤À
kPK'¤%ÇâÙw´\§?¬\ÆuÇâ1[ã<uJÐpAмJyóC
+ýÏ;¶?ù¾µÞ\´#!\AÔ3û è+©Xþ°<#ù%-XFgÙföH§
+Â4jÅÌpµ;!\A4
+¯-
+ëeóHÇËÖâÁt[£º©5fÁçØv$+Fá9`£2Î;ØXÒò5¸æfêÇxVæÖ¡Â AÐ(\
;TÏp\t2Ðvój/&i'<òú7°$¤¾xòËo«íSk¤HôóáiUñH!]® 3{QÒgÀx<¾¸ØWÒ¹ÀafV+ý4$-
+lTFÝåáeDØXÏà^Rt[è¹hYæÇc~Ç]ÇàÞcðô*§VzýÎFWÄ¥À^´"\);ðºxÂÇ{%íP,JF1$-ÜÚZ®ÄN´î `|¸³ðz³Ð$<¥i^Ü~L®MíÝÛ÷Ik[ðÑù á
+ ¸
+8^ÒÒföFK'ÙW)µýÀ³I¼JFfOIÄãbfWµÖww`Å"Çô§I|v >t ÍE©MVR^ÍïK¬2á
+ a0³/%üSÒºYiXîpI/C$}\¼Ä-%SÙ
+x¼;¶¥vÈÍüþ»³¤Bki^`<.<âëÐÃÝëó"õik¯#¨® Ú¤î-e ®p+çÿðbfWKºøÂi`!\Pãb²ð0·¤~¸./L³ãpqú0 ø OÒÍ-ͬ$I[3Ù¡mzåAYpAPi¨lC`àLÜÊi3fföÇç®îmÍ:Ê1YãF¦¥ßãô5Í-¢1¸Kü43ûTÒMÀ»fvX×ÞøOýÚHW!©?î@ñ[\vlm>ªRÌìeIî´ÐÖ=îf¦¹§Ýà}|x0¥±ex"io<GØNe;'°n!@We!i}àP|8n*.&gÙ6´Ù=îâ?Ã]½ó¢ô8Í>¯¶}Ú8
+XÛÌ&QåhàªÜ7è B¸ (I²&öÀÙúâr£C<{é«×¦^j)+=~MÒ»¸C¶}°°½}Ù/3ßïíðìÈ[Ï3qw<3sÐApA0ÖÆÅjs`
+>1O¬x.°¤b¢47ð9ÓÒ£4·¾(£/û^´¢©"Ò|ÝÁ¸olf/Yõdàïföqû&+ $ͧéÏ[ÍÚ
+ 6ÌDéàDéC3\~%÷£$= \'é"à´Zy1JZÄ°(³Þ:xlÅ%kÑ |B¸ ¢6Ä]Ã,(á"s?ð|if [sÔRYq/ÂCjèß"fö¤oI:¸,E¯IáC}Ç»Þ*
+¡þØ£ÚëÕÂäáWJÄ-§ÑÀ¨\y
+¸6·}ð4°)°ZdE\Ìãs[ßâÿ½Ò¥gýè~,iZ9F´FûEZu8p¬¤Ë»çZsHÎ ûâ!®7³qvårÜ!ã¾
+ë5 + | ¥Ei #jTA{>®µ ¯Yl»ä&þr*ÿÍ
+±,þg¿
+°8ÐXxUÒÆföz
+^vYÙÀ¯$-m
+¬ i.ÂàsqSqËqI\çNÇÿ
+lSk|!NæÄ´ pAHsJ¥DiA<åüXÒ3À
+ÙvGSÙWøZ¨'ð¨YÿçÃÅl9à IçÙ[íݾ½GòlÔXX·4»Ñsð&àOÀÛm ¿$éh|1ózF¤jGW´)Ó¤¬L¢¹(Ä£gÛc«IÑQ¤c.KÎ ÏQ$B{-ô|iÀzU-5$+è¤!¡ÑµòTk+æ eQêÇÉËi3éæl_,Xí¤5i§ ¿Ö¯ UÐNp
+¤nø:¢ÍìôºnO|-R)QZ;ÉÒ(<n¶olGyÛí¤¹ñ_5ÊÍù´/!\AÃæ~öÁÀöÇøQÃöûQZÂ'ð?¢¹(½ÜíKó>AFÒ&¸ëý¥ÀÉ<l;£Â4~»8ovͧءõ5=ð(-¹æ¢4
+¸3·oLL¼Ï¸HZø¾`/3k1sÐñpu%%ìÛ÷_y}ljf_çÎïKË¢4 Ê¥×ñu>'^«aIákÚvÆÓ´ü²Ì »AÂÔIð?=Ò®Þ§LnL2êÁôëîÉ=o ñIkå¶Á¦® ØMWPI½pAù¤ãûÉÙb_ÜÙ"[ÀÚÄéÝÙñ(÷Ñd-ÅäxPKÀEëbàæ°°:!\A3$m˸p Lô8p=Ue»ÓðïÝdÜ3¯%áZwº0æöÀÌ^ų8RÁËx̺ÙL,zë÷§HÚcfٯͬ'>µ A÷Ràà+|xð+<.x\¼=§$ÍSÝË «WPÈDàRn`e< è`\HöÂÓYTM:0x8¿?¹©/,îYÊYxIÒ¶ÕZ|AtB¸B
+ÓT<ÒGü3mÏ×^NÙm¦2äy¸$0HRïH#36!\A3JD{ÈÓ=ÑQ}É0³ÀK©A0s\AHZ}xÏ_AP7B¸Húð ¾(ø]`ÃpG ÞpE´©î¤±ADÅ á
+¦CÒð=qG5Íld}{AàsFÐIÇ'¥Íoñ¨{géÝÍì²zô- B¸é{>p\ÁñW® êFWPÈ0à¿ÓQ (FWÐ3;8¹Þý (E8gA°¸AÒÆ@?`8ðVAP1!\AG1?°DwIãpGä7³Ñõëb® C0³ÿÔX»ðc`'`II³áÓ\ØÞ2³o4ÁFWÐᤤo§rGþ¤áÒã¢>¡ÀBKå3³{AÔ® ¡0³/(Ú¤;°0n¡- ,l¶ûHÊ[i°½)P ëÂt
+Rº©Ü?&iv,´¥_Ò¿ë3¦·ÐÞF
® Ócf_Ϥ2
+IÝp+-µÁÀ6éy?IoSdèÑÌÆwXç ¨® ËbfSñt,ïwçIê,AÓÐã/Òãâ¾ Ç#02µA á
+fHÌìkà¹T¦¬´i>ô¸Uz>gÎJ+ôxüªãz36!\A#YTï§roþ¤Þ4÷xü9ðÜJûâï§ù¹vCÒÀ03Ñ× F!+Ê$y(>Ê4ä9_Òd¡- lûKAñÅÖ_Ö¨kO/Iz8ÞÌiBtfB¸ $ïÄQ©Ü?&©>Yi¿ô
+Å=ß«ÄJ3³O$í
+< l(éU<Í]á9tEB¸ 1³oSF²Òæ§ÉB[Ø8mÏ#é]{<~^â:I:8X ¸øBÒ ÀUf6©ö¯.êCWÔd Nåü±öjqÒ&2½
6÷<¿å>©üEÒÙÀáDtB¸ ÁH1_N¥æ§¹Èéq^Ü¡d$wÙït)pf3:3!\AÐ0³1Àà¡ü~I³àv "UgK ûIzø£½ÐÝ
+v!IA×`Nà` gçuOeàyI·¦º
+¤9%mß×Û1v®eý$íTË6æpA'GÒVø<×ÊÀ¬ÀxàK`ðð ð08ØXXØø¬ã{]E¿tàõÎÃW¤K$åÛX ø[z´HA'EÒLÀiÀöx³w7÷hZD=º5×zwp11³5hfc\ ³6_ú× Ý aqAç¥p¤-hf+Ùfv]afÙÈZDíô+IK'éMIJOÒÓiZvÞÒÔCÒ¯%)é/>t½¤rçÎ!é_F¦vo(¸æÞôh²(³ýôI×HúXÒÚt·¤$½*iÇÜùI:BÒåFKºLÒ¢¹ãHZBÒ¬^*RúIZ@ÒFIÚ=Õ? \ÎßVÒ 4]c¡T¤×$ý:wì·é5]úw¹¤Amý̺:!\AÐI1³ïRRÎvCRààd¬¼mfcï_åNßx=õ©?ð[ÜME<ièI¹s¯ÆÔ¶Â׳ý5wl^`U`=à\àCTç8à|XñàfÜaeyàÏÀeVMçÏο;õCøðeYÍlbº^V¾Â]'~Ì
¹|üX¸%µ×»®]1½Iúiª?_jûÁt|rj3h® ZÂð?âÕ$Ínfæb"þئy5î
+\«û¶]`fâQ=z&þMp¯ÆÍl=YpÝcÍl¬ÝäJ¹cCU9_ï¶\jë#3»xØ%wþ£fv}
+\
+lZô
}Âpmÿmúö1ð
+>¸¾ä`½Tgrz&¥Bwpªw3³!ÀÃé½ÊxÂÌ®NýûWzoá
+ $I¶Âst¤
ÓáVJÇß1³rÕ_Í=ÿè
»å/ÑtëÔ¦?ñ|ݹsÛÏæ/ Iâñ>|ñJm5CÒÀ©Àϳ(%æÃÃyêNæ(ÕF §e¥úWø>ÍSfÛ3,!\A´=jfãÞwLû'ãÌ~À>4·¶ZbnÅ\eòVÍH`Ióæö´QI«í
+"í Ühf;Ù©ø°dÉvt Ì]àu¸Z6
+á
+ $´¥<¥pÑø wÊÅøüÎÀµå´ifâóR§KZKR_IUÙÅ×pìLII: Xøw%$g;ñ9µ±N¥0X^Ò<6v+¨þ°SrN=ÀÌOg$§}uË*©AFW-aÀÞxà»pkéüiÍFâÂqu
+(1wÍÏ
+<¯+ÿóûzjøZÐç,¸ð[¸v}óW÷À6v~ifÙðà;¸HÆ·øXÆøz·9ÒkÛ¸<WzW¦><<kãTü}:Xø³mÓë¿+½îsKÞM}Ìøw Z@õ@Ò à¥ IýðdýêÝ 8úÙQUÔµÌìÖÎÚI×·YYpg$,® ªBÒá¸eqIVÐDä É/ ®»
+ Ý á
+ I=ñ5E+àu³Ç×)ÈÚ\.)´Qt8!\AÐÅ4ÓÔb¸#ÀËøº¦³Íì£4Ç® 褤 »K1½H&º©af6©N]
+¬¨¸@½LΪW? #á
+"YQi.P+àë2º8·¢&ש«AP7B¸IO{ÙëõîKP{rVT^ ¥¹uaEA3B¸ÀLõîDÐ6Â
+ÚÂÕ
+ÖÆïnÍ¢F§ãÝÍÓñ7Ìì¡ÚÚ
+Oi°.0·]êo,ç2z¸DÝYñT
+wÙWéئÀsùÚÖÁ#VªîÕ¢¿
+TfEe÷¯ÕÂÕ:ÆÉõÀá-i3{.%»XOñp¤Íl¿mÝ<ÇK6M² IDAT{*ÝßGÊ~8XÒÃf¶ºûãwí#Ó$ý8èÎx´?gÅ.Ýö#gE:LÍ*¬¨ ¨1!\åñ
m i<Ôó9`\0æ6³þ
+tQ.f!÷Ùi©>f¶RÚ>øPÒyf6,_ÉÌÎÉoKºOFwÐï&I'¤ì³»¤ ¨A)°¢2
++*êDWyÜ{þ"Æ<½ø#)í7f6JÒÀñdqŸ7÷|M ¤Ësû&à\3á´ z}`NàGÀéºC%}'ü» Ïô§Ê^bc#IÖΡ˴¢îÎ$¬¨ ¨!\å1!÷|
+нÈóx
+Rä3µúáÂܾñ;ùB÷1³%]BóÏïB`?IãpQ»£HI}ðT%ç«hw ÓÔ¢xÌaâ^Ü£ïãRíAÐñpµ¡ÀzÙIKàÎÏYÿ\vKC|À4B6öH¢5°%pCîøUÀÀ)Àeùö:#)Êßã1®²ð¹¾B©¸8½[Qg oOW0³{%ݼ+é.<ÞÙföjM\{$tªg}Ü{°0õøåÀ%é:Ó<Ifö¤«ð4ã{T÷êOr,98øøMu¨poͼuaEA§&«uÆä¶ïÇÓ
`f;JZw?¿§p«é\Ý)ÀÖVÁçV¾N4³L´~{2bf'Kÿ)ÿ¢ìYÐþÀ½Ñ)#%$<
+Þn¸§å7ÀÛîÜRVÔTXQAÐ áj3{©`ûcÏSafÓ<x©¶¦ä6³ç(2¼hfOlæV ~ü¼µ~4æöÃkætè[<eú0IÐ\ 2+*s¸÷è+*f B¸ºkàCk·bñ5iXïOÀ4¬ímh²¢î&¬¨ á áêÙ½4w³oX$Íϸ`úþ/¶ÞÚÌFwP÷ èó^#i^IF»àst-}ÿfÁIÚ¥ºA'!,® CHnüÇáëÌææÂ[ssàÞßáγÿ´°»}Öñ½ á
+Ú
+IͼÍìK<òHkõúà¢6/M7?p´¤³"¬RÌØp5!y®Ê*éñnàJÛ2³ñ¸÷ätA!\AÅäD*¨q¯ÀçS¹8$ÅnìW·AÐ% áê RúUåEJ?|aòØ\æ$w8)KïÊ¥¨HÕ«AÌXpµ)tÑÆxx¦Mϧñ ºãRùèÏãdó9ñ¼[JÜÜ^¸ ºÆ}.G¤6³Ú«AÂUC$Íì
§=Y¢{7p½ßJõO(?Ú쬧,¹JRoàvàj3{²
+}-©UðE¿H]NT
+HW
+H±óöÆcí½ <jfÚÚ¶MLå(Iááÿ-i8pM'xýËT6/Õ© :!!\m ÖÀq7ïÛ;ä Îôw<¾ß)BýñiÔ<4w(©
HAÐY áªIëãÊ+xrÇç;òúfö¤ðöïKú_¸û!RAtQB¸*$yÅ.föp]w Ó;NdÔ£x$õM5ÌlhGô+ £ ᪠I³ãus«¶zZÿ¬Ç©Ë½TÒÏ[$df7AÐÅá*IË7â}ÛÙ5j7©ü¼TûJTQÌìþ$^·KZÔÌάE?
®2´p>_t}ÚÀôÝir¸øM[ÓxÙ«~
+Ü!iPj³&BAPoB¸ZAÒ`àj`ÇJæ³$ÍËôsR5©RÙXIë ×wJÚ.Å èÔpµ¤þÀxfá¢UH]`fcÚ½Ó9Ìl¤p¼Ï&AЩ á*¤Y[«ÌìÜþ¼HeÃ~Ýhr¨HÂ̦HÚxTÒáfvV½ûAкpIZÇ̪A[Â×@}<#éĪMÿö¯D¤RȦ¥ðĦ2Wø»ðq3û´¯#ÃÌ&IÚ>½§ÍìÑZµAÐÑtzá48·~ViC;óÒdAm,Id¶bʵ= 5¸5ðS<ÈîûÀ{À(<Fàx&àË% n3³'ª}]fö¤Ý«%É è¬tZáJbp"r©;°¶}[fÝù~NJ¸@½Ç¦m]\DõàÀ=x¤ÌlB+õz ?Á£Ã_&éCà3û_[úcf÷Iº¸VÒFf6¥-íAÔnõî@¥HSÒ9À»ÀÿáÃl²J$Í'iKI'Hº=Àóx?«Ù¼f¶ð=pk[DKR?IgàwßÙNf6¤5ÑçdfOÙÀÒ¸sÅÅþ'iÍjû8×Æv êB§±¸RÔ#ßâÖÌéÐ8àé¼%
+ûAãÄÅÀ~¥"^¤ µ+µ¡Ëá¹³îmë\²þ#éj`àIçÙU¶gö^t}ÜþAt4
+/\zGà5kîð÷À}ÀI+FúEÀóe:¸¼Ú ´¶À£ßÙ5Õ´Q$`WHz¸)EòØË̾«¢1®Ãß× NCÃ
+WrG?ÒêIsÁÊè üêDªðzK ÛáNÕÔß8ØÂ̶af£%
+\<&iK3WES§/K:ËÌ>©m/ Úªç¸$í%éZIÏHzKÒ³n´Sr.hCÓ:÷è;èKqÑïÿúøb÷6\à àB3û¢Ò~üØ°=E+Ã̾7³=ñuf·¦Ì˶1ªqXûAдÅ9ã0`G`U`q|Ni[àܪ¾@oàÀäT||;LMuzk o§
¶Õ²D·"$Íêíkfo·áúcf§à.õվߧ{§×AÐ)het?p.ð>d·°O:¶¤CÍì«
+Ûüoff;$uÇÓÌJÿÜãü©Ìöæ1³÷˽¨¤eîföJ
ýwqÿ¯Ý^EÝZ°ð¤CÌìüJ*¦µ]Cpç£Û¥wA5¦já2³CòÛÉi`;|Îi*.fm&9%|JYHªôÚ[ wVXI«áîê[WZ·VÙ7¶t¿
+«°óqÈ® :5YÇÀýµYT)f6¹Â*[ày¶*åÀõNbfïgáD*;¢àA4<m.IÛIúéw^Ú}6)¢S iN`y ¢ÇÅç÷þÝýª¿«IúIuï6q Ú
ö±7©³°ðzë¡vþefßW{aIËIÚ<EöX½Úv Ìl"ãô*ªßlÒëAtm.3»ÁÌfæ~_ê\¢PtæÁ-ÆJY
+4 IÝ$"éeÜý@Ü©åò´¤`ÇäR
+JZ¡ÂzkH*µì a¨ÅefÙÕÀ]¹v^¶;xب²Ô·Ô©°^wà
+ÜÝÿ`13û¹mNÂ
ì*Ä4×vÕ¦øÏëTzÍ ¦*á´¤]²;t9« æN«&C=@åײÀ°4<W ÇÓlbfe̹ÝÌÖÁTß\åúªÛ-«¨w/°qõ :j-®Eÿ ã%½|<Ì¿ü¯ë æ¡rí|^II3;»´6ffC+ñº.YxWÂp`±
+ëAt8Õ
+×<bw`!ÜàÇàEY¹±¹©`X¢¾XºÖÞ¨ ¤Ôx¤#+¹HZ
+p?Íßr¿A
+MUÍìq`PûR/ÆãBT ³àa¨*aV<|UY¤ô#gânî®ÏgS®á
+ Ð$%ʼp¹±@¥×
+,ØêY͹/EÛ(¡ÀÀ´À»F+¬ÂA§ QÓ¬G³,i6àMÜÈ÷Ìljé&ÊæC`
+ë¼.3*éoÀ
þ¼ßZe3"é^|qðå\î<àq%ýû69ÙÌRM¯ ¢!
ËÌÎÅø"©/î*}Óã¼F0½ ½Uá¢àñ0è%i3«ÄIã\|nl[Üð^Å_o%Tcq[]ýqá hHR¸òÙ×ÀÓ©L#å Z&AÛ8HÒ4 Ù4kD´úñÔôÉ$ÝlEPr¿4r¨4îãªþ® ®R$«êµT¦!©î ÚZxd¥R\ÅBm"Õ¹ßìNeCxÕ0îª^ij÷&TQ/ Ãè´ÂU4ïõn*ÍR$'ü°ãÖ4
+;¾¼@ùóhwIÇÌ>j×诫j
k|4 aérÂÕf6_¯ÔÌ)BÒ¥À7xØ£Á¸
6÷ÁôÎ!oÙxIÿN¡)fMÔø)°_
Uç¢B±KN0=Rø§ e®¸øCä
óh[ã I¼
+¬-i42©Ô<ZµüxÔÌ*µRy4ù k+N@ópµ¤ÙóÂSæ<Ú×ÀoÍ%JÌ£
+3³â!&oÊ£=ªx='TX' èp1m
+ÓxNª!eßl-Ë/à"óhzSz=Ú"ù;p§=RÉk4;°³°Ââ
+ SÂÕÄ¿?Ppá·À-À=ÍìN©Pò¶7MóhïÒ\Ì6VªÉf¼!ðDÂA' «ëc$mafwTR1E¸Ø8xFÒvföfÁ9ãñü]Írx¥¨ñÙ<Ú
+Àñõ ¯JÊÚø°ã-tgsà¾JúX¸°p§¤n5PAP2Va=HÇ£²WSÿ;3Û8
+ø¤¿JZ¤zðHû³ ÿ[jý¾ÀÏp1ùX8!éCIIº@ÒA64¤ø¢è++é{Oû ÅÏ$&iç*R¬AÔø#Êaf·Hú¤mÌìæ*Û¸JÒCÀÁÀ³iîìi`bîñ·°>´·
+Ïl;3ËGy/»rû4ͳÊs gXj¥æÑ26+&E ù+ðp¤SKªH¢APKÂ[wÒá̬ÒhèµìÃæÀéÀJföCÛêl,G_(=ÎÇ |÷h,*^kIàq`|¾*/lóã$
Î!ÃÍì;I× Ù%-´¿n}LÆã.ÛZ~1IýðÂýÚòúöCÒQ@?3;ªÞ} Ú¤k[ÌìÚz÷¥½á*ÞÛñ?õÃêÙJ4xÑÌN+r,?/pmà_øìÌ}ºy4IçâgÃCepp.ѯ®'«k1#WgW|ï3«ÆË°C´)±è¯4öz*ùzÂ_ëÑø<ÛÀ¸ûþ$¦wÝÿ+°1°$\Èötp
+«é ( «fö¥¤_÷KzÍÌÞ¨wJ!i)à
+`[3û¦ºiþjmàr3ûkA»sS|íGr§Î·¶ô8p¬
+æõA´FW ÌìI7IZ-¥Wi($ý¸
+8Ǫ̀¢þxn°¥
+ÙÇxGrço\§M)üîôHeC`ÝëT<~AÍájä!¸
+pWò4ü¤Þ}ÊH®éCð±ìË«læXàÂÖ^WÙx.°>¿UÌiC¸¶îä²Í-´ 6ÂÕ
+fö{IÇC%mÙÃ)¬ÓñöUM¨Kü÷xlé¼¥ÛqG xlÆYI¸[ÿû¸·â;¸«ÿH`¤}ê÷ÃקAÔ®20³%
+´U¢&HZf7pX¢Z ×RIËàᬮÇjd*£Úê¾AP-!\ebf×Jz¸AÒÀß×$ñ,ÿiC;?Æç¢öoé<3{Ø·ÚëA´ò©§Ü¸Ý~Þ×4HÒU¸;úfmÙ«ßGÒÈ :#!\bf#Íl]àÀ)O.å5GÒ.À#m6³çÛØì9ÀЮ¼81®MVÝ%én`'à2Iï ÷·%ròà[wSß\¼îø¶Mm¯ÜÖ¶ êEWHs\×HºØرqç»Iñ KµL.An¬[WwâÖgµèk°y¥ ®ñ^
+\*iV\|6ǽñ4_ÌûQzì
Õü@O`0¸ODÙbàÚJIQ0îN1³kÙvAGÂUcRº»È¥"IkæN¥?¾þj0¦¤mFÒÀÀufvA{^+ #áê 8} ¼Õ×M!¡îî4³ªdA4áUØEIVÞ½À#fvt½ûAP+B¸º ÃEë÷õîOA-¡Â.¤]³CÌìº:öc>`Y<ønAÍáê"¤,Çç ëwT0à4$¹l*Ëå»õÇBç jJW@ÒºÀùÀp`53ß×O$§åp×þ×qz
+wéÍÌ>OõúáAPB¸:1ÎVÄ#ÅßZ6{ 3½5î ÔùÀ«f6º× ¨®NHÊÇu8°>õk3TE;1½@-|@@]0³)5yAm «²1ïÇ0¼XÞÌ>*£^¦Zø
+§Wq×ù³7[
+QAPoB¸Ëp'\°f.0³OK»lAYèN@=\ÏCU8 ^p5úâw×Mei<úÅQÀfffJkµ
+ùæÑ4Ìw'>5®Ã_HA;ÂU$ ز;_*óÏ àbõ1°$°°¤eEwi²¢.IïutVæ &«$«é÷¸(ÞÀ#]ôJe0°pd:'¨[Sðy¨ÉuèzAÝ áê`RàÛeÛÓãÚéqMõ8ðOàu3P§®A4$!\íDZ°»4Ó{óõÁìf"uî(ñIºAЩáj#vóµ ¾`7¨¿á5²N]
+ ètá´µ[¾«äP± Ó<ZM@]¿2#A5¤ÓWÓw,îYWáJ©î];ÆEé5ÜEýàõ8 è :pIÚ8X¸ÑÌ*B.©.H
Ã|=i¨+ña¾/jÓû Z:p¥áº-qÁ»ìÕJ½¥~¯?¾`7滨1íô 6Ò)KR7`;àt\lz§CßÛe¡Òy1}È£E÷h²¢.K#Ìljǽ 4´p%½_§âqúzçOîV´'.Rq,¨Û?ãv¿ïÀ®AíDC
+WÚÛ8¦h
Ì
+Â#O< \/Øýº£úAt<&\³}ñt3ÝZ9ðpEXTA3 CRrì{ôÇ篦âC_á®è
y¢fÃ-³aë¸ÞAõ¢a,.3 é<`3 ©;0
b"¨ sâÎÏK:8'. º.
+#\ÅH©âǦòL©ó$ÍÛ|ÀÀÒÁ Ãihá*3ûøx¹Þ} Úã
+ rá
+ :!\AA§"+ èTpA.I+ +=%.iP½û´´(| {úL¨w «"inI«ãk[O¿¹õîW{ 3«w ô*z¤;ððmZß^mAÒx¾³Àdà13Û°¾½
+2RÂÔµðpk Ù¨ºv,¨
+IÇÇà˦ _ËÙ¸ºv¬h¤u\ßÓÔ¸xïñÏÄ+hÅÿè²ÏhM<qjWçD4}xuIf¨0 Ê¡kæí.96;iÔ.û{k¤¡ÂðdÔ«#AÍ8øQn{L½:ä+zâÎÉeøPoÆTàó:õ¥]iç :äq6gÁîÏÍlR=úåÂAt*i+ Z%+ªt°¤/%]^ï¾3ä40Öö^2³s;àz'gÙkí}½Î¤ñÅÂßÙDI_Ù§éøìxvð±Ù¾´&`6`0Ï">ÚÌ&¦ããÌìûë Ï<>;ðnîü~i?Iý)f6¾H½fö]»¼!U ii`î"Þ6³69I:X¸ÄÌoK[Mó\ÿÝÞ^7³Æ[SkfQ¢´Z½ îè ë½®·q½_{#àOé}¹÷ ³ôÙÌ\¶³2èêö=<O~GÌ0àS`ïܵVåÚ/t=¶àZ¼«÷fnÿ·Àþõ~ïr¯kH¾pp
+Ú¾+µµG½_g
ý¼Wä=¹°Þ}+VzHZ/iØ$3{24I½UÓæfÖ,»°¤5ðu:ßÙÐc+}3m¾ Þ1³osç¬~ /ÙT@ºö~øÝÀYé®óà#3;²¶¶î¼ÅÿGÙÔãÙ÷\ÀH3û"wl~ ?ðM:Þlå³5ð"p*08Ø¡³}ísõÖþ|lÜê\ÛÀ%ú 7óWÏ ÄÿàîÅãPn
ßd\|ZPïDàyàïÀ?$½fe
nÍm?)©;Ð03û
+¦Y"½ÈYiü»ý}XØxjk3{§Èþ
põ`Lö»I¿Ùñ|)©/~ó1¶Hû¥óú¥Ý_YR¢
+Þ#
ñï¹xè½U¯®)`üÿ½Yzã£xði¨¥wÓó¬ùÜûùMHûºáÞ,©Ýɹvû¦6Æ3á¡©ë9>,·ÿÁu^,wl
+0°àø3L¯Ü_»£Éí_¯»_§º¤í5Óö;5¼Yõõf½ï.¡PÄâJ_öosåûÀÏrÇ×Þ*ø®l=Qðýøæwûaqÿ2ktÁþÒþËð5=BÅõNÚÞ8÷ÞÀ×pMJÛóë§ç©Îiß]iûð´=$×
+Ò¾ñ©'äþþRï÷/õ1³¸.(rl&,ÙÝÒ¾{Òöi{qà±ïïÒ±Ìâú'¾nÑáÀOÓñ>øM^¾îà'éx¿ÜþñÐwSR»Ùç0.º¯Õ:+W§:g
+[½ß ûµð\Î;¥Ä9kÒü÷<¡à7õél|} Ç¥Ç+rçÿq«t®ÝÏmrçJûO¾KïG³7ðÒtb7\)K ×iÿéñèãÙõ:ü/û¢LVHç%\øxþ2À@÷´¯P¸fÅUxѺ=p]èQplöô%>ö¿`A½¥kKçõ+¨¿hêWïzÿ;èÇÞL¸mhÃÓöWøÝö<øâGn~
+¬êl+ý&÷]ö>ÂUêsÈë?û¿Kû/åÊé; ×ÍéüÓö¹62áû|ßÏ?4í{"÷
+׶4
+¾TPN¯÷ûú8$×Çq¹²b:¾þ§ü%pZ:÷®ô>vÏ}7¦ßÅo_§ºpOuïNÛ§ã½ðÿÏ
+ñàÆÿHÇNÇóÂõðÔ·iÿ¹ßÚpÜÎßöÇ¡±iû`K`$þÿ»f÷dó\ßâ{t|ö\?Å-ípY= ׸Õ}6þÿû}z?fKïáûé¼p+kBjçÀtÍ/Ió°©ÝL¸¾þë´Î¾:<gê¯P \éÂïѤ+x2á:<mÏX5ÒØoîºëx#»çäêðB:ÖªÅìáYݱÀE~è§æÿ¦»ÍÂÒØø0·o
+
+4~ß?öBáúwÚ¾$wNö¾ìÞÃ-îEÚ[4µy.lÙ]èªéxWñÏ!®ìϬCsûfϾó4 ×
+i;®Osçg¿µA¸U15m¯ÿá>¶ÿÎß5m?FºKÇo0³?
sm/
+,Uï÷/õ%®qømVçÎù¿Üo|40WÚ?¦ð
´ ×?ÒöºiûÍÜ9«¿þÜå
k´ïâ´}\ÚÎÝÓö*¹:ýqQÌÄó[½g·ð¾l[ÈøO
+áIDATþk/»ÑÙ¦Ó¬ÍçÓ¾ÓÓ9p]TÐn6÷ú+ÜùÃgÒ±=rïqÖnfÕÎÉëø¬Í¼;üßqËeo\Å'àN
¬
fúXJÒjEÎ[Ò2øYæÁø~óq$ð;|~ìüÏðþr*¦<PW ½ñ7fW|åzIó¾3nξÉ6ÞÎKÇ¿Æ¿d¿Ç'âB¼!þ^üÅ,<WþµË#=ifÍ¢TKê<\Î{¦l ³µKo»>â7`4LÒsøÄo«iÌÌò¿ÇñÏvüFää´ÿnüÆm-`¢¤+Íl8p>>äö¤§$
+^~\Õ+k?n4³ÕseXîØ4
Â[ÐÂ,³ÖJ
^Êæf´$ðþönL;^ÀóéqbÁ9½Óc6_\Ö)ûmvÇçB·Æ?i!ë=`fá¯ñwi÷æʵÙ#×ff}F¡¨`ûô¸K*àó¬ù¾öεûmjW¥ÚÍ»Ã?¹Ãÿä/ÀÕµÝÓãµf6YÒÀþÀn¸ªç9,ÿÙÃEÚ,Ævéñ3;-=¿®Ìºã¯í]\dÁ'£³±ûksçaf×'gãuÌìZI×á?úo,çþ-éÔæaÀÀföjýêJ¼'ý\Ò_ñáÁårÇ2V´¡=&Y{áwßâúöÅoTÖy&§iÙÿÒ⮸5; ¿£¿-òLª÷FÚ¶¿Í5sþgôyjó÷îÃoÒfǦ.±äLefJZ£ÿ³ÁÌ~+éü~@jï8àÎÚ¼5cx1c¬Jÿ×áS&Cñáìpç×ñØ^Àþê.hfïæÚÊþÌ໤v¯6³$ØBÿ2G§Â6Áßó}$
+£¹ó
+4}ÆÝ_ÙH¶ h,JIÇà7:÷á7'Y¬Ø,=J¾Í-ÍìToYü»§Ð äÜ`Ùkðÿí{°WUÇ?«ÞÔFÁDÊGZ£â8©ùHÒÆÉfÊbj¦kÆI1c>¡
©)N ch2&ä^ÕßµïÙ¿ÃïÞß岿3{îoí×osîïì½Ö^û»9Q¶"þ¾óÊ!æH¶UúM*áh4%5x:·Ói*D«áÈ[6-9qÕæaRKïB/¤o& L}ìÉTÌg6)ëÖT\©ngO®É<¸_È?
+yFÈG
ü|í»E6æ|3ñÂf×ÐÛ
+ÛЦ²SÙ¨ý Së³{ô"Z9~9þ^üåèþ¯ÆEÛb*,©W]»Ã_å3C¾9S<ïÄ/Dùd*3êKñ¿Ìx
+îðÈ,èÈò p4)u9Ú{rÀ£<7¼«C¾<äéx0û3® y3ÒðV<±{27ëckö9ÿ=OÍƾʤwF'Sáø&ýçÇ'êfîÛ"ÒîÓ»?9´$SaçR?<ÖV¸ûJ3[+?-äÀ^³ZÌÏêßçîWðÿaÒlÎ5³{]«»1.SDOH³xòÖInÇ¡6GWÁÖ:Í^f¶»»'u|³»¶ND÷)hõÚ±]ã .ÜCÐv0»ûSw?ÇÌæÇîðhrS¬¨ÎBf×h5ÖFeJVëÿîí+Øåp+cIl%<^´W¸ûfv:09àî×ÙRdÖÚYs[ýÍháþpÈÏ¡ßMÒRÄaþ3ÐÂzÚOKxê]ÌzwGûÅÑÇ?Ììȹi-Z8Þ^üë£N]ë]O÷Zïwvþ)t8û4uZ¹Üý<3»Sí
+ÞU¦Çç'ô?ikPi[ §!ëÍX4,kMV
«Æßp8¼Sãj2KÖ5®
4Ñ0+#^È
+Î]Ìð=i\£ÑM«ç
+NzÖ¸ÞZ:¼îGª¯Syª$kß4®È[óéÈ{ÀþFå¹óÃV¯"K*©¤]#Å»ñf¤d½§®oõØvTzÕì¾mñp?æ!×Ëëkõ¦Å=ÑÅü©Ì4é3á"*×ÈmàîOÙhE Z}¤Ã¦q
¼*ädÛÌGG üb4Ù¤ï»ÙoÓ¦ëýÑGZ)lÛ'"·÷Tï¤þC÷ãïÈ[PPP°#°9ÄL
+yR.lÙv0JX
+
¾ `ýØÌfÙ=×.(è[(WAÁ®ÐÑ-GAÁ;F1¼k0³¢½ÃwÜêñì,P$<¹Ú¹ûª(ìîîÿµÎÂ
+V»ûú¬,nq÷²äuwoÏê@Çs÷Wã{ ïÐ-È`µ7cw¹"ïâ!gâPùH´~Æ$ÕÌ>@0ç¸ûÆì =ñqí^Í~0®«µ GѸ
+ÞM|â'¶z ;ÚÂUh£ýY3kfgGþ*3[/tÂ=»¹t?XÙ3;èþo î5³tøsý*ûίáCþu´õ~'Æwò
+È `ð(<lBç
ÖÙ9Ñï(äÆü2³áèXÄt}Nôõõll#ïØw|'v
+´Ú±¤ÞIh%Ûy`PV>&,Ðã0äÉ9°V6$ú|¤O ²òìxÿ,¯ ÅMhúY¶46tVfXV>æVËÐhH at -}WÖçàZmÈûBB£ä¢L^<]ÓÌS¢þXÖçsÈë5ü¼ Ê #ê³×¯_:BþZÈ7¼ML¿§â»Û#îiê³yÿyÜnF^¿ÇxßDç#¾¿í¡sDND@§²çïhr{O«MI}3µ| %õÒ.@ú]OÅXýð¬M:§¿ ÎËÊS?S©/ÖÇDù!×ò¬¯Q±k<:?¼;³ðddêºÆñ,>íR[Bò}h~i/¢<1<ÙêgÓäY¥ê+!§s9¿ù42;D´fSÖóhí^¤«j; ¦P]M\³C6ªs_¥qâ=1Ä/ÉòïÅY^ÎV1/Ë7*1(SZý\J껩
+û?FfÛÑËg>Ús¸örÀ»Pd£P ÂÁÀUMÏ@{Yw F±ÇÑ>&©ÇeÍ%µòÑË¥1ÞKÑx%¢"»i³£þè ûf6Míè¥ú¯¸=Ð| ñwFãl%«ËºøØRP½D²zè'¢õk#¿NPü¼»§MìÄÓF÷x:ùÒX½MN¢ÚÙrÞî¡ìs'e|Oâû;ÃtĦRPÐ9KêD¥qyÕw_´¿@&¾Æè4þ44Á½F#`Ò¸¦¼gÖçt¯q¥
+CNƵ,ü _ÙY!ÉúJÚÚ~Tm\rQ%þêW!sÖ^~6MUÒ¸FX_¯fÒ.S¨å!×øñþåIãz;ÉîTZÜùQ§+뱨gݧiÔ¸Ú²±O Ò¼÷AT@¥æܨsx\ã4 ª¦>"í>ñUþõݾÇ%õ¯T4®þ´ºM«ø×ÝýYWâi¡³ VáHëI¬Ïõ|â{±y»Vò4>ɱÈÃÔWò/vQÊ7ÑÈk¸]Ãñqào}'Äãï
+(ÏA]Ô[´ÒÕha±*ÄDWØ-ê/Gâw_ÖMý[Q»=Ñýÿ
+íþpCDöD¿AÖbvËÀÝ;ÐÄKêÌ<
+èɼS°ó£Æ iXDo5±Xjfû£ýf8ÕÌf¡õ$ôqôÂê
+ÌìçÀé!×Éë¡þ¼Ê&Ù"*SßFªFW#g¥È¼9×Ìƺûfw÷9qÚ¾ûBü)ú-¦0B3Ð^Ý#!/DnêÉÜv1ºÇFÞcHûªP?=& gªWnó3ÉoE͵H3:iG)&×[TôpÏÊÝ·Ù hB:iòËP¨ö-A¦|âú¼ÀÌ&¡ô0*º´ß è+(znAA×hµÊWRï$¶
+CrPȯeu§ÙÁȱ=äG»òOúÉT¸:këÀuQÞ©0o³85ê$SáìÚø?&)§2!m%¢M£ß&¸Ä0ï(~Ù÷'SâZ2Èþ¨L
ÞAd*ì»Ç{Uß[}ÿJêû©h\ý
+aHФ4
Æ o¡½vwßAõÎF&YÈâ#è|Nï#·ùCQèßFþøMÆ3ñÂ/ü¥Ñ¦!§»?hfGæ¥QÈTx»'cïhw»¿afßCÙnîþ»¿ff³sÇMî^xWÐ70(ï@.õÝ¢0gl7"Ñg¶4;êAZÀæ8èz,ò^Ü8Ð#lAß
+CM=V.( ìqô_Î.½»I«Â3*ªíÁÿ 1t³
+OXx IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mpm_pack_pack.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mpm_pack_pack.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mpm_pack_pack.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,307 @@
+PNG
+
+
+IHDR µ
+ 3ûÅ sBIT|d pHYs
+×
+×B(x tEXtSoftware www.inkscape.orgî< IDATxìwTTÇÇ¿³½°KïM;öÞ{ï½Å$FMbÆXbª½E£&QcîػØ*¢Azï°l/óûC×T0(¨ïsγoæÎÌÝ·ï½ûfæÎPJQÝ? j TFz mÊHÀº:!Û@Ri< S ðJ¥7 г:¨Q*ÍÀ2dÛhYFú§ ,J¥y\l uK¥êÌ.î [uàZ*Íþ
+ê< w©4 )eÈ6йô1 J¥9Slg ÍÊH@R*ÍÀ7¤ó ö¥Ò\,C¶ ßRiì§:J¥×Ч:ð*fàÓ2d[hÿuþ¯÷Ï»xÏ¥3sÏÿ?íMßóCP:£:~ ° ÎÀ/#Ý «T¸Ya2yzòI©t aupÊ©³à:K^ ³è:s_ siY A9uf¿AEeèÌB)SKßÀìü¯ÒÿëKtæ¾AÍÊÐùE×â¿t~JY×"÷×¢è×bY:óß²Îqÿ0÷ü¿ufîù×")q200000¼Ó°ªZÊ1jï
+ïQ#´"¸TµÕB2¦BsjLÔVzJiQ9Û@F)S÷ôb¨<t´OÚBÜØUµÈ¤¦Tµ%!HxfV®<ðHUëò!S¬)¨JXYB=§mð§Ýø5a¬°v%ÐdH \FRXúy<3O®
-÷utc¨tJ¥Q[@SÕº¼÷aõ£íÅÄPÕ|¨d)(û`zjeÔ ss7wǯ
+«Zü¤[¸àcìòÊSJ
+ Ò+jÔ ð"I]Eˤ ÀÈÉ?¤ø/U¼«~i*»z]ªóõ½ÅP,'þÓ,´ÅYUÊ+©kË"ß´3®*bÍM
UUëð"Ýz¤ºªõøP ÎI
Ú»Wjc°u©£¯j=>D4yéïÄ\-ÃûÇ;aÔ!| J)c¤þ
iNí]y£î À³ª`````¨¶ tz'zj N¨¶^tU¥T`O¥µâûzQòBåC1uãÚ]Ò#Q/¥ô?y[20000|TÚð#ÕQ;½x&Ã0-!ªhÃܾòYUu&þ¿ÙÝcó4ü
+ϼÔ0nfÜM¾R^n×UwT¹Ak¿NÙb-ej(Go³~ª¸¸ytS«»¶)vsßt÷ã+Úw®È}°aHÃ#õÃ<¿qx} ¹½SâÿK½ñ»g»,|QÙ»§Õ8¾¢}ç«:u?¿ÊúuËÙu}]Úª×Ëd®ïRóà¯
+F¿n9wßêºáJë©ÅÏR´6j©G½#Ò6|¶.aâ~Av»ì²v£EgÞ{é2zT|mǧÿPP.a±å/¯ói;j}ïZÆ¿pýÝÎYëZ^òwI
pbE« ¬bY,nº{Ã~;NÜûö~ÃÛâA¦^òÉÂlMô¹
+£Eä7Ö_V¦Ý¦7>³<`:®¹2w¦e í(aå¯í'¹PÇSüæµg0}ùsº¸ïµ»uÿO< ÄÝÝ·P¯UvÈM©ãÖÀIYzój¨²8ÉbsÕlO ÷O-cÐk¬]êõÜö¢²)Ïת[sùâû!§Í?¿2aÜòo+ú[X\¾Åá½tÙ+0°Ø\UEë6qò÷.AÖù¾nùRiFMohÊâ¾[ öøQç´¼¼£Úúyÿ¥nB|Ji~¥([I3Í>»4å eFq»gC¥ñ÷üÍ¢onÓ}Úá`WHOüloЪFßÜÚ4)üD^©ÃÀ«ÅÉíÆütà'ORª§Ï<ð·{~)®oj^¿ËWAMßØ=¥FÒ~ÜÆ ÐëTäʶukuH¿¨~«¡ËïØÖh®}·ý£:ÅyInVÎ
+n>ªcé5E³6nÜ5}%A P¨¡ÏÝ20$]o9¸.? Ót §C5ÎR>Ñv÷âå À©»D\b{@ÞyÕ
+¥ïªÞÛ!:sWs¶êìcógÍ
±\6èùXKÝÀSdjï^ÎÂAÂR¥èÇ4$sÙOæªuQÇÔB¸C
+^¯#ç½|,¸|q@ê£óÃ,::ϲ a={ÍI¼Ë»¶sr^k֤߽.<#Îo6 ÓXr¸gÏ36W âðDÚÓkz´Rååð¡y)¡õüìÓqįQ[Mrk8¢QYg '4¿6zQü¼Ô0îñåíî
]bëÛknFÏ:÷×ÀJyF=¯cýõÿõÙÑ3k{7/ÈìÁáÒû͸¸ÃhÙ¾ -kÓMdîÚ+¤÷vä¨Ä¦¦ÍèY\þ3C~~õ£kòE)=>? 2w2\Þ:Þ[)O·Vç9éÔENÍGú·´8ãز6Ý(¨hß|¯/¹|³¡?:±ªsû¢Üøv ¡µ;î<Éïqeü'Ö6ühTQ¶ÄE>5á"EW`´êÍQyá¹*
+«2hUÞ7÷Mw =_le}ó½¦ßÜûÅjYfTçݳ]üÎsÌMv¡ BEAjóôÈ¥ëã ÍÓ}Ú£¢§÷ÝòÿöoEAjyV´hÇwvB|vì»3m·@nò}^JÄÿ{'~ù»(7¾Ã©5=NlÒ öΫ¹.+.pFYàðÚCCôÙÇG9z3 òɳ%*#öÊ»O=ZÔýÐCw¿óÇä)Üн¥ÁöÅ8ÛÍ$céú%ì¢\%5»¦³üäpÑ þ
ýï§ëòTF^¿óÇ®¿löÅ¢wÉzÀÃ,½äÃ
#'*ì6FãÕôϼÓt ÐvSþèc4µâòVTõßÖ9yWY8Ó*eÝ5|VüÝýÃÅ.JæZÓã^§¶dq¸Ê뻦$À±åm÷tj+@V\òI¾0;¶W^jµ[ãdËGZ»4z¨.Îozm¯ pçðl§âüäÏJ
[îIAEVÎ
+ °ïÇZûTEÙ^bç/Û¸ÿk7 Ø9Ëñ¼´ðaNõαØ\
ª(ÑHÓ
+sú§E]ZÉ7³ÓªäG´Ø ¹É÷ÝrâÀÙõýYüPj«QÉ\-hü7 ä§=hxwA§6ç
+¥©WþÜ Ö®cÎÂÁ'ÐʹAÄ¥-c}òÓ|iíÒð¬¹}«:M ÿ#¢Jë©ÑQ>H! ò¢ ¥ôÞãMÐfÔÚ#×v|jûøßÁÛ;"§gÝØUù«Väõ·<½/+¤øM¸ç?hä¿·c_¯ó[vgª')üø'IáÇ:ua7KÇz¿ ¥F«]¿Ñ¸ÏüìK[ÆúRþøÀ6»/lQ¯~ׯc)5{4>§ÝØ¿,nxwpN]ß½aÿZõá®â»s{l}b)$òÑ
+wçv?|£7KlnOµÚ /j½9XUkvqäoº¿Hn¬çãEm5T¡÷XÕÇì( (´Fñù6¸Ä°1Håé$aågq êþ÷i\¾A
j4Íâ1Kûí©¢;BÔÞuí8Á**Õ^t¿¾=§\¡ë>tXlË7
+Ø0¤ZߧÝØ¿ß0ôW ¸°iD=9ò·¨Í °{¶KãÓ:ɳß5G-] {æº5 ôùÞzË!ËÒßò+[8=î8qkìñíwæ¥Ï´Hê°×$«.θýó¡FÞÃÒ±îgn
+ú*÷íJÅævµî O(½üàÔ@º=¶´ÊfãVf¶ãp
@pY¿K`f}rðÜ S NmÿÆüzÌíùy)¡f6gxBsOh~/3öÆ+¸?â·¨- à7ÃzÌU¿½:NÜs{®×'ïOæð@fzRØaüæ MÍJ[{L)Õ®4£Æ!]
gòk:)ÕÃkMr*«êwgõ¨Eqk¬
+Ø0¤azÔÅ¿.ü32 ¨Ñ`¿gû§¢ËG¾¨@#ÚÇ7¸`g[MÌíܸÏül ÈMiÉå
ä¹éýü´ð b aµûw" 8xµ¾µýK °vmücBÈáñ÷$Ö5þ:?äð9åÅÅÞ9\zÀåÝ¡j·9Å»xðÒ/ÄióÔ¼ãæa @) âr_ø2Xßí,eï!=Ïçã
8«9;CÄ}Ãòfε¾='Ã$ïiÅN?¥qiáÂͱ³òlÄ,- ´påflRµqÉ)-WÇ(ÂaÁ8¹¹0pjaÜ>ï<6îÍd<¾²Ã»ÔíñlΩ07ÞÍá¥9<QFYàs-Åæ¦ý?]¢Ó×|Y=??veï?
[n£Qä
+n=bMSÀÌÆoô¢ø5ǵéV9?/5, 'ñ®7¥#Ëj ÅQ$¶ã¸6'ë©A{!<ôYNÂâd&G~nw½NU dQü§:*ÌM +H6ɱXìea¦Eéú{M?uïÔê®òÓ9´°ñ"·&?öqéÆËtª(6ü(mɽbÔRÏÌ-jg Èܪî@ØÈsþZZYmT7Jz;öz8Í©
+³\tý&¢öSèä «²?°*{ÒèÅ + JÈ{Îȱv§kýf\ºéàÙöÿ±* ½ÁX9×Öi
+ éÔE¾uR£äÖo] +þV=.O| úϼ|}âïyCu9±0'nvjdÀó½h·NIű¾d;1+ÿQÁ¼?YÄ%ª«Z¼ú©åÁk-®ìm :ÃóÓZ
+cF5¤ò9äÙü-õÿ ã-]¹iÙ{Óq|¾Á±Wm~ ä(V*# î¥éíëÚqÒà»v¢¨°éV~ëúKN¸®ìñ¦ÎÁûDÏÏòÒµÚo-^·ýk:¢
,3£Qä³Ôü.6nM.v¿)Ì ×ÖÎK
+ãZ×îUmðÅVFÍ¡ÐsËÿäðDwMf%8;ð'
+¾øÏÈñ-¸Å&ùý3jaìúQc×w¸íRçI~©Ñ`þ*OIeaf;à5è:NÜU2_(±?Áâðd¦º{}yrCÓ~?e¿¬NBXJW¨,3Ó÷ÛãWd~iéXw,óÑWRi=5×9¢Ç²Ëºé«NeíPß6ÓöâïM#ï#øÎ7è5<¡4\§Qx´ªÆüÎ¥n_l}ìào¶óÅV×zo2üç=<¡ôzÔÍâïùßµ æ¯ò´Óí³wÌ´aïúÞñw rzL=wO«0æήÅaÇB4Ê^íæ&?8%ºê÷ñ¾Øò¶A¯µd±¹I%ß$ª~;dýÙ,<,Ùy1y;r'4$²PÓÝyKÁ¦NÜä´By+WnÊ×mD}l9IvÉú6tä¤-éaRvÆ7$lVµ¾WÞ=Oi¸Y°³½mØ[ÉFKTvÊyY³³ÓtKÞIÑYþvIѶ='#En°¨eÍN{u+ 0fIò¿Üî}ÚO_¹ïز6¹³ànx fÖîXÕéÑ6'³<mÔiÿÙÞ{'ýÎÞ£ÕàÉÔð¼.æÎÎ vKm<WûsÀNÂbR£ÁJb]cûî·rª¿(äÌâ¡gRj°è>åàÒõP£^ê÷ÕQJ©Pjçµ¼tÏ®QÏYGîÿßkÂbRÞ~âêü~/Ó_ ±Ýçÿký®0'²x¤¥b±¹éF£ÞÚÁ³í-¼.ÝOÍÒó3çEéOüQÑPbt´à<pú\\LA0'_®¡©eåÑng ÒòÈó%õZX¬zÓ¶r87ö|ÞX)ÏpÚzFwþdWDÉ :pôáåõxBóüÖ#Vß±vi¤Ûþ3]
+2"{uæî¹?û7nÔkNdÉ^Rξ¾kj_®{~ãðú FÒ}ê¡ wfm«¾=g
+H;Þ¬qïyWkøR OÖÀåÄ×;&u¸å¾ÈÜém¯¢ÉKgú«¯µ,ûq¥´Úî@éðSgÑoÚßWm¡rFjeI7nfO^nÉüØ<È?B]³%»pX=AªÉ3ñfÎ*Oiä¨ÃÏئvÕPÂ*ÑwËS¹÷Òô=jñ{cÞ®vq²Uíkpó àV²ÎòËEý6
+¿¤³Ü\'âÎ r4Rík°ôuääôõæg²ÞÒ*¸57V¿]Vî¤Þ|;-BÔιqÍ~sn¼öôIQn§(/ãäÝù¹çPzôeðdú¢<õ\Þ6±vrøñÕWôHû÷NþfçV¿·Ìäm"øÄÏö5É7=Lìåø
÷¡]¿¹'¶pÖ.W̸üèËæ¦)zT,i>páKzð©%èËôjuV¹Â ! Þ$ôF<¼Q³ xå¼-£VÕÚ¤?äªZ0Fzb2j÷¾°ÚYÕºxZepàgò̱öçôþêÌÝ7ÙɨõyåÚl§¼¼Qc¿±)¥~ø°t¨£³rª7¿ªõ`x7¨eÍVLo-º^Õz0§kÔ¶¾R°¿"ãë·ÑÎâi8Å¢w%J?CðÅVƳ/Tµï6bö£&ĪÖáMÂ5÷w¨B,@a`````ø.!Äû0j p®j%ª-\ Þï£H at UëÀÀÀðá¡ÉKW^ü?x(¥J Çß £ö:æÇsSÃN1»eWFeñ;³×Wf±·'LmUÕz|¨dßê^[A¡Ì1ú«ïkïUÆðß!¤°Â±HßO£¦Í7ÄßùܪVåCE«P¼drýÃuýÃuï~¡ ò^)õöQ(
+R}
+«ã«Eç½4jZ6Z«Ízµ Ã
VdeÕS 10®ª§Ò"µW2o-
+Ãy?!Ä@&¥ô±Ò!3Bæí»*QB2)¥ÕõNb©£yU«ñ!CtJcqAV* YUëR
++±eMGf¬§jQd'ä Èx¥ B@Ïw¨P(÷p¥½
½gEÖÌV@©$FpÙ Õº»,Ôô¨«Ùz\¹Â¯1T>w|aQ\P=/W_cýþ¿É«ZsËÍã²Ëî×Àw¨QJ£+ZÆÓ·¿Â¥Qßjwð}&'õ'1:à_{)UGX"3£KêÛd¨R¬<ã*V
¦/
+Å2îªï
+, XBõÚ!.fSIw
+SOÍÀ1B;!d MxâjËÀÀÀÀÀPí!°! >$|
+à )¥ÕfÑSCý:skb ÃLÃ Ö ø@<yO7\«
·uf sSWzVªªÀ
§z100000üJi¥t³ÉpIL¥¡Nõ4Ü<è-ûEñÚÍù§´Ó*YYeeô5|VfÜM¾^§zn
+[fÜM¾F_n#®×©ÈÑe{ @عå6g×õmjʼú·ÅÑ¥zøÙþEe3ãnòËÒ£"å&p-oÛõUrG¶êùºm|¨dÆÝäïë>ïøöK¦ïýÁcæÅÍûV¤®³ÖÝ>4Ë üfX6¥üÁ¨3löø¹îÄÝûÇ·{æºÏÛ7¿Öçþà[kô9¾³Ûvn¹ÍËdvÏqýõü¡
+^§þ;g;ÝØ=Æë}xxy½åñí;þü½KÛªÖ,ô:eF=ç/ËâZݵ͡¾ÃÎýÙ¿±Rή¶öͯõEäÕ¿ßG4 (¥4!ìºO)ÐbH»|¿Ú[%Íx,¿7¡hepfmï§×ô;º¤åSÚ±emº^Ó#îäï·²Uþp d%Üv*Èì ÑÛ¤AGæÔ*eÎzuqË6¯ú}ìsúÏïh×,§³ÿ(ÊM¨ðÒ
+yv·0;vÄ«ä
+sâÆU´n{çÕõººwyÖc¾F7± =â;SÚé?z¶Tå|¤¥v«H]F½ÖÅt-ظ6^ Jy:»8?ùÁóîNñkäïuQÎd¡Ä.'¤eÆ^_tâ÷ÎC_ç÷غ7ßèäݹðe2ö¸5ìô:õ'ìyîµt{(Hh^ܺ8?¹u~Zø¯²¬èqÅùÉòWµneqmǧÞÇ·Ûe:¹½SrdIËëòì.½F4ùþÉ®ÑFק07^\u½
+ B¼ t
+À
âE)-w!ûåZõ]Õ°9ü»
+YÚ0 û 0'v$+¸SR&52@~á÷&n½'2wz¶N%þ¿ÙÃ+5®ÝzB)Í£éðÄÞ?ùÁ)Qè%£X~´ÔÎ+DU+J=*®á;H !§Úé´J6 °XÄ«óûéu*²gë®Gw4çöYàÉïßÇM}{Îwòî¬.©×Ùõýô~ÛQëîÚº7Ó8zwú ¢®ÿcanÔkYEùI6½§6q¬ÕayÉ:BN/´ËM ³ë>Å?xÒ{½¾{j'?º¶É·Qïî¹5諺þ¹N]Ô¤ ãQöÙõý¸JìWü>n¨*Ì´·«ÙòQ$WÊR!,%ÍK9¿qxýîSü#òÓÂGòDG¨Q/¼Ô0îåã+åé¸é}¶ïjÜg~¶FÏ:ù{ÁÅ)#¹|³Pس0?=b[øþM»#KZnHl® À_"w @À!
+óSÃ;Z» ê´ÿìOûÉòÃóð×(òYg×÷ëZ7Åæf»5軥ý¸ pbUçöǫ̀aÖElá¼ØOáòRÃg'Ü×(ØW¶´Ã%i
Rûã]?Ý»×Ú¥.7é^W6λͤÂÓí¢·Òªd-RÓ]>ÙíoíÒH·{ë¯B3ÛâüäQ,.?ѧݧ«<Û*dé#ÇL»z6n7
+ÄÖò´èK
+:gBXEÃ~
+û¤ä}ô¾Ònìß ÀÎïìjY×86xnЩ£K[õ¼´yONÒÝÎ<e²£Wû°Ä°cÄÒ±î
îÓs¸BzióUQ¶¥º8ÇY§.vòl1ú@ó3àôäÙ;RJÙ¶5Zï>Å?âào
+GX8ÖÈIê+¶t 0ëúe.wÏvJ¸h¨ØÒ%¬÷Wg®s¸BzuÇ'
9qÎ:u¥FYàE at tFÎuß|¯/Å.áê¢w®Àìê%ÉV³äï;»¾_ÈNÞOt°% -l<ÄʹaDfìõ>|¡EbO÷´pðÑÀ=_¸§D!¶r½ûNÿ3L7 ¦È
+V rߦ"/âJ©pF,/è÷íöàâVF£ÁÍ<3Þø½øϨý²GÝüRï乿ùÀñ:]ÛõÙ¢Üøöw}ÿ§I>úÆæ ¡Gfå§
µêÂúÔ ·eFµÉ½Ñëö¡YÏ".]Û£¤.®Â.Öª
+íàøöþÚp§<3ºÃ
÷6iè÷ÕɼÔðþò¬Ç®íÜ!-ê¢(õáÙM ¸µåã[~~ñ÷þ6Üï[«#q7ù °ÓÔÞ®ïxùÏyÙ wîi³K)Ogç$óS"ÎìÜ÷õڢܸ¶9wÛ¦KNR°Ñ¨·ÕªdõdQm
+sâxûª½#/%¤F_#)üÄ°Êø?ª3æöµd'ÜüàH¯SûÍlïò.o?X]ӶͨuÓ8<QvÄ¥µ àïÁí²´þ-/,[GôgCÓz²
+ 4íW IDATÿë÷ÅI°*ûã&}<¢,HbêgÇß$0³yl*~Üã캾MóFòæwàìú~]
+sãµ²ô;ÇZvÅßóÿý©NÞù©¡s\ôY;jAÌpÇÚï N«hª,Ìä«yJ>Åâ(Û^?I«(hziËØá Ó×Wç@ø
5ëÄÎa½§ùX«{_Ý>©/ è5fÊÂ̶G¬ÌánÿØ¥nØÂÉ/¶>6aUöÇ}¾>w'5êÂwv5[mø{Þк>ÍYV8~ßûDQn gWp
æ©VNõ£ó3:¤NõÎç$ßr|y»þ Ñ0;1hA¯r´×ï[¾uÍI
+céXï
c Å)§?º8_lá|¯0;vйnóà̺>Í]ß´U(±{TÛsß<5 îtoV%wµpð¹*0³!,ÌÂÁ'ÐƵq¹}ípº¨û_êN¸í?Ó¥äoØ5ÛyY~Zx©MÍ ¤°ã¿XÙ±# ç%O8ý£Pj©gt>»¾ßç pî¯A¾±w÷l;åÄõ4´ígñ/!|BHKQ»` ¾ ÖPWtøñ
+ã
+Îñ½±RøáWÿ*:.W<©^éÇ,IZdnëµ>7)x8 È3£Æ¸Ôé>k̤Å>[K×éÛknÛYOô`ÔÂØõu:LÙ£.ʡשHÈé
v½¶V¯é§
+.;¿³ÿÛï[«Ìõu dQ×j5~öèÅ +}:|6Cõø# ÈN¸3ÆÜÁ{íإɿY´dÀ¬ëþõ£(åOX3qÜò´Ùl® 6èÐìçÆñ¯lÿ¨5ÍÆÈøfìÒä_9\ÑãÇ´}RÔhÞ°û·ßY¼P`fëqº{ûqØþcKǺGF-]oãÖXcÔëjz4á7rÁã£Åÿ^9ÿFõ¥Ûgû¯êÔEmï=D ¶>
+B-sQfö´qk²Ã«ùè¢ß]ۣשeÆÝäæÄuÚzîõi?Y>dþý£ÅÎyY^ÍGqøâÀÿê¸Mª×*÷vø)?+áÎY ·ç
+z¦ý~öÂÜþ°!§MÈNêf4÷í{cÈÜi_Ç [âøb+cÛQëþ=H¦ëgûwx5]dãÖdª0»{ÉìгKl§BÖàâæÑRv±,µ¿)ßÁ«ÝöZƹÕïsR§.jSÖoâòÄQ±7æZÐhgÛBWøÁ/Jí|¢ãı}¾:dáX'QRÍá§*
+R{ä8\὿Fmúcè!Âbç]ß5¥¦FY Ô(ÑiÍZYÒkú©{&y©}í¾¿q©Í¨µ?hUò^ ÑWjãñ÷ÀÙÏúI§U´2ͱ8¼ØQc×÷~:Xjç@»¨×'ï·±:¥Ç´#a.uº¤UÊ<ºñÏñ3mý\üÃ*'ñ.O¯)ncåÜð4+T¥ögäYM×X:ÖÝ<hö ÷FÖh /5´§Äºæ¦³/ôvôg·E àæÔ(¥tI ~ Î
+Ji ¥4¥²êk=|Õ¢ §º(gPÃß7¥gÆÝäzÇfýÍ çºÝïë4Å-@¯S7n?vÃ# ¨ÙdXXÙ5ÿF=¿ÏesøgÖöi¸}Pb·ßts+ÛAßU[½Î£8?EPÀ1èTÍcîìþuÇL»Q×7/ ôâvµ[MzY{l®àé;_dV\Ú¢d~vüí½¦Öv[w̴۪ש<4|'úpR}{ÍÍ ®@¢Ó(ÜJ×/2w2X8ÖY}cË¿oN|("s'Oh~¹8/i®góQˤKXl °yB
+ê5
+@9Å.vë!¸ì<Zí,ÌvnÙ0¾ÈêhÉ¡ºÍø{ÞP¾ØêÈÃsÜÔ(à ÍY8øZ8ø:Öjÿ¹W»|J)Ö«Ú3°9ü'×!k èsó¹¥KQê¶võ=ìR§û
+S¾µ» øbk5¥´Ì½ÐF/NXéäÝyF)÷:¿qø¥Ø»{%¯:ï;bç(Ó÷?ù|~b&+(ä Í
+ºg½"6WðìE¶L)O·èôÑö{Ï6³åYXÙñ¼ÉI
+ $Ö5R À£éðbJ© 3î&ß Sy¤©Àkvatà6; àp
Ïô(îS=·<}Ö°ÃZB4®muc³3¥T$Ëj#ËjcЩÛ@SKǺI `åÜ@F 0hU"s °Ñ\Ë"ì7àRª¦^gB6> ¾ðãÓc³7DUáäÝYÍJ¯px¢ï6M ;x¶Õ;+äôB; HtÑÃß 6Gðàæ¾éµ 1ôh½ò´cåÒp§,ãáuqîк¾8ðÿ¢í8qkìyÁ'ÄN]ý{Ħ¦Å¹Öï½tªì~& '¾´§ÉËÚ2èÕuMß5*Y}
ãýùÖnYì'C^O>9
+û)ü ,´',¶Ê`ÐòMÇæÜ>;qu~ÿÚ'~^¹à¿xo¾+x·ýäkFÓMs&DR39IÁãR#ǶÊæºÔí¡Øx/Ìüàèز6ݨÑàôª6zL=NFs
,c²G³{ÊväO¦¸ãõ]SjJm=ªymëtOìõåÉû<¡¹Òa?
GËã
+YÚ;g;OæOÿU¥âFÍ»ÉÏIº;J(±;W2»åeéÅÉTçÚv´#´i¿#8<öeúÌâõZ¥©7páu»OññÛ£e,6'--ò|Àäÿ·ª8§§³O×uçÝ=eÐi,_UTÅé=ýtð¸ßØÕl9»0'îXnòýv piËX6ëàÙV#Ø^,È|Ôx2·PÒrȲôÒõZ9×Ï£Ôøì
ãö¡YΦÿPbSSÂR³ØUûqS£ñà#£Æ®µ0v}·ÏzÎB©ÝeYfT;àÉð©Ñ¨wå9ª$8 âID/üÀÀTT *> $ÌSø*#ôíô2Ú? ÿïÊ~àõ§ÙÕJ׺³$iqYéf®~áçÿ'êÆ륬g¹ `nçµ'%â̽?x\Ò©^j`LôýæüíßX,as
+º~_L×Éûv_Ñ~Úõ]SjZ8xoJ?±lßW at Xz^m;viÊ/¶îM÷dÆÞX¸w^ÍfÅVY¹
Ôí8-´TUdçwö³8¼,VU¿Å Å¿<×Χ{íüÎ^¾ó;û¿øb«»:u¹}í³¾½æÜÇJn¤?¾÷¦NÞ&?8õ5_dy_¯U:s¸Ð÷uX/²4p¸` hÚï§ì¦ý~º <¡y®VU íÆm8|mǧüGïæòÅ!Þm'ÍYZÝÝéòÖñû9<Q(_d±of S3=+|®·/ØQ+òÚ|ø°¹ È Ö.tR+3b®vî7ãßÙõý
!§þ~ÿä¯Ö,?Þ U}ÛmòþÈ£K[m¾¹uqÔõ¬DN÷¿Ã
Ìlµ ÀbstêÂçÖ÷;,0³=Ñvôú Àá£"«B ðnûñ× ÷Þ7ßës¢ÚznÏæ Íl5 [é8¼'¿¡Åà¥Á6hw|y»V.
+×˲¢ûoÿÖ²°åB3Û3'neö¬+ÄÊ}OòÓkýfXËYlÞ¿Mi.mÛ§(7~
+ÍK5õVÖ.Öò´JYc¿ÖA©À¶Fó P¯ãç'î^øßkPʵrª_æ³Î·×ÜkcüfXÙaqù
Q×6}Ëâpã©ÑhIXìvc7 ×Æn_ú8ÐOO©AÌY^µ0výt®ßù«3wÍ_æ7Ãú °Ø·¶ÎPJAK)Ý ÖQJ'Xzþaæì0Ið/g2j%Ó^dÔ
+9ùreMÜód?53Kûzm®ûWþÿ°ÊK ±îôÑöé×vNöÚzࢮÿc}k{³vcþºfíÒHW²|lÐîVu;N»pï`^ÓOÝÜ&Íx|Õ¾ÓGÛc\üÃJinòD3löÚ¸7]Óçësw ùÁ)QÔ͵zL;òì¡vuÇ'B©½²Å ÅE¹ K[Çu¤F·vë·ëv&xE^Ø8¢#¥FvóA®[8xë®ïÚ çÇC.kÝ£8/¹«w§mÅùÉN}¾ ¸l28gÖõiVÒ2èè<Ç3ÅÎ'í+Û'6êùÅàɺ»¢¼$q»1&@øùUÖ)ÏÖnÚÿû¡gÔS¤xY×í4qk8_lU¦@Nê#Î¥mÃ-Ù ªSdÒ
5jwú߬ïÜ
+o_hù¬ý?yûÙ¸6þ³Ï7·ßT;±w÷Jnìzú£5òöoªrò÷.6Ù w«Ù>!¶
+Ûw¼«ÌÑÿJzôeº8ãÑtxqyäS#é¯X´´øùöo-ÏÖïòÕD3µW«qÿ»½»WâÕ|t
®m¥<ýàâöÞm&e¼K~~µ
ÊA_eyê¼ú·
éVQ®íøÜ2ö®_>¥´Bõ&£Æp@8ôÔxÒOÿ%ü£V*jÔ!m ¤g^íeFímrëÀ·® !'èµJï «r&¼É¶LFmÜò´Ùo²òµòwn}ÿÃ<Å
ÑâW¿É¶C¯íütãU¹¯½v±²ùPZe`2j&÷µ§SfCL±5 z=ÝaZN)ÐÎlo /]<ZÝà,5f®·
+\°êM·åìÓ5¼ ýá{ya¿ï8x¶ÕL\_¡(%¯K
+ßA¾ªAcøo|´º WUëPÍP8Wr»W u ð !죪_TúmRos1o§N¯d```xO¡ d×ð¬%P?ý¼N ï/¦Z ~Ò½U©ÃÁdÔØCñ`°ÝH)UUZÏó4Ȳ®:;00000T GQø¹Lu
+@Ú
+@ôÓC¥¡/Êâ¤â¿ZáCCcT±k£ê0Ýj
+ÒO6à,íR[mRJ¿Zêÿhu@äõG7ýÞÊVÏC©@§«ös²j¨iRäVRä÷6zNuG§ÓUçLid!ÆÀ´éÌ3¤ªÐU̯Rª ° " ¥ÝCÃQ¸uÕmqVFj4ãá^
+¨N½ýçxº³{BVÕº|àPT£hÒ /
+FÍP=áPJMÑÖ©JE*)ÞNDhSL)v«øxÛrØ(3(/ÃÛ!.iô/#XBì¼^J¥4»"*¼ãò;Ø©n7{Øù¥AXÞònNb`*r
ª*|í¹ß´åWµ"×ôÒ5ªGUÇ B3kÐÜ
yé©"ÉZ² ÂåÞ £öÔ+3R÷ji!±°¬©m5jMÅÏC¥°i¸uUëP8lPo[n
RûÐÈ6Vëé
+Âæ5±¯ÙVñjiÊ$3_¡]@! í89/YK)-WÐÊ·Ì"Ã[Ãõ]¥¯?D²7Þz#\Û/øT5aÒPJ)¡
+9ñ{û.²¬¨j9ÂG)ÕRJC9 Z½@&ÕÈ°10000T-~ÉMºÛ×ÂÞ§Úö^ßÃûÄ¿q>qÁ{%§×vmûàÒïÏæ CÏ.²»wêgû{§Ö<½®[ Ð(óYgÿìÝ"%â ò8úÊÄí\ñçyu½å_»ÒòtöÅ-ÃëÀÅ-#ë%4;õGçö±A;%%e6h|ruÎ1W¥õ¼¹oZ«Ûw)YÆÄK¿[_Ù1Á»²ÎIeÁ¢^1} $ãÉ"l*ÐXkàçÒؼÞ+RYè?}KaNlçгü-n8
+ bîîyuÝÖ¤ð£sU
·¬w௲ÌGݯì°ïÐâ£$Ö5õ¹Iw'øÿæ3Y£ÌgÝ>4c,+ÚK!OÄÜÙ±ÍÔÆ
ÍûdÆÝ ©Îm¹¹oÚ¢¼ö¿>ple«Þ °q`ïü´°~Jyzÿ=xf}Ö rÐlçlÿÄð£3Tòú!ç,©ÿ¥£ê]¸Ã ÓT¡HB!lÎÓ $¨ ʱøÚ ¤¬^òÍ%mBXP¤®TåóÝY{êìVZpdBH7 ñÒ·¶%xEÜ&¼úw;Jl[·¦%w¾.Ä»<Û͵ÀÓ7ì bKÌ®î®.Îÿ/Oµ
+JÕyhôàñr÷éìÆWPÜø³Â(L_?Y¿´"£µmsgnÂ×mDá^ÖìêâÌÅPADæNGÎß°Ô6ìüò] ö !lÙØ%ÀÞÝØxnôýÝ÷ÏüfqiÍ. û:ßþÃÅ£\X¯>+HôýÝ ¸%éì½ZöúâìÂñ6nÍÖÚÚÕö0óæù+;&x§<<ó3OËôîs5» #r[¡çwçòÄá£$-(wĵrã?ónóég--¯NÁ$ Æbkõ°@ ¥tëx²ö+¡:Jø®¬ÓuöI[6²l+mÃY 5Ìä^[ªé~a'VvìxëÀ·G5|OJîvì»É+åéì«»Þ2gÆÞæ&l+ÎOn}eêöo,.îÿÿÃûß}µ{PªÎãôaÓ¶/ì&¾$âç"®¨tô¹Xw±Úzé
F¡é8En°ßI|aïHó£Ù
+£Ùâv%åTF®Fÿ¤#LßKS¬¥ìÒiF
+¤Ê
+cµnöþ`éP7 õC©Á2)ü¨ ¸i°IF¯)jiW³U8 4éýS6¥Fi\ð^s*¹ãºhP½N_=Û1ÝÂÞ{g^Zظ»Çæ8
+:Ç^¾kÊs©Û3 ÚÞøب×Ô×ëTäÔ;ìm»71ìè² A§¬ ªÂÌö"s§ ²ôg=þͱîêjfÐ'ëbwº* b Ñ ÜQÎYsÁg·ô éØcYPH«ôÜ#ö6CùG*CÓòO«
+2M°pðY6hÎís¥ódQË[Ç÷ÔªtýÆ¿nÇi²¿÷ 5÷Í÷ú'4Oñí5ç"!ÐY´ öΫ9+)ìø(6W°+#æZ} PÊÒZY¼0üü*ëG×6ãzL;|^dîd>ñ³}JĦ ¨yÞ^-Æìyºi(.ü3²nnbpwAg!µõ¼Ôæåëo÷ì0x£·¶²,, töàåòvªÝ¶ÞS5Së)ÏJÀ*þs äâ¹ÇZ§Ì"£ÍÓE=
¢½ü©å! às`¨iÉVi$x8/ ¸ ÔXû¥-')_eþÖÍìüÕóùXm= ðuà$m"½ 5Væ~YÛ«4JÍxDµ²·Ù
.\Ùç}/Äjë
+8D«5PΩVûÞþúðeEÕyu½%!¬B÷AÇæ°XÏü8<³àÄ ú Â/¬°!(<.
+:ú½³RöHê°êÁÅUv5 z}yîÊyN?ÇÞÝý
H긧d{iQçë7éýÓ¥[¦{°8¼G®d<ìT»Ó¢®øGYÚdHQ¾¢) $vÊÂÌÆ þõ\s×{lê£s^×]Õgúù[¥ó«
+J)ð,
+òE 6áóȪ×5$)Kµ©Ò6Ü{£jõÇɳO;²¤EÛÿLÕ(òYG¶>¥×©Ìùb«¤ #óüC-ë?ÖÂÁ'ÐʹAdéúz-ÃÏËM¾ï^±Z%Ïldnï}ñæ¾éî÷O-8ÌY¤ª²ëùÿÚ`/ ä&Ýse<Z¥*Êi 0³zxyý¾ë»¦ÔL¾,H}°ZbS3ÈÆÉ1Vh!#Cåòe+ad±
+kýûù²>§£5ö¦¼×·
+¹5Åj_gNʺ[ªzSZã$¬ÜßûHÎ ÜNÑ9üuGåµì²C7n4 j¨dTCÁ iV»9päÇ"5M/}b¹ïÖ«Ý¡z÷qZ[ Ph©¨/òþV;»zò¯¾©l
+ G#5M³8tu²åAÆ ½=²ÔûöyïÔ/[DæN~eÉغ7?$ϾÿgïÂn;m/ÊKàDnYoåÜ觿ĮîàÂz ÃR¿F%éÛsîÁuɳ¢'íÿÙóÛÄ°#k$Ö5w / ɹ6cÿÏ3)CM²ºÏ>§S¶ÞóË2ÿu>9´¨þ8S[ý¾)õ:}5.7ùÞÏ'WwèüfÎÎëcê©IØQJÓl't#§¯ÜÓZäӬ滲þrú\\éÚVCÏ»»þ̺>sâGÞØóù²»Ç~Ø?fIòÂF´d±¹éëQ Àá ÃîüGïé'Çßó×õúòä} ¿çoF)úÍ°>H©ÑÅæ¦ÕëüåáÄ°c>Åν8a ìÿÉ{²Pb·wðÜ S NmÿÆâRøùUO¼¦QY¸ öÿXÛ-=úr×ú½w%Zu¡Unß^vkÐ{©B\ÌÙêY¸®7ߦ®5õXÑÈÕ}qÈNÌRç)ö rÙUÏÝT½{Ô(Ò\x{D~
+ ðÙD;¶ ö©kzÛrR¥|¢V®ÜØ#Ïn¼6qbca m$í·CÖ
+ÀÅ~>üN&Ö·ç$Mi.éQW¡X{¯{se<=ØÛ|àÒt ¨ÙxØI£^ólx¸ÛäCᲬ¨~×wOîаÛ÷ë´*{|{Ô±V§»M> ÆnþþÑ
+>¦2\¾$'Põj1þ9·û]fÌH?Ú¬Nû©;v CçG¬¾¸yXSRfáÝ{þæäSî àÙltg³Ñ6ôUÊÒÜ=¹ ^¿ròîªôj1¾H$uqÒóÍ©a2j=ð|Dê Ä·"Ùe4éWåV9+°ÞóM¨#!Ö TÕ(ÂÉ3øb+ã 9·Ï8¸M¸ÿë«×wMÙ¥ùPj0eFµ O([=/HºÕ°;Õî¤ØÔÔ@bØ1°9ü(NSì)6w¼a:f±¹©éQjÊbqRLé<¡yBÞ¡ï EÆ'¦=º0áÒ±³Dæ~#~}´
+UJ'¼YpÜ`q1NëöSñ} (.byUª/Í" #KÞZx§¿ÿ¹ëËË~â\Ë-?öHól><³Ø(máÌM +.ß nâÄÇæ̬D,9 ,ëivNÑ!êSfµÙFÌbb§¾af6ªßÝznx¯Y¿ÿzFXØûèûϸ~Ét\»Õ¤ÂÚ&
]ë÷UºÖï{ .¨;IY1Þ§íäñ¥ëqðj_بÇ3%Ó8\!í9íÔ³¨Ú&=(ßcʱP ¡¥ uÚOÕi?µÚÈB¸ jÃñü"ìÚ RË[üN8_¹
-!¡
+Î/ªD=M4ÆÏÌjÇ=_¸¾Û¸5QÐq
RG³§©Ñ(<7è¯Qc×Z»¾íèõwEæNèô:Õ³¨wI
&V+÷
+YzGàIïÎ ×Öê0áP 0èµbïî BÞÞÌÒõrQn§ÓGÛcÆ.Ký±qïyÃò]äo/*}w¦¸ÙHÓòkÊ:wSuÞã|Ñf,»;kìy×SÑ¿ûj÷¿ï¨¼ À˱åªþîPu¹úùð3rFËÎû.¿¦¬®óÐD lB?/n¿'Líºø¢C'Ã3N7¿ª·t°B.ÑpÙ¤:ï®ð^`åÜp³w·üÊ®'4O÷i;y|i'+Çzó%Ö/~¾¼'p Ôà ¥42ð4s¥ô
®Æ%Ѥ¸ ³PQ=ö¹øÅ- @Üà IDATbÿ £24¥^¨zÞ¡G¾
+ÚÝÅæ¦z[Øú@«¡+Ò >xÿþ}?Ö:Àb±ó½{³Å}¾ ¸-0³öß=ÛÅÃ?h=|Õªò´ÓrØk6èæ7Ãú (åKmj®|b usÏ{oîùBÇæò
+øíê-ÿõÒ£/¯bsøqF£ÁÂÌÊmÃ</§¯7/É/Dí³õÊ×Íÿç éÁ6nÜ| 8=Ñâø®PµûÖ{êFb.Ño,x Ë{îQ{^Iкõ$÷¯Ãñ²fÿkçAuùwLßY¸>ÙÒoÅ
+eýDÁâÂÇÛÌX ౡßXzð¡¦îæ ±¾d ô¯ÛÊfvf¬Â?úIÈûþð«rú~}ùÚ¨·tÏÏDÿ7«í3´²xj³NLB,=ÿ0sv$xæ#¿¡$ÌUüUZVèÁö÷ö¹cuA0'_®¡åî
+_Gsݶã,ÞfþôèËÔGç-[Z\¦¿{l¾Cãr-|þóÃ"1ô¨Ø¥^O%+¤ pv}¿&ÙA_Yôiìí]Röå&Ù¼Ô0nÌ]v{ÍÍàÞÚÛwÀ¦áÖ©NgPJs_-]5Bêm$ü|]³ÂªÖåmá¶<÷«äïmÖVµ&=ÔXþ|Qq-M®¯´5!ÄAdîhcãÚÓåãýÌã[æüÆAZeafö[ßOͼ·È÷ºÅ=´åäÝYíäÝù
½R}ePÃwPÛ`p¸BZÒ µK#µK£ê¶¡èP÷àÕR%1è5[M º×Ïð¨sH$׺^«M×ã©å'UCõg×péåªÖá ˶ØÍs¤Ì
ìo¢pµ9Ï£á;p^º:E'4(±ÿ6(l `XWÉVùW´Vìë'!Ä@&³ýCU på¼5oÐüËzß}UyçTÉ:©uwqøËä^ô2÷¬Cr°µ(yìüeâh§4l ÛPÁÐÃ
{ìùN5<xÂìÀÀÀðÞCõPHþ
ìÒ®(Lí ¬ÁÕ^ìp, ù¯|¯«
+w®5[Á³ã( ÷l}¦a-¡W^ã{ÈÌýrW®[k7Hý]fS÷o¬
+\¸/íù&c¬ï·s,>1ÞÔçmµÿÀw¨QJ£«Z·AqÚcÁÖܼâÚ¾ÝN=þ>óìÝw|Eû ðgvo¯÷Kï Uº ¤"(M±ëëOA_±÷ö×
+RTz¯Ò¤'ôÞ¯×ÝÛÝùýc%\ïçãG27;ûÜ&wÏÎîìLÎpö[ÿtÇuþ&zÇé%Ã¥a¿Ff¹®ëϱK¾²$|aI¾ÛwtbáXÛ>O1æ1U?¡R<\ôLݲN_FoÿÓ;¢V×^v\¢D¨oªÂó I âZ¤¿^YÀh¿¶§¢ÂqØyL©
+i%èoPòQVù»=·S
+À i¸Ä%ÑR|ø$]zÁÂ!N&3éBØÚ,Ìý{ÂkZ[ï¾ýÏ5 at D!ÜZ]$©×, UN|ZËùH/ ®²²êw{ äºûÂå RéFMyÍFWbçobv ¸E«æ¥Kí]"&ëþÎ_Ù£ÃM»ÆUøbýÕê
+Jöý¤x¦ç#[«6øöb[e¾t×â9äZÅ:mç,mÒ¨ôg¬ðËZ:kÍí#÷ÊëÇ2NÆHs2/ã J¼ê*óWìáq
cd<JâRÄ3^ÓuÞ±©ÅñQÈhM®¯Ó&<²/t¦"ãÒþîÓ¬ZÕAv61Åÿ_HÖÅâH~5|_þÛÕ=0 $½Þjfã? Ú+~øúr4öákÐx 8})÷ÖB: _T-Ï1nðºÖàÌ<qç,_O\uBkÓ5ððµ!"Uá3dNUwCä9µ«Äï%öuô.,ò7æák ¦KOm\úèG7Ô$ZÖU{®å2I¡v
+A¢eù Õ%µ
+¡ôM¿ÂÉäÚ¡ Nó·Âc/kÔvc' ,
+¤Ö¸39E¤*,\zlI~?v[KJ àªMUvä¡ñ½"µ¡©äòWñzʲü=Õ `kéXÎcTúXò7r!ÂÎ|cZ at P$µÆP( %t¸oßÿÞ ¹±ÙÖì_ú¸Þmmòi=L¡çÏü¼ÉgJ'.ÍeÏêÊò÷´êÁ"¼ß#Çܪà-˵¢ÄÃþ¸ÜíÛ\R @HCcRÉLã-ÉP㧠VJ+ãÕ/аEäifÙUü=~¹í
+n^Å¡Ø3@ â!B¨oP$5 mKAA´Z ¤Aqùc¼·¥c Z/± þAA\TôÔÒoµßç¯Â£°u´
+Q¤Ðë?ÓµâùçWºèÔnMH;2@hQMÔU îN½ÀRNÇn_çAþÃÊï|£ÂgÉÏ»tkò×ÒÇc«%Õ/©LÖQýq´%bºÖm¡8¯ªûRpôÕ±ïôü>>25sØ=?e6ž~ÿì´7_o¶ÝÎÅ÷$ùýÃ^g¾oÕº¼¿©zþöÛ_Îü&P¶ìåÎwyíc1tÑÎö½¦ü÷i^é¾üñÌ'Þyÿ2òòeòýqÒ¿¯Ð+@uUÞÛÏxÁÏñºSΨ±©2 ÇÔË«ú U´{lª:?-\·&Mrù1efSüªô¨EÖ.£d(Ó²Òm "⪽ú¬§"]¢ë]¢ëÍÅG?uTçvY®wTç¤5×>¯Ä÷Gܲê½ÁÏ~ÞòÕ´ßÎÜäqTtösîÐMÏ4Õ¾X·erSµìLý$oÔ#«oõÈêÛhF~Z¡X6êÕ·}lã$ ÞïEy/SÔxýã¼3TÖ/«ÈÝ#+:±VY¿Ü\r©_ `«È<ïIiö¾4ÖòSJ½rJ lÇw³ÝÖÙ}n}óÁï[oJê{çSÚÐöÿzó|m:kò%¬ÛrÎ÷ECï¸<_í³¤®JwtªÍ¾µöÃ'^ðØ
+à½Õ£?ûü"½#×ÕµW¢D%¥ü¯¬¸eK+²ù#oBjÐ&(bYÏ\Gù0÷Q¾'æq¨atgSµ
+ y Ðlgcÿ³á øîÿtcã»û|à]_ä/{¹ó´ßßTµc¼!"u§D¦òUáí¯_è
+Y8lLipXÊÒû" |ÝØg&÷îäý^´fÁÐQ{Yoh_»~îwÛ»¥K_LK>b.=>*4®çº¬8eÛ¢i+ó÷½nk |Ý£úÒµWfu `Ýæ~¢àXò\Ò#!ñ=·Uæì¹Kiþâö2iæ«@{¬ÛBmütü£2µCÿË®û\ ÀÒSgÆ÷Ú[³ûµ1nÿÇ6ì0
+ °ñºK
+ë¹®¹y00
+8ý ñ¢ÄìOOǾEA%ø½¥JÃæÛ>:f-Ïx!ʳë{!:uÄÃçürjå;Û+³fa,ª0L½ÿη_ øa^øgj LIú}w¼óñ⹡)Zbül `Sl÷·Ç=±mOIÆ&ÅÎïï~÷{S taÉ_MxzßƵ¼Þ\tä1A8ZªÌÄ"¿xnØ72¥~Le,¤(IUDò@7 @ÿ)ÞÛ¦Ï'vÌÙó =¢h[rß»Þè7yAÉó¿DÄ*ø½©c¹)¶Ûk7Ïݱ«"wlëS^ä9OW ð`ܮоBo»±©ôáɪ
+ Áª³sî/ò=bël÷
+Ê;iÓ'tÑ¿»ºÏe3)¹)ÞÀÔÌrBOì¢- °{ùLgFN³N9Ý(Ë5ûÃWÌ[±äÝÆLWªIE;ïêi8Ù=Zn=Zê3¬8nOqs¢¬Âá×NÕ¦Oï©ÏEàó½ÔÝùî$ÇLßxeî¼!!ÇZê8] Ö6Ù@Êo}cÍ+Ù½9Âó²8úÐ)²¦jc\zf^¯«Êm-¹¯ðøgTº¨£èÎå.KQ64qÆp øäºÛ¿ `¯ÊQ¹mDª°"¯ükÙÜ Ö½?r¨³&ÿ¸«Ô¦øý¬Û" pY©*80Gm=Pµãù¯v °ìåÎwÚôÊs´<{×Ü_O¹ À^5¨<kÇ¢üÆèÎ$2U%é#:î
+ëY%SylåÓW¼ÖãÖãê¾%Ï'/ó¹jÚ)õéÇ6/ønÿoÿ:óÞ,ÍÜòJ}ÈRvòѵ Xþj·É¹»ç©
+±*rv?
+ö:0`QÐÜùNÙ¸©¯ç}0töâ?g.4ß6cAõtSL·ÿUdÿyçzÀ³i£^5uÖûÖÑ~«ßÑ
+oîønV2Æ¢zÆêé3ÔÜyÇk9©Ï ±Í|ßrsbï©< ppåsÃ0`fæBó¤ëÆ<s¿âÔóµõE$ð¾ëLýdÖ
5S;Þ0ç3DI
+g,¨º{Ê«Y_õÝVDÑößßìsð'#>^÷Ñè>·P½ë¿í®øÎ
5Ó´aI+ò/Qf(Zbù¾e|TÇ¡ó¬eéw ì_þä@ù¾e\§a> ð\«zÌÛ )êÌEû-XY>hÕIGL ÜÍô++GÏêc8þÚM;~:lëgæTO=,gûýÔµ¯ß_·|§<Væí©(·zxùúLgïíÕ?ßûû®\wØãë^¾}X²:÷Ùuc ¬Aº)ËÙëöªwnܼ6ÃÑuK¶+²ÊÅË6rtùzJÌÚe3ã~ØEsµÍ¥Àcs%µÔ¥Ú®Ûg3W1-ffÏqÞÖTm·¤Øî_j÷¶¾ß.óèºÍR
ÎåqT´§hiaeîÑzrqímÏùmÒ'>x_½æý^5Æ<5æ?ëÿ<ãë\ ÀXÔ{êÛãüs{Dbÿ7ݶ² ¼öq±Æ¼:~Þ®É}ïzÞçª9{©wM~ñäÏ#î[.Uè(ZZ5ú5»zªfÒÇ5Åv{Õc+õ÷ê¶ÿøTÔÞïE»~¸·=`,Ñ%ʵ©\»»àÈï6©ï{küS»·iC¿uY xleãbÒF½6þÉ?·Ç¤Ýø Å22-M¡
+ßèé¦oÿ$âǧ¢,ò¹äØ~ÖÕ?Pªvz{©<£èĺ.}n}#b¿Ü°vÉóÉeìüL¨¯KÚ
+ pôO1ÆêãÜÖâácüV ®#ç%©Ø¶hZG QìOê=µÁ@}DG~ú{t9o\òWeî_ýñfß1;?Ó~¶GÞá/,ö½2k&çu©³ÝV ÁÓx¶+ ËR4LmÝ Ðëæ+)4½Iè5hF/}î·SbÔJß´õ»õÂÛ1øí¸#AÁPìêtgâ7ûdäÿíã1 ~Qܼ¨àçÖUè«(¸½». F'¼¹¦D&Aâæ,W»!ªÓqÆ;6US¦`(öH©Ï ªX&vÑÅèï$õéÙî£RÂ
+¨ùk+nØéjo¶ÚÕ7 aF°iòJÚÁUºípÝgoÔ.{¹ó;Õ
o*t4#/æ9otà5F¡+¨½D
ù-¥'¥ãÚ½ZôCeþþ|2ró¯¦ÔÞ£CÈÒV @xbÿQà Áß®]ÛJ RÝ_.|T }©RÁewn»c×ô÷*~ï~<çé¾ñÓñýÌ%Ç:bÀ"³¿"³?E3¹:$påëuóË R¹Æ*¼ @ü Ý'
Lyu hF~öÞTî¡_Rã6ÍXPsgXBÿui!öR%Ìx¯jNÚïÁ¯ü{õïj°nKÄÿScY\ì4£(æ¼ö@,òaÉ+ EMhF.Bñã^¨üâÉÚ°Ån[éî·8EU¸ï×f,¨º{Æê³>°Þxö½Id, -U`¨}Àh©¢ó9ÂÿA¨¿¢ñâ÷É¡¡G·0³3×Î
+¢D¯ \×Ç+K¯WÞÝÇxp|'mnCÛ3ů°ä§»bWÍzLÁ @¯ Îþ}
+"Ð4
ÎNùE!ýBí³å
+D^Äømvü¯=c¥¿±whyéæ;Wîï©q¢¤â_RÜ3ÊL ò/¼±¼E-¢~¼òðj!Ô Àa¹¦jóRQäìºu
+÷øÖ¡ ½¹}Á3¹ðô¾ °qéi3«Àùkéã}Ç=±mwî¡e70rÍN ©\½ýÈú7't°n×÷H{ê4w6©BWãuTh?ïYòh|ßÛÞ)0
+×å& ÚÓíÆ'nùròü¬øÂÓÍpáÁ \³ãøæÚ÷¼ñèÆ·À/1âÒ!òxìå=×}4Új.:<çbõ·.ê¨Êi¯L˦EµÀ³goÅw¬Y8¬ÂQ;H"Uî×GtäÃÛõ[_trݧ«ÞXâ¶^GQLIÚàmùÿ«Ýn£ª9²þ
+æ·úÖGt̵Jòy,íôa)û}ns¨ÏY=9¬]ߧº(AªÐmÚöõ¯Æ÷úA8)ë2ÞúÌÁµç92ià¦ü#¿ÿoõ{]Öâd+´ø-q`{ey;£Ô³¿Èkôñ¢´[ÜÒ#Fn^~ÌÑ['§Ø±
+ksHÑ@.¡¸_£g.y¹)ê¼/ÿ2÷»¥6ÿT«wr¢²O²=Û^éâC6g¹"»G),;rÜ)Ó{é9x¹Ï/ÒwöÔçöUT=½¦örek @Ì'5Þ&JÌ+ÙÏÍ° ðcB%F´2ùsÍ¢&3`0 dÀEWkmNruÈuZ @ÑLñžî×<ö?×~EIjD7$÷½k. BÓRvrö÷OCøö='Ï NùMѵÏÿiÄGuÖàPúã^8¸åËÉ|ÿi¹>¼Ãçn[Y¯ì}o¢hi(ò!LuðÆ? 1µûpÍÂa?Qm>D´èÖùÎûe×yìwyW¼õý¦9%1 {¾º×2)~³BQUûï-Ú°¤âÀkÝGÏÿäÄ
Seéc#d-;Ñ ÀÕé_g×jSüFCT§|©RÏVåíK+=µyLi8Òëæ_ ÔÑwøÂ^3\®2¤ùÏú· Íù9ó¯¥Ï*8úû4ÒxzÌ£ë> 0Fw-æ|Î
+îIè>áÞʼ}åtlç1r.©)>rÍÈË"ÌýèÚ¿ ¦½YôÚOÆõ¨)>r+B7Fw] 6ÆþaéZP{B©ø `ðÌorhì¾ÂkfÉաǤ
+ÝÓ!±Ý.i1G¢af7¯·ªbÇL±<Øß´Ý ¤ý ónúþµûë[ªBRÊ÷ø Ý ðÌè¥ßûÒÆÊÁ%íziTø_ FæõZt
+Õ3gW£¤ª(²résWÝhTJ\/
+_x-É$+^yÒúù^áÆê4e>Ýë«rfJÚùèÀ]Wç4 z5ÙÊ×æU¬É_åúáLµ<¾`ª±+_7R©Kì}¿ªÏä×íMÝ6@íPi}DG64¡÷%õ³÷ý qÛJäÝGϯ}ûÍÑÙ9»§oÿÄÐiè#ç¬9sðÍùîOuÁAiÞáå!=o~©<po§®C«_ï2Îz©qgìüL6øÁËZçjí§cL»J0Æv=5)¦ã¨^inéXÎgñ!¿Ä¤Ýøò°9?7É3ÍeÏêNüÂ
=â×¾º+_kCtµö;ß¼QÛú,ýÛ³Ýáß²öú~jÌyOzÛYúe¬qµü$ׯlH¿i¼¬Õ~94¥ä~ÓlÎÔop @c @hBo.4¡÷yWÕÜ?»TЦ#WlÑ'·Ú¢mQJoRÒW}yS Û7¿4¼¥c Z¿Û_Éüº¥c ®}ãæ¾ñÊÖziñ [@×s¯^-AÄÕI
+!
+mé8 Ö !¤@
+¤µ³ZK¬AÄÕ' @YPÜSÃoé ÖëÌsÌ'Ô°#ѯè\ì¹²í/Æë1Ó%ÇÖÊsÄùaV^5ë³Ó»Ï1´t×*¯ó&ËÕè¤V½çª».^ñÂü^WÚHC¼^À¹ÛQEîvus´O\ßïoßmóU¬¨.8ØÒq\ë|-À¥È®áä2 E¦kfNáW{hlR³9±MõPs3ýxKÜÖ&¨h[0Æn hÕ³-ÂyÙ'ûE4Ïy8QÕ/»¬B À4*©áÚéG®úÙ
+BèF ÈÅ78g]¸1S¤A\ #×xúÞ½î×$Òæ/&\ÎÙj Ö¨i²Z
+BÈ ^qP\ª "¸¦É)±J]$Ôû*ÃPe«<åkÌ4YÕSk)yA Ú.·EKÇÕÇIÉÄÞW ¨úw¿)ïø}c7=s¤FÑR)R.tªY&H?ÓKtù!fGSÕ»ö^}ѧæ®ÇTøºìðÛ´¥Í±ºDÀü»õFOÅÐk kIìÃÆc Þ<NÉ;DëOS÷uo>§`Ëx[î×ÊDSlNø·7S `£@yc`?¦9òFÄþÂjú±|P<&=5P ¸ÏX#hÓr«ÔkK»'fG3VJAùiâS?Ú÷zu'×)_(B8³ (_b^íHJ\¢KÒþõשG˶.ô¯òíÉ8Æ0/äìF¶½£u·;¼î>Õ©rkèÍÀÏúþʳk°Ñ*õ[F!iµaBR èI
+ :@ ä·pAW ¨ãû{¤áîÐüñ í®Ä^[Ú`o÷é å?ÚºnTçÐrÄýdëÎUóÒÔO£¶¿³ø&ycIý(ò@Ýf%Ê/`<uËcÃë`æ¾ZÕYÕQV©N]ñÊͨ Hjãí-AÄÕFÉ/
+
+ ÀâÛF bjYQ"5Ò>$CBÜ#¦ý~Ë»é8ì3VþfO[¦ë«,Öø§w Pð^MGo_ßùëèÝMüÖÆØ "©Aµ4Ýå¥÷Á@ä° |¢.½z½3Ñ4\ï>ÍÃnÖz¬|hÚ§QJYR?4§Ä?fÊ
+´5S_5S_x¡ýÿb-ýÞÚ'b²îpî+U#¦è
+TZ}o
+â95 «)ð-¥ú
?,Pu`¼Wsÿ®>º³ÜøÝ2 ÇoÅ Pæ·2Û~O<qÊcWÍ+TÉ2;¹{îFãè+õ+}
~màgUÌÂè¾DÙdDò/X7]ú½2³QÏ©¤FQO ©Iªò(
±¥ã¹P G úôÆ>|B= c\ÞÒ±qíÐtÈvׯµt×Ë&!¤1AÔ À v()Am³&?åø×o§i,ßAÏé£<~Ú Vþ7 Å/
+cÓÒ1qíÁ©ëÂùqää¤ú*ðð"úêoVmfåocÌ@AP$5 "¥&%©_NV¤ Ø+@LEA´AÑSCQP; 3ªIAãL0KOm ¤´tAD«¥ñAÑS@ÖR' Îcìo"©aÉÈ# â¢"©A´u2Q»r= NVÇËIÐyÇl:í¨ªÔysku§O«d;4¿o¹U IDATIUØ?AYsõ¢o=åADµ-Ûñénó ëEÓzê pH_hvÕµy
³wnÏquI02hÄñÞö!ÿiîÔÜq·FAÑSC%
+clkáP ܶlWB8EÎÍ4% ×Ç+ÏN>UÍ©üÛÚ)ßÌ
IReÍêcÌúñ-Éá5sWÔÈ(ïg¢· j¯*í.sj4ûë[»zê³^ÜXyC´±í/ô&¾ySøÆb_½ü¸½3ÀºéOOVUxý·ª|h´±-ñÆ÷o§Ì¾ÿzSAâ'±+O:º¸8Qo`ªßùgK§AÉ g°ôÔ" @ÝÒAA41©êí¹î../±ø-Ñ/à³ ÿwuùØÁêÂÿMÚðw±7nõIGìÌÞúr.¹9Ъ]l{+1%TVÎ Þ_äIS0÷ËôØßJ[°³fØý×ÍéküûmÕ7Ú½Ã"u°ØÊP ~19zMv5þÕ>K* À×û-Þ±mÙ̸ßìo:|µMcERÃïôtAÍa@;UÍï³âì©(ÛtÚ6ö«üe^~¤ÔgðòX¶¯ÐýÑn!¼5Û|¾vXU>þ¡¥7
ªhçýÇ d4Å=4À. qý)WlZ¸¬èºh¹µg¬ÂÚ1\V´*Ý ¡ÿÐ Ó öOî¦;y°ÈÓ À¤8^ØP9pÉ[»x£Ô}uHãaYñÞ ¸üHÑÖé´ÿ¡Æ3æüZ2êö×ÅÈ+å4°×Ç+KÏT+5(éó_8>rUÇp3ðs¥«e[r¦ûÂ"E!8;øF ò"¦ PµND×vz¾³nMº3zs¶+yÉ{ï?î_Úäo¾ EO ¢-ûý#îh©Ï [éJ|HÏXEÅõñJ³|¼H
+MRUô×Hi ÂÔÛÑ2o£ÖzßIWx²?UéÓ(÷éÒ+Ùø[:k ü,ÚgIus"½â¸#µW¬"å1ú»Øk×ISúÆØð?}<º¹`ii¤§FÑÂ|¼H¿½j&¥ÄqsæHß8
àõ±~9lï´hµ?C?þïNrûÌ^¿³uùå°½ûwScÖŤåJ)Å×mWJ#!ÁÀ]d3TM³÷7íxg[Í
+ ÿçÓ6£æ¬ 1($*¯ºëÇâÛúÄ+sî»ÞÁúàÏN¨ÔÈ)Ï^ú½*)Õª'¯B c\ÔÒ±ÑöV¾*ô§vz¸¿ÆÕÒ15''+H&}W<mãý [6¿ÉÒÍò_ÝÖ"scV¾F©`r°ôÔò ÀÑÒAA´EBؤ¤ý) ¬
+¤1.½x- âr¨¤ðóô¸U-ÇÀ `&E 6$5 ¢ÍËgn rc®¥c! Z b¥§6 Z: ¢Õ@¯ è©a׶tA\»ÖÿäSÀÿÌyÙXc7 ,¤FÑRÒ«±ûÉõviKÇqp°ûlOAÄy0r]qoZüÅëMÐÛe I ¢Ïb?ëpûY2ïCKü>ñr¶i²R c\ÝÒ±Ñö!B@ÛÒq`Ç×\JE KOòLAWÉhr\ (AA\
+Òû! ÚÔ 6#Xî©AÄy! 0AÑSCÝJlé8 VK
+ ³b BÈ ^±¯¥c! Z@O-(AA\ ¸üHA$5 ¢Í¤R#f4PÞ
+!4 ò¡ðzeQ¡[¨;!Ô¹^×+OA
+o 1¡ze:дêö@õm |2B(¤bNE
+i q¡ØzeÐ
+ÔíêÝ@ùgîwÖ-Ek î3ÓÕ-YZ¯¼)bîêÑ@ù4®^YBhLu#RêÉÏÄL×+ïØ@· ¢ê
&_ÅâóØ@Ý¡n
+Ï8³¸oݲDÐ
+Ô=g ùÌ_QÌ×êg¾7Bh`[ý @@xå* Ð6P ÒzeR 05PW ªze á @Õ+W ¾6 o æ°êª@sfY ºÚ0¬^ B¨«9OÌ¡ ©W& ãybVÖ+CgbFͳºò0 ëÉÀÐ@]= (êQgbnèo±¡M
+ü-2 rcnªÏOC1këÿ-)oDÌçûüÏüåÅ|-æÃÉ@ ¢ÍËAq)HR# ÚÔ 6$5 ¢Í I h3HR# ÚÔ 6¬§FÄ5!Z:¢ùMRCÉ@Ñ)°üA¶E¾S6-ö¦h
+!¤ Q4E[Dkã cÌ]ÎÖ!DËSi&>h¾ûK'úó=Áô¥ÔºÑjYÈ,2J#ÚÐVëËÞ¦k1F¡y0F*®M¢5à\G»òý| ¸¬¤ @3ñ]û¥ä{¤y+rÞ% ¦¤QñäªA²ü&¿·+w(å|S·K´,䯢/^¸"ADAADàëµ>ËbÆÜU[À{Ë=U£°èjõ9#¸.?!Gá½y÷±X°õXD©3UQo¾-ÓO±:ætÃØ+ÕÆÿt°9ömÏ7L`³`ÁHËWêwþÞû!·úýHÖº|ÈWt$·Ð²vGuí×l ðT¾+Qt³KµcM½_¿{Ò]þâPÑ_ÔÔŨlQÇ||!)¹ïÔJØónâw¼c_< Å9KP0ʾÏëÖnv>ÄÚWO6¥¥¿Ùû6gt/ú+&¢î7¤mÜnL=ü¢ÔòVP«ÏºÁsnUsöµSlEØ÷ɳæ!Ú)ú«e ¼çÀ@Þó÷ÈæÚ¿ÀåwGHfX°F7×~+ç©|=Î]þÒQ0·§¤ñû%³óÞ£gBôVò²·úÃþͱowÙü1{j"¢õE1Ö¶üC[Vßûc_DãaÑEù]{¡eÉËCºÝÚµj¨:òå ªw6 è/3`ÁÒ¯¹ö¯¹ç{S§>¡]«j¢ß½ElìyÏYìµµ =µfä©xùFDIõ)ý(Sä ¸Jç%|Õ@ Qj9ÕñD©*
+þþ À{ãÍD²÷*mÂ} i}D¾<æE6gЪRuÔ»Îwönì¾ ÀÐìo¸">ËÓ(i15³îÙö" wÙSI ~£Àw±çÝÄÓ²buôû§ \%¦ñCÝ3«c>ÚAËR8 gñ}]ii¢E`³M/=M¢ìuLóqFCûÖ¶[ö% _øÙ7.ÇïÞûÈW.¢$áB3¾mâx«ÿ
1«½3Ð{V>\ àwïUr¯cì¯9ù ®Ý¯wJ=¼Öì3D¶`AKѺýêèw^é'Ú\eÏ·÷Y¾fâ6löL ZÑùsCòÖ?Ú¿2ì²À¿å¦Ù5®ò3EERó¿óËCzjÍÑÿ¾ëéëî÷T¼W÷5¢»QB@ò2<íO¢ëa Kfçÿã½Gqû(&ò(çÜü¦#â@ ÍêÄ{=%°YchE§õ·uvÍþöj__'¢,ºRëÿ lvÆ®-è&°Ù1 ÌNOø¬?*
+ÖxÞ{|-û%/C À96Üë~ÿ=αúE¯NõYÿlË8©¡}¸h°(C´¡U^^ºÖ(Ã*Aâ«ä©ï-½ç¸JJ¼Æ¨ú{ÍÐê·NÑ'o¨¹Ù#ï¹Â 2ýóµq_ XgÉÜW °`cÁÙWä+®SG¿uDÙý#ÞsôEgñCÏ«ìÙDëéwÓß,(!s_÷~9HRkFªõ GEåõªw7O´åE%7ÞeF¦QÊRm»ßþÔÄ}{ÄïÚ©¹â{dióõI;þÐ'ï^JK~ô{Üy¶Q,Ê=¦k¿v¶ÝÒG°èëà,Ý«ß&ÑaO.¤(ôT½·Î|"tõt{9Ç:- ¶Ýï»Jä©«©étí×luÎM¹êè
©o:Í 8gÑ=ÿi3ÆNÅ·Ór^`T}çó¾óD¾òCâyï19ïÞ;µÿÜSk=ôIfÐòßþòÁÞE¿×ûÆUö|{ ¤~@%ò4V"Oc D6ÿZ°%Z6OŨú¬Â}hß?-7ÎøTn]£OÚ¸Ñês×MçÛ¿è¯Ð9®Nh/Æ|«=&IéÚ¯Ùjê\6K÷íõ¬ÝrÞsä%gá
+Õe¿& `µüô¾ùDèzóÐõWp'`X ¢UGm Õ ¢é"WÞÑLd©S§ÂÇTQï£å¿ýe#
w®Ø,iCõyϾîh§âå'-íß²d´° óÙËBÙ{örUÈ£{ Zù¨óÅ °YR{ÞØORæèw}Óôï¸\EW!eÇ.%Ó51 `ÄZ÷¾'Æ\ÀõTü§úã8×÷"Zóï9¬ª|ªÈ
+õ)ZØz¾ö´ñ_1¥e¾Òµ|<B´Û[ý¿ðí5)rOí*éo³Éô·ý`NïÅ{?ÀgÏx(Y¢ 2òµû«lHäþõ¥1(uL/E´<EÈýUûlÖ*kVß?]%Õ%nÜxnMh;£öKÝRZhùç'ñìçcªÝHÒà%EËgl9Ã> 8CÊyudQ{_Ë[³h3Ïfß ÿÕGHZLIc7;ìû¾þö¬} `¹«ìùöê¨Wó DÁÚQÚÓ²DióD¾jпæAzjÍÈY4û:WÉÃi½5_aÑÑQªr Js®ög?asË%?å^xïù[ ò´§òõ³÷Y0fÛ;gô °çXTËw¾ºïhjÊ×ãêÞõ»vê rÀ"
+ (y¹(ØM×ÕÀ¿1fã)I¨K·èXà?E裥:X0÷ümyk>HbVæTÔß·è/ز OÞõÅÄXZWÙü$sF§ÿ:èê³.3Øó§ôØÜ»(Z{ @öx&Æþp{þý]eÏ·Ç¢¢å)?lÞ[ÎØQsÚ]ñZ5{ø-ÿ´Öòó#ª
QÖìa°àê%ÓYÙÐþ-§ûÍt>â©ZeË9NðL£ÈWçÝ7é©5#¯2ùÝ=ç³þ,E@;0æb)i½&þE Ê°§þrÎoNÛ¼ÀÔ¹l"ä'¼5ÿ{Ë3|/¢dùûCiiâ7Êðg¿ @´f7çÜôùD¨c.R¢ìý¬Üx¹¡ý[2_ùÊ; Á5ǵÐòoRsöF´,oÍWÿç©z¿3Ek`Jì×#J}Xûé ZÞy³ß½ûsz\?Z°C¼kçÜø¡·æ³_}Öw#JQ
[ZÞùG}ÒµµJ\ôö Z}JäÍ£%ÊÞÏ.]×eÏ4¶áR³e
+8{ÙQ½à1aª¥~}âê(ºYXÛJ k_õ¢Ïö!ÚJ1a[4q> ÈÓXF=àiÞó÷x¿kw´L7æ~CÊ®¥Öìaï=>ÃÇbª)&ú?¢-,a§§ò½ bT×?¥~7«¡ýcÁç3ÿxA¤%}aHÞüãÕy÷0{Á!
:ò¹yèSAwYµÐ\J¦½©>s#÷b8çVµà;®é'WΧ{Íƹ1-Ïò£QpÐÒvþæ¾ùKÅãÕØÓð%×FB(ÖhLú 2æ~ÄCîÿKãÙ¬ ¦¥í
+5q_«[G`³¤Ê·S)iMñb!@íCÙ~×öÎDÑ=Ký^6 9=îcþQÙï÷He}N©¢ÞÌmhßÞêO"üî½çºTE¾t4ð@ká³}I»æa]³=BI5#;\Ë;MóY|Úµz`KÇÒÎLhÌÚU Óßf [c¶j»@3ü¼ÜóõÎà«cÿ éç«CËR¸úN>¿Âço3¬Ád }¤BúÈ9% "¤D$®GDyIKÇA´~ËFSeKÇA´>rãÔ,zmé8IjAD÷ÍÑ'>jéÖQõ÷0ªþmö»~$ ÚÔ 6#¨.?r¬z6DÜÆ°¾¢&ÿr¬
+Éä
äo¥á<W<=í¢»ò úî#.( Æ>LCú @ÛÒ¡Í¢Ä1ö4EK!
+Èû¢-¢µñøTa½³5B @Ñ´14I .\! ÚÔ 6$5 ¢Í #6§vP\p1L"hañ%ÍÚ
+ Ê&h]|AÔB
+FÕ+QªV»â*qy0oÇ~ïÑ"±¯)Ú£¥qzF7*¢´dT"ß¹Ý 9WÐ-3La4ÃÉUª6FðoÍWAÔ ÍHZ|³ôæ.{ò{pÖJdÚñHª¾áeV &rÈîÞÅÉ¢ 0Ü4+8ÆÃF{jADBAÑf¤FA´$©A4¿û@£¦ßâ}2Q°6z®Àå3"_Iæ}²Ænl{HR#höüÛ\>s©õùw<ì.9¥ñû6ÕYôpwé;;ò§ÝÛØí#ÚýîÒgÒ.µ>IjAgðÃrGáÝ=l9£Ç8
+gõÛs'±p§»üÅvgëzËm9£ÆZ³Mùʳ= Ëgl¹ãFbÌ!uÑ=|ϲØxÝYüh5{øÅs ÆrÎêi=ÝÿNoõçá¬}Ö5x-{ä8αYs¾¸
sº[O_?Ý?¥Ýr¿ûÂ=l5kè>ë2 »â8gÉãYn÷Y9Çf5{ÄxOÕ¨úíÚó§ôw?fË5 ÀU2·-gÌè@ò¶çOéhµÔ9
+fô¶å8¼/CfË5ÖUúd
+ «ô©doõçáãç(Ù µý¦·f¿Å[óuèÙãTòxGkö° b£Fé¤Fqßýµ¯þå=Y³N ¼Æ¨úò?î©|/Z¬´-ç¦/³S
+Ñ_É ø;tÖ¬áïÑLL¥§âõwÙ³Ïвöù®²^aík´¶Ü[rÎÍ(©Zä«×ß¿%£ËK(Qö>"ò
+Á¡¥eÉ9Qé(ºïõböT¾ãwíÆhFìAæ_+]¾tÍDÒ²ö®Òyo pÎ-=Xë²çii|¾è¯9î}&y«ÿ÷¸»üø×Gü®?GH}2-§ûÍäÜ{ú!Ú`³e|½öõ½÷ùÛG JcsÝÿÀå%¼9Ê;ñ [ÎèO¥v±ö5·[³GÇSî©þd ³ä®0Þ]ñV¬«äÉhYûwÅk/ú¬Ëö¼I9ûºi$´JôWÞØß!IjAu JuB¸r6þ»Ï®x( (XÂXǺÛ0ÍÚW
+p=ÔbÂöèÚ-Ý£k÷ó>¢« ÀUöì»hâ>?ÎÚVÝ1fü®=72OÕûÃß©á¿Òµ[º¢uëîWôH0öFRv-ÕÄ~¡|©b¢½¼çà`¿çÐh½
+Ý·(º80æ}åZd®û-KôòÞ}ýî½ã saÊwb hiüZmÂYÛ Xâwï± gí«ë'QÛîç/ÔQ¯æ\ñX,8¢yïÑaXpvaík´ HÔ¶ûù+}ÒÚMh·!e÷UÄùÊnÊwbëگإ|åSÍ©ûììi¢`¥6g:úõ¬mÙXbà8I½Õç½'ËM3éÚýºÑúýùýÕÃ×AÍs! {!©Ù]þRÈWw0¥zÕÙç9
DZÆ{Ó åißùÌ?Ü£}øDëË$ÒèÓúÄ5¯[NuØÓ& (Ç3ÕÝbbx 0æBR à©|÷NFuývMÜçÇkG®ý%çjÇ8B:Íq?æþø=UÄÓg{®Òù·PÒ¸}âÊm5'ã¾y Ñj; % /,ì0tØósÇQ><ý§¼X÷ùz;ð²=$^D;këiÀX¨úY=Õk xïQ#¢äµï3b¯=wü$¤vFÕßhC¹DZ¤OÚ°þãÔ#L`ó P1רµIR#ø,1§'½± iG})ÓO¬ðÖ|hNïð
+ƾܣ|¡Ðg]ê1§§¼
+â5±ÿ[ ÿj½«d®ÝÙçuuÌûo¸JæÎ3g¤õ,È¥º1¿ÈôWzÍßÎãÉn¨Ô $ò´eÔ÷ )ªe÷í´4á8ëØx/äÀ
+Nè(º·ß¹s ©Ñ¿ë¾FËS38çæÍéI£ óçÜÓ&|»×Ù{¨9#õ9 L3Ê^ëµ ?hh?zèÂ9Ï Ús:S§¬g/tõ 7%ÑgÓS^,¨dú _ (Bî]é*¿A¦{? &fá&{Þäùæ´ë r©vä¯2Ãí«½5_<eNOvfÃ/´úfPB1?LÕö¸Ë^@êjîG¢C:zA¨T}
+©-9dÏ¿Ud{².· Ta¨YØà÷·úÓOÕëÿxxJ. Ôàð»v«¤a®ºõýî
+JbhY2w¾}rÎmjZËê`ÑE ¾,©DÙ£Á¿w,º(¿ëOµT;ÆP;x
Fû±4÷eÈ0_#©ÛªûB¾P~÷^%¢Ôbà2ê
°¶ßôRÝ8{ 7y1¼÷¸üRÚ=ç8añ£rFÕçV9÷TF»Ë)$÷Ôk»â¸À}gÑ]¬YCo½ûuÌìeËuSs´m=Ýÿ®º£ôêr?fÍ<¹1í3:ýW`³¥
+¶Wô`Ê«÷;
+ïîÑý_Mé£y[7 $Åõ £êã½P² j¹êÖAZ<_B¼Hh eß
DÆ6Я],FFÕßs) @¦h»Ô p©ís_jB«$5âÆÚWam¿õÖ|&%]&OÕÂ(Þ{\^··úóp,ºÎù¼ø,?x_ÌSõad L¬´«ô©äú_öϸJLý%,:ÔXpê 8Çf
+çܦ®»=kûMïù:40ÜSµ0ªî3PsÈSýqdÝöyïq¹§êÃH,ºÂDÞ¦ð»÷*yÏa9@íY0ïËaÑ®À¢ëìe/e±é|ÏV±ö5Zå'=1XôRýz«? ¨íQpÎwxÍßt ¨Ær>äwPø¬¿ÄpÎ3=ïEcÑEþ«dnuI£î4~¢Í²kiKÇA\>rO¸¦aÞA±Öe6ÄUþ²>ówZOåûÝTÏ?)7ͪ¶dt~ÑÚ"OÕ»!.TÏ+
+lï*{æM¤fD)ª½5+Mi§^säO½öÖ¾ª=%8iHÙ±Â3j¬Àæ
+BÁ¨öö£èÞn~ÇÖY¸/^´é³üæ)ý+$ Ù
[wÅ;'¢xOåûÝ
+vÝÃÙ×Üï¾DÑútOåÂcêáÿs½Ôµ¯z¢5y"_= 6¸J(W´a½«ìI´4.QʳgÍæÎO!JêÄå¯ÆI5Châ¾<xÍ{Ë0Á>
+ÜEw'ÚgXûêÖyª>ÒµûåM,zâ_úõ¬M ß©åË÷V}ÔÞÔ)ûiGѽÝ8ÇÖÙvÄïÞïDÂ
+Øé³-A1k\eóß¡¸-1¥H\ IDAT{Tn¸ãû«ñ;¿¼ç°§pR7ùí¿ûârz Ûfc÷'°ÙR$ (Ú«\qM£¤1iiû]úäÍ« ;aL=¾P¢HûÕg]ÒßYxO/ ¡È<DNû¬Kιd(3Üñ1õøB,²!¬}VúÈDi,É-7 ÷eÞjè°ûYc¿ëÿØ øKû;oקl}Jªéüw`²RSÚÉw$Êî02¦_H1á»Ýå/wõY~É(º/1¦ý¢u§]Åõà[ÇÉ
+>6¦"ÿbïÛSµ0
+ÎdΦèCsçmu_ç½ÇoÕ&üü)íäÛh ëXw;Å ¨\Ù0Ö¾&Ѻ©î?tíîamË'"ÚE1y³øÑ4¿sçeøão;ìûÞ²ý7þ¶ÃRç;ìû0 R +Ó'ÿñrMÍö½`úccë%_V½KfßÙÛó'}ÜTíÔ>
+à(ñäù^wÜõLcÚ³çÝ~¯«d^×+ìòØó§ô<¬}9HR#®u¸î¨2D©*kÿ¯vèÕ`Á©Ä¸(ZçÈ;éÆmªß Eëj<#Êùj©«äñg(iL¹"ô¡_óúÚ½`Ñõ#$qbÌ«0î¼vÉÏÄ¡r#J]U[&õ`Á¡Æد JqfµÃ¢G È¥ ÄÁÕþa1ö×½úºíþ*% å¥hÆKucë
+éÆÅòg©ÝæUÒØ(ZçªoøV¢ìa=~"ª}~5¢UVÖ9uÿ_õ
+ AFIBÏ®T(Fo¹iv:úÿýåq®ß`̵øÀ½°`íK3Q¢¿DQ{rèDOÕgf½Ã[óe³øÑ4kÖÐé½YÛozkÖàIÊ÷¢ë¶é*$r
YCoõÖ|pæÞföð ~÷Þ³«p;êlË7RôsÍgþ6Ä=|Bà2»âXgÉÿ¥Z³Ofí
+EM µ½,[öÈq΢ºf(¯[_Ûþ#\¥O'Y³O\"öYYn·åS7ú3زG p>dË560÷$ƲåÞ<Â?_`¿é½ï¥îL'î×âlÙ#ǹóÖ|jÍ<É5xòKæãYûº[íy6ö÷@qc=3x6{Ìù>@ø/þÄ¢7JðE|g³Ï^ìùê~kÖÀ)Ü4»@d®0ÖSõÁ À ´4f«åT·çìy· $áeº¾´åÝö^Ý{j#ÓßèwïiÍ6AôWöWǼ»QöÞà³|ÿkÖ Û±àì ÕÝtXðeM´f òU궡~+!ØDQ°k6'¦îë´´ÝF[ÎØÿZ2ûÎÆØ À¨.Øìá¢àÐl^2`¢S¬í÷;E÷ujG-ÙÁ¢`Ó \A{ÌÛ¢ÇïîÒg³åÞ2Ô7q°Ü8ÃEo5{ÄxgÉã½5ßF°R@´ZAR({P²ûiα¹#k[úÅW 8ÿó ÍD¹+ß|ÅUöl"çÜÌÚV¼F1¡kçý®ÒùOPLt§êÃ×þÕ¦¢í(»eJäÝß½{¢TNGÁÌ ,§®{÷LCÊmÍörÝí=U£\å/¾C3e®'?ðYüÎÝYë²iil!%1øýî½3 ¬Ù£ÞJéñ{ö÷»v?
+ àwÿu7 çÚ9µ-{b¢=ï¼
+ ø2µyZ&¢õvGÁôWÏw\ü®½÷û[ÇJT½2Y7ÜÁ9·¥$¡5öÜߨ¿ÛsXô*EIçÜþjí6{¦ñ¾,yÝl9£Ç°Ö¥·QÒèr{þw ܯ?+QtÊÈSO¼E¼¢õ%e÷ÂËù¤F\ÓÔÑïd«£^yb¬
+ã]§ä¦k äÆÇäÆ(I¸`êõÍÄ"JíR>v¼~°G>£èbS§ÌÇ tí=KÑZ»Ü8ã¹aê³ {R<°#ÕÉgglÑÄ~¡âuÞ{âì¥.v´YnúMmÓO*L3Öi³Ü8ó¨*ò
B]Âs)Ix¥1õÐ=´´_°ø "ìÿÞ£REØãsäÆ)Ê°ÇÊá?MÑz2üÉGäÆ'ä;³äÆ+ Lr(» DEÈýÿz6ɲýwî%e×Ã
+Ó=ÿßÞyGQ}}üÜi;Û[z* 4EAAQ×+*XD&±,(]* RHï}ûÌi÷ýc³qÄþ÷ó<>nfî{çnÈ9÷ïFªÒC·×º¯¥îË/u{nÙÄZ®{Q±}ÒsÆÍ eRÕ«µ^×lLÛ°K´â ÀEë z|~+ɤ԰¦+ª :¾!B1¦®õwì_ý^413ë¼.qi AÅm1¦~°Gp=T¥}nèþî>Z3p½àþntëù©í&¨øݤ*m1uý^DhªCÁ4 ¬yªÉë+F("Éþõ:SÏ·°©a"µ¤K¾ÜXv
+Wß8>I©û7twÉöÜèkym$ Á¤|mèþî>J3î(´©Ç¦ÆÔ^ïìþhÝùïS×ïE¤¶oXLPÑ~ß3Zòe.»³`¨V°>eÍ]Ââ9Pq)VøÑ{pù^~ûÛV,ó©æ?|nÎØùB¤ëDó+ù'`,èE~ßXÀþD®nnÔîÍ×)R£
1\ä!]AÇUkã«ú_ DE"D ÖrµÜ` ` Ü *ÓD ¸ ¡ÅîoïïìZ(·:êöMô=õ¡cæ,¿1íÓíÛjbfÖkbfÖr _ @ªz
+Úø *ã¥nh:zFc¨
+ÎuÃjg?úzè`Kó@Ä<P~,|ÿN¼úhg÷|ëxÖí3õøâðcÚ¸GÛþøPê¾~SM[ÃÏ«L]*ÓÄ6U
+JsßÐíõ FÝð½'êÿDh ß(ùt Pd§ÆàwA0^ î"B2Vø[f4,] ÕõÔU¦µ´?ÝîJÊÒe§ Ë
dR±ì2!BëoLÀ$ @ÀõETès;[¤¹5ì û(oóÛ׫LW~ Kx²¬ùH̬ð¿-#$ÑÚ¡Á{%Ô5ºÄg_hýÝ ®îqca©ÄX6¯a\÷Ñâ@ $·^[§ºõ5Møïd¢U~Ç3_÷Øýîò«.u,ýáµ)ò¦F¸xéé W7'=\IüÄïØ`v¿ðßèû kNéìß³áôDüâ!,sI¶¼Ì
Pu6vö¶ßs=Asmy½pusÒ;;OëÎ]ï,?ßßû![~¯yáçtñTÄú¶¼Ì
XvdèðAb{}nËë±Ü×¼v Úy¢v!H&ùpÀþÞ=¶¼Ë æ²
`¾ËÕ<ð°-¿÷ö¼ôgýæl´çg-s]ðB ÒøÎÛ¼z®-¯çbhuëLW½çk^s-?ça[^Ï%"·SkËËXÄ×/¼cÁ¤2]ËèGÿ,ùr'×ü""a¸+®lèþN§OäÿøZ^Qĵ6~Þò=ÿD~Æo¿»>ù
ü?k+¢(¡Kü"§¢«ê¿cYeØirsWúöÛß³ªÌí®Òc©©¥×/kOÕ§ÈïSlOá÷ðMá"wÈm,ù°,Úúê]5 ¨f®ÌòÛµ´~8GfcL¬y²ã÷ôߢÈá~´ô±`À? ÌX °â¥Õ}?3öøl»½ðì±ìê ÖrÝ:mü¼Ê£©Ï#D{ dR÷ßdLûd§Èï½ öÛÜoÌ"ÂPaÉ:¸ÚqlèuÔÒ@Q©cf®ð5¿t`E¤¾ÊÒëà˶¼'ÕQ·
2³àÙq)ò½ì?eÎÜý¯yM¬·ùÅiÖì£ÏÆlËË\ ¢ºý
+_˺ëKÉ7gìü«}¨gÀ¹éz LL·½¦¿´¼+|, 0¦mxNðlOS¤Æ8¡xL?Ô»in÷TÝÑGôhH^ý»ò¦Û1b¬_w]u¾ä;r iÝyB. DZó® Þ&UÆËÞÖ%-?fËë±ãÄ?Rç|.Ì*r{Ì"÷ã( Èo9Ú}
+BcQÏƼjHYwN<Õwç-Y¿.FÁó~5çØ|à?TWù
+Ý^_r¿tò*>Wÿø÷d£}Í/2glÿä÷öoËï5Ï]¸Ð=×±mÉÉ#\åW5¦~¸çßm×Çó×ÙËyÄÔ㳧R´8]ø;4 ýaïcC¾~áHÉ×'ìRÄÍS&µw¶ bÚögÛÄ»vbÛ¾Bþ³Z8gûãT¥ÿÕ»ü^E¨¯2MúбåAÑwøJ K¯}¯³Öë_%èCç' `
ÏÒ&,ZfÉ.-z÷Okµü¿ßDÐ ¬9%a
÷6HÀدG¥ÄSò`ÀñÉPévÀS<Ë\ß°$Y3ó%oóóÎ/féYO~þWY¬
+ àkY{°Ã´fðwÖìü§}-ë®cô£¿Ô'¯\¡uE~:àÜ8]÷ÈóÖ¢ÇL=7é®Þ0&õI+#¨è®æÁ@ñ² øµê¨é»DïáË nÛ$aì®öá1ªÔ'\ ØS=3[òå^Hk|jÉÎ]¾ 3w¯WGݺT¥í
+Ø À¯»&æþµ¬÷K¾£íò°â¥0Z?g3¶ÎÓÅÏ{Bôìò7|År $K¶îÊÎ ¸¾ªÈóBáå\ͬ±Ì¥sµs/]eW?]â²E§ú»å@©N«ÏíÌ>ß°$ÙoÏ
+|»åjfelcÅÒúÿ$À"êrus{oÚK¾#¬Èí¾ÃÛ¸,Qävjöö©Î&è,Óû·ù
øpe¿ý=+W7·GÇöÞæâCaê¡ñ·ûM)åCMÇ9PÌð
+KÃÛ©$ÔH"üý{|¶Ýsl¾9ãÇO$õwcéuà£ßgÄ £;¿ ¦AðdY𨬠°å¥?KP1Q¢"{Ò ¢\aOHÛç
+ª´
+ D+Eî§4 í HÍéá¢M¡ó¿·!í£|ã³Muh ¢÷¹Ê§UdÛYîï¼ÔqÌØÙ¹ XqgÜvAävÈÐUJÞ¬bááwâ/ÈÁ²³'W;ç «ÅÏ £«¸Ú9¯ù¥8¬øâµñOÛò{O,j¹Ú9I d¤{äyoÓóSmy=ocôcVº½v(dß¹QæRÐÛ±ÌuåPGÝÖlqâê³`K :Ib7µpõó¢öÿ÷Ä'ùó,¢Ûæ]
+×Æ=6o\¼ 6"Ee¼Ô-r;ø:]ÌDn§ÖU1m AYsË4k¹ö%Oõ}S¢öcïfM^Ô%-?Öñ:{áYw Vh ÔN¬ð>é¹ Áó°dõ;?#5ûøÅÝä@É@oXä°ôúeMÈ·qEÏóãŽÃÛ¸"Ue¸ømâÓù|ÃâéÔ5¶}÷asÆö»iR"ÒPAR©£g, P¤FÒQ4âQN:¤¾çË]wÅõ£Ép}BO3w¯çjÅ#mñÛÞ4Xs
+t¦Fr&£ÈR멽üýb©
>ÝÕ@NFWQÎø'(@´:zÆ·Xv%üv\68KÆóTÝÑä;þܮ˽˱a¸6nÎàQ Pê>?
+îo'·¦{hãØy·L÷Í(ÞY:q$ &úîE϶ù¸£³±!B L·ïP»ôÉÏ¿Aë.ØÊÇÚ Êr(¸OímZÏZoþ¦ÔQ36¨£ïüÖj·F±Ù_ð
+L· nØ7 ¸¹ï©ÌS7ÑÚ³Dßáh}ÊÚ×(6çcÉ; ý<ù4Q·¥ÈÎÓnQúÓj ¦<UwL Um}Þ¦ Q¼:zF#Box*øV
DÛÑ+ÎOf¨túTÊÕ?q!©JûÁÒëÀ+¬C/ °æ«¾DÈ1Á³¥Ój¾XñERyÔë¾-h QSgÉÜû>é¹É_p¹)ýëyÖì¼ÅØ4¤ãC ¶Êudk¹æ9Û> Í2£þ`
ÀW;g°§jÆDY
+,Y^´få. ¡KiÍÀïL=7nR}×ÏihAuÊBÕØÐqÖrÍ+¬#+0öÅc, Éwä
+cêGóÃÕHÎdøºyîò©wþÓýr5³ú¹Ê¯¾%ü»òËùº¹Yµ÷5¯u÷Ï«J,gÄ¢F±Y;(u7 ©Êø<tTe|T×±oxæ6Rqb3¿ @ª
++JôîjHY=·ãµtÐg{óÖzÃæ,?Åö>@iÔ S?ØC©löÛß¹Juó-!õ3v|lîùÝr,;¢ èmÜÜÏsæ× Léßl nEîªÛïù½C¡QLé_½Ç]9mä;§º¥Ym¶Ü×òòT_ó×(Òô¯ Ô} èS^ÜNPÑ?kã|üyÍÆpÑ|ýÓ' R+r $É]9m6QúäßÊpñ*¾qÙtI)"ÙÏ:ËvãW÷sRlöÎSµ;] Ô½¿üwèoG÷ÛÞ¹+Õv´Ç
+1ÇGW ÄÔZ{>`Í)uÂx% Fm{ªTÄÊÛüÒc´îýºÏf¬ø«¥ `É:ü©J=Æ7.ë,½´Ct)
+P¨Ðï ±ìl÷o!2¸¿Ae_??Upo¾5Où -±d³bÅ«Aö¶ïa@¤O]è§zæÓ¬¹÷ ©í<c¸¨)4>,; L#ÊÛi·æ,7ÖqlØÿ
A®/
+ª;ú8/﮸~p¨]HAD*ã;ÚàjÌàjfe:ο«Î7<â(9)X-:»âº³]eW87ØA\e]ÉÎñyªgfÎùíïYELVÄúýÒÚ!¿ÒÚsê}Íkb##¯ðTßÙ Àïüè\É_x
£häÁR:;µÎâ/ãNéhÇ]yóY\í¢B AE3ÇλV$_¿°³øÂËD~&¨(2q@08ÄU6é¾~~jhe¡vU\;Ä×¼&6¤Âr
+b
+å,¾h¼£høâJhÞE#'uüwpn4¹Ê§w¢ïïp?ç{þðyÇÏÇE53¶}Úîç°kÝ¿jãçm
+ýÜ1Oɺ~/ ´
Ö3~ü X½Ö±ó#9P̸ʮ¼ ¬ûÃó9BÒ¿û*ô:¥5 `Oû6ß| ß~ÖÆ/¨ÐÆ/XÕÙLªhÉ:ôbø±ÖÈĶèDÖ<y3 lîx- @«m» Îæ2DkîÑÎSµ;]0tûÇsãä6W"5´ôÚ7 $d;úþISÛ¡ù-WóÀ
+gñE42¦®ÿ°¬¼2%ñXN7ÆÅ^EPÖ&Dhjö²Z®Ä~ìU·tÊDZa³¡kB¶dRÅð¶Xöôs
+ªõ)ÍàO 0Ì÷7©é|®Ð'?¿Ãqlø+âQ<`6gìØ %ëàãöÂÁsŪCViY¨Iâ<Lê÷Îñ!B_±pÜüÿe°ÂhÒ<ìm~a>¥Î-x¶$Òº¡KDþçËÝ7&î#ê«ýn÷µ©kç9<ÛF(/=÷]¿ííE4ÿB©³wsÕ÷>¡2^z¿ Ï,Ð7¡qÛ,2gîzÌS}Ïýz}-¯EK¾À.GÑÈçÝ°·DnÇ(gɸdmÜ#»¸ÚG3ú/ Ü7åèqý°Â«Eþ§{iÝ°××wôSÏTt"TÛ(M¿B¬ð«üµ´nØj¿íõ{$_îFcêûmy"·ëJ J3èwÅ
+/[s
+§ ܱÌ'3úoyªî"y\Ni}æ*²Î{"6ts¸RzSl-hÙײîvMììyªbÅ«Ûý ±8àøp"T¤($U|ÃSUÆq·\_[øú§0_À
+§ox*Å×òêÃûÛ©¶sF,jPÈigX³N8a]
Tõ,YGVüY;þ^Xë?cÉÆ B§°U¦«*b=Åÿo.A'I Zë
*ZeÔNÆHeÐÏËíì';hí Û¸Î#éÄfuOßçw|Ü_÷È"ElP °¦ÉKí§¬@TÌèGïù½½T¦Iý¶7ÄuèY¾vNAÅùÌ»ÞçNQÄz>ù
7:ÞAÇ~KÐIU*óÕ;BÉÝKKeA7÷^DDI-ÙG¦{ªn?:_h<Ð)Öì'ÝÓûc
#B!ÛÆæóuÃèG~e×g ¬åêH6+ÐzËiVÌÛ6rµ¤+²MËèGN#Ui§ÍÛ"t"5vEà 0åm~i©êY(ËncÚ§ÛÝ7z$_î ¾n¾ ¶º¿³ßUv+u´EkúlL]¿××£µ\ó6îѪ£Ýn À³·¹OÐåÛ| ©/öTÏÌùΡÔ6yªïÎ,ÄÞc +ì/ìÁ7.I&å{C÷wö;K/5)b]§yo ÿ1õ£ÝÎ
+{Ë Z;8WòåÙõIϸ+o> ¢~6¦~°«ek
+kÌÏƾ§O~!ß^Ðw(Wó@ Zwîûn¯²åg=®2_½V°¨Ô^Ð÷®æþþæÌß´íñ:"õÅÆ´
+» |-¯YDn§VòoL]ÿ ·qÅ@ÞnL}ÿ'OõLàÙrÍ<(Êr$%7°ÂruóûÈþüÞfÀ»áûþ%£¯ùå¥n¯Þ^o®#ÿÙE-BV £èWå tä)ltÌÍ£Øì.aQiG;$*{ZK¶´³ÙÚ.ñÙb ÖÃNóbpøÂ<Úµ#X ÃS?h÷æß:Ævã$H³lLýhwÇñ º½úkÇû4¦ml·?¬KXܦ:ºàçãÕHNÜ· % µf<iËïý (`ô(¢ZC °LªîM¿ð EvtêJF®M½dZ?DÈ"ÖPM2AeÆpágûû+°Â¥3¶¾é·hÜó¬Ùùm
+#ª}E¡º ]'A÷]ðRÐ
+
+ @±Ù"·;
+ @ë,!!ïp±6 +~+©îÓüO at P1ABÛ¨V (ÅßL±Ù|ݼ(Ë\z(¨b³?wWÝq7"ئ`JÌ
+À/:h¿&
+Ú&wå-£Áº-½¼bËë¹+¼QQõXjk7 D¹*ú W7oÅpÉ«'ºï3bOÍYzÙP1Å¿¿ým«³ô²1äÚëK³dìøÐ\í#>Y¹+®ì,;ÎU>uè©îÅ]yË gÉØñîÊÏ:.@à¿óûÐ]âÒ¢;¬út
1\\¡H-gÛò2²»Ó඼§å@éÅ'jw"hÍE,±åõ\ÚÃÖ'=WeW?4å#B§¨£niF¤¾Æßk¾-?ûQGÑÈIºäçs±Â'Úò2
ªÑ¿§OMÜ#U ¬¶¼^ÔÑ3êQ^[^æBÉ»ï*ÖrÍÛÞ_'Ùò2Ds¥ÜXË5_ÜOSù¶4GëFØüö÷æê}Ñ\*wcèþúEjº1\ÜVx+¾[^Ï%¢÷àdµõohÍÙEr ê"[^ÏÅXñ% èß¡HM}mù½æÙòs ]kéõ˨½ ÿ½'ºÏ3BQÄS
í IDAT=3[eXÕY¹õ¿Á³UpnJ =Áÿ<Õ3³®OgSlÖ' zÀ±Îb[v[G©2>Wdg¬"Ö!n_3÷t<i;ÚcÁ$îÅXd¡fTTêï¸þiZ¦¼z"oDQ$BøE°ÂïJ¶?"¿GÓv¡È
\Ü'BÊiÙ_Âkvþ~Ã9J-/c&vö*JÝ;Y?§R9 87<5,ê]q «ìªóe±6U´üãp»XC)bÔ¯ü
+Á½YOiúzO&JâRù/ è诼ËÏÅ#d !X²óÅ
+O8ßJÀX³t\r±(éò7tÏ·íö
+B+þ8Jý( X¡ô)kçÞýfûq ä·í¶!Ʊ¤SƮӧ¬9â(y
"V
+Ä8:kNÉÃáãC¦2<0 À^pÖXáÚSò &öá·Èï{ÏY:nä;ò±ÏöFwÁõå $¹%¤ê¡2]¾Kó@]Knü÷ píkYûPkÔfÓ_ÐÆ=RT
+iî
+ mÂÓÏró|-¯Eó
+OÍCH¶÷W*Y¨ Ö<õ-mü
+{áÀXv¥"õ5¦^uoÍ)z<àÜhâê¿Ý÷«ì¿p`L1Æ?ÔÆÏ/rY@P9ýo±âO³åg?Jk~ÝÑu:ðgÔ<ä@1Ã×?Õ×ÐýáÇùú
Ý©51Ô¹+§÷
¿2ÐÆU6éÉ7Je¼t}g9qÈfØ<Øúß«÷vGeÓDè®.fa!H³¤ùíH&UìôW,h 'V)!èØ#à?U?']Ð\_¸ÚGïc-׶ÅLr3 FítÔÙâ~\ñÜ.pF,jX ±â£1ökPÙ¬Y¹ËíýïájîËQÄfB»%'¸)±$ÞUQ½«¦{V$ø×ÜK|öQ¬x3,9¿æjì#¸¿}(ªOÍ5ÁâÏCiúa0ûòeZ²÷ 8>ò6¼Ky²P66ªwå®fV¦ßñÑ#ÇOrg;Úc ¶QcAoÍ)ÛÙýÐÚ³}Ðþp~/¸¾¸I7w©ÊrÍv4ý5h^ô6½ø°·q¥QQ»(ÍYþk8gí]7ÙS=3ÛoïjRÕýuEjhÍ)uü¤ùIÀþkïúr q]jHyéqßkõ;>¼ ¢_Å2`Í)y¨µnWfëüµª®àcÞ_¯2¤¬~TTª½MËï#¨¨dVüÒÐ/¥ß¹¡,|oà
+oÓªø¾¯åPÒ¹¯yM,¥éëiUó¨dô£lÿ¨Òââµñ*øúÝ :WGÝÒ²±øºy=T¦ uûhÛy£·qY=uKC('2àúr4B´ÆÍXqk±ÂY¼Ëã¸ðD^_óXÖz]3"tä;ÂbÙI
+Ü=ÛAëñÞÆeÉØÙÕáz{³^ô¦ºs>k¾²1àÜdIJDbÖrÍ×òJÊ<ÙFfY¤èÙ¦W$Za-7ؼM+TÆËZÂ{%¾*4æ,VøE¬gù§SÂ÷÷°Â~Û»ÑáU"^¢¹ÿ*ã¥nñÒáÇôI+ ðÏÚ>gÄ¢IÅ ÒÐ(UñØØT¥¶¹
+×7 `75zWJ"¤Y&Ué6Dê
+ ÊlSÄd hBC[JP±²:zF#߸8^pÿ`@â Ãz¿ã#è¢Ì»Ù
msâÑtÌ ©Ä
+Cë.höµ¼Ó¦,HR[oX©HMÀ¹ñ!Ej$cÓT °«+®MiëËtD`øí^ô¹ >ÛÉý mj%TtÀýHC5 I'×(bc& @°Ê±dc , øº
®ETT6î±*ßû§êö
@¨ÙyKN4oóñ¾¦çg"ÒXæk~>Ãuø!_óê«ÎO¡ñJþ¼*ãåëCjû·ù_YU#Á$ÿ,WÞl|¹g5Þ¦çkvî2OÕ}îïn!èC"ÿHp Îïüxºh}JŲ3FÇ.DP=ÖoÛâmZÕ_¸ä~i¢Ã^pÖ4TzfjbX*x¶õùî"(ëϾæÎF¤ùW(¯e]ϨÞå÷î+àÜØ!.àúlí{ü¶·W"ʺÑ_ð_¿h&"T¾aqÊxÉZíÛÌ×/xQQ;°ììÃ7<!yWö7glZØ÷æ6UZ¨Ü àmZù "´u~Û±Öâ9ª;ú-S©¯õ6¯ú+"ÿI0ì/TuUãQ34È+KÞ,©îø'«6ÈB9;sÝuɯ"±+µì:S0èºÒV8B1§Ûßûtä9*ãøÍ"¿jÐÝötJPHSa¹Ú3\¥&TÔÏÆ>kìÀXf]×ájç^×>A¶,¸ºÇÓ¸ºÇÓüö·è{·Éþ Þ¦ !
+ sSwWéå#Ç>CP±_2úQAs%cÇ{jîË@JHÏ
+A¼*`·¹Ê¦L Pd×`®ötOõýWtÂn]Òò_©ù®nn_óØpÀÐÈ Z£âccô£7ëV¼Iküª{ô "6õ6.Kù/ úµÚÛ´*Þ×òêU Á> Ô´öÜúÕ¯ÓÚ!û}-¯E3ºáún¯>OV8!ÚÅÕ>ÞÉþUü¶·.C¤¡ ãË ÉSuÇ@Sƶտà2Ñ»©ÇKtKJBjÁÂ
ÔÄÌzÎÜsëgØÙyP
+ at HXn±ÏÖÉèË,{ß2gìøµÜð"4e̽o
»]:þ ©ê¹ÝÔóû¯ iþÕudÉf~ì·½y®»òÖ! èø2DK|¶·Æµ¶ûÅud%AÇí ¨¨KÖ¯Ï#DzÃu õ)/çÆLPQ> FkvÞbÍiPhKÖ¬ùªÏ¶ËQÕY³>Ki¾IKÖ·¯_Ø/dS3³¾MÕ¤51\ò¦%ëðsKz9PÌ-Wt¯P¾{x±ÌÓ˺XWÙUzP:b/<ûfgé½MÏw·åg=~¦èÙÑå
+æGÑùW;/~¯_㪸vö±á*2¯_xhgðu÷rWÞ4 +a?vδ6'Qúàëtw^> À×¼&ÞU6å8OVG
+wÅõ3º2¦Î8#5ÍÞE©ûÛ)ußBJÓ¿ R÷Í£ÔJµñ*T¦«½M+o\_ Ð%.yTðl¿ !J4öøt-ÀoJº·b³w?;(u;Åfï
+o @µ~6¥m¥5)_HmyøØhMÿ&DèË×ã×ãÎOû¨L]ê¨ôÛÞp~:.dKä®HM´~Ô;Öì¼Å Æ´O^ÄX¢EnϹú¤s H6ó;íã 0¤¼òa¨ !AZv
+îo/A¤ÞfLÿê5q=,¸¾¾ØײæjÀ¿¹¬I6#Ù¬6õ}ÒGD~ÏÙê»ïUÄF#¥îëg7<å³½y
+AÇåÚ©LùZÖ]OªRsI¶×cxTòçe¹+o¥µV ùíï]驾÷qÂò`$×+nûy¾uiÉþWBj7AÝ´vÈFF?ª<¨ÎÑZ`Q)a+!×»âú@ñj5±³> ¥&@VT´ÿ·ædÛn{¥-Ä ©k @ÃOͤÑM±Ù¿¨n ¶ÓÝzöTt«ôËB
æD·M ";hUA¤ÑXVǨjí[ã
w#Äø°ìÑv°Ôî¡Ö¶B*À'AÝnø+¤*ã_Õý gÉÅj*b
+Rù}jwåôþ\íX= âÊþ¢x,;tâQÆp¡'àÜhrèky- ¯ê©¹¿£høpEp\åSºÊ®á*»êüß]=4¨:råp wå]eWÀ
+Gpu§É©p1\\IiÎÚ,å´«lÒ Áý,Wù5ç ´*¾<$¬
+ ੾³·£xÌ
DÏV§ê¶~ AUs£Iòç«Ü7¤µç6Ð!¸ú(Bå¢WÄÝ7t/p{÷·¾ÃÅ^:æ,7ÖU~õÐh¸"ÖPáª)ºOiîüm®º¯®pF¸C~áåôÉ/æµ}jèµéè±æ©vÖ<u]¸Ð}«x@[ÎPë5w
· ©-xjîÞ"ÕÃT1íʨ³ÖZXëMí>¶(×Æ?±¢£ª¹çv2[¦ô¯¿}¦Ô}ýæíðõóS~KÖ¯í4Ñ÷Ôk¢ï9NLÑâý¨¶Ê*Ó$§Ê4éð6ºE¥ºEK¹º9éççé ÇÏ%@p31\ØÎ諸ò&vv&vö[Ýã¿Ê4i£ÏöÖ,DmXá²XßÀ\z+9ë Bq\:Û·!Úé(º`2kòc;ìHð6¸
+c1 ÒÞÈ×?9×ïüìÅöévOõÌGñèú¤ß
Ü*ºoaÀõù®ò)nRÖl³v¥,Ö' D z~'ڸǪ|-¯EejΡ4C6üë¡/²¹Ie¼x{gç)í$ïÀf¯HMIPåuÖîEv$j«ä=8ÜQt~º6nÞ×"·çÿ `¿Èï2ÜWhãç=°ÞKiúT/ò{¼¦·ñÙ$_óY´aô|ÃSóÁ.<[ÈÊKýÈI:á¸Dt¬pàÞü"9k¢p{Aÿ¬_<ÛQªô×T¦Ë·Ûò³%ä_±~{áÙs´ñO¬ ü¦_ EnÏu$ú³ä/ì,HȾ£1Ʊ¯sµ¤ßFëG¾ÇÕÍ} ãô68W¡ØÞÛ%ßÑ ðqh,:Çç®üîNfÜ®©åMi /w0k½q¸¾æ(M¿BéÀJ Eög¢WÙwN¤±Ë®æÐË"Û/ QÆïÈ(WÙd©Ç¦möcÃVUSvr\ÜMeôK«¢ÉAÁ³íIRÕã-ÖtÅÖóv"ÎEíßƱóø´ÖEòo ÄÐ%,.Ñ%,~æï°ýo£_PÁZ®ÅÕ<8P¥©7Ô)bÍ!MGOõÝ6¬p¹×þGøºÇ{!*&R 0elY멺ólq1úÑ[#Sßÿ)àú2Ï×üòZ7ò )ý«Û½M«²©oMÖ'¯Ê§5ý½cÃØE¨, P[§T¤ $kNÑÊ[aůÒÄÜ+Õ*E¬/ P[®ÿ`ºy XËÿ½¡2^Ö~o¡q2ÆK±â3tÜsìOå-ÔÑwÿÀ';d¡V¤ú×}ß'J* Xë´ÍÕî°%ëà2¾nnOñ©ÌS_aô£\ *ËÕv×h¸ð'Ûyo|v(pðß*òg@6×ÔcÓVÉ{p³lÒs ðuÇ6¬åZW7NûZÖðºÄgí
nÃ)Û=@a|-kG ªwÚkß'SnÉM~ !ªÅ¹ç]Ej$½+
~q°d?5O^ÄÕÎâõIÏHÞm.}sÆ+íý?&èÄoôÉ«ÚúͬÐãQy\ åçkb\¡ºÉþKø8[HòTßÕ`¾RĺþÔâfc¾Ä²C À§4ys¡{Gn1gî^ Ðr´Û+ííÅ5)RK.qi·qY"Aöz|¾
«}°:àúv§úFÀB¼è=8@¡%Qº
+ mLQvKæOowýÛ,j" ©ê){|¶=ôs¸Hqè
}0@PãývòB moüm:º¯¿äO+oò¡ÅÈ
+оø"B¯ÆÞà PGßÕ:®_PÑÑv(b³Tס£MIµñO 0KÜLë8~+;ô1X¸ô¸<±peZ77éwª1zZÐá+ð»Í16M÷ãÖ2V"à8ñßpÒRKPÖÚðGÑ°©44íc)
+ @òdÁ D¹ Z²=®öáþÔÔ<H_C¤±dRÿ~ÛúfJþ|+ 4a,§JBP1¿îïîQ'®Üß]W.ñåªÛÎ @·nÇADXx>n/¬M¨À2ýÛ 2 VPhZsVàþþhxdt¸¨qh~E-BÚ)[^úReµÊ0öI¡®³åe< kBÑÓ¡K~îWéÚò³ûUaôqîÝÜO¢úÔµ+ºðÙòz,ÇX¡iÍàõ¯¡Ô}6Úó{? q Å»¬c¿ãàÞr·1í;ù
ÃÅÎÔ%=÷§êlùÙCˬÊ4á]Æ8ñ3¿ýÝû×W<`ñ¸D9Z;d¯ßñþíºÄÅ
~_1È-ªðÅ:[^¯ØVl&5q8FÝjËÏ£¶ÞtÜk½©ÅÛ¼ºÚßk> )Ttk¹æÇÎlu3BQ$ÂéMDQ$BøE ¡îeÂ,Dn§¶«îTÛ©%èx±cø»ß±ÁìmxúÚðXá[~ÎËÌÝwaÅGt¼¦ãõá±]EðlÕªÔ@(+!û?ðwÐjÊï%¤(rFD?FðwÁ7<b?vÎ':oËï5ï÷سô½?1v2'³kËÏzìtÑü<]¡Øì@Gi¦ß³?Hëó-N¬y²£c(@&¨$lA]ßÕ1ÃèGqáª$Ð)ÿ+@Ðþg´p"Zÿ<Xáð|*ÁýAòa¹º9éþ¢fÖümѦÞÆg$ßÖïØ` P&¿týÈboXj«È«}¨gø"o¼"sí$¬xS÷f}¸è3V¼m{7Áþ>°KýÅ·iED8íAÁ^û׺e®ÙSð&ÿÎl4ó6H¶æÎæjçLSdGúË]gûxMÌÌgmy=#BÓàkYÖ<ùA¿ýGu ONçjç<íFkóÛßÔ[³pW\?Jlñ×)ùTY(Bì81ÆS}÷ÑÛ¼ºÊ¹·-õÁY:q¤ì?:ÛìmXì·d^ ஸv>"ÔM¾uZkvÁÿÐtE+hH¾#,©Jº¢ÐÌÑj²ÔH*¢Øì(f¡VºrÝlaÙ}:ȩƱ:êPÍ,ÓÐ(áoÄHöUè-²+ê%7µÿi×ãýèu¬Ã« 1.®ö¡ *s¥×/k¡ rZ H¶d^Åè/z³3[¬õµ¬#+°âK ÐDßõ3AZb²P5öÄ£PTæ-ÙO*B]»$SÉwd¡ÛóÙyÏ(²£O(¹UeºòUKÖ æp%?¡²*vÏöFl×mÝt±«bÚøSµsÿß¹cCáëæí8vÞµÎÒËæxWvI Ä^8ä¦Ç¸Úû»«f;u¿Sr5³2 ÜUwpWÜ0©+}8é\UNÏÕ>ÜoX*í%zvè\7°¬ÌÉÔKBDÞÔ"ü§ÁXb©o}*$ýXv« HUZõ /B'A«ÚBà1§zæC´vÈ&Ö<uW÷èIj_!¦Ö'{ÜAyÓßúddE
+î¥!Ò ´ET¤"üeîÍz¾qÉ(qü~MÌu~dzÈmKüEi´öÜ£fÀ7 A·µ«üÿF!BëÀ`Lýp¥´Ötñõ»aÅ£ù}}iÝ°CºE¥"¿GÃÕ=v &úîí'«nà®Þ_-n¯ì\_E~ÏMu%ËBÙdRÕë-Æpq»âúÁR $Rõ,0t{?V8Â]qãyPû
+ÝßÙ啕/K*'9F:ÕÑwníÉÑÚ¡Õ]îüù*oã³½ÉfF©ïÿé(y ¡\§\V± cuD©ûJq :¾áéQ*ÃÅ¿hbg×ßGh®<ÕwöF¤Ñ/r{°æ)?ª£ïj µçät2ç·¿3ZkÏsÖRÖ|Ckn pWL$²(ÍÀáb§"ò¦á?
+£þMÀ¹éNGÑ+±âÎÔ%?ÛY»Ö"½pàÁýý4 tÊúN
$¾qù-pÒktz½pÐm2
+?C2©ß9K'<l?vî
+±!×ßöÖtGÑð)+lgùdþr qWÞ´ b½M/<⩺èÙp|²
+.JÝ×!ò?Ý `/<+¼NâÏÖ§ DîÇg§Uðl9ÛoÿðN¨õÛÞ'x¶ê$_¤jI&µÒSsÿ E¾í
o|Î,ÒöÂsl¦!ÊMÐ %ºo
+ á£4ý
+ÎÝE~ße~Ì.Dh öþBªºÙßJ«û5"9JÓ¯RõhsÛ îÍgÛy÷.àúj%`IþcC\¥Ú<Eº Õf@ "T#èë³Þæâ®/
+îÊL÷*_Ë{¹ºÇÛÉà
æJðìpl¸ jø%Ïm=Oðü(KBªZÝ¿Pòå«E~×T ;¯àÙz¹«üê¡]ý#Zÿ4úäÕGõÉ/Ì%Äkvþm1µ\·µ\S
+ 2]UÃZ®{ ÀSô(c÷=©ÊÜLÐq ~Sí`ÍW¯"UiBðóe1ØØcÓ|2ÛYóXó5 ¨Ìÿ·ÑÛ.ʵ\wc÷99ëgkV°DRÈ®9cÛ§ê¨[_£ÕýYsÍkµ¿Bsïj¯±æÞ÷ÏÌÔ®vÎNØbL]¿Ñ|Sä÷ @e1mãðèC,siæ[?3glÿ!ÚÖÑɦnL}ÿ'IÜækYÛT¥ú$_îßs)`!ÎÛ´*¾³1(Rã9¦?¬ÊáÉA=O¤²Ó³JµqV"y}Òsf@#ƾDÁõÅ8RÓìwl0cÙÓWò§HÍX?µÞÔò[ûÎ÷©¡;lJÿj3kúa°¦b»sMWò è¤o©î!Ué_ÎÏz] Ð"¿gÆ
++¸¿¾èDsËèG7¦¾ÿ"4Aw~ë<ÑñÍP7w¬ùe6àúâjÀ¢^òå
+;ÝDÜþó´ª´Ukw¡ÐÚ³}´öìj {á Û°ìNDt ^øMµ#¼yHqb³Æ´;ÂûÒ%<Yè¬gø1MÌu P×Ñ~¸¢H¿RÚ(ùÏ P¤f"ôâΪã]
ôËDy Eëq§Ú _÷Ø太ûQcÚ§Û[rßT¤ugc@@¹%þ&â©`QGÝÖÄZoÎUßÝ×Ûð̳æÌoBS||ÝBtÒ Pé,Dh$ÀJû5QÆb""oë5Æ"MÐñu;Ì?µÓí´ÊÊ·v(aÿB# (í\è÷ +ùó'Dõ.¿ÇY:a´(:ïTöCDµº¥×WNÝ*Âé.qiQÀõ
Ú¹@Òjã[,ò?%vÖÖ÷£ðÜeÈ BLý©ll¯|Á³å6[^ú% ò KÔк¡ï{ªg, ý$²ùD®ò©C%h ¢ö+d§ì´åe.DóPÛ-½ö¯C¾Ä×k:júº{^§ÑùÙg{ó{ád9nÙÐmÝÏöÂÁ£mùY`Rø¾3Ù¸¡SdwnºÃõ¸.aÉó mrp`Ëëµ cÁæ¸7áQð¯QÐ%þIEßöTE*ý
+fi¢«Ù[ðlbÍ)züTýKþ|"ÔÊ©Ââ1"TÒ§
+¹¼Y%æTýÿÞp²@¿ß§FÂuB·àÞ¬ïjRvHQ$ò¦!BèJÕeÁó}
+_ÿø½0Tkãç?×A ÒIDAT%»lv +íbpWrÈ:[D¡SþÉ
+ è¦ÿ;ìþÈ¢!B Cʺà pøßGöD¢#D!ÂCdQ!Bg÷c"t·iU|ÀñÑHDE5èí"U=wÅ´Aëù½hí_ Dħ?çÀO˯ީ¾«Á]1m&vÖQJÝ×ïk~)Nªuá©þ"oj"DÐ ²Pn¢´Hgé D~÷sÓõºoàÙ:ÒïØð ÉfÃ
+O"Bï¦Ô½óùÆgÉbFk=Õ3Ç x_º@A'ï1Â_AdQ!BN@VÜ?\*eç`ÙÕ7tµL}#¤EH©ûn0t{ý ;
,Á³í
+À
+Ã×?Ñ_ü·²Pvä;Âb
OÖ%>[üïÝÍÈ¢!B°¿·>iéZcêKËÆÐqíÝ.Of »âúá1^kvÁÐT`Å«¦Øì "tå®òkfªôoþ{ø/ÙS!BN at TôOõ½(4 ò¤ùR´ö¼boÓªi¶¼l¬xÛ
+ŲæÉz_üÀöÑ'»>Â_GdQ!BN°ôúù
+Û©¥´çxCåX¬9%ývþµ¡ÏØÙµ¬õúéPK'DËò(Nø°«I×þ<E-BN Îwµ-AÅÊáU=Õwö½.4¤¼üüß3ºYÔ"Dáo@¼ú( =eÃ)@"DpÆYÔ"D!ÂÃiå~ýGox*²aH¢Ó£þQ3eP¤ÆH"ôÀéUO æ
+#®ã¿¤VEÅE!uzTÄqæÅZAòW=¼« hJÝ;È/ÇÀ¢÷ÿ<9ÖoÞ5´ IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mpm_pack_unpack.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mpm_pack_unpack.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mpm_pack_unpack.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,301 @@
+PNG
+
+
+IHDR ´ *91ð sBIT|d pHYs
+×
+×B(x tEXtSoftware www.inkscape.orgî< IDATxìwXTÇ×Ç¿sïݾKi"
+(ööÞQcL&ñÞ5$ÆDcbL11jb½;ö®X "é½,Ûwçýc *(,ûy`êeÙsgæ h`¥¿ ´Ð·ò` ]«) ¨ò± |«)@ãjÊß`S¥LQV.¬RÞÀ´jÆð0±ò WSÞÉkuRÆÖáZÇ7ÐZ}ª)ÖXk
+¬¦||=¯õµjÆö©Ãµvj µ²UÊ]hÃëp*å6Xkp5å}ëp`«)ïú¸k Ü«i,º ²r9 Y5åV $ÕÛ USn@PM¹}5/SVNªs ì«CÀ¶r1 ë'aeÔÕZmª)·ÄZ
ÕÛ=åk7ÀZíêyÒZkÕ1
+´Vë:\+S¥µÀZåÕ+êp\¬ÕªrÙã® C)Uç)¢ ÐTÒÈ<<<<<<O)¼Bãááááy&`Z ºWh<<<<<Ï!d,!Ħ¡ááááááy8 7<ÔÂ"Å)µ"õ/ÏýÐ2%zªR¥4´<<<<O
+k ½9JiLMû°V.r¯ tNdªOáxª'¿(Q"hh9xxxx0´ b¸Úöòl3Fåèîo¨xBÔÒZÿÍxxxxe(¥ ü#Ï}!`ÂR'PJêj¬ªð
+çAì ]úË*^§rÖ´ êO¡B^ðo}jM§¡¨ýîqÆ0&S&g²®DªÀI õ;O=A±0£Þmhaxxx]!ý¸®lCò£¡Ä§¡F5´,õD)urvqÛs¯ú¿¶þ¬Â¡© nÿÅ.ñú־ݦ^óíúZqMƹ¶¾SÜ#ÆÏYuàç~]:µdøgçNfFsÇÿ0\SÓ.°ï?µê÷q^u}Ó¢B@ujÚ)¶óÒe-gÿy³ifüù.ã¾¼µé~mn\f{óÄ/^ú&öG#')TèèÙᱶï<<O¡~Â=r%
+-ÈóÊÖ[zA|þTCËQ_PJu êD¡¥Ü<0¤´0ýóãMxkäÌKG àæ±ÞÒ(ó¦DÛ^ôíúZhMÆ)εÕ(óúXÅr"-5 8³azUaz÷?y)ª®oRØîJrßJ¬C
+3¢^9÷·bÊÒüµ]+YV¨z`NdbXÁ#Óî_ÚçìÐwçÏóÑwk"*mh9WöEé
+-%¨3+GHv¤8'a<#ª¢tV§.îÉ
+D×Êëµ¥ùÌ?FôReúût¸£ý°¯³ À WýK¨K²d¶îíYDG©9¹z²oaFÔ4FÚåØqíÚøfgÐÈR س°Ó Ǧ#Í}Ä·&.Lþ Ö~h{øÐoÛz÷àU 8ôë EYwººù÷Ý×ýååóøk¢_VÂÅáËtùÝV 60P
+ ØeúÂÌaµ/Lüc«o°M^ì¥
+¾Ã
+ÄÅ=^^¹ßѳîÒÎOÝ2ãÎR¢.Ép÷ï·»ûË+,íÛZ_õÒ[¬@\0î«Ûý6¸}aFT0¥F½{Ðþoï««¿O}BõļZ2ZC[³rìñ¥t¼5× ù5BÈûÇJ(5Z
YìplÅ=
bÅyËë·}é÷§2?¥Xnwëø/CVk [fû,*-¸ÛSjåQ~ûÝòöé·ÛfF¿àФ}ÃîrBqkÀ5¦¸ièÞ9# 3þ¼¨ 3êk7¿>¹e ;¼Ð
+.b} üóëý¡7v~³ÿ§Þ/ ÀæÙ^¥EûØÊÑû¬Pb}7?ý,7åzÜÄ PÓ#ãÎe¬PO©Iptùè} rÝF2 .íüÔíü÷vÄlj2
+þ:p ä¥\oRvë'MI¯XîºesNR¨Ð¡I»d¢±rò¹lëpýÚþùNÙ ¾²qö;eëpÄhÐ÷oÁÃÃÃc)n(þL}Çø« IÚ㨸·«©6HDÀ ÕãÕ©µËîès)Ê}ɹY÷måå©G%F½6`âÂäoGμtDfã¶:7ùê ^MZe÷!;âó!2[÷-UÇìó~>'§sBÙÝ~on¿Õ¤õðªÂ´ p~ÓÛCbÅòÝA[Úgí6ǯXpC¢pú;xêÌøó"®´³[àaV ÑHfF miþÎc|4äÃcG}quù®±2Hv~ìÜðíãçǬ"SxrÍæëÃöJ¬NKNr;XP*8³aº 0¬ é¥oã5ëÊN(¹riçg:þ>®Ã7ú¾±í¶NU ¢Ô$×köÃç~ÿÈåºø[ððððÔ7Gt6úlÓ$ÛAÂi-vZößl5Ú¤¥¾ v´¤{BÈ4RG)PVmÏÞ§.É~ÑdÔ;÷~}ctyyüÕ®asÊ+S:Wâµr¢³qö3 TÑè¡Ý^ú-0láÑ?G·RÜèìóÂúò:N$;þêÏ
}<P+s¦YìsîïÆRQaft×ÂÌè®FÖF,w¼róR¸Yçɼ¨æÒÔòYNt·(+¦iåz½¦ÄÏdÐ5*_$³¡ÔD áÉåíVP¨×ü'«AÞuiÞëâøÁ~î²û»öCöðððð< äý«ë<U bOVÇI¬&ÞØ΢ø·Nó¡ùtP"µvÞhãì÷kåò¯üO©É&òôr (Îï#µv>Þ¬óäBå=_¸ @Qvì5ÇÊÑgCÆÓs@©°ïôUëû¾±í¶Dî¸îÖ_?ì9eu!l߯o}iAܲÄ-ëûƶ]CT,'ºsôÏÑ4VUØÍ WÜDÎ SµmÙçýëM÷0ò±GͺòGß$=hLasÓcNZ@af47à{Â^^þ«_ïwKò^ªÉkÀÃÃÃÓÐ
+MDd±'[aàÆHqǤ³%å (¥Yuúêů£WWWnÓÈ÷ûÐ=³×îc`Yaj«~ [·?F^þwÔ*ár«ë[þ3v
lç÷ÂÞóûûµé8zÑêÓë_?{eÏËì-ù駥J2±Ìîäøob7òê²$3öÌgë?v¤D^mÇ~^uBÕÆÏ\÷SX9oôé0¡$'ñJÅN«÷ëOíû±Çë>²ßÉ0lÉhpm3xöÉ/µqÛväû?#Bd+½öfFȲÂdÉ`oëÒbyM^êÑ(³úÆëd®©Á&È
K×[vóA}6i<&S @©£ì½%= ÀIÎÅutZBö§
+ÂLÜShº¹Æªµ< ¤ 4Ò¦!eNMýz¿¶½ðq¢íÇ
nVøtpÏ1ª(M:.}Øñ_9±6(ÎoyçPß7¶÷soÑ¿ÆÖ4a::x´SVí~d±}ã Òªå¿hú 'eö²fº$ór_sþÂÌh..t³}ÐÀÙ@Bk* ¤Çß½}Ø®ì~í¾DY!½vøGN[ý v<<OßöOÑYòÿÑúà«ã¥Bâu~t\rÄx:QïþÓ`ù}]&ï%¹ï$êð d+M¿潿 |gZ±I±1LÓuÑ ù¾±-EäÛú$ðùa¥bÕUõ*JiDmûB¤ÎÞËUëâ?Rv*:_çó»¼½Ug³+SX×Â}Bgf_]VUnkL¦ÌíÆâ0ÍG_Éá LÙ0Ä"o¶ªÊ ¤Ö®Æ*³=:,Ìy_aßôçÚ(3 8+§ºòÖ>{àΰÌ_ì>c6Î~êJj«o°ÆÕ7øʧfNÔ5
+(Nþ¢òº8ãWÔm4&éKÄaÓÚK?<PÒI§âõ¶c³õ_b 1½ÑA y*dû-¿\Dô»nkk©8!ßè|é-»¿]T5ß©
+l$gÞï*½ÞÕC,^ç¸%\㯦ҥÑöÅâvÆ ÀeÐɽ¯Æ@
ý|·
+_oW©np{Or£ø¾ c¥¦UgÁÁêÆ&mjÕ;eI9!°Æ?#g^:à°%æð]âçËRä°ÐCópÑ_.¨ú]HÑ7æ+ÒV Eʽ·¿dä_£¬v6¶fÔ£7éä.È]:Dqy_´¶Ãéi¶; ó|¬Èl<4Uï5¶¥øF¶Ò$Ù©íöÓ`ű¢»#µnÃ5þg½çbÞaÚîâÑïÛÿSjïÒvýqbkAÎÄE£½ìØâ '®è@®Õ
7mÿqÄmxêŬNêÏ}Wnø!¼Wá0£v80[Ü?ÆYX; cJ©êaÇ<<<<µ
ÒrÀÅ>c>ì&96Õvµ5[ðËEU6Ëò_1Qàïkjo©h6k|Q9¢[}Mí_Ý:ü÷ú´Ý%Cº5ƾÝYr Ø°éÄ)1íÔ6Ü\t³¹[:¥8YÄÝŽ- 8+WÛ|ØÒþÍ·öFi¹Y1^ÝYÜ{û-{ËFÏF(0ßu_{²ûí'¶þ¶Ä( °ÏÆÃÃSgBxÀt eÅ_:HwKÊácϪÊîÍB[ü7mw¤ÖMk ôñ¦ @oa·[R2Dû}û¿«ÛIöe¸J! z `Éÿà&01]{ÛnõÕÍ~¿¤î¼9B«Ü3ÉÚ"§Mõë;d ÉmXOmÊTuj¶ÏÃÃóüAq$¼KàS > pÚò,9§ò»e>Î;¯sP騸[Aî[%wîì¥D3&@ÖÖ˲0q¨#Ú¸<£´6ó÷Ý9£mRhl½©qW驸§ R.»#µ®©EFqH®ÅpQl\Q\h|ò4zaù»
FÇúXÿóWöª¨®«yxx}! Ãü@G &-¦ËÑØE)ýÒòå¤SvÔ¨ÐÍÍÙSvÈYÎh`ñ@ù¿KÏ«:~p@é$õü>²- |»³ää[{8ÈâåÃg¼íÙÿypMS[¦ÂìÅ@qjbñæø-E#eLñoÃ{ÊëZ8rñ
ªÛ.8i²ÕBtcTQÚ¹d½ý'Jè8HIѽeÇ,ó<?p FØ
+]Øòðð<B ½ ¼ `Ì;°ê LµpX4@~}Ñ Tk=8Â_QÙê±w»Hcßí"-ÿý۪ܶ¶ì+Êì+ª°df0«§ìö¬²ÛUÛ8L±Ù_¹¬§ ïÊ»û¦¥âyt! kRú×C[wR©Lÿn[rñ<
+JN× Q¬y_!V >ð fÖûQ
+` ¥ô©±®KäB¢·2ÏÁÇS5±µ1
+1(Y)Jå#¹ZñÔ¼E*E¡BæXÀ¿ì«= > *'£VC)m0f(s(³¡åx æXQc
F)5Bø§ç2+²²¯Î 6àWÖL `¥¿âij¬Ð!VB¹scã-#ÒÔ ©mÈÃSÝ£Íð.· Ì-«Ò 8K)m$ f+GO éÒv k®í°y
+tØ%¿±£AçñðBÜüóZ;Ji!dÌÇàÙ ^lHùxx8 ]ÂCbãпFíxêÔÈÓÿ ÊÃc !£ ü àM[ V05ö§*RFçB 3G)åÍHyxxª¥Ìßl)~ FPJ/Uªöy·6Ró qL 1ðæL
+}°Uê³@0ú§Z! l9úGJiq&¾ RJ÷ü§sN$h'´µÄÁSw¨tÏöîRZ `=¯Ðxxxþ!ä] ó |L)]f) ÖÕ`¸ð zKG_çù/UH9x
ÆÃÃS!ÄÀ N ºPJï«(¥Çk8,ÞòIà· 0³¿BĵqÐç!- $<¯^ý<<<f!}¬
Ùq.¥T_ãÅÖ6öÞݬÄ{>^lr-̾S'_©}A¹I)ÝK`ÌñBkó9xê)ÉgfüyQuåÎÞÝ´õ1_}PÍEÿ»_·×³lýêäòЯ:x~§ .ÆãáyTÊ,ľ0ÀZì¼j}ã¶êöCfñ]ß´yZ"ûà{BÈ nÂá¡BD <9Jéîú,úì*ëË»>ß &Á a. ºMü}O OÔ<3þ¼(dù¨eÌ^^öÏg®z/Ã
+²¢Ï®òvòì8{ðG/=hrí
+²" ø«;Ï£R¿l AÒÜtáá©O\ 49åPk3Q×$@`½Þ¡ùu^ä×}úP Ø<ÛëCPÊNø.ñÇ«ÿ~ÙH$>½nj#UQí ÷
ÿk¿2/Ùͯûô+¾]_+¤Ia{öMé1'}zLþë¡©0ï.nû°N]dã00¼ÝÐyÙç6Îðtðh[pc§¯K at zçqKb\K;·ÀìvCçe@jäQIüÕ®6|Âö´Ù5N3è5í/ÚVbÕ¨HS£0ê5þSæ+#')´"={af4waëûí:XpÃѳ ÎmáÙÈ»k^µm>Rk×Âî/¯H,ooЫÉÑßGt²sä#}ð48) ~ð5¥tYCËÃót¢M5
+2Wk46ýNöÃ
+ ð?Jé]B7ÌA±?{X'Ji!
+bwéñZUA&I¬>òû0CnÊõ9¡4åÒOÞ¸ylé±ó"¶E]Õ<ãÎÉe+e¢Ú,3çFµ³qï÷]÷
+¥6'êã®lôl7tުİÝÆ_ÝÚJÃsBýÃv_ðmÂOIa{d§×¿¾c2îr>·*aÒ¢»_F]åyt%à ã"y¸A¯RQaftWuqf³¬Édt8òÇÈ ÿÛ åkÏ¢Îsâ&ÄV×þ:è#{÷V¿ýèÄùÄ°ÝÆ_ÛæÈ $±ý
æé1'ÿæηO.³½ºoÞ?Pz=÷îu/Qߤ!^{B5å ZèM)½ÙÀ"ñ<¥ÜV2@føZÂ@Èz>ÎxÒU6î v ØXþ
+fåÈ°\úä2ß©Tt#tïç̸ó·òÓ"Þ°
+ (¥²ñó£_ÉìL>uþýÌé<FFSj·èñÖºÖ>»çD ¶º0qaÒ"UQ:»uÿ¹ÜÄ_oü¶'FLZt÷+ XûõÙ¸ÐÍ?Ç7Úu¥Â¡©!5ò¨äØq¾´ ®âiuÇüV?gÜ9½xÍûVb¹ÃN£¿_åÕn²(;vjëþ¼4pVÎ
+Ó½Ã÷}à< ¤¶g^Z·,ìðBÇ°Ã7ø3úüßÁ±ÕÙiKóM³ü'O}CéóÄa (¥|:"GÆ~¤0Ôa¨gÞ¿ÚÖÊk¯w<BÈ8)¥!xµ¦ý9BH{ RÕã
+SRÛÐòO¯Ý;)lÏ"%±(ËdÐ×±(B$³3 +§¨K²¿s1êìÊ7-Üväûb¶?
+ù ä" H¬" @jíjdX.íÊ/©3;å7þLñ¨Ó¶+òXNV~YcçEl°õâ¶Ç^þç»Ð=³'qBé£A²ôû¥ BH
ÜÎã
+sãàwN )Éi+µq½ "á·êâuäá© eA
¿ ð·jâÍÃó0ìò ïß:³ñ{ÀÇ0
µt÷à ØãÞ|F¦B¤F¼¬°k²qôë{þ9ºUjäÑ7*5¥Õõ/W4!+ƵL
+ù@ Ðä´ pP[ÏP£ÁµÝÐ/cOü=éFÓ
+æÌÜ0´-uz9ìnäÑÆ ¤Â4Yn硧@E6mi>S®L»¼¸ôîÝ[Néµ%>CT,+öë>mvÇßý'û-!ä?2åöa
+z51tþµ{Å!B ®
+-ÇsHöýJ+6¡,¨°E%{ ñçE¶Îþúòÿ3À|O-;ô Y}?öèÕqÔÂb½ñÌúi=vî`¾'¿~àÎ
+{Ïô੪
+ÏUn]UÚ²çû.ý~t"HªýÌwoÝÿkC,ºxøÀ Ü!sê3W¥,D/G)=RÒÕÂñFInâë[æø4Ö©ÚúJü9&0+áâd¡Äæ¶NSÔB V/¯Ó©zmÕDhЩü
RÛ}6Î~Vý?9q~ÓÛolÙø+£^ÛÊ.ùu^t7òhãÊãÚ8ûXV´ñs÷b
Ó5 (ÍO/X_0õ¶:uÑ@Ï S ÀÊÑkeÔ¿%\Ýv
+ c2¤&-ºÌÍ:¿ròúÁ¯oÕD`Ы½AÙ¶
+ënÜòÖqCò¼Pk0èHªZG
+ó}YEPaw_®íï~äûë"©íIߧÎT*Úlô}Ú¬zsvfì6Îþª¢ìØq N À±ã÷I»Ä
+Ǽûõ=øsÿÝ
+VÖ¢×í}]ëLÆÅÙq:õ±)´¢¬aÙIWî<BÛþUÀd¡Ä:cÄçÙ|sÒcLýÏÎPJ/Ö°« «ÅîÐÚN© gÛÑ;YNT9~ôìkûNü=éNQv¬wÐÏ×'ín Í:MdJ³õÍ
£¦iÛ±ù¶¼·K]åîÚ¬çÞÓ6E·±soµ¬ÂÁkGðkëî O %>&9ðs¿.ÖNÍÓ_ø{rÙø,+¸'ÓÄïïN8³~/(Eïi¢ÿ5!º03ÆO!³½ÚyÜOßÙ»·ÖÀ¨/®îÏI
+=z~Ë»Á0Æ=g\ÆviÞ³âÁ¹Y÷i ЪßÇy>'
+ùslo[×-F½FÐ8ppzÝ¿Ò
+Àx-[ÌQ?ù»Ò ×7$±æBë4M$ÍÙbë.zóýË\¯i"oÃåË9=°$ÌTJ
+q¯tÙëÏ úN)½l)yjaØ4½®´C^j¸ÀÞ½µ>öò±¬@|+ª(=µnj»V}?ºéÞ¢Å_In"wzýë¬øÿwjÚQãâÛë7 Øû}×¾ å¬ù^ÔáG;ß¹Ç^Ú È=ãØcòª ²4( lå17öÒí}½´|Ì#¿kÓ¸åàÄ=gVëäêɾ%ùÉ.ú~ê4²Ô¥Y%")3þ¼(êÌÊ&
+Ï¢¬¸sÞ}ßØ~©|ççæ×çï&C+Þ1ÖX%^ßé3ðý;?Ç¿{ýÀ7í¼Ú»Ý¢çÂÔÈ£mi~;®4ãð²¡ù~/LñYzâïI~ÅÙqMýâË?ïF!® zT*JÐ"_dYÑShMè;ùá?G½_ß
+ üºO¿
+ ^íÆ)½Ú«x³vÿKJùÏ÷ócÖ0äãSgª«+¿g+Ç3hd©gÐÈèÊe@BËd ô¶9
+ at Tuã9zvÐyén¯W×ÆVþ}л+þ9¥Ö®Æ_©n¬g
+ ÔI õã
+1yhjâP½P_
+íæÈ¢R_6;{«¦¥ÃQëúçaBZÃTø:ª*üAL"Íñ3ë§õõEè2w¨ÔªÑ½¦¤ ùcdPfìéob«óÇW½4Onç±fÌÜ°§×MõI¼±ûw¡Dq.ìÈâw)5: @ZÔqiêíÃèQZÚRõVU IDAT¬03º«@$ϼ{ûppë½
+ W÷ÍÁ°B ++KÃ0bAã '×Li~÷æ¯9<<+ñ²Ïã¿\|q~ôßa:ýqËX85tïWÏ R£BÖªÒ;Þ¹°Ö-)l÷&²BiÔæ9ÞsýºNÞyÜÔ~ÉìÞqôì²ù¦tªf¬P¿î#û/|þVëå¦F
¬Ï;Ê
+D)WvϾw»¿x£QçN©QZ]|5ýܦ·ç <.=æDg _ZôOW·0 Ä Z -\ 5vô¦b9:z´[íÒ¼grCËñ¼Bi`!Xì {»Æ_Ñ+HY¬i®×»ÕrÖDÕr»u&É(¹ó^I0Õ3SUGAÕÄÌ(îf( 2FÿZëSwÞ/élÝInÝMsç>öÛì'ùþêAz«{Ö*$¦{va&@m²Üc}¸äÞ:é[UçPh÷`Î"ý¥t¥ç·¼-áÚ¶o/Á Ä1+,-¯ËM¾:Öºï¯#g^:riûÇî1Ö¬ °3ýΩ¡2[·uã¾¼µ)üÈbkû¿þÿSÖ#6Ä]ÞØá¥qËz5ùçSwoÿÅλý¸"miþÈ#¿RÞvÃ'L{j2Ùøt8 2îoãâ¿jø§gO¨ÒÙm_ì7èÕ«ï\\7L$µ=QÙº*Ôdtî5m]°GàÕÖ¹ÍßLøwpçqK*gµírº¨G¹ëö¯[¾saíÖ>[ NM;.ðö¿7v}Û.¢ ýöàÁïþêÖß®
+%Veö¸}ò÷¶-½[ùÊÒäl×:foÐ7ROjüöð¢w É÷ßjU«´dÒT k !+ -·¾%l¯Í8!¤;!DVNO*ß=pª?e(»«IÐCèÂd[rnCP¡Ä$y°AGmöR=åJoé+Õ~vý±Ûìc%æ8vëÔ¬èýª8-tfK27¨=½ÉCÓVª;G½V<¤ÉLé
re ºlèîÏ궿ÒÿTT¡äºÞ³"* P´iS5dGÙàe e /Lü=R4;ñòû¶®-·U®ÓkÝüûæSÉàsR¬×´³ui |KöÇ÷@BÅrÇm§~1äϱ½Y¡äZå°sCع¶ü ¢¼DG Щ{fF¿¶þc§Õ;æb.7üÈeþVN>W4Ã
+bËïÉäöM"têÂëoøµ£ÉdpZÿ±Óêõ;Vg÷1uÖåõ½^] 2·£^[Ϫg¹w#~½öÛ£;¾ð yêVFD.Ì:êù^PvjWS8 |dGâàoïj >й¡ä·æ² @`Ï(U±F
:ÞhoÛ[
+ BW¶ ×
+Îê£CâÊ À9gEb&Wkt±~A_Ûye\±¡J@g Âõ©cz ¸
:*lIvMþ)ÉO<àí}ö,ìäQ^ÎdWÓ£O´Äd^Ùó
aØ,Wß`@$/Ìiàväéå6Ôd|¨e÷é[oún«VUêФÝïëzNY îß%Ás².. 0P VY»^9ëò¡Êmã®l¼XÐÀ}ÉhðN9)võ
+Ö(óï$Ö7*×ûvzõâ¶K^Y=µºþ¬ð¿%êL&CElܲkñ!Kì¯ï¿/òôòCUïùêÇq¢Çq¢º2³ æû³^ ®¢Çe²Ö¥ôB
+ÃóAs6c1ÌGÑ N¡ZUl
é«Õ¬¹®¼¡oj×Oà<E0·´Ç§²ë&5e¦ôUj/PÀa¤(ìÎÛÅ]}WXUXÎ
+mã$÷!¹ÇZÃÁ½]ãD×Ôº³ÀÒGß{(¥I³Î=çú ÿñshÜf[füùï6ÏöjSöÛº¯FÞ]÷§Ü<øËæ/6Ñk aîkÅXNëåF,1´~ß;\2öñɳë>²WîYÔyK³ïÞ:´pÓ¬&mX8G§.
+üCæÛÞ^ÚwûÄomüÜÝÉR8$ÌÜ°Ç!lå+"ù-º°w³N/¿Y¹Þ·ëkÅ×þýêäúVevç
+zu#Ôöιa;î'¿u£æ³.-ØüEÓF^í_ÜsaÍ7b©ÝQ/'kieVPJ)!ä"»0gÙ¶GÍb9 ûLÝ¡ñXBÌ~M0§>Ìwf ª}µYê«\¢>ßÈH±Ù[¨U1z,Í`DTkÌåé³ÂäE¥íÇ.±VPq6P9¿"
+M]Ò°Ääò(\¡·k2KrcÚê%×u2VF*ü XyÕlU×èóìPÚrMkis6Óa0ÅR¯Iÿÿ¾OA#
+rCÿÄ»ý'ùw¯ ÀÀwö_ÏK
+vnÓÿz´8ë/¿îÓ ³YzÌÉWvÍöî8acaFgШ¡Äº4ëù xwx)SU9»òج@.ÙÞcEÙÈ»ëØÊ¿û÷xó]uq´ç+ÇôêÑG
+ë¬SÚ7m;f? ´öuVûa_;øËNÚÒ<Gÿîo îoH] À°¤f^p1 ÿÿö,-·võëó
Wû³ `âÂäoo\fs~uO{d· ËBËÆVnú߬óä8Xñ= zïPh\èæ±w.¬maß8¨Äµy¯²îøÉí<nwyÅ=;ΧBÈ0 3`¾¾ X KÖRZ
+à,¡ô¾.U'²rrkÓ´ÓË«øt'
+DÂ
UòÛW×PênCÌOaa:÷%ð`-òçlÀû¡Y¢^¥ßû$9LWF"±ñjÞë]AC¦I¹y at zaË{Ó4¥ùÃ|ptHyLÖúàÌé^7vý0姼1õ5GmÙõMÇÂì;±"u$ôô^nõX×SÆdÊÜ~Yi,ÓÜ×½ò7w5rUvhª¢tã5ãle":B]}äúÒfSp7 Ò*ÕJïn(B +,,ÏáRXîÛªÿ'ãêS{þÙÅ9ñ?ÕçÏ0' Ì+³n4P>(kzU8BÈ (¥{zR*Y1P>¨<uE!DsòÇ0ßj©l±¤\<<µÁÕ7XSÕ¸£¾(ó=ÿð<ÕP~´?®ì{"+4 Y j3MÀ¡V¢ñÔJ 1'ô92»;ÌwdE0;@Êñÿ1/KaΧU'¼yxx_(¥;ì|hÃ*B ºrÒ&dc8D$·o"|xSú@]eЪ
+,R sÀç¥
+ʾ
+Ì QYSÌfû<<<<!¤ÌÖÑÀÀJU·(¥Ô`#¼ZÝ¡F at D2;k ªô?×fF
+ê±É¡ÞFP:_`~à 0æ]ÛRÅmäááyö(5ZoôçGè¯põÌöÛ_$ËÄ8áyåÄê<qe^ûÁ0ç+_©ê·ç^x?´Çäàoýº4ïôÊ-Õt0 ð®ÒbBHÌÆ)<ÙoyòîϬÆÞðÔ+\ÙÕ1JéSïeÞ䥽wWáôµOÇÉ
+ ´>!¼ àw ýÊfãÌøxxFSTvûoÝð<±[ ~ÕTSJ#k:à&Ìf×
+Ê
íï6±skU¾§ÂÁ+§ë¸ß îÊEVâ%;±ÜA~çDÀ°Ï #}zÜ
+ìýQ [5¦Uëþ3£tÐå§
®øª
_×i± 7v¸õ¼¦"¥KÈÊQ_ÛqaëÛޮͳî\^ßÒÙ§{|ÛAó²À WÓë_m¡*JsöáÍ+Uw^W÷ÏuÎ9ÑÒ#pXxëþ3s*×Å_ݬH
+ßãÑçõ·ëûõ²_ ÛL¢FTª*°RjÑ Ä<Oe<Ú§¾ÉyÂÿ_p¯1H9É ªÐ!Ö zsÒjÓ[¤»ÞÝÔJof']ñJ¹ùoøKóÆ\\Ý&/5l>Ã
+
bë«7OüvøÛ5P¾ùíS¿]i~ââüôî!+GMømêÌ#Ë~Åp¢l±Â)*9|÷º´öú¸ù÷WX3Á?3îÌN |óßÉ7÷ 8¡,"ïîõ¶ W7ï;7jõ±£;dÜÁ
+$iw~8ãæ¥Fͼ¾Ë W-s=ÿ`J¬nD_ÔºÿÌË忼ë÷;ÖüîàÑî¾Y«&Ê>øRZ5Cn
ç)¤ÑÐæ¢W90Oex®g,%nÐlF5Í ²®¦¼¦WZ 1OÔ6']ðMÊW½lår>'9t Pj½¼({
+ ìü®Õ¡ÄæÔø¯ãÒªò-ó¼.ä§
/ýEÄ[æ6Y¿é·%&£ÎeôásER;Pb}ðÒîOFñØnÌÖ½"XæpxܼèUÉ{d§7¼zÀêoºàJè¾/\²âÏEdF½`×ñ¿Æ¶#&-Ì|£ªÜé·Zß<4Å#`ðG½¦üóÔ=E®Þ`
+¥t}5MSJMÕóðü9Cæö5´Ï+Ë/©íZðX;´2KëÈ'J¡e9wË ãoú& ì÷`¢eng+¯} ÚXVwuÿ¼þoî
+³s
+ü3;éò6×æÁÃDRsÊóÆÿI¸¾mYFì©=:MI^S6,(Kaï MZ,þú¡ùNÅ9q¶woüåDI,'Ê1´- 03º»Pj[mr»ÆKeÆØ
+ Rº º6¼2ãáá©K(¥w |õ¸ã<QÇ ÚÒ¼å?:¯À>E ©½&Ù
ª3[æû.£QïݺßgQÉ{d¹w¯ÏÙ6pa~~Z¸ º½´< )9µ~ÊçB±âK³^>SÊüä H:*¥¢¶æegÜ99ÙÊÁ{ÝÄoÓ>³qnqe¯£ÏEª°Mur;zvüª(ãŽ;©®þ)ãw×<£¡áááy²1ØìMFTO«Wk!~u(BH!dymú3W!¶u!Ìã¢×tÙ2·Éf:H¬B*+r¼ÛM8ªUåÜ2×sö9D뼺iÏmñÔÊy㸹Q%6Ç,6§¼×miÞ.Íÿ©<º$gèyM?;±vâ:±¢Ñ? 9çÄ¿¾í+÷rCßFYÔÞS7_¡&ÍÆY.Ëv,hñ궯W¤½(
+º¾¸lRq^Âk»µ]o/P=C ùPV<<<âÖ¢#ú]NûY½=ì
Â7ͪÅöO еàÁ8 <!ùÿÌ°ÔÚegï×6GwáÙ +Ò«
+ݲÏG,ÒÍÑ£ýÚ#§å§
ìÝZoøöáË 0òóÐ_N¬ÐQ«ÊgDR;ÔÚ%½8'þr¯WÖßc ãìÓýkuI¶GÛåV£gÝØqbÍÛ%¹ MÎ^xcGsÀ|¼ùò÷9N¯Ò<?="УåÐ póë;ߧýÄÆ-¨Ä2ûÉ7OüÔÊ Wò|FOI Þ Ð
RúD¼xxx\L´Ëqû¡¢ü¬õôßÕã?,=ï³L~æ1µ³"Ó°ªI§²MÙ RÚ ¹µªÆ8ôS§+ùu^ä×uú=Ê@B¼wâ\ùïvnõåÊ0+Aï¹ {¾o?¢8/áÍFM»Ì«:@$Óö{ã|HÕò2e Í;¿vO2À¯¬»àN¶ 7ÿþj7ÿþñA 9^0¥´¦Ùayxxc|×*ÿÜèqFö?Ú3ê;ƾ G¡``U VÖ°_)OQCö<Ú¥?¼eíH¬òx¿²/ Ø»ýâî?àLhI!-aÎsö"¥4êaíyxtµÛ¡ñÈ)5I\¸ÜÍEYÌÂTzÊJ¤"yåÆ0G©röRF;ÜO.`&áÓ2Ü 1ºIý¸ZÇa¬B<RJé1BÈq Î5éD)ÕHzbZÿ7÷Ö4꨼«ÌàwC.ÖÇ|OWÍóߧ>ÎSÏÁÍLbäÆÂÉÝ=
·í¥Lé⳪Z9sÜÙûÐnû{þÔ£¯Úüãaê`î1åÐ A¼ ³*Ìì);új[qÅñaTQ&áCåFBb|×)þ}Ìá ø (¥² Àë5íüÄ(4ËR?è ß)¥[ZgE¦Òd{"^'ìí-ÌïÉ~½¨jÝ«©ðæߣÎU\(°þÆóò]½ë%·\¸âí75î¥:*ýúDi{ £^2H~ æË.µuå~<§ò[s]Ý~TQêOçU-ؼ=QÚf*.9Wp1½ßUe+aôJe.
+ôuäòÇëNi#¾ìe^÷T½Í¦pMóU;WAÚg=¤OýÕSr{DÑ.ÍVȧÖÁÅ d Ôe.DÚtæ!oØA)Í«I½¦X~ëäRGåøm¸
`ãÃ[ÕB æ$zç(¥|<FZCp-ûr+ûÞWÙwW ö ØóɺìoúÊ6[B®vn%çTý¾<^Z<±µ8Î×--¯ëýwÁG.£ScAú´ÝÅÿé+ñwâ,Ñuñ¤63ÿ Yb[*_m¬¼¢îÛÉCp{L(R.N}©øÚ@¹N˦F~`¿²HC]U÷íà.â+ùè rð[%çßì(±·dØëí%ûù0)±yÆ;<ÉP=%·mRÁÛûgÙTY Wi¤6ØL¹ 5µéÌØs°Ù¡3d·Î±^Ûs¼Y· #£$KÑòÀÃ[×0ç2{¯Çäy!p ¦ èÀfEå @
+@@s<QÙWe öj!Nõ¶cU÷x[ Ñ®½®i³æº§#¼kõþR0»Ôdûná% èÔX÷OºÅÆO
+Xúû3Ëàõ]Å#LD í~òc `¤Y7ÆêµV
ª½;°©óûÊÂàJªÞsû-{OaÞnåH«ã.
+Fk¢ b´¾ovÄ«õT4Iú
+Óøzã«[Ãg
+Mýäm¸99[´9[´à"YÒG§H) ÐÀJiâBìâjº3«@HÇQÎ.XfÆú£ mMçG}â¿Éné=×éV}É¢Ë1sþ-qubLXbª*^'JüÜ(¾nÆ#|À@o>âÏà !ka~èms a
+³ó½ô~Ý`¶:{@"CðpqõÉø@qêø@qªRGÙÞ¼´âº£4À×UJrÜW©,(?ÔÅC/E)S`-& É5Ú9+«)Ê6ÚõðDT@Ô.
+F ÍØ¢5×L¶ °mõÖΪÚ\W8©°ñEëõõXª§ÖDDâJ#¯q
+r³°ø±Æ5ûÀ^ªe·" »ø;4FLL²æ¢í Nzc.êE¡_W[ßÕÃqüεAÉCÛõ|ÜËOC
+`ÌyÍ,òÄÌóôC)5Â|³ÒÀg FãÿwfQÈ 0RGieIY¯¥é[9,¨\H,£\Hôc[Ó¾:^ù}d×d Ôzj$"ªìR¨òÍ^ÊèÊYuk)ûß!ÎMgÎî%RÕ9õo&Ì>£óìà.H0@ü9庱V§M§½~Ì}G§§$òÔ>T¶:f3³¡e(§L æ=ñ
+ÍP`â²v5sªÈ¼>4y0gŨõ
FÛÛçñÖ©©«ò½rö4ceÎd0©Ê;ªtÊØTègÒSÖ¾<Ñ¡¿"#òíô^77IXÓRäÊ6~Ó.¾|m^¬Ë3
++Ï+vhlEÈÜ#J7§áhwìcÃ4¯«ÚJ« ¾ÐRó°ö<<÷!À- ݪÔ)a>¥¡6i|Ä·m$gòK´TêjÅäMï gð¿ÎÃ6qD¯ÒSqáíýäaÃýDá3ö
+öô4Û5§ScAA3ÜiyþË&
+Ò£©0ª
§L+6ŤøËãÊÞssDûçÅáÔb£xàÂÉ®VL®Ö®¯0ìiVfO*!D
+@ó¤?QeE& hRôöN5ÝBÜì<Þ:5s{q@û£ÿ*#µò[SR@Êïymüºe¤ñöëi}Ü^µMr® 2Éçk#çÈ9¬t)º¢r©\æ8Dè4Ü*£ü÷Ò(£ë+6 i"(*¼ rzZ!$Àz #)¥±kÏÃSBÐÀ zØà/ìåeÍJÌ¢.k!ËøyâÊÂþôê<£¼
#WRÙì½.ÒØ÷ºHc£rr7+Vc%2Î Ý,«8ÙIøÄáªã6µeÕØÿU¹ì¯ÑVgµô"ÇVöc²Dñ-»-I
Fg¥]ßÍ÷ìWEæÍíY%¯ÌêÀdjwÖ Øb« £Ò$6*â|É KIÙæ®Þ!iin H¼y&eìûÉ3ç7~Ëîü£Ì-i"(T'ëå r´¹]°ü©pÊ&x øÀ[ÒçÞ÷§æB`7æ;?¼F)UBvÀ|¦ÙÔz(¥ô#Skgî¾y´ü¹:íV®«£²2 ú ¹xB@ÌXÔÉeaecþ ¥cÑ55ÏÄå-Å©Vm%YN#Ò¯ªm"ßJn±ÜõßÙ]íûÉÓå-DojÇòë{ºØUp ªmYzò¯yíe¾¢¢Òm#ÛÒYå£SÖüÅÒÝ
+-ÏOÙn,æÝX?Ý;^¢^Ô¦0'U0RZï>fO.
+FsøU
+oÉSÇØË
©Êjs
+¹3(µé.MÔæ8Û`Ylù¼å?û|ßèôÝßó%"ÇáÚ\ç½ÀéRÖÖ"ÏÈÿ¥¿ g
Éa"ZÖRTèõ¥ÓÙ¼ÊF§JDÄ t½×
+ÁÊk·¸½a{=cSa3ß_]BtÆZE~TÅôRüù ípRú[ÝJÅó¬Aq ð*̪U0'N£TÓümOw~9£9|VCÌÇ
+-ÇsH
+µVJT
+MîSvEEñÔ $7âg¿W*~.%PÖ=þ½8B qöu¤+ÛÂÌøSò#¥"%í[ ˹áòdµñ/{Ê^ æT<<ÕBéónl = &?èè°Ì)Ì»²§ÎÒçÙ¤ì¡JUk
&·nÚ¼ÉÔSy¢r>Û4ÂvU5~4ÐRÚ ]!7C`[a4ÀSÏP=%Òúl9¡Ny7¦y7ö¥´&FN~0+3Þ¸ç+;Ï«MBÇk+Æ:Ë´.oÉSd«¸#v£,Ùè Ìù~£¥T[ïÂ=@acÆÙw
åôYÑy½´9[,pdx®2*@ ©[ÝqÚccRS¶4Êh%oÍFjÏX¥Dî{Néónl0} ¦RJkuL)½ùxRòðÔa0ßµÔØÊQ!0I¦· ½ì
+ùù\4ÑÊjpÓI`ÌÊ,¿¾e« "'Öbg³Úd¬Wú°93VhÜ FÛÂúãZ·1R6+ù«R¦_ÉÛ
+f×Ç<Uaÿ^C±ð
+Pcw(¥õ²v ,D5G)ýë¡«AÊ1T!bøËàzF©ÙkLé à/ )¥Iõ*Ô
+Õ¥ÈÙ©uSÞ4Ø\Ó»Ëü¹,ïÅòk0I߶,¾¢÷àD#ä2 k³¦qî¯ÔËöY²9 IDAT-»y÷g<˳ë/Ìy«¸÷ËÕýM³«£ÝyÛ µQã±Nh7Px¼>Öû !/À¬ÄÁUáMJéÙ÷ªJõT°öÆ¡!ææRKLµ¹®xZ±0öÂóp!^0_èO¥^khyÊ°øÝ2Üà,oÍå©îl
+OéîµÙ9¹¨ñ½:Á(WE[üc}4bháHY 2K#
+ò¬V-wZJ]Ú6cºi£âÄ[cGfïàR
β²23i)1´pxå9 KÛTk½CÛÂa¸0º¾×]
æm0§ÝX àÃZÇk[
+÷Eiví»SØy óEEVKQ¯½ÇWð
+í)§ìÿ¯)¥uÿ!¼ h¸L¿6½±51Èü¹ÌâPcé-£Ý QgEVI ½Uëm(¢Ò¨W{´àÈI°
+ÆdïÔvècOúwÂê4NqOWýcft4eó\^$Õ×ïC:w)¥'-<ïý¸«5 ÕFÁ<Õó\¤ûâÚS!DóåþJéʵ·<. öè 31
+&{j:pÅ¡zçWÄÉ¥xûÁÂÒÛF[ÍéAUÝ1Ê
+OëÙöÜN£òZ ¿'º6ÃtÏΰøÏpìû%@@}~ÖÇÚRz¥æ½örÛÆÎ4´ Ï3¥©Y ,rÛpO éâ`ÍÓp
zù@¥tvËB`¾¯ù æpH¡ nÂÂ
+MìÁr6D'taK©Áü*rcJNDí0T^t¡Ä=¬OÁ(¡3S$tfUVò6\zÄÐÂ! &Ã
+Oé=¼³î,È¿=¡¨¯6Õ(¹ð ÚôKYÄd0©)StQïÍYUX¿òVT%ò«êó¬cãÀ´~ùÔ@Ü:¿VQZÚÐbX@W¬H
Vª3±Gbn
jØÏIßÕSúÀ;ZeDÜÿþ<Uâª1PÎVÌj{øȲØgç9q Ìá^&6¤ aαVÛo Lªÿ)eçVÆZ-`ÿ)ø?öî;>¢ÿøgv÷zÏ¥ÒHPEQAAl(*öîóØËcï"*té5
+é=ëmïvç÷GH~B÷ëåË8·»óK¼¹ýPäÍa_æûCÙðü¤kK®-|U¢ ua#ÕUó¨TVþ·¢~à·7P.lüYò7ÅÑêBuRǨRr4¾çèùùr:8°qn§n<üÀ¬@)]ÐÞÁKnuÀxï¢ÊË%jóL>ðáÆúA½bUËêc/Ëÿiñ5__×õ+¦!ñ«kk/ì¯)Ëemí÷³®¹¨»¡¢íZqòBîpsÚëÎúð2ÙÑu]
+`;¥t;!óì ¿ïÙÃ&OÚ»bNGz #;ôÚüάa©ºì'GE7Ùìn|RàÇ}®®ÙÕÁè)ýLyÝ"ÞeùîxHV½±®®QÍî¹ înÝlQú>Ù\ùíng³´µ_ír¦%G(kxS>/j |±Ý¡tÍæ:%'¹0o»3#Á¤pm)ñuÔÇ´¿_µ öVL¿äºSk=a}ßxMÅuÌG5 u\à4<kÖ.Û×Búø
+@<þ¼k±Àã@S*N½²aNgnuïÍn "çÔä2[þþ+ÁÄ7ÄÉvø¹Ê¹:UÏUÍÆ"_æê{ØCæ¯]· ôÜ`TïXUõC«.ÚVâ·¤YUNGx at WmÅYÊ#¯góJZ£÷Ù|rÞvÇ°_ó<éûé
+EòWÍ+¢äì ÊÊ+>/B)àôËùÛÃïw§÷í¢®±¬zÔÏÙî xú×QÝ"õã{ó´ß~hت£´-êl¢!¼`4 G'w Õuô"ÞDƳ·ãnÑLÕöà¿I7Ü罨=cêÐwhWõ7²hùÀ{]=¿Úé8;#JUúÎÄøå®Æ´µ Ð/^U¼(Ûùü?'¢irU¥r <82j= P
+òÒűëU¿ÙåLÉVÞ6$" vVø×ôƤG)]aYæ_³Þ¨æÃÁVôte(óeÝ'i§êª¥êZ}h½¤KXô½%Ù¹0¡5BFÀ@ÓÂ!4?2sH}ùÿ;ÅÞ¤.ß7Ö9 X, Ý!YhX)×!'/ên¨¸¨»¡Â+ÊüõÊ&ü°×¬Up¢LÁm*öu ãhw«âÊS££WeF«»Ä²:«³7.)¬Í1z¡)¯_^pÔÍéQJVÉùçì#®%9.!À[ÅÿøÙf{ï¿*;£_¼¦èù±1ºy¦FUë/~$ò¯kÍztxOµ7Ñ>)+@@ q
+
+0sðfÕöebï>)3T/¯?Cx©=ã d(Ðá:´Üê1#Zíâ SrÏAÖ(¸Ð
Ýõïn´q÷
+·îÒ)ÆkiëÏæÍïÐÌZ.xäçÍ;^¡/zeuíb{X¢$¯&pÿÈm ¬ÛY°ÑEm_È×µ_¦$,©V¥ç
c6
elºðÃC7HZs%¯Ðjmijí6Ê>üÛÕhØÄq
+ö²£aEãKhXÑh àðd{eög:pÈOêJv(,çy%Jxʬ,ËY®©Ø¿ÖÜwÔªUº2-ñÓ+ÃÎzÕ;ë };Ħ̵5¡çd¦
+f²$nº¦]v-'¨ $y'ãö¹ÓÖTõÔñOPÖ$uô4À5ýÍÜüuÙ8µÀ
¼¢¬:?CwëÙ¹£2ô9,®mPqþÙS~ý;õ ±§Eªª&^2I¦ ç¤èò»þ2GHcÖ®Y«jFÈD«äÏ^³¦ÂÒÜömùÄXP/©bd~_'z Éá»ö÷BÎ ð,{ ¼s¸8¥ûó¯ýìå9+^ Y
+%Â9 ÇÛ Ç9¦¾Vwm{Çw¤u_LO-Íþuê5/> ª<á§WͦTÖs_³öÝÌÃo2h⬽ºº¾|ïUÖO²&ôíÉ¥_Ðíp©ë¾ðïËò<Õg¥ùvE wC{ìü¨ÜYâéRJOóNãÚ3Í×i.(²Ú½"ÐxvÛÜƹ0 X}{ê#¯jUzÝüMó²çÇÆüáe^à¬þ?k¹øÕÔÄEÕî°:Æ 4ÝÅþxcÒÂú.É¢ð6?¾3#$¢aXñV ; ðh|öD¶b¿rÁô¯s /þû¶Ö·fÒ;¿ß°àΤ|a(ÜõC
+Ç+ÂC®|=ý¼[û}óKÝ92 {W½áui¤P at pÕD¹û¦¹²åK_@å°"cðÔíÝMw®}M÷Ä>ãÊóÖÜ'å9=GÞÕÔYC~²òËûw8eúàëÜ ½æ»®P µ%;RBA·9ôöÿõqýÍ15åy«q`¿öÊëÀç¬à¥P°éÓ«dïí¾5o÷:ÿ¦ÛïÜVϾ¦{ÚYWì]õFßøg}¢)«£*OX?ÿö³úËiÕ7þ_0Vx4iü"ïÞð£íQ?¥ÔàÛÝ¡J 4=Ré9ÖëÉ¥ïdÕÕ8|Ùæ (xB3¢Wgsx.m))¥!4|+rÝ®Á1§
Âß?P°í«.¼B}дjÙ»ãSüîêþ¯t®ø`Òýg^|ÿÊMû7Îé¶ßÂÊ"ÂñιDþgêÿê¦Ú¾P¿îé?©õ@)Éþí=s÷aÓ¿/Ù÷Ë¥ÙË
+vï¶z,wÃÇ]þäî
æß\°íëw*ýæêÂ?ßñËóK'?ÿqþÆ9Ã]µîâEJ±ID¥ÅQ7$,úvrÒ/
©¿Í½©Û©³´¦ø¦Ïoê~SÀk¦P鳿z2ý¡3&>4üºìûå²åÕBSP[¼í©âÝ?¿5áÑÍK×|z]fñÅo)5õ»¾x'¥öü4Wü¬7+á?Ú<^Kdû2Ñì? ]ÁiH['ãþß¡µ§³ÂÿóÍÉ_µwííðøô" ¿PJß J©B¼J)õ·kÌiC¡6l½zfѬfEK~ÿêî¤Êý¿UÛ+s.° Çy®{µúV øì~ËÒm??c+ÙÏñBÅñÏÍIxÕ6wÕYº|{ù»nûùé}«ß`aYÎòKµ¦¸/¯x&{^Ñ®Eºµs®_àãçЩ¯ÖÜ +>¼¢Wåþµý¦<ð ájÙ»&nÿöÂßJZSÜq¬þÔÔ箾bÒã;Æ"SÂ?Î2ª<wÅ f12õ« n^ú˲î`iÕÁ
+è#ºÎ¾ü©=ßl_ülôîe³v¶âÛ{B«CwØ~v"<ì4®l®~¨=c! äPJOÚÓyÎÓø* Gþ±x»CbNc:s¦áÃ_9Ì^¾÷N^¡>BÂá¿wãk
+¥®) Ï+Jk·$ºýûmßÎè½yÃüÛoüúÞ =F½rÞMóó ÀÚ¥Ï pÉê½+_©È_£ÎA± }^ä~¼ ç
& B¥;f~Nsl÷ðäçö àÕ\ݽdßÒ·W|pyÎPI¥pì/jL$Nx
º¨ñ¼.Y£vµk¿ÒÚ¢-] pÓmÈb 8sÜS5{V¼Úaô]k¾ËõGHïݶèûõ
+o{ÇÄ°¢a.aZ2
+A®oaãóí9=q¼¢iu½bßô¸/\3«ì1µ>êÏw.äèíR
NyþàÛ7¼á¡·tý±<wůÕWìë »½I_92 P·9kôæ½@eà Ï7,3&¤iµ¥JköQúÿh½õM +λyAB¥ÛðÚRMO8Þyñý+núZÍS_«vÍK%3Bæø£cVëwÙ+s²c£²}bïXë2VxânÕ¶wgv8éC?Rº¬=a:.BÈhJ)
+¶pÈÜ6a(ÔÖßÿåã©Ù¡«ÿñ_ôÒà¼òÁ
+¡0à¦ÖE6íàí©/üåã©)¢ÏqÎÒe. Ägü©pç÷ï~ùXrpT£ç
+ÍQÎ)oÚ¾0rÁ#Oé#×yíeg,
Æ´3,úCÏã{ÉÖ¢,yýüÏT:ëZ9,yAUå³yÇI=û§Ò}¿¾ñåã©)¡»!\XÝØ bØÓ"BÈx ¢¡3kñ¢Ãù¦ÕtíyÑ[¸,; $öóvLêÙM ®záп¾}ñAÝÒýâ'?.Þós2 t8y×QÑ4$uák]{PªÒîe/ûE¿3²ÛÉÏ
+òvqã1©ý'=b+ÛÑmàgMY #¦Î.8þ¹W~4yxÞc?íwÑ£µ ÐmÀäßݶâ¦}ò
^9#gÔ/ïê©5Æ9/þÕúõóníã©/ífí±ñÜ>{¬q5ãäçöxhûÂù»Í©PéóNxa3 Äg|(åõ
+±\^çª9ø ó¹ùkÆoþþáóÒκz~}ù¾ØÄÞÿiþiÓ°üÝga !f
ÊÐK¨ N|lìpcw6®°â©Uþ`ý
³2;èqÛ(¥º[ !d06êC)ÝÑu1!$2¡÷ظѷ,´µw,ÇòÙý_{wÏõ.Ñaæ§N¦ß>¾6¢`Ï5Ò´Á'!D{2¹ÛûÆtX*¦\öµÉµ+°ÿß\ç¯üã;´:$(íâQOó3'W½_ ´4Ü×*ïoö=æÌXgÆtzÖ.}^Ï8Íw!dÒ¿=©Wâ¼³w
+©ýÖfðn´Á¾(4<kö$¥ôoeYaSÝ%ÿùí·ö99 '|ÙwÒ/ª£'GÖ`ÓÂû[õJBÀÏ PJÙÒÃü?+é¿Jð´ÿ»óÿ
+!D ¿@)Ýx"'ÊaQa¯Ü§%ëÐÚ ÒµêâB\¹Ò§[³.aN=ö¢è½ÆóoïBUÁVMª|Âsh^_ÉÀ}¥÷õ 9=òvr
ºDGz/mÅ*ÞBÃÎÓW´bÃ'Ý8ØÞqüÃSfëO¸CãÔ¦PGÔµÉÒQÉ/óõ>«u´þ¸+tjvÇF]b¨jX¼û:^ËIêEîôªÂ%5\s}BÈ`¥´ClIÁt2¢LªþP´w§« ;á^ -ëðÏ¡ÉʹvúÿVVüfÝ ¨K?¶F3jzûV*Q©H¸×õÇ?«c#Lp'!ã`Î^³þöéͦöãô:mFÓBÈX (¥tð/Q( û©êV
+I÷[wûk®í~SÉÛ¶¾ª8EÓr ,¤.yÇvHê["²U±@ñu=3fÅî¨þÎÕEòÊBüTsñ±+=Z·§£÷6þ¼yè¡Ë%¯Ìóºcgçïè!# ¼àüÖ~®9Õ{íeöÁiA P Ã5IYpíÄØWû»Owãs"½Z׿Ϯk<^=,ë½øÕ-~«m¥' òÿ[5$å¿ÛUñ@ÎíçñCâ2¢ÜG«Ïplñ%öÿ1iqó:
+_©ëáØàMj^3ÉÛR§gßàÿï̲ |
+`
+¥4»½ãa:¯ÃÙdNS¦ýÞÎj@)ÝuÜ£;e¬à©«OT$¯ÌSDªôi¾·m xóq%oÙúY¤\úÌØ¿÷>pcÊÃQ«xý;#Ë0m*FøÓnÆ3ÔõGÖïÞ0<[3´÷.+Z¯` (¥kÛ9aA`ëðshÍîO´ ¯ã$B É+ó®~3&µ)ÊÚ´gc¶ª~É+óÈ9·éreSåG߸)¦æZØ.)U!móºÂnåæ<ÙCþ#{~Ôe
ªKÛ-
+9YàJéöaæd8¼s[ïÐ84Éz Ф(ëËîzgĶ=×^ 0ó~}u ¤>µùà3Ã.I´
+Þ.7Yr9-J}<*[¦t¼gËHy(*·ñZcÕcÇêW
+wåp èñnüÚ¶\íøoB üA)u¼ãaN5'XaT_ ëIº·r\L3r®XÇõúµ¾t»üOB> à2Jé);ÿÇ0s,!är +)¥k%N¼y@ï~R(U§ÍRÐöÆ *ºcɳz>!äi =dÃ0 `/ ÿß=!,zME+©Uö dñ
!üØ
+ ö¸2
+Àu Î><ÎÌ0Ó©BL Î(¥ù'r"¥2¬÷¥_ÕOÝJ¡1G¿+Hë|êÞÊ
r! SJO¸3d9Eäÿ£E!íßEý·ïêgþ® æDÏ!ô0ÀJéÃ0LÇ@)
+ Èi]¶¶FIDÃV0·QJ7µw<Ã0muh!ÄM:_¦þÐÞñ0ô2òWÐ1!D `¥Ò·Û;a¶$ XÀÓÞ0ÿ! ø@5ÿ¶s8Ã0mæðMÙRZÚÞÁ0'ÅK º EÿîÓòÃ0ÿd϶´©Øg]ïN©rK¦8£à¼ipľ8pÌtS¿z#3¢Ôî(=÷7ÖgÚCf¥ÐÐ]ÙyéúJ¾nuG¹À% RJíÃ0L[:¼9qi]RîiZZ=.=Je6в#R'xë½aÕ_óÉö³öTæ×ò¤iDÌRÙ¾ØæèÿØ⪡yÛ"ð(±R{{ÇÃ0Ó^:ìÚ¯yî®ÉÊÊ)g`@¢¦éúÒVÏÝjï±·"ÐõÌ®Â[rÿ(öG;Ä6ÚÌÝf¾5!n9 ôUWOèm,í¯¶Ý³¨â2 ¿Oÿ¦|ôÙÉ¢ey·mÝdRqÁy;}ÜI36Ë;©© ¦S>z at WMéªýî}âÕ¥wµîÐòâoÞèyÛý~IoRs¾O&'üÚï!d ¡µGÃ0G¹bmï@4.ËXRT/ÆÝðeÙØ6Ö÷p¥¦Î÷É¥U#bôgöÅ®¤þh=kT¾2ɬ¬¾muãçW%,1iø¦MK½¢Ì¿×bQV@~m0ñP](âÓ) ?¢yrYõØ ½y\½áóöÁ;ËîòÔ»ª#>¾²Ëâ`ò¯¬© ïÿnr÷9Ö-¯Oüþáó£7´õ{ 4 ? ¸RzÂYDa:
+;w¸-ÒcB`ñÍÉsÏK×çï(÷'ÿ´øºÍÅ>«;( lb|¹+l|umÝÁ0|éǺÎûëG^7¿ì2¿H÷ü£±ü¶!»uJNÚ\ì´jy×¹iºêôH¥ghnÿÒ<wJãq7eÞkÒð¡[Ïس§Â f
í5µçÌÙbO7
+m1
à OQJ¶uýÃ0 !ÄJ¹Yø»YöÛJ tê sÁÔægUüa¯«{ZdÔV@>;I[ÞxܸýǺÆíC"ÖLèmüÓJN@N0+ü Áñ4mÏsÅmJ¼,ð
+P ðê¥që×ôÆ,Íu§Mú¬dðÓæk¤¶WøÀWÒOÚ¨NaÌ à»(dÍoÌoÞh6̬ãzÅ©«¬:^L¶(«ÕMÃRµÕÃRµÕ*H gT8òk'RÏÈ4]U7lÞTì³ØC
+|c2
+¯±ÍÞ3¦Ü'í=ûĪÕç¦éªgý]-`
3t¹ÿ
· äSJjÃ:a:,JiRjë°Bfo¶|eMÑ â|}â5¥Wõ7 ÀS£c~»ÍÞóª/J':*CsfÆ>¥¿)gÎ{ßÉsK.ûàò.ÍJ[?j{²EYÕ¼'.ZþùV{O@Ö\Þ×´½q
+h÷N[ryVºôÁÛ à³-öþ³VÖXt*>0:S¿¯[¤ÒÛVïÑ0ÜÈ0Ã4C x)¥9dÖ¸cµ.¢KҮ¤Ç;}¶ýïºqÍ©¶w.qjvÔª¿ö;Ê«þéÕÃ0àj ,c¬ZÁÙÞ10Ã0ÂB´9 BÇ;átôí
+ßµwÃ0ÌqY \.PJÅöaaþ;/:ì¢aù;¯ñuØeûÃ0s"8BH!Ý©1Ã0§4
+ÛÚ;aù'!!Ä*üôI ç{|KÛ1GsÛQaæØL .?á¡F
Rë, Z, ¶+r⯯½c`é(¥6 PFeJá°ßç®îôYB:"IÙac þ½ÏHB@LëÃü
+.Jie{Á0ÓÑ É *ØÖÃ0Ì©0®½aa¢ týÛCÃ0ÓB, .aÃ0Ó)°ÔWÃ0L§À:4a¦Sà!Yu{Â0Ã0ÿ ª±48êÎíð 'ZNZ(çÿ¢ü¨ !|eÇ*'Q~²ÚÄÚÚ9ÛÚR쬬-¶õ/ÚÄÚzì6µZ[ !*BH&G)ýRêlöZ_ £¼¡ÿ9Ò( ý[( Gå$´P~3 ëAjÜ|øßÍY¤ ×´Pq8#õÇÉkkFå× uÛ:¹
ò8µÛ:
k$¡õÛÚ·
ò8ymUqlZ¿[(¿§v[Ïk¡|Z¿æ#Ê8ym×Bù@´~[ãîNV[¯h¡¼5Û* JéþAÃÝ®
r
+ Må: êÊ
+ --ðGÃåär¹
k L-+Z(W·r[MÜVc'lkK¿?E´UÅÚzÊØï IDAT¶UÛmå(ãNb[õ¡¬¶¶ôûkõ¶²eûÃ0L§ÀV92Ã0ëÐaNuhÃ0L§À:4a¦S`Ã0Ó)°aéXÆ0Ãt
+¬Cca:Ö¡1Ã0ÐÞ0!D at CJ$¦¢Ú;iÄ:4¦uizÆ+µLBÌt¢gkÀÁöãï hUª³ Ù«N£A÷JJ©[ h3ºR^Ï;áÀ¶*
+8Ú+5Õñº¸ áäöiîÂ1GmÒ
e ¾Kjï@+àøJtopøMa<×Å>Á>p:ѵTá,½½Ã`iì®aéXÆ0Ç rTþÚwbåpuQÙÃùëÞ¡Tdó= À_÷^è^¥oëzö/#õ[dÇpÊ/
+ñ×ÍâñA¥q«½ca:OùAÇ×RÙÛàÝÞÊ',¼ªÛÌí³Ã¾íjgáe¯Y{ÜÙuÛózß#¥×poå2'D®´dîxpz6%pªÏëu¿ªPõ¼Ã¾îR^tì2
ð&©ÛÒ'»^I,TØóÏ\
+P çøo5¯îó±9må]×ÉtÊvhõynÅÒË(¨Õ ç5t}ëJµeJ½ýÀ³¤¯ZÔuÛrz=DÃuçRLáÕ³"2ÿø¬5êaÚGÐñí]ÓZ2þ¸S$E×/FÑõk %Jó[«nN=¨þÏEêëmþº÷b¼OÎwMÙhJ]¼ªµêd:&wé½åPù]ì ¨{*À]|CÂ% õ=
+µFÝ%i£¾Jóp¥"qöo<ìß½JÐô
+´F'Ã)Ù¡y+M
·k£ï¨Q îÛ{óÊÄ ÐpMmµá^ÍiÏ\-ºWþ§µê`Ú¥"¡k°B7è>N ¥q¬Kië wÉ´×À¶/z ¨,×=¤ïòÚ~gÁ
ý»¦S*ÆN«¸ùy]Ü"9T&ØóûË«û|,öÜL©dæ]¿1gnùåQÛÅÒVüÒø³&òjí¿I °í4öm=mNcg ¤Ïv ³àÂe©îBH¶m_ôÅø#¢GÞKúϾªÉó,äT©_Z2¶| öü3odAÛ»SÙ5ÍAMämOkc,9²nÂéemÌÃe @ª#®ûÃS¶Å,ºWF¾mõ¨SrMt¯L8Uacg Ä÷÷*tC|ÎÂ+J¡Ir¨rbÝÞ¸E¶ìç è\l´eg>[»'zuíåõygÞFe öýï¬Ïí{¯-;cfí¨uu{æ{Êÿq¬úÍéË?ßpÁÖo-ÓQRN\*ºW½P×ë~wñÔ3¿®õ0 ÓÖN6§¬ñ«èªA!ߧúÿ3¥,Íñ;uï½'«yJCÊîR ÷ruä÷)
+£B¥W:¼XÂþÝj®?S$lkö2ÊtÙ¯Tö´e'¾ã8xî s©ñ5còW+9ÞºW$Îoø[\ù*¥"ñV<üÂïòæå*óJÁë *{c¤à¡;yUò:C»㠧)õ×¾õ^ãç`KcGÙóϸÅ[ñÈÛ2ñ#mô¶3NÑM9}%iuû>´ï?wR ~nÓ¤¥1éÓMû#'ÄþdN_5Ù¾l ¸Kïø +ôqÏ^¥±^§,_ì8xñ$ 'RKoáè½ÆÄ/%¼yßöùX¨h¯62íÇÒ}ç
îìç¨äÌ:úض7úGWÑÁ À)¢E àÕYA^$DICÞS8>r Xòm1+MPóU¿ÚxMAÛo¾.öébcò9!f$÷W1P*WáeÏSÒV~ߺ-f:"mì%ÚاFÞpHòï»Í]|Ãoõ¹ORÙÃÞ"Dá$^ä aoùý=¨ÈP.ûJWª9U"×JÁü¯I8M9mí"åªz]ü¯Sìæ|â_Þe©.íqBÿJ9ª#¦Ú¨:ß_ûöd)7Í]zßÓÞÊç2u[ô Î
+Â
)(ÔYA ðU¿Ú
J³U^IeÀ Ñ>N³R. ° QZ27| ¼*íMûþs¯öV<y1yÞvl*Ó§M©WXòþ®ußðPȳæ! [<ã©ìOõ×¾1£é¼n;h°éB7<¯ñg^Ñ%'¨;çXõS*{nÏg¨ìK5¦|wCKCÌéAý`
6úÁÿø»ä¦¾AÇw¹§2¦,Üxä±R°° °ñHórÂs~æM*ód»»ôJY,4Wí_F¸Ko[í.½m½¡ëûNRóNºS²C MäMµÈÞð»ì¾úyzÊøÝöëÒ#
+ûwÇÎîo^N8]qÓpº¦_¨ é êªjÅ&0§
n¨O¡¶(èøvJÈû»ð¦0 *«yNiÈ:ATU<Yy~ã]~ȳ&ç$¤PYoeõ±ê´çõzÊ®^Ä9Óº¡¾Öisª1$ÎÞ-º~ÉyláB rÓ#%2±ÞßUºØgU[§×¶t
+*»²Ôϳâ8ejÕñêV'ÙQvwÌKÀ:´ÖdHx#7èX´C X
+p!ÐPSþ@^ݳ
+ÎÅJuÚÍçÝ£²·éöíPS9Æ)bkÚ |¦¡²³çõ)hÏZ¤4;ò¬IÝËî"&§±s!:ÏU8iB?bÚrM¹B?lè\ü¡ãÀ°¨»VÉ¡ZUÐñÕpSêÏß5^7ìßs§ü?
²X'«Ç*´^j©þúÜÊ¡ÚKº³ÔÏë¨NtëÞÊm«÷é^ *ó
+ÃèM:¾Neo^uÎ{ À)ºî9=ew®ãÕ=mú·²E综UÏ?òmûXm¹úPÀ6'"Ìæm *Ò^©2_µÎ_û¿û§ÉÕÅÏ<*§§ü¾îR 'EaµGKL¢{ÕXаUe¿¹ßqJvh£.ewÒpþ^äÚ¢k îñ àÕ;B
+÷»KnïÍ«»×éb)õ×½¿Öoûì1I,}_ys^À67MìzSÊ×
+·î4W?øõÆ_|5¯ßJ¢RðÊê÷T<ÞM@Ø@%G¢«èÚ³ó©ÓêÚðm`ZQRpÚªç·{D÷XÎKxÓNMÌMw_Jã¸!ïK¶9ã@¥gIó¶º&ßòlî.½ã6Bx7á-ÛAMC
¦ßAûü§@Ã^ú©Ûò£F 4h&&?ìß5µ)$Þuh§N\òl¸Fª{ïZ
+YMª\¡;ûÆáF]Ü5²{£Îîá<ër5w¼iH}»§üþ»EÇ/ß© §.TêÏû¨é¸oäPMO_ÕiàÔEÚÇïliHe8Èòí¸ §9¤2O¦º¿òÈc;@£y0ùTÊåè.¹è^1JÞî²e%¯JÿÖ±æ ΢©SäPå ÂiËY93CÞ-WÉMwÐpÝ9Jz©KºÁR¾ù½>·ÿTö$(Ü4lNY¡±Þü.î©âê¯Ï뻪ҼL¡ô±)õ»umÑþ¿ëp.Ç2r¶[rbfP.m¶útMN,
+{^߽Ƥùg)MtªÿÝ
cpmÈoï8þBN;3étNN\ÛýQ#zd¿ÖÞ±LÇW§äJ©û¼C3$~°À1ãUébD榹 æ6)tgù=ö¾à¿L¶fe¿àÅãÕÑ}Çû Þ?Á°aVtJvhsªà]ÂJ㸩î,o{ÇÂÞÔ×͸N½buh ÔÖkQÉ¥lï8Î%5&/`~0íNóøQA:Ö¡ÐF?С~gaïÌÂ0Ã0GbwhL«
+¯$W>C%ÛÛ«EG¸½c8¢OPóNîmÇ´`IÓg QÆ'Ú^ì§Cuß1¯<í¶l£áïé(¥§D§F ¨Ú;¦ÕÒÀý¢;³¥4ÔÞA0ô6Bi§^ÅÉ0Ã&Ø¢a¦S`Ã0Ó)°UL«âUi ¼"FÓÞq0'_(¸»¶=Bl@gE)¥^ ! ¶3sç%Òv(åÑjcòg<Ç0sÊÝËOé§ÒVuwWNwZ&Éî¼dïD ;4Òxa :æ.ÜÌ)*äßIC
+ Úyiµ pl×åN
zs ºþP&¶Ùö;%Y$¢sqÓ+ M/r*mÃü=®;Øó_Ã6N¥!a9&Ö¡1Ã0ëÐaNuhÃ0L§À:4a¦S`Ã0Ì
+y·t¸daÿ5¥b«¬l¦²r:üé¬CcùêóMküÙYxÅë²dïPã9]þTÀöEäɺ»ô^®¢©À[5+ÙU4íêuíÖÂR_1ïúåY,hß?Ò¡4Ú ¾ªSCÞ½µ1®Tƹ ÀSþHZØ¿3Cðú*Al<?èøÞ,º7t}3Ç_7;J
+0©#®.óÕ¼%k¬¨Æ@Eâ*¾å,È>58hJùz# 8¯:[»)tgoÕ'¼ X¨pÜu.=&CÂëë%;ï*ºî<cò«9Þ"5ÆâC¾Ígèãgþòí4?ÔÅ<¼Fiåö?.¨{ØÕÖiuîÒ»³ÊC
+£©t¼Ø¬º}3ì[b< Ê>1iöjN¨ìá\E×C8ß<w+ ¸J¦÷üûúpÊ®L)ßüÞ¿'vÆ0s¦·÷Ú¾y¦ DׯpµÖ]zÏs `Ï?ç*ѽê\Nªs\2³ùù¢kE×gí( ÝËÓE÷a!ïVCÐùóë ¡á@îPç¡PÉÁ®eïRÐHÁ¢Ìú¼Ó® q
+ý9ίsÜÖ ìûG|@"Ä+$±T r¨\kÏø"ÇG8;³:×8þW¥Ô/èæ«yý N®qOû0ìߣÝkÎÝ«R äùí"ѳ&púÂi+m¿C¢{U¼èùí¢¶¬|í9Tâ,8 êsû½ XRwÖM¾ÿÅÜk®UÎÛH8£·57ͱaæ8Æ1.ÞkHx#·ñnLßeÖ'¦Ôo× $±èb*{£C¾PÉÛ=P?×z¼ëΰËÜíç*ÓØï¥`qß2Õ!sÚ¯K-ë?Ã5g
+Û-AçÏS Iòmê){0p¦nÖ?ߦ2w¿ö½w¦K>m¼KjNP÷øÞôÙöwóp¥~øg¦pø'¶o©!¼©JÿBÁcÖ4§¯X¬yx¡®î¨o¥§W8{®KCç êÞnJEèüy¼ Ψ;Ñ÷ûbCÃ0ùSHA7øð% @8M¾ËËï4vxÍqÊ$õ¬5*Olº"®A @i8 ¾mBoÀ¾Ð"
#¬=þ×~༠4\*è×¢¬WwÿLtþ|£óàc"áO9\ ov4üÛX%k @e_$¯LúJ«,9L KÄØ"
tô<!á| Àñæ0(º³Üà´¬Y9º+ìUr³»ôÞ,_ͯh¢ï»ÖÏçÊîÐvå*¾¹_{Çp¤ÖÉ[õ|bÀ¾ÐÒZ×gZ§ÛdËîþ«dzß^WGÍó=ð°-§×ö쿦}¤Ê([væ³X6ì¯ê! [vÚ+ÎÂkf)tg2qR2Ù²»?#/ µå
+;áMmÙ/Ørz<é¯}7 Ô×Sèkß?bÖ±V%j£ï])÷²eg>5®oç¨ÌÖý{&Û²3
+6\Ë:u$V]Ûï¿W¥¼2áw[v泶^×ç¾Þ]rK_[vÆs¢{Õ8Âw·Eg Fó`2KNÜù¸Jî Aû)¥ím_©fL/p
@Ðñ£ÉSñØíÖ¬ì n_â'½Jnn¯øZr²cªÏís¿&ò¨Ûª
ê
'ëúǬ7oÐ4¥þN&ѵTá)¹¯"®®?Ù×n
+!yNWµiB¨µë
+:¾7+£]Óõò¬Ó)ôÃ9§$ÊúüsÞÈÜp7¥!Â+Sâ]+Jã(wóãÃþ=j 4}'gØ¿GÝü<Y²ór°P!hûðµÏ¹×é?Ã
+× ÕÞMãÐxYôlÚ°!G¦ùjÞ8mÃm9Y!áÍ·A)_Ûï.JE£6ú¾O4·Ôøjþ°Íp²6ö¡¯Ô)MÎ ç
+Ú~Eº¸g/£2]²3äÛ/åPù"z¯%cÃW²3C¾-ýäPMON»×ÔmÑ÷aßN»ôÎûÊñªÌõæn?® GÁøR08!*gDÝo4Öå*¾±¿ª1§ýº´±¬>oÐ4Âëìr¨&]ß好3®¤4`R¯øV÷Tq}Þ iÝ7Ïi<VûØ÷r¨v¤¯æAçë §õQæ<å¤
¼ÎCU½ o,±d¬ùpzÙUtýoëhNÎ7uûaQóýú¼AÓ§vSÉhHüàOÙ'È£«Ò8úGCÂëyÎCö úøYoÈ¡Ò1Aç¢^!ßßÉþì*ºa¼®é®Ð
+]lLúd£`Ü(*y
+r¨ì,SÊ×Ïx*&êëL©ßÿæ)$-èüi2¨¤T/¯ïòÊþ¶ø9թ̹ééq?Ü9åèmGÀðÏ:²cËñÓZþñö:o;3 8¼Ê3ø§tlÈiS¨[×^¿×3Si妲¯§:âêE
+íÀåþÚ÷¦ ¯æíGtñÏÏUY&.öV>{{óó¥Pi¦, I,ë%EFI,NÄâ¦ÔoCÕý|5oÆIba¬,¼ÔòåL*{¬îâñª 1éóW-ÙcBÞZwé]=¥@ÞHsÚÒú.¯În¬Çqð¢1!ïÆqÆäÏ7¯_W¥\D¯zʹW¥æh£îþÂoûäɦ׫2wÞ¸Suۻ津¿Jbiº,ÄÂh)Xp©1yÎKL²zûëfG
¼'Y2ÖÌÕîâéCþTw¨bB´tßöº»äö鼺{®)åË7ooëÔ{5§-©ÐöpBô¥aôg5ß»oMeÙøáë¢kÙ½aÿµ,fÉáª,KæǽU3ÊáÚ®Ì3Ãþìóýu³£ïnÒÅü÷CkÏü§Õ«JNößs4·HÝ·Ì>þLKÚ¤CÄB
}ÿÈËÚ¢®Åq`Ô%!ïFm{Ôí<4q¯öí¸ö¨»N·OóP6æÁ}²äLÔÏ·Böwó?tW ~Áµ á¿ú4eEàU©«M 'Df<ëÓ ¢6 Úþ¥áüUáÀÁa¶ÆUtíöü!QÙè¯ý gÈ»q¸ °W¦¾Ó5ìß=ݹéN9ê«1é£Å()=M)_oÔDÞRp¡ ãÇ#·åþˬ
+"î7
nW$dûÓõóQ*FØ÷|Xקˡʮ¾MÉýBÊaÛ wÓgá Jüu³£xeê/¶ìôÝvd]X<He¾l¹B?ÜË ÖíÞªÏ
nÐRNÂìs©dO·ç}¢{yºB?ô[Oå³Ïز3gý»õÕ¦ãÃÕ¼< lï8ÚBth7˼*¥¸-ê:YxUJ 'DµËܯêVÉ+SÚìÙ¶$¨³| TÑT@ð§yuÄ56pêbsÚW¬Y93ÍiKf4ãeR¨<RPÉÑïÿ/Ã5ëxVÉR}oJEònîÇ+»îõÕ¼q.§ìº5¢ûÖ ÎÈDP÷Ú&ù÷
+4¤÷i¸Â¦Ðý¦=ï¬äPÙQÃò¼*] Âë<wkø°U*óx'!êJÝGÑAçb#©
+A+]r¸¶
ûSg©4^¸prkVÎLkϼgÉ}{Ä rãPáM»UæñßX³rfZÒÿGyS1é£%½o¡4¬õ?ÚÚEe· 8Eì{M_JE"Këû pÚ ðÊÔÍ"~5+gfDVö£×¶èbßÙ«ð.^¶ÁWûÞ£ãg::ç¡Ëεçé©xº{Ô/(íùC¯i«ú;fÛú:ÂM©?W¥ÿ,%)
+´Q·¿¤y¨Ì1 a.Ñ}ë¾wºøë>|Þj¢î~C©fy7^`GݾÔ7 Q8°NÐôÿÁºp-;í@ðNmSèÎ^+ºW^ ¦ßbyB®·òé#zìzľä¼29O
+è§2OX¬{¦È¾øSaJ]¸ (-;ícBN¼ã#êÂ}çRAi<ï[C×÷ö9'EC@m½þ}ÂiÃþºO¯
+k8EÌ>KÆoßß/R/*v;ÃÔíÇguV°>·Ï*óåßÉR½Vt-¿TVòêÌuæn?®®Ïí{f at RY{xôOïavúK 'p¡»÷UÍL
+ØæÞÂ
)Túø3ÔSmÇîuCü°ÍéöïÈJÈî[i>§r*4}D½ËÝýC×·_#1 §9Þt TÆ1ï;yTÒpBT¶%sã¼Æóµ1÷¯wÞûH}NÖ97ï&¼ÕÏ ÖZðU`uÊá:3!ÛÝýu׺¾ý^8¯ñV<úX}nßaD0ï%B¤[ßåå<ûþá=mÙi/¨lÖ¬ìY3æR¿ÿÍYxuÐQ0éºÆ9±8M,4Ógûë>¾1h_¨Q.x Æ¿ôUÏzDéàëj P.]t|uØ»}'X*9Áê(¡³
+ 8!ÒFe¯_ûH©è^¹«áÿ)Jº!ß?ßÖRݺÿÌöÕ¼~Íþm4À
¬=óró<À
@TvC×·vùëfWúë>¸É¾x²>þù%îÒ»§×çd½$¨»/VG¹I¥¢¼ `Lúpµ£`âT[vú &ú7uN¤²'Dði£ïÿ°Uþ N!ÎÂÉCoôÊbE´9mÉ
+wé½$±$®1[³pòp9ÝõñÏýâ«}§*SÊüµÓË!ï·âñó{t±O¸Kïè¥4\P¦2Otì-!÷ª®ÄöøëfGìh£îüMeè:}5o9 ÓDݾ\qyLíûÍiË~qÝß]
+ä%ß[%:±¼Û®çqëú¡E²dçÝÅ7#¼ÅeLút®æ=e)Kn'X\®ïìlíR¸®(
+ªÉs×p¼Ej¼®ÑÅ>¶TiãòVÍL¹×ôÕÅÏX¥Ð
+ñ5Æç|¶¯$^fß?Ò§±SÄ
Ü¥w/hz´ÆìqW9Öí]lHüð9\§ôT<úUTó&
+IJnÝ7Ï%;ïx*St¸R¡ü3¯Lª÷×}ürdï+Ü¥÷f
<¿oHüègáäY½
+ï©Û³LðÊÕ*Ëz[vÆ»½î¨ÛÛåkMäôuqÏÕíK}ÃøîSn°·>§ïǽKnt¼hØ?DðZ{îÂ]zoè^5εï庽]çX2×ÝÒ¸RÔíÿÝÚóÀ0·Huûß5&¾ÿ¨ªRz«^xȶô ûQoEö*j±åôzXiõ£Ê8ºÂ]z×S¦
O8¯¡~¿öÝQÓzI³ÕçýIdïÒlÙi¯hc}WÆ]%w¼`ÍÚ{¯-»Ç]Üÿm~ú39\Í{+ë.ºVLVÇñVo ~Ác
+m»x4}zKÆï¯Ïí{B?l
<
Y¹Ï×çy 9ãcÒ'»þî/·#®rl+ÎCGÇÛ
+- IDATÈ¡ª®Í;Cæä9W9Öí[Ä)âªLã
+:¾¿ð¦jNSöící¹ÿº½ñ9EåÓÛ¤`ÞTAÝë9\Á 1ûMiKØö¥ÎUè¾öm¿LÐü4¨ÄÒôî[?©Ïx3§/àq6ѽúJ
aÄBѵüvsÚÒ{´ýå1^êÔFÝ]ùÿ1uù¢6)M,]ËGp¯LÙömhHüèYWñM/*´¾ÖDݾË]2} éÿªHdNðæ·±k3S'mõÕ¼ú é»D×ÆRÙo4§/cËNߤÐ9C×&NWoÉXÿuݾ·uż2¡JШ:ê+Å}ÚkD÷ê#{ÝÑ·òdݧO©,_ÑFß{оÿÜwÚþ¼a¼"a9}ÅÏÿê{Ä*Çã9rÊ*y¼S1ÙF8ÍA àñuTöDîÕúúÜ~ý{{@
© @8m ¨#&QÉú§ëÞ¥²L©ox.r÷èâ) ÐYiãj¸¡$*Tæ+¶É²ë,^Ýc5 º¾Cew7WÑõ`Þ×|iëáús8Þ"IòG§újÞBxkn ~^©+O%g÷{ÍhOù£S g(
+ù¶_ÓÅ>¶4Èë*¹c§LX
+ Töføkßì)t*ÇòåP¥ 4^øº¯úÕ{mÙÝ^k>L%ºëóÎz?ìÏÎ@¥ÀÁ÷oø¶Í)bê¨ì9æÛ/Dç5´IoCÑÇý}1
~Ä~
þÍíÓpAsúÊOtqOËáêäpmzØ¿o¹%cÍlsú² ÎoN_±Xi¼èg)TÖÏSv_O"XvR¾Þ¨²\ñaØ·c!iö9T5 äPÕPcÒGëDϺq¬
+y~¿TÖzÊ ù!ïS¤@NªÚrå_dLYð¡>þ¹Cr¨ì"*9Âþ]çQÉÝ4È¢´+äÀ~¼ÝÃìá²dOIJQ @&ß¾b1Ì!*yzÿ¶Ê
+¯«óÍiËh£ïûFUõó×}Mï7§ý²ÌøÑnMä-5aö¥C÷@ÅXOÙÑ)£k@·!áÜ sq$!J)õµúøÞ
+\t²CÿjÙ~Ðñc"á4ejË¿{«f]¹ Kγ<¦®UÃ9e×:JzçÁqcyuZ1!÷ðwMßÞ oØï(¸ô|^[¢pÞ,{«{F9ýú@ýüÇõsw«#¦ÚxeÊò kéKÚè¦á(D iËÍi*tgW[oÞ°¤Qè·ÍIrÝ×C¡\Íñ¦0¯L\A!.³¾Ø¿IVG\]ç«~@CÊBø@Ø·sª>á÷5ıSvÍÓÅ>ù{ þJCãM~cò¼ç]EW=°¥¾·²á=ú)pÚReâ&_ÕËãüí;,æk|ÿæ¤!¼»iȨKÌiK^9üeº!CáMÏþpJAÓ¯Ft´$X ¯«äxDxS®}ÿð+ oÊãpJA¾Ò<oKóªCu?¹Kïæ,t¥%sÃÿhLL8u1é7ù÷ ú!NÂéògóy·h@ (tÊö!Kv¾±Óÿ_{çUÑõñ3·mïé¤FA)""(Ê«
+¦B¤¢"D,
+"R¥J¯I
ôlï·ÍûaYܪ÷÷%wwçÎݹwæÿ 0E+o·âÚYª&ÃBÈ«¥úß("&V=dZ ¢«Ù
ßU p®}!Õ^ôØ_$|B#%)¿ø,c0%IY @ÉÚ5P²ªùyëjøä1ZÑñ+JÖ& õÛXëú¾©©×&ûd¢8Jêå!$UsîíªYݤ
+ Ð$,6-ç>ÞVûé뮺¹ ´²ë×ʨÙE2ÃÓ¼Öµi RÝ]5D`' &þ«×xO~ìñWD¶" @5ûUα«««vÖHQpÚäßLÌ)[ù3/s®1¦m¢$). FÝÿsRÒò©n @´v`´=þ
+ïÉK `ô°KÉÚü1UÅ~r BóÝ
+ YSò¶')y;%Kß @Éo©¡¤û@J3öP²[ê)yÛS¬]oÌÛäRòvM4ÕþkO¡á|8ªÆ'_§ª³&;ÞkYñëµ3b/|Æ¥c¯x1ýbòKÙ+_jå½Ü
+EÏcVäëH{ÅèÌËû¿è¼ÌRØ'Û9Þ1éBåe!O×¹©Óxç¤úá« ${æÝ9%þ? ÈÃ_^Í9÷
+0æeL2æ¦ÌpÕ¿eÌË|ÕV>z4l-)EÇÃçµIÙã[éÈ×yã¹iÙQ²6ÜgÌM}Ó1Áߥ£É$p$³3@ícä¹Ú ¤é^ÚeÌMcÌKì¨$Õ=üÇøÅ3Ƽ ÆÜäÙ¼ë4°<"$
+ÆÜ´lÞ{JFPãÆÜé^Ó²1Mÿï/4nÊUW
+qÖLMðW<Ò\×ËÏÕPapTOJòcÔ½ªc?;z%uÝÌÜl{h9q
Ï\¬1/c¢D;hEsqÕáÛ¯l½^Fðj¥OÛ÷Å¥o)ì= Qz£?õÇ{rç2
+'úSfÊÃ_®=×æuÉÂ^Üv.}ÀÁ^þlk PÅ.:ë{Â{ò$öògïÓ¥l[q©õþ÷ÐÎ
ǼB'Ñ´\ìÿdsuóÁÚ6ª(Y+·ß«õRÚù»²ÍÕ<.õs?[B\
+ø4赬ÖЪn9®]ì\ÿ´RÔ0²¤×#J>áõ+mQÞYGË;Nú»ü ×'^Ëj³nö ,Ø#!5«b,¥]\¦mÆbÑ«õynÿÀ§©È9ÿì 0Äsüu8kçÄx«{êR¶-µ?ÐKðÝFJRvj[®ÞÊ»ImeÿE{Àºyû®úùãW`Ñ.ÑøFðW DyUÏ_T1æ6?có;Â+
ºÔ]ß©¯îîÆÅOB<è´^÷ÕAÞ[мH4åwNÖ§îYâ³yF¬(X³yé)Y»- ÓÒ®ºwÚRòök5 Ëwû&ÑýE¾>Vv]§ýì(Æ<X@ÖaE®º
ÈU·YÛzµ£zêXt$ÚûRFM/6çwHâùºV´²ë:À" `)º·à-º #Th"rê>ÀàO^mÑRÝ°%È)7T͵¿js±\ìysUKiçïÊ6Wó¸ÔÏýøèú.\Ìy W¦nr!®zÉ$pn¥Í
>wÅ릺·=8Ý\¹\ðzRùÆ".´W¼0 @9ýsCFþ,ØÂíϧ³ö-JÖ¾q´*fÁuÜ×s : °nëi\4V9íg[éãE®&Q¶¦àÍïæjXi/õ "ÕªèwçcÁ~Ör«þ½7¤úGVé[*ѬdwÖéÒöLSÇ}ù>kýõ+öòÑmcÒq2[ýÞÊÀÏhEE²i&ñ§·Yû¶Ç H&f+%kó£2 PD¼^i±!=o&á»= XdååÓ8ç# ìeO>HµE´îmÖ¶ùÿD¾¹ê[¶T.²å "[ÑU´îM©ad¿^GÕÄ'H¦E±"|ÜÓ×}c\Ó 0+Ó·:2[ôÆli¬³vF¬à-¸S´nÈÕe
+lE²ÈÕÑ"WÓ @`KѬ½Rýc_yLß<uE9HkÄÐÌw<¬KÙqÕ×:ýXKíDIëÎx9^ªñɼûhÿµ<쥺o¥Q0¶¡÷ AGÕÉÃÇåfm¥¨Ï½ ÓÊ9çÚä¼Þ¹Js_îÔµ Ê#RÝP£ê¹Ít²ÓYä¨ø£z"`ÑÝw2 lY$AGídTw:Ïekg*cÞÁ¨{Ûí/uÌjM'³&d}[ÀÕf©b>xQ÷µ!RÓd¿áôÚ>!_ àÓÕ³?ÛÚ^1f EG-¡¡òÐÑ'%Ã5æÄLËo]®Iüi»ÿ3¯mc¸×üÃH@¢;ÉÝøùY)=ÎT?ì7,áå]¤WÝ
+ ÖKQ¿Nèªÿ0.°<)MÙàêö#ò¦¶º´ýób°£fÃcü2 @1imàkßÒ`âvd$íù&*$I+üO§îÆOÏëuÄçÜ'£YîkmÇ xDª
s©á\,þq¸ã1wärÅ.Æ)/¾ÜÊ/JTOJÏݼXÛ>"WúweD¶æ]GG"çü³¯¥ð®ïì/§¯<ï:ò< ÷?Îßùñ˱ëßÄUÿA£jâYRG×3Xt¶ØÚYýF&AjO8«&¥ ^CúéUT?ì°ÈյǢÀE³ @ªt¬£jâL¯eµ$í#¨ð£~ueôÛ{ÊpÜcZ)òu$íM®³ïçØ®ðÙá XǤúG?WÇ-y@TbÑ}Öw*Ñq2[²õEι·ÉÓk]ÓVuûIôë"#¡°èU¢æ5ù!!¨Ðý´¼ÃFCzÞ,]ê¶ñ ¥M+`Lf>ÛÔùª ©¾XPJ
+ÿ× @2±MÊ2ª;lE'Q0{ªóY¥bþ[É®ÿ*¾eYÖ!ïùì\a7Öa;*ÇÝzeu<¸ ðï൬ÔYKzóÂ%ÏÏÐ8ç `¿1/c" Ýa;¢OݳķðÙÓ $¨°\]êÎe>ÅW8 Ú¡IX>ÏUÿ~:çØ6 Æ¢db·\egD(ªô½ËÚ·v$Ù"ÖþGçØ> iWL&$ 9¿Ë¤Ó{! cö Ô}~ wã¢0Wý»£ 4"uÅê¸Ï¢MÚ¤u `¥¨ï=^ËÏ/¨¢ßm.è9Xä*³ /yúyø+U(¶åÚΩEnãñ °ÄÛ7¦4"ä5úVÇÞcmëÕöÊqÏæe×ê[ùÐo¹àö¡"Wß@ÈÃ'¿ånXðÆBMßêØ{îÆEa®º·Ç`cA*ÕÏ»¥ BéÐ$þ´Ý\Ðí!RT¤ùà9ÿg1v (.eó<GÕk9Ƕ¡ enز4,:óÒ'ë[ýoåº!-³ö@º¯} Ñ
+5yëäÆÜó¡¨D¤¾Vªjò¿ÜàKíNpåÓ©ÎW´]HÕ[ê×Ö¶üy¾µdø£gÔ-BY ô££úµçÍ'»<HÝ
+s¶-ÑÜ7ßVö¿ hU÷ª×JqÉÓR/A¬GLD¤® BíXôPX0Õ:kçdpm nJ±,°>F3`×ôÝ}+GP![e`e¡ÏïtTMxÎt²c>mÿbYZÙãké° ¬Í&Dj©ã RS +"³;«_Ì< amÒºlDjK*E¾ BÎÚþÊÕðѬuQöøät}
ùS¨#PD¼^Î9vì4Ìr!RÕH
+Hõ)ß5ùK
$ð8WÝÜh-l.èiaÔ½ ¸jg'rÎýåáã6ùWHUx÷áeô{WXÛzµ×òsà-%¥©Åªsy÷1©«þÝk0LL,ì
|Gå˽(yûeÔì"{ÅRj>_c+ÑQ¢}°Àcþ6SðÃ. [éð,yøøcÎÚí¡ð\]&ñûMPö1ëà´U*váaEa+û_g
=ÿ[`ÿ¬§õGLÞø嵬Ժêç÷F¤Ö¨m¹zôñ· %ïpP³ ïBcf-~ð«¥UÝ÷*£fùnb§¶«!«ãn÷)¨ì;ª^ëCJâ®X ûÆÞßWGÉ;¬Ö$,ßÝ· ¸_L+á¨z5c^bÈ(dÎïú¨£jR7Dªí H4d7h÷]ZCÆ©q9 Xû%=J,º%§ï
+±!ãÔ8s~×Gµ3³¡t!BÞ O;8ÃtòÖQ{ÎHå>cÌi9 @ÓòçÉîO¢]Öªã¾8ðW¾ ?ò°±»l¥#Æl -°Åwd²jã6-*eÆÞhcnò,:Z1ê>Ó °èQ#RW¤OÛû¥ñDëqêII}GGR¸OÛríƳÆLôª©)Õ§íÿÌRÔïnDªk³¿rT¿þìíx÷,ZÑåGuüÇc¾Ä¢Æ¢G@
+§ÏW`Ñ%µý¯3 Æ¥j1k©³fú {ùs]oAR²YøýfD(EGÕø¯õW!=gî%^ûkB²jCFþÀ÷'³Ó&ýþ+ üz¦L«ãó Ù¥Èì· e©üH´§¯íÓ_Ä7¼c_ê7ýðÒÿÅ=§»´2jz±2júØæïK4ýg7O÷ùázvùß×·:² Àçâ,Ñôÿ0ðÿ¤úG7«}Yèsµ²Ðçxë[ùÀ¬IXöçÃRòök8Çî§e£>¤Yn}«Ã ÒsÞö<⵶"¼íIJÖÆ ÀÚ~@JRöÛ+^.ÑôÑû#{4õõÔYSãüç³ö-˪÷e·)¬}óýS"%AG½Öuóiy¼c¥èOhyǯ¼æñ®c;$Çu³§ñîcsÎÝCÕñKÇÙ+_ÊÚÖ'¥inÖ¾í9uü7söm¯LÜ¥«5¸5ûô^´QvßÍÚ~ïc)ê£KÞ¼Út¢Ý[$°ßrTd+e ó1/cIGåNf®úù®úy3u°`÷h`¦ÝÿôZWµÕjïn>NÍ¡]÷{Í+?eTÝ뽶õïÓò¬7¶"Ózê~¥6yãZkÉд¢ëbι§ß^§Kr
+hô!,r-e!Oú?çÝÇ *¤ `bE®* úÓj
+#I·( @¶pÎÝúÀúið#5"ß&pÑÔÕøÞÓ3PVÜö©!óÔXC橱¬G,©RÝ#
çëÛ¸¸5 ¦Þcú>!i= D÷P1l>[S¥ÿöM^ûu:3PtD) AJy×±DohE˳ΫEFJ \EÈÕ¶qTMz°@#D`,Xie×rßÈ+ücú×RÏ ÞSéX0¦;ª&=E2"rú"_oÌËXh-Úå\m_ÏÐòNZÑéÊän\P¸°`Ñ©ã½p©Þyÿuu_ Ò©~ÿÿiLÙâÅÄw r -íEgç:tiÓ×À:R½_øãEäÔÏÉ» ¡8¦MZÿÈUÉkÚ.÷¡à9ÙW:ª¶Z嵬Z ùðM JÖz³fú}öòѽH&ÖÚ^]Êæ%Ú¤ßÖcì ó-Ñ{i¯õ±èÙ²®¬}cA¦MÞ¸Fóa®<ü* ξu
+)I8Ð\Êcú¶/-ï¸DûÙQÿÄ
Òk]=0¯äÝ9]á¼1Äk]û0Æ"Ã:þ¸ýtkÖmhüIà*Û9ª'%!BY¬IXö§D3è»+¼LWæåHÒ-¶YK=Î9wË]uï´
<³K`Kú¸êßâ]û立o½úe;oÁ}öòQmoQßsùúHGõê7y÷1))IÜì¨zå α]áª}ºÔQ51É\Ðí!αóyZuǧ»£Õo$:ª&%Ó¶"L+²Üú´ýE¾¾«Çô/ºßÓßUÿnÀô
>»µÙà1÷¸×ºVí¬ÓÜ. VõZ <bâwRý°U´²{%ÉÄïr7,|ÐYK' JÖöà-éìª)r5½ ¤º!¿)yØË¥!OþD+ºsíªèyßÑ._òîÜ.ªgÑîÆE7,Èr«ã¿Þíø/¢IX¾[ôûºæSA.ÔdÏRt>Ãw#Y¥²ÅÜ
+éy³BÚÔö À" À» BV sZ©ã6`V À»sCÕbÌ"ÁSØ Õû]
+g ¨ãü!pUÝyÏÉ~¨é«}rιï´ïsþù!=o&£êö3ÆVd¹ ³ô Iâw¼;g0k[ß$Ä
Õ"ßáÍ9÷ÉxOÞ}ô3HiêæsջᣫºÕ~b:IGíÌI}ýõ+ÈyÀ¢åýý¸
+ÃßÕy1\´RH r%IYH¨IZ·¤[ÚÊ˹öÅK´-RÝз<Æ%ÑÊîËT1æÒò[*(Yëà ¬Í1JÞ®ÔW_«-´µµ>ì+Óî¯r§2¤úÇò°¦ðîc RG21Md)Yæ>,XÃYë{Yë{Yû&½6iýjRzÀVþÌˬcW2Asºµm¸_ÖÄ» @ñúDÖ¶®AGjZ®YáëoÒͽs9ÇÎ( Úçnüb¸D;ø]¦¿M¸b'-ïô«£jüξ¹mS»Z¤díª TÑïd4÷.uÖÌ|ÂcZ6#jÖ%è°¯eåýÒí PF¿}`Zö?Vtúµ«¯èþÈUÿÞOãâ X`ËCmåϼ,xÓ-f/bÔ}m´¢ÓrwÃÂý7"^ËJµøþXt®úw£¬%ÃÎv\ø±ý¯Ý
Ký{\ª2ʵu¾;k¦&xkÏåû¯BÐsÓ²Ïw]uïoc'ó2'sSf]WsçxÌ?>/ÑÞ¿ªÙ¹vDjNsS¦³ÖµÿhïÿÑû»S²mï>ö«aA$AêÔE¶ñ FÕ^þÔÆÜï¤_b0BÒzcnZ6kßò( ""É$®7æ&Í5æeLôÜP'¥úoÛÊë1¯ÐùíQ¶xë«ioÌkõ1/süéåHdÌMËæÝyý/4VíÀF=QÆÜÔ7®²ÛùË
+¶ B^cÌMÍ;þz¡z/ÄUW
+¹Úó2Ç#Dð¢`×¥l×<ïßÀtâç(ù».Eéþâën3Vݹ^ýþ«]÷¤Òû9-k¿T¢|ÜQýÆ,FÙã³ÀÔ)çÃÛݤ¾WCÅæJ TiÌûÔûì}Às~áºÔÝßN´+}q©,äÉÓ[ÆP;Î¥ÆT
+9?^ËJ-£¾ÛxÝU¯¦xëiâ¿þ¦°ç»¦£¢aÌMËhú-SFÏËðýßÒó<L Ë;kÛ¨j -òu$ïÎ59¬m£RtpùÕ?ÎUçßoߢ¼¶8çnyS
+ÊäV
+¹Ú¨ã}(xòå~wäk"òoIiÚ?s"ü-¿õ¢þ¹n¬%Ã:óîCwtÌauâ¿Z
+û<¢7Jà*S5ÓúWÙÂVö¤À9w÷IyØó%úa
+¶¡}¶üVJÖf³*vá^-ï/ruíÍîc»t)ÛÎ<]îxXäê3©®PEÏûVvsNf= PXt
ÉO~!¥ê´TÛ0Ôåaå¬ÃÚÖv¹tDHê®ß¼Ö5LÜmòÆ5"_GÚJ»G`ËÛS²¶5 Ëw[úÞE\ä*³ÔñK¦9*Ç= ò¦$
+)`ÔwíVD¾Yb-~ ïÉëN2q´I¿÷·g¯x>ݯ&Â(»¯ °xÈVt UÝW¨c?;Ê9¶+U5Z¢éû³²ÅÛ¦þr«ÈUf1ê>K9ç®Xt
ÊÃ^ú,PZËße¸&ñåêìLÁ{2M²s¹9ÿ¶«¾ÃX ½Z«ïéª{Kïµ¬Ü À»ÞjÌMJJ¶iÖÿÖ|͹D&ÖNÒ'.cu¡ÉÌßåQËóOf ¶J±yÝçx*\`Táý{Ó¼KÌ .v⼬Éìü+«¯ZÑÅu-'3 ß?èßc_ RÝPSó° óIDAT`Ù¯e¥sî©ÿn®ÀÕ¦ÚËê¢ò#"yú´(E§ :r«.yójÖ¾ù)mÒ¯stiNgÔwl%Ã{aÁ©Ñ¥îÅ»ÝÇ9v)*l;ºsIàd {å7CFþ,vT¿Þ @`KF2ê»7KÔ÷þà6~1 Àm\2A9å,,4QÙb½à-~@÷Ù[ó2¯uÍMËUÓxoAιOf+Ù.¥Ï÷±¶õj«Ìùúd]êÎ×ÕÙ=1`R¿tÀÞ'xCìϧó,}Úþ"WÝÊQõêa UÌ<¿*öã ¾LܪØ
sXÛÆQ ö1ÏP²Mü×ó=æF |͸QÓçzL˾dTwn¥ä·lr7|Üd cÊQ=¥
+çÜÝO`«nÇEWÝ Â¯é*Ѷ R}Döâ§Ã\ Î0MËÕÙ¼'o/EJËAú|Íçþ ]êîoýÒp~ôi]i½7=¡9k¦&ØJGtÄEóò3Þæ;¾:¦]{<æåzË©þ½¯µ7nãH:j%oïa·mä='Îë©IÉÚþh.è±Àû+"WCÞÂ"ßÐÊßu &¼æ)ç;×Y;m¨1/ý5Ás²ÈÕ¶ @HV¨]¤Eg¼OñRÝP*îóÍ7ý *t'ìæ$¨°|ÛëSWyÌËâoQ«ÏðÛã1¯H `w¬'¨pAàÊo¨ûl£YnDê÷ p]=@t¶0ÌEwç$6o3uüë}w¹ ycëØÙÏZ:|, &N;-Äê¡ÈQ¶[(Õ>tR¬ÉMÇó=¼ûH'À¬ uyÖâÁw](æVtÚpºÏåÓ7-þ®ì_¸ÏÙj2ÿ"WIý][·ùºKî¼
L`ÎÆ«ÅåÚ#
+fòjÝ,]öF2ñvRÒ²³oS:«^;#8,°e7Í xNªoqÖµ¶ãfB¢îw\äëÛ pîãmI&þÐùʪ¢ßÙY6
+ªZgí̳dâöÒófé[¨l1ó"dV,:¤ù:RäÛÒófLô>>¦æj¾e>ZÏñe<=É!á´çª?Ä £÷ø=Ù3Û·×DÈX =ÈÚ6uá=y,Û P²Öû¥;iHÏeÈ(xMóÁ¦íMÖ©ýöú^kIuCÒófé7¼â×Mý+w¿Mõæq«í
y
+%¿åOÞyà%JÞ416¯ÿKå¿Ï7¬ÓÑÕÀ\Øk ¥°ÏWíìô£=[ù¨¶ÒÇï|ÏRØ{?ÀZ2ì1{åØR§)¿óHË©û&¸ê?¿¨òê(aェ ìXå¨|¹µdèzÞ¹øÛYÚݸ(ÌÝðáp}«cï6ùR¢ø"U^Ö¶©%muT`Ëc9Ç.tc^údeÔì ójcnÊL9
+£¾ë³À
+eGõ^ó÷O QºSâ 9ó¢l µÿY¸b§17ém Ê©VÜökßô( %k·V¢tÂY3u¼¾ÕIæO§ ½D;h"2»Ô\Ðí!
+¯ØâL,8¢ )"5Åú´m¥Ã³8ç¾ ¤$a6é÷uMOBóuïÝ ¾4ÖS'I´¾óø÷ijo@<ìÅæuT½:Ë×LJõ#>¿RnÌËXcÄSKµ| ïßüØÚRxÏü)9ï#DÛ0vGä5"[Þc^%}n¶?näFG:ªÎc^¾×4êRUüûÛD®F¤Æ
+±cª± Àrjà«y Ê©þàD*E[éãVEäïHõnr5|ô¤9ÿö8âC
+*ìOyDUHM1À¹Õ0e÷Å»æ Ö#R×drET¨º*]F at 4ï;ÖTS3½ì {²ß!H]A
º T±m´ÔzjÐRب|³Äß5Õ2 í-æùÛ¤åóÒ¦ÒÊ;V!R] §_üöÊÃÆ}æn?Âcú.ô2Nf«_¥ã RÓ$ £yDêRNQ3rLöµ×'ÑøÙcþa8çÜsQºJ
+qôùÖ.¼µ3bÏᤤ崪w9çÜ'sV¿ÖVÞq\9¥slW¸MKD¶¼A
7 RéVÅ|c-Ü]òÔaD8wã¢TYÈÓùê} c$ýT7Äì¬+òF9ï:ØF:zÈ7H¼æoonï>&å=ù÷»êD°ö? `Þ¤3t¨ûìUDL. ð¾6¸Kî
<µ]ªzÆiÇQ5>YdËî'%i_I4÷Öøö{íZfÐÿïkߢtÖθÅI´úÕQhåíGQÓm¥wÀ¢]¡ÿz"¢µäá.iÜy´"+dlö1¼;××KÈÚ¤u¶¶éIJ*U1óó|v~kp7.º²«æCpA/ÇƸÏÙ5Ó¦>í&éèb@(°åÉÊÈé?ÙËG½iÈ<5 áXØVC«C½½Ö_õ®ºyc+BpÎ}2wã§i¬mÃÚäßGîM5ÿ]ýö0n¨ÉòQHféèÆã-¾
<5A]Úø¾:ö£)¢³Ó×ö³ÖåOXîé+x
+îD9
+¯ûÚ·ö7¤çÌm<ó¥.uûÓ¢þc *¤X²m
1/mª<ôùOe¡ÏÕzkÕ^ó©¬ãgC2Ë0æeN¨û¬òo¸:k²ã=¦¥Ïc,2íÀ=y×!©¥xð¼ÌÒçl¥#:òîNòð9*_ý.¤M]WÝÜh·ñ˺Ôݳ¹©BZWÞé¬ÚÒkY;È~ü¿Gà-dÌ
½ßÉ,}®ñXÄZUÜâa"W-uT¿þ]hú»¬Å»\u>uÏWzqo$/ÇÖ¶^ín\Ô,Ã{?Yþ䵶éjñ_órôZVkìcH4ýÞ(´^D+»~»¢äVQ²ÌJWýKhEÖ,FÝ'ÇU7ïu}«Ã/rÓÖR²6!Báùú²§~gí[ Ñ<kß4*$³ìsAÏÁ·p0£ê9$6º_Mdݳö?Æuþ=3¯#Íù]æÒÌuú®ã×ýD¾áZÑe)çØþ>ýøHgÍ´dÖºv$ê±µm|VðÃË~é[£jüÝi2Ã%Ω :¶Þk]õ:î˱QØZ2l!£ê5N,tôa[éÏ$º!ÓhE×ZWíÌá$T7léíÂÇ£þ£é·µoíJÒ1§õ=ù¼çxïÜß^äkÛû¡â?b·/áÝ9YY¤´ÃZòèGªÇG¬cÇH2ק\xɦãÔ»>DË;|[ÈÕuPDL>o`,"¤§:è1ö4 öµ>ÖÑV:ìMÀײ²©ª7"íÝPO³é8£Ä9-£îkó¹bB`KhvÈQ´eÒV|ëX´·´>ÞQÚ¿?ÉÄúбæUãÇ|}Þ( ,Ú[ÊBGEWBW9µ*ÇüC4"äÕ úbQ°øösi) 4ä©,º[øÆD}Aî&}Ø¿Ö ¦V¢éoè!ó=±ÐQXpÕÏo at HicDqºäÍÏ^k{\>í@+ Ò.wÒcúª%¢tG4 ßïèþw¾ Uµ-×n>_ £âÅöÿÀUÜÊ{ºÐª^nÞ}¼Ï{
+sÕ½Ó dâשãîgí[;RÒêø¥ûIIü¯6T¸ 1Óò[On(YÛ4 ßíA¤ö«vv"kÛÔ@¤9Ç®~³&ûLTÿ¨Ñ¯vBÉÚx¶:µox 0¦\õó³5ÓzäÕñKhÜÁ¨îtøËKuCÌ"ol¯OÛû¥6yãZ,zÂ}û{«b/TFÍ>³Ê y² ÂWÙC°â5{ÅÀlç:t=!'¿³ö.$÷»:~é~J±új]§Nh»W`KSD¾q éé@÷PZy¯p5,¼ú4ïÉÏôiµ-ÄØV,(Eýïµ?Û!ÊyZh÷Ì="USï´?ÝmE¤VtÖNÏ
<õ8ï><¯êA2 ¼¶õs¤ºGÏxqÎ=÷¹êÞi!²ÕÝ\u[FÙ}
+A
1æ" H:zµä~å_º}¬íóɬ©Ês°`OvÖLsÕ½3$l À¢³½òå4ë©TØßÄQ«þÝ(GÕ¤!¸AnPH&Ó¶\»QÛrõÖÿ'ëÍ%kW¢× ²eD(|9s&Á%A²?hún,H±èh©^ì¨4`bóé'¦¢Í¢` Ri H}=¬ ,8Ï¡A²»Ï8 RéSÞ@E/MêJÖþgCzÞ¬Öÿ§Múõ÷sõÁV6òV NjH?1ê|ÀI·¨Æ5¢iIô×ê¢Ú¸d8@m6Æ·2±0[1e2%oï¡d·Ô#BëÛ7>mÈ,~dZÔcÑ×?,ZH ^ Ðd!ÿÛIIÓ>¢dm<²çJZõ
+ _ÙJQßý±ÇøÕ}¼s¯,
HIRÖÖ¥ñ£(¢Yû;iE§i´uÓ§¤@s®}]T1³þR* Ð$,Vç>ÞVûé뮺¹ ´²ë×ʨÙE2ÃÓ¼Ö_R ¤º!»!-
+ÌgF0ÑÝƯI
+#fR²6yØpÎ]w ÞâdJ~Ë MÒÚå$]`+{r,çÜ@ÉÚX(iúvMâÊm´²ë
+Gõ6æ*"&NôZ~îO0±yÚ¿ü @c{ BÐ&ù*pHI¤n êçnürÉÄRÒÔ_ûx%»¥¥ïëMàÒmºÜ>Ø+Fg|é¬ë¿rý#yºÑ:sü9Tj¾ªyJvË,zZ*"³K©.EHÒ @J[åñî#sÞÌ«§¶Gäko5æ¦ÌùÍ?§åíþðW<m.ì5ð\¶É#&áÝÇî6æeL2æ¦LwÖÎ=W9FÕ»Tä:sSf`Á ûì áƼ´©ÆÜÔ7 H&v«17utxè¸ÌZ|ÿLcnòRrVýØ+Ǿ ØU?ï)Óö£e!O6 RUiÌKjÌKl.¼ë>eÌÇ°èhaÌM%°w¯®KåºR
+¹J
+êIIÓ²qº÷B¿C1/cD{ßOÅÿÓ×gÍôWýJ×ëqÍkYqTO~Ö;àúPçhÎ¥Út¹}0æ$¾§[ü£zò$[èOr#ð_ÛCrr=+
(Â'¼~áR£¼³w¯¼VvùÇYÍ ¹yÿt;72®ú÷{aÞØÍN¨¢ç/ IÓvc0fÕò°ËB®wÕ¿å1~=åãzjYO
+êAÉÛ*"³K-E÷ôhæ\£oI¼ÈUÝJÐaÇu);;*Ç¥r®}íD®> #kZ®ZÉ»ËìϽ RºCÛrõ Ë©=o~7$V}«£ïûÛ²=Ñ^äªÃÑïn±?;@äRåíëT±zÌËõ®ÚY# ÆgÅ
+Ù+_Ncm æT¨7ß÷ZV¥ñ®Ã÷ BbêÿàÏk[¯¶W
+DVMJSvh[®ÙôÏ\
AnN®+¥YèsµWZ£îmo.=#Õ?jü74 R'ÈBlø§Û¹
>ó"Ç
+éy³uo;]Rý°U´¼ã¿²
«~ÁDEÔ¯%ºÁk5Ó8S\Eªà- ØÊL-UlY¬Àu×$þ8]äêÚ¹êçG
+lIà-¹O°l{Ùw¯:nÉ;ºÔ?gܾs·Ü^1&Cðì©MZ?KÙâÏýíXîéË9w÷WÇ/Ù`+{âÔ5jÖ½íµmú?¯#ÕS_¢U½~\EWë@EÁLzÍ?WFMûL´v%kãêÉ5däO\æ6~qNoGgíì{H&î!#ª"âæi-Hë
ëê -ÈD(räáã+y÷±FË©{Lß@t·tT ÿÝéþR¸µñTH.çØ @P¡RòöFÕk³×º~ ïÎ=ä¨;éÁ¢;ÖÝ°0÷ät ÖLwæ¦sÞ}ô)}zÞÔ "W}lQ¢~] ÑÝðI]1ªè÷N ¸êæ6÷rVMNG&7ðÆÊQ9®§£zbG ,ØìÅúhØánX0ÖÓ²/£é¿Vd]±àr ÿ%®«'´ 7?4ÝÕd®²
Tÿ¨i6iÝÛô¼YÚ¤uo~NJ«ÂEX°´û«"@¶Ê§ª!
+¦Ö³sîmG21Ç]õï÷ ýú´ý37(iæÁs §Eh#¸m¾ß³ BÐοÒóféR·GL.C´Îݸ(sîcÑh£<|l>l©~¯X,:Þ7XòÇ,©îá¥
³2¯ H4÷
+E¯Ê#&ÏöZ}9ãäæÀRÔ§ßãðz"øä_
µñ :ì17-[³`_¡2ѯl!Q÷ýÄRÔw`AFP¡¹ºÔÝßøÏ¿¼Ã^ñâDS^úíÔE¤ÁMP R @¤¾ VoÔ"DÙ¹i爐\³àcÞ/sVOl:ÑöDi#*Ä®l1÷¤¹ [17i. Ñû"ÔùÄÛ¬%üSPDNûÖYýúcÆÜä! k*ÕøÄU÷öX $THzRÌÒòßzÎ @<üù¬Íæü.sIL
+ùÃg«¦J õ5i°ÙËë-°%w ^FÕóí¢¹(¬%wA¤Ú)²ÕaÚ¤uí£3¶<R÷ùÀsi+}¬ÁÄVaÁ¦Ð$|¿ÛZòpMÂ÷»ýçûãRyO^*öãÍ$Àù3; b<ʨ9¿ó÷FsÎÝÔq_¼¶=¿q¸®¼\]®G/Çkñàî"W8¹zü½G®"è¨õÍÀß¼©©#èðjÞu¤¯!£àucnÒ\RÚjÈÕ$\õ]!«
+ôõò; L2ù¼kß`CFÑøÆø
Ríï|ZöÒqkÉCÓHIêFF}w<ìÅ«57׳c WZÙ½@䪪¯µAn&¯6yÓbÔ îÆOîBÝ'ò
+ÉX°v`í[sjmË5¶6çßÞë|µlE_Djòî#-°`oÍÚÖ«ÔykÓÊ.«(y{ ·) NfFpBrSü!rÕA¤Ý¹´\´îíÓD³N 8ç^xztó< "d"l "¤ê¸Åï&µ4dôênø(ÂY÷öGõ$+B$"{É©Xþë'´ A¹DhEçeÂ>Ù>¹+LÒsgLÜ&cnÒ\_"Ò @I³
+
+ô "Ü ´²ç7¶Ò¯b¬9
6iíLKÑ=³ÉjNª{¤Rd«·{«ÿǹíÖ¥lýùÚööÆ!8¡ $ÈE¨£IXö' üé1¯ÐI´- ºí?pÎ}k(y;17é3 mòu¼ëÐfRÂúsÖ©ã#^ËJ-£éoEÁº´ã9ûv¥D;Ð
+ _r þF6ȹNhA rHuC̯ýB½¶Ïÿ^ { q©üYË'$H W}ÚE×Úÿ"Á -H AÜ'´ A rSÐ $ÈMApB$H 7Á -H AÜ'´ A rSÐ $ÈMApB$H 7Á -H AÜ¥¯ü³`è1}NÿÕn.D¾ n°"DÞ®µA®&MS=" Ѳ[b¥^èkOnɵLðBp%àf
Ã_vÂÌVÜ~írõ¸¯à-© ø{]LîOô IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/documentation/pictures/mpm_stack.png
===================================================================
--- trunk/openchange/mapiproxy/documentation/pictures/mpm_stack.png (rev 0)
+++ trunk/openchange/mapiproxy/documentation/pictures/mpm_stack.png 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,109 @@
+PNG
+
+
+IHDR ~ Ì íM®7 sBIT|d pHYs
+×
+×B(x tEXtSoftware www.inkscape.orgî< IDATxìÝwxSeûðû9Ù³itïIKK¡-Z6²NÔWý9DEEÅ-(¯ÈÞ{hY-´´¥{ï¶Ùy~@ú(PÜëâjç9çܵýöûJ) d
+vN]+¼´µþæ±µøøÊ;W|mgíÍcë>ðó:×ÜnLâèW;êý5·Í÷÷;xÕu¨ú±¼D×1o«º±õwòê±o¬luLè ûN\ŽmXÐÙÍé'ÌM(¿yl㧡nK`ðÞÙ²Ç6}ÖÕ
0ÓíÆ:ñý¥·-ìæ$Ü<¶ùóîN&£ýÄüä¢{û*ÚÑ iäLþ(å±m_Ç*ÕMUü)§ÜÓØ7½êÆJAkcÛ¿íçШ*O]wóØïÉjò%·«ÊNý43÷æ±KثʳdS?Ëʹyl×ÒQ²ÚÒùôÏr²ïelÿòÇ¥ÊéåfÝ<và·Éò¼xDZseå^´cVNærú̺E@/S˱#«_gtî1þû<ÿÇ
+-ÇEX¼ÇåNc#?Ìî5ã±3f
+²·¹
+SÐeÀºc [æñ3ίséõBa·hÛ:vq×g¼+§W¸DN-÷
¦åØ¥#K¸wî¦×ÖPJnþܲv¬?þØÒ5 ô@ì7É|£¦¾Äg2QAËl6ñëúعÝ2ÆâX~]'Þ~¬ÛäÖǸÆ;|<É<oãò$,Ï°1D$÷æÞÛí:ä>·ñ2{ç¡Dìàwoc";¶[Ðp"Qøß2ÆÉÙ.ATØÊí4à¶cÎ}Ô±Óc%ÛÙ¯/HnH9N>½ÀΩ3ç^ÆR7£O$ÈÃnÉ\9JÏ(¹ÜÛØÞãàÖ
È\Ão]ÎÞëàÚì[˽9rÐÛÙ9w¹[·[Æìü¹Ç »G°oûp¥J?»GÞÓDÀÈÜg÷[Ǿ<Ì8ôcQÊ´yLªäí\[È6%¬ÆdN~<¡Äx
e{ã"';ÞqÌ»ë6ÃðoøÌøB±øuÌb8ÂÇýy¡ã×}:ÃpDm³sàóøvO÷igwÃTîÃ7µÚÜøº?þØt÷,Y{üµxnq£«¥k@u|&06-½e?B¶±t!B¨}`ðC!²üU p+.°-]B!ÔaðCÖBzâ'©¥@u|zM
+!Xº,÷ kQþØ\üC!tGªÊ<æÀq lçlþ¢DVRj:-]B¨cãí©GçáU ½ëd¬?B6ËÒÈÑ4RJõ®!KÀàB!d#0ø!BÙ~È*`;Bèî0ø!kí\B¡»Àà¬EyX¿Yõ.!Ô±©*ó_v÷$-]BÁYJ©^æj°t¡
+Û¹ [Á!ÍÀv.ÈÖaðC!²üB!l?d!Ú¢dlçBÝ?d-/ûÛ¹ BwÁYà>ÿí\Bwí\ÃଥT§ðÀv.¡;âí©{ð jÀv.ÈFaðC!d3¸|)ûe¶sA¶
+B!À« º®ºø2'åè®!t+Ô©)jÔ§¥®¡G?d!ìñï^dI÷»¢ÔýRUÑàÆYBèß1èxe%Ç2`ünéZzÔaðCÖÂ)éàWv}¦¨þ7+áóì£Ç¬¼ü Bý{Y{Oúeé:²x²z¾ ²t¡MUÇlÿº'¶sA6²
+RÒ·'^¥º#À:úöª ¥kAÈ0ø!²\¾ö¸XE)Åàl?B!Á!BÈF`ðCV®/ÏÀ«þB¡;Àà¬
SÒÁ¯ì,]B!ÔaðCÖÛ¹ îJUÇìø&ÆÛ¹ [
ÁYlçjß*<"ê Û¹
Á!dutZ«¨ðÌÒu +Ñ^SÖc;d«0ø!¬NzÚV·¿×yËÒu PGÁ!du¼|xì®!:¶¥@èA °&ÌOa$ö^&K×nïïucFwqîâù_{jµuâа'Ou³{ÇKýªª®ºw
+p¶gÌi åÜCûßî]UæI)e\\"®ñcÃp( À?'
+
+|鯦Ær/Iûò @}]¾ 3cwp×nÏç l\?ndç°©WwW«+e~þÃ/ôíÿñ% «;®$¯u÷ÍMI^×ÓÉ)<{èO;òQxNöp þÃ{÷Ù W3ÿl224lú
Î i0hÙ]»=åðÁ¹M´y#0 TW]îÛóÆ° OlÜÆåIøÈBè¸ÇYçÄ=â9]\AþÉ>ö¿5M*u¯J=Ë÷Ê«NW««Ånn=®:ùÅÓçÏþì P[-Ôëy¡aÓOyûHÊÊÜÛ{˦©ÃÌëÊÏ?Ñëàþ·ãñ$jG§°¬Ä+Ø»ûµ^ 5ÕY¼1ÿÛîØûÞ|N(TÔ;8tÊ?¿dúáïF T§8ddìz6aÉHW·è«n½
+÷ïÕã\ÂÒ©ry at QüéÅOÜÿVw6G`ÛûØ;ëªxq¥ÏÅó¿M
+åè¦*/¿r*î«PóvãN|ÞC¥*vÂÐê(p²Uþ=ÅïçG·ï ø£ øq±W¤Ñ¨çLº} @EE²GVÖÞÈî¯d¹¹÷¬0iÓ ¢Â32½^ÍIOÛ2 ö×åäüø¿ LVFúöÃF,=ÝÚv]Ý£/·ú0 À?'qÓ®l`ÞCh4h
ÿsµ³Kd Àásövpô㿠زi
+;5åïÁ
+ùöìcC¿;[\|6ðïucTÕzED½´ÁÇ÷±J ?¿¡'Ò®lîmÞ}(¶kÄÛÊîª&9¼bb 6XºÚîñCVRªqñëí\¾¾C²ÍBJGÇ°,ósÔ£²¡¾Ø À W3ÿ]Ñó{¾·mËÓ3²3÷öÒinØ«ëêÖ£yY?ÿajuµÓí¶ëáÙ»y®·ÏÀæòùöåæÐG©hÔ5¾~C2×0<]£©U¸~SuUFgعhÀ /._ïÓïÃúú|ßü¼cÎ/÷5µüØ>ï&ßÛ'&lçl?P»bXìæó0 J¶|n~|ìÈ:JòúìüÏÿïõ«;?qÞ°®úº|{óãT6×t»íÖVgËÍ«ª®:°XÿËbqC !e³yMUéÍó+ÊS-çïÝõByi]]_ênæ×¥v'çnçÏú.ærÒ±½O³X<<ï´Áv.ÈÖaðCuHªb-P ÔÕæ
+®¦m¹yNAÁÉnµ5ÙÆÆrnÆÕÑr +·[_^îúúB~}}!?'ë@BrÛ¹àÌÝÑõõ
üêLafÆ®
+eð øÓ
+òOÆNxbãòΡS·Ø;{FCC)×¼ldÔË'
+âbÊË»öyëÔ¿ûBèÁÂs¢BRLì»ñ6ÿaÛ|£QÇ÷ôêW__èÝrLæÿß=ߧÔÈâò¤5'mZ~»õIí<W.|ßdÒsB²a#î¾ÝÜá#Þ¶yã3~ý)ìS
+bkþQË·^Æøâé1o¯qqªsq+->¸iÃøÉÏ>j
+ @HèÂ#߯ârÅ
+î15ìA¡ @¤¥@í®Rq÷iB3åãLW¾Ôù¾«]>ôCEÊá7§NßsöAÖþò±"°ÑÜÆÅìûï\>îÛÿã?»>[QqEììÜþvëXôµâóa#þ4¶¸²*ís[ª®º*${¹ÿm!ßÌ W3ËøÍïÞcæÆÞso»Wµ]Væǧ¾4}äôf4±iõliíX×£" ÜdsØ®g&
úVZºÔ>&JþHÌho,]ËærzËÆÂGïÑ]déСtì|Ç+/Y,©AÍ´y. Ü!°Í àÌ©oS¯læäúPG'ò°Ñ¾³±t!¨ÝÔ^-³
vã«Ñ!.µFõGb³¥ëxªz>ÏI9¶¤6õÄ/»¯øYÀbq2Ø<ñY¾XèàÜcü·Ù<¡O´·~þÃ::µéPª_ÀðCrEPßýR««Î.={͹ø°·
ٿr¢;¬§6ZºKâx¼þ«NcxØgÒFì¾,wñ"«@)Õ<·¸Qç40ñìö÷¥ÿi£Ñ 3ª»èjë˯ì¹Ãæ
+ÏóDì#ÏO»
cGÐ豫¶uîØqk=ÄRµlí:&OLå.U5EÉøÿ=²IüÕé>æógßØ!ÇÖ<ûÁ ¦Ô$1ú º.H§©ÛPk*¼²W@V9Ãâf³ØÜ|©Äݾ¡¡+;c«:MSµËsk ]É°¸Õ,6·ÅTqyJÈ¡J¢ð©rï4¤Ò#täÏs2;í׺̳ëñÿqd0ø!«¢mªfÒOW%)ì]C©)I1tê~ sÃDJEôzO8j2ºMjWAÓ åÔ¥ªª0ø!ÔÁp¸¢Z;çN+õA§v04
+¶Ñ_]_ª e©òÌcôÓ« 0aU1»aØSÅ°ùl® ÃTQj*"s² Rª¶ð[ûW!a B)ÅÓXP`ðC! N àØÊ×æÇ0.d0õaUUIèh«ç.B( ÃåIv*½£W;ûõ)¨H9üæÝ.&@µ?§9ûÈá»Í+HÞ%,LÛ¯PUåʵ
+
+V¥0êÕFÆI¯nª-Rz{ p %!D å PqÓ×Ö^«èY FÙ
+ ¿Y[ÇôàaðCA±Ö\k_¹ð¿Äå Pvýk ¿þ¼2tÀLì5£Jâàc 8¿ë#§äÃÁ
+ßçDL,'M,÷^3éÇÝN¾±Zkí\úG=T¡#<BGæ@þíæ´lçBµ5ʾz@ÔM¯)!MÐö XI)5<·ÙRHy ¶Àd ø 6RJUsÛèÑÁ=6Ü´î_ CùkÒͯSJëÚ°}·¦ú{sè+JÝ/H9ºäïëç÷QBH# ÑñDút°¶ÇøoàÛGÈæZÆnGG)z ¸kwB ´ æ¦×äz¸ÍÞC¸50VÝÏ![JévBÈ{ ð tkÁo!d ü Ç(¥ôNë@¶º-BZ9¤z¯R ¨ÖÃ\êͯQJµ¸Ü*¿Èi ^M¬~òWQï@´l®ð½kçUC_ÙÇæðBÿN«b>4/zØ¥§-]˽R×2WMv#sî¹ËõðTsý_úÝæB CëA1 úÝô!¤ÚkÌRúåõóý ñõ&À0 PBÀJJiÞ½¼gd}0øÙ ½ÉÄ'»9
+¹ »éõjK\lnç °éÓ·MF½³Xî5¯ëw·øG?ÕæÃMMdú1íz7½®ATV4ÐÝ#vG{n¡ûUW磪+èRWß.ç»Lz¶Á {
+±Y<186V&=ôv.×&V^ÿwW ( õ ÿû#ÜüR--@ ðàÚ¹ $×ÿÍ· !áÚÁd¬±¥+º~6H7( `>Üæâá¦sè(¥ÜEYçÖI}zîøܺ¯ïuYßÈ)µ ðíC(ëʲO¹u½û,nïm#t?
+÷Ç-14ö·
RgM{lS qz !+ѾÓWÔæû»£]¤R#\ûù[Öù\æ £n3{ýkw ø LªÊ+©ËOþ6gÐ]÷^"ëÁÏIyÜ¢úÆ®ãaðªòz?ËdnÆ°AoV=è¶P &Kl¡ûqa÷0 òìSÁ£ß;hézl¥T Å PL ï®íékÉ MpmO ² -ä,عMw¿)ܪ¬J,PÜüz·K#,涧ÐT_.ìNñ àÉEÇÞò0·{Ú©ùgGcQN}üJzùÚü}ÿû
+~/n;ѯXÕtÃ7DX¹blcwZî£Ââ+ *ãsU>2IÅáWvm¾æØ¿ö?n0Q!Æ(WEÖ+Ñ!iJ!ß&;°È+µw5¾ré#Ý
+!ôèHØú¥&; Uuî0 Ààga9 ð5\;¼«kÏñáÚE+I p ÎÀJi©y9û`·]úú·éÎäï÷¯HÈÄn¸0.tæÏYw~ÙëϤ,=6Säjj28º:µa1zïñ]7Ç.×m'~¾wª®VíȵT\úî Çiì6ø¯^ÍiËòÖäøsk¨rªÜGµæ~×q_ÁïHNq?.¥ñ±dÝËrGsKºdU×D¸(âË4%Õ]%¤¾2<À}óÚö·i9%wqxµë.gXt*yö§Îéåádsüßθçb<Î.Óû¥k±4B3ma!á
+dxñBQAÊî P¢×¨[º[v½Â ð À 8výëEJiõÜÈÃ>u|â{?Ün\¯Ò°
+÷¥:B¨×ã]JÍ{Y<¶jbê_ç{{·¥ÇÞ`¹Úß;g~½>£\X'wX.t±»áP¼²ÏñÁ[þ³ `[ô×/§ývrh§c ÐV7rZ8JôyÛ/;+"=jÄòNA0é¤è@R[ÓÄõVÂðo¹?±®VÍÖ7hY"w¶`w£ÐÍNíî® (9!׫´á!å7ïá,:¦àÉ
:E¤g}}F¹Pâ«PCò«ù|±-âo^ËϬ`w³¼[,عñæzò¶_rø8¨ûø×u,mmD§ÒHëÒËmx;Üó©÷}¨·CâíÂR²ðØÅÐÔZW{¯ñÕèÄÎö
+ "Aá©·ç~u2)ø³có¾»ÿVl4 ôÊ:áÒø®õZ½`X{úÔ0¿þÂê{òµ3 ü¿ßðáW'.õÛ:mð6 ¥ñ)þÁJûäòjóÅùº]}ºkÀ
+ýƧøÇVøpXá©pÿK|\oùgù¹4_7°±¼Q-8SðVlØpgÕäl·=ARWýVlØEO;qó¾3=ßiSJN¨¯\R>!Ä'gkZ×û}»¦è&òþ¡sEç\ÿYq>Ý[)âkÆvò* ÐÌçÇòkê#\ùsbÂϹȯkà/?]Sïä-Ïê|"¯TÑ ÓËÒ+k}ÞÙ îìh_þÌMïÓƸÄoy˾ϴôBèFMõ¥cÌw¡@
Çÿáß÷ÉUwm
P X o[úìsìèúóñ»-àÔ_øtwííBbÔÂ1+ÎçïÉùûü8sðÛ?æçq%G2Æqí
Eº:µ³ßÔ¨U½ÚêN
+i2»ähÆóó/þ5´æJI¨¾^#',bÔÕª]}'G®êóÛôc Wÿ{ÚëìûÛß0é|½°äì¼¢©ùçݼÞÓ³6õ-Ë1\ÞÄó²ÛwrdÊþzÝ Ò:£eØ,mÿ5Ï|ëÒ/ Z[ÝÈÙÙoñ5!,!·Vꧼ\TØÄÁ3Ñ^u;û?/ð#>y þ-1e'3{N¼òá× §^Ûù×Ùç¸RA©®Níªô<8âàë öúy|åùüÞ\;A¹¾AkïÔËç¸ûвS9¨ÁÈÝ3|Ù\LP9î¼ïõ¿Õ?ǯQo`Eþ¼åí*µÖ£³Ã"UóW'øïßêá¹½ÃS×&e]ÜóVl´¸ü2ûñë,qØ5"AÑÖ´Ü'ãòË~[:2æTkË³Æ ÒéÍ®ÃO ©ãµF£ÀD)ÛY,Ìß7=¾°|ŲQ±q }Wí|æriu0'ùIÑ~q"Éqë×ûë¹Ôáu½Æ`:Ø].mPó?Ûp¨ÏÑÜ!JY|eÆqSJöÄ#Ϥ°kúêdRðÇÞòµ$Æwÿ#1«6%ï÷íúvVÇþ)áÊìwû?+ðô×Ö6ÌÝNT4¶×U7fÅö üåÒÔoâ.
+ßQpöÀ3#ÖU4i8¿lý.ÐÁî¼RȯÚUØËW.©)kP´£¨¢IãXReþËÈ_µo·»OCݯê¢$Q¯íÞâ%¦,;n ´¡^GñoÚ¹t4ÒÄöÜ^Sqÿ/^7?çÉEU#¾ñWy|ìʲc¯ùNø=ö§)' ¡M%uÜ;KåQq&g( @êÏÇýJfýeê{þÓ»û`G·ÎôyÅu@` ®N-ÉÙtѵìT¶{ÉÑ!òp·3-××XPÚëû'>z!&÷úòo¿Ü碬sãÙ÷·¿!sKxlÓ8¾ñNµ5ÔG|<òÓ.o= °)ø¹oyÆð}¯L»ýðTü§<~îÝNÏÜØ_W«V<6{}KÃÞá˦RmÓï¡üÉNk^ìõýÄëWQ.Üóí7I_îOò2:«,.kä¨ã³gÏÔT4pøJ±¾è`êUN×Øøw·e;¹ïà·ûjÁdÅk7?tUÛ÷ôð
+ÿ·#®Zë=kòç]©q
+³kT :7J.৾þÄ /ï8ºîrÖÓ_
+qØF miyÝÏû\)¯íT«Ñ:}20rõÍëÌ=e> ÀKÛO¦ý3u٨ظE§.],®¼÷éá¯Çz:ÝõV½ÉÄ+|kÚ\ c¹%ò}
V=Þ÷½} Âmóöþø!Û§
+Ùúë¹´Iý½]¶÷<F/ßúrªIÒ÷ÿʸá,B³& p¾¸r×ÿîZz,·dßáb]÷ÂèU7/·!9»õ^C)UÛ¹ 3çD:J¯_!J)_ÓP9 ~µlem×í\¬
+[Äqîí×|hk/j ÈZw¾a>féäæà 7ª½e](Û¤7½WÂLÿéÝ ¢>}1íת¼-®O Ô\.93{S®NíÌWsmx~KËõñä¢ brÍ˧.?ѽá| "Ò³D_¯qøpø~óáÝ;ÕƵCºLÅm(¨ ³s½|zÖ¦0ËÖÖF T%
ÊB\.wz1öXùmù,³7ëÂóª*/¸UËwp¤üÒ¸¬Náï¹Âó*>µúy÷¡!'»}0,¯?°ï×û~ý}\¶½Û'ü¸ù¹X H¨
+K/¶5ô è&!: üºß(WEyìîÁk2_:[*à^ PÕ¤U4éÒ&o©8ÝÄÌ:)dÉæÇÏG]Z{)óåÓe²Óåþ"Af[B @Âîùñ®«¾,è¾<ü»S ¥QiõöuFJIeÆ{¨¿ûæù==6_ÉñkËv2ªëL²b~Ûþ &J ÝñÜR·£SWOçz-Z·0ÂEÿnðã=Ümî|FåÕ_F)¶|ÍhÐu.JÝ/pòH\dÖÛ¹tt\;AU¯%niÚ¯SØ"^5Ãaµùëw_ÁpXÔШp¤üNÓáyÕzo~îÔÛßà-ÿÙÞ_ÍßûÝÃSÿ;vèÎWþùß|î
+¿×9"^®^#P©Åèå]ÜêÛRO.l¾ø>A4 IDATE[) ¢WiEÔ`b]¯«É¥à Ö à+DÍÛUDxÜ1[P½e~¬«× ÀÔTTÛ|«Pp÷óî^Ù £ãÞü8aîÖþ9/¹ºêÔN/÷ù-êÓÑdï}?!i-0LFJ{YWN*ÀK&Î @¨ÑD?ÑÄP `1¤ùjFDà×ztÎÌ®®Ä¬ØñÅ[Oôÿ︾GÌã¦Û×M a(CÀdÿûnìùܾQXè§
ù»v×kÅÂF¹VÞdjÞ®ÁdjÞa( Ðe>Ô«1æqÄÂéáþG[lîð@×P÷æÔ¹½Ðe_Faakö~óÙ ¨¯^yd ¬NS? nøùNh/ì^ë<¯îµQÝ<
+³7^ð,;-kK«ÊóùÒ¢Ci#{ø ú)
+s
+{ÇkSKEê_Y°óú{Ê5üùÌ?*Ë:âëW ÐTR`ÔècªK/jª½äa®%.ýKáýí¬%G;u}Xʽ¼/Ç>µ,>§NèbWÙwÕGnç;Jk¯À~ ´§[ââw ¸ PTØÙ<&uÍ+=1ºÇ¢ Z»@Cì)×\7c/ ì=2í¿Cs7_õéèD¯6j
+üçß~_¨<}kjî&
+çnmVõÖ¬nÒzþ2º÷2 {qÆåò.FJw±¡?Å_pØu}¼o9ißW.U?Ó-`ÍÊóéϨâ\$B @ze]¨ÒM,Bèªéá".»*ÚMY××Û%c÷Õé²ýÜÚÔIÝl\°Wæò³©BÁÈ6_ 7 £Hµ?«0ì3 âËÃÍsd|®ÁAÈÏ[é÷~ß®)e
+jn~]c¨¿]& @°R_6à?V/þ0RJÌëç°º`@dÒIQ¿leÎ.îôjtH¦½WUÕ¤±»÷B÷#aë;nÔd2ï0ߥ¡UU¹ÃÛºX=MEÛ¾?MhùZ¯'íîüFÿ´ßN^<<iå».òDªÆâ:ù
+Ï_Û3¦7òûuIgà¨ËUõYÝìÏ
+\7c @ÔgcÎäm¿<nsègo9Æø&H,t¦uygp«=Y^ÉM^räÒÙyÛÆ:>çw ÍÒnújËÀS»S]¤é!¯öË põݼäÈKgóÙ9V_*ò¶çÕmyÏ>º®Ëù'qÊ!?:*»{]UåT9êê5¢¡;_ù'lÖÀ}Ç_\»`×ïx;Ïè4ßÁJí}9gã
IÇýC«Ê©rS©<¹vüJ ÈOF%fo¼³{й.}ýóD
+U
þÃ;_°rª½ôõþáN±~ *ÎæuWF{% øMJÎý'qÚqËÇ=åå½~xâLëßÞ}¿Ã9ÅÃ~ø;Úü\ÊãÔyܲ¥#cN)(
+úaãÒ¥,^k4òüäÒõOÜ [ÛÐ9øÇMsµ°V£w¶p?ù
9}=¤Ç®Qk÷Í÷^´þK¹W[«
+)*xÍjõv`_
+>¿þrÖø×w²iÊc; ØÑû,Zÿ¹£HPQ]×ýÅÈN? ¼¹%5w×Ä
+¿ t°Kà°aôÇfúãnï·SíøÕ%¾µ:1#U)äÖ7zwwS&¬8`ÿÌ×Ï?tþÝ°e½5£E¡åòÑnÊSßNþ¿m©¹KÔÞönylùÞûc~Ûæöí_?)ìÎL[£ê|ú?cæÍ?t¾OBQEwo8«^«æÕ5,ÓûO ¡þîçI~©Ë²ÍÝÝW>Þ÷è½þw´òôáò±BAAÊî@ÀL& L¥&1P*Ôk±µséBrÛÛr>~vîâ¸ÿÛЯ6ÔO]it| @åUêã»×¤3pXÖ©Ob·oñÛ¥ù*_)Ö<<s~ÂÜ-Cj.)£½OõþyJó.â¤~vÖD~4r}ÆñÝMz# ûÈÝÇËèjêÔû©»Ísï}íïw¶dÉ -=©tèêpõÍáJy7²Ð{ù´ò.n%¹[ºLæ+ľ"Î xOèZ¢«W/¼úû~%uÊ'ÿtxÊÊæ»Fõú~âi¬¶`wrw©2?àÇ+ϸ CÇ_|ïS¯ÿÝ·.½ÌÔOç9*´-âEîö%%Ç2"X|¶ÆwJäÎ®ï½ à:(¨ª÷òir·$jªÛtÁÍH/ç/ö<5ìò½,ôßW½ÊÕ7ç!ærô-?.9R^ã¬ñ^Iqu;ÓóR*jä8=Ü+[kÞ\¢jâþ|65¸V£òÌh¹wî»SÆuòÊoÙ´ø@V¢ ®A<#"(7äÇMïÄz:Å÷÷qÉ:]Pî9È×5g\°wIËõ¯½é_æ-`³u3"¯[Í´ôwr¶X îçírÃÆ#9Å;Óü4§¢è
È Ücÿ\É
+QÚ©|q"饢·¦½m?]ì°ëj¾ß0¿ôüÚ§mÙJfi|ryËQ?êí¦¬Siõ¬ßΧù§WÖ9*ìÊÿÙ)³åùµ{í¥Low©¨ÁÜæNuV¿U;S+j¾¹ÛÜG !ÄÍ/jÊ#ÙÎåÌæÙé§WmzæÛº®¡ÛY3Wñ·Q¯!©Ë½ªëKG2l^¾NS7(åúFLô¨´u1±iõl©Í+mìòö¨c³JÙ"^ÏÉïNømTCAµûã s±t-«¥s~7·s±t-Ù;|YØ}íñ{®[`ÞÝæ\?äÑòµQAe£<ïzBP÷ÉÀȤÖÆÞlÑßÎìz0¼á¯é]ü§wñ/¼yîÝÆÌ&
úµöú תÖúþµ;p-ÄÝ<>È×µjïµe£Ý·|S\ïMxÃN c¼ÞÓ¯Õ{)Êø\ï 5¡cîØ> !tÌm\aê}#§®+KóR×´
óþzßtêÚ§¶.êÚBæàïÓ\É:Jiï
µ¸§0îRQ¾Dhñ¿ä"ÚM"¼§; ûG)mòê2F{÷¡{uSëß}ú>Ó~Ín96maá<®@ö¦±jÈíïH® Äö^j x¤÷r¡ÿyló;;ÂÞ> gê=ÛQ÷öY]ðÛÿÌðõ·Û[Ø&ú%¼ôxøFD¡£±®8Ø¿û´q±S~Îmm|ÚÂÂyøBAò.akã Oè`ê÷Ìï5RüCÙ¤~U/B!ëÒwú5N¾±wJS>Éý¼,;×^5!îÕíñC!ô`Ý-ôÝë<å`ðC!²üU ¸øë¹¥ë@!:2~ÈZÔxi´t¡MS_Êìþa!¤Ã_ÐÃÁYlçjÂæÈÎYØÎÙ(v±ªI8}Óà»OEÖR MzC
¥ë@!Kà Lý][½z¶ÿP?¼ ¹íØu1¨uBvVuýYÕõ®µ/Ãݧ ²fµi¥[ãßþGjé:PûbSJU.!BíRq÷YÈÚà9~!B6²
+ØÎ!º;~ÈZÔzÀv.¡;ÒÔ2{âí\Âଥ´Ñ»Ûx¼J!tGÍD©lçl?B6ÃÜÎ
R("Á!BÈF`ðC!²üB!l?d!®'Ö¿í\B¡;Àà¬E½kàÀ&KêØ°²uüU 6øELÖXºPÇF8{= ,]BÁ!ÍàI¦A/l¨¢âÈ&aðC!²üB!l?B!ÁYBË©
+ÿgoé:B¡²*GïÄÉÚ½<Èy¡¶ÓÔ2ûp",]BÁYJigÔ®£-v.î;*aë;nw³cQïAqë^h¯²°ÍZº,BíLâàzrù3g{´6¾ý»ØÁÕÅ¿úKF{×µãI¦A/n®Äv.ÈVaðC¨
+z~C
+P*N?µrçÍáoÇ¢ÞªV²9ól ÷H z 0ø!dl®è0¥&ôS+wÖ¦¹ ìXÔg`UQÒr "{.!Âàí=öÂ4Pj²/Ë[ªJ ôý¿ã®!õÁà¬Â£ÖÎ¥sÿ×SJù À¢Ô$¥Ô$»ú ;+°çsõ.!Âà¬Å#ÓÎ À?ú)Ãâ\½þ ×[·=O$ßa©º²vúRfÿÏc±²UüUxÚ¹ñEò D{Ãt
+* !«GB(`;d£0ø!d!
+Ϩ@ÀÐò5ÄÔïé?R,UBÖ'Q{y[¶sA¶
+B2pÆú+È
+ÁÍÅ6.!~Y+:×9B°B¡ Bti ¸ØÆ!ÐÃÁYBó©¯?2í\ÌZ´uÅÎÆ6.!&~ÈZ4Éݹµ¯·uÉ À6.=|ØÎÙ:¶¥@èA Ö?·¸Qlé:î/=¬i¬
+´ö6.ªªvÜW»YºIdçZÝgú,K×nÛ¹ [Á¡VìýiD÷öÚ'*Æj^Û l¯í
+Äʺ~O¯¾z÷NS]1KÎËøØ`¯êöÜn{©ªhǽ íüJ2ò|ÖÛºZUH©Éîa¿Ú9õøCþ\§¹ËêÙÒGîB?Z!ÒfMÙÝ·²}¶æ{Ôuí±¢¶Q-K¿ íü ØÆøÆÌØvßn{Ø¿7ÝùäÙ4Ò^Û«,¸ É
+&ôu¯i¯mõÞ,Æ-A ¡Ö6ªKT²Ì³çÀ
+~Ù:~µ!@ÞØ~eò .yNöíÝgþ{§.ç(Ne\l·¾«1Ç:tÜIÞÙg-]BV/î@¨h¯ÐBȶaðCVâ|fÓ,¥ë@!:2~ÈZ4É\:ë,]êÎ+´×hwýyg2QrætÉDñPø\=ç@ÛðtF&ãt¾¼=jj+ª9øËX%!oéZ²~È*PJë;žØdé:þÂJqIU}~]É-TÔ6pvMÖâééëÞK¼Xt×ßõõöÓÖ-(*ªÃPp-kñ¤ukÕw=G<ç|ìû)ë>lºÚR#(% áÙ$~uoþ´cÂw÷hËÜW¿ßòì/ÛÎ?ì²6|©³iÈ+ÛË)¥jK×%àU½!Û±ýÛÑ#YþAAÊÒ]»Ò¢årAíGÊË-ÿ%¾/ÍgÍîs4"ÒÖ¼ÌÂOEÅÉïÌ°qøðNç^z¥gylË?ÉkVïËb3Æg:Ñr[o¿¹³ï~#F lÝâ~òDß·Fk¶%?=z8+Üh4±ò¿8kvËësxP¬:ïWQ©ÊøM)³»Ù»JÊúnÄÁ+Çr¯¾#ñƾÛï¸['e 5Q²vîÞÜÄ@.é5¹Ë>OvÍi^ßÊsþg6%÷â
+8A/v¿áó\þÂ?C>u. gµynYvµÃ
Câ[«mó'#®ÎïLB£Æ'<öh«¼*¡
+÷ø!ÔFöéÚ/d:MýdíÄ óÿ¶õd{móÊ¢ÿ`õô¿^ôi¹Ìö¸÷'>Z3eäÜ3Þúig?ÑÔ|x)·´Føôçë=oÕ³_¬=Ñr¹»?ÿó¯5¨µ¬i®Ø Ö²Z«íÈÅ,Çéý5~ÄÜÏ¿±dÛ &¾ÕyÕ+eûö¦ß²%¹OL¬Wrnn÷g7<÷é'&*
+u:#ç?/nzÍ<άý7¬O×)Ä1ÛÍMZþÃ÷'ÿáû¡ Gg9¾÷îB·)<Ü%óËÏO1LÍÅ⺥¦+ZnûlBA×Öê=sûÕ¿×)Ø17"Ò=íßÏÿìQó³xòJÜã7'N9Ý-¸¯÷¥üË¥MøëÙ]âF{uuÉ®-U)~~nÓóüú{ô
]iý»»_Hy
+æxõÄ> 'Ö\ôùgᤢ*@Âõìªå¶2âzfUÛç\,vÏL(èÜZ]K¦m°%eo¤[º[°2gçw'>ðs|ÐÃúB·Â=~µF§g%¤ô/©R¹ôéâs6·´ÚùÃ{_ñr¶ÏpWÊJ=yþqðU/'û/cü+»ê<wùîYn§ºú{gn9<lê'k]6.xj½Áh"?^3S"ä×ï·ïlz¯*w »2 )«Ä£°¢Ö . ¨µ×¶Ý¨ÑíxÆuí>êúÎ/»Þèâu¢G´güö¸¾>^ã±óË¿·ûô/èõ&ÞµSÿP(D:/OûÚÞßûæ¼÷.yþ
è«ál×.¾9w®Ð>*ʽæÐÁÇFÙýùÃã yj½`ÓßICfÎêüÛ¯ñ}<=eWÿükê 'gê«/¼~¯õ&²ooú³ú¬4ïM4MÌ=éý>øð±söÝ?xÌÛýì!a3ƽ?þÏË+Ç>4°´,«úÊ'W,¬+oà
+¤|CúɼÃ^ëµjôÛ×öf~1üwÙUçõy²ëãk.öóu>ÿêê'v °¹
+GV{æ^ë©È«¤Ì4cé¯£Æ 4ÕiD§6\ê7øéöÝ#n²
+çN1/ÈzNü¾öî³ÿ±½;5±Ïe.3¾ëi'â×ÿ<gü> ¤¬âNÛâRcüOüº#¾¿£]ÆÚ¦ý àé$«ùdõYÙ%ÕÛÏð¨kÔ(-~ék±g|elLJä¾ÿê~êùiëé!a¾.çV¼óÄ. Ç"òƾÿûÂÂÊMî÷Î.¥RT¨Pt Ý"Ý* &O Ï àóÙ&Wx±Héå)kllÔÉl>Dëvá|Q òepcylò𬯿<jº×z.^(étFÁª ãV®H RÆ`4±©>{SÜìrC( Gg§J6Õ>4° ÀÉOÞÄb3ºìsE| Oo28±S»4f¾Qniçw¤
+ ¨¯ltÙéy¬ûã!GVÝ{î½z*ß(¿çxzÃPÊ&.OÈQýë7j3~ÈZ4É\:ÛcCcb;g 0¡v"~e¸¿k¶yÌÑ^\QXQç PQÛàîïl< kÎÂ5ôEÌ¢J¥½$ϼ÷NÈç]Òì·Õåµ
+®
u¼èRJ ¥@X1\Î.?JÁÒÎrí8Ëny;J)
HÏb1úÔ+å~ýý* ²²ª<[
+ pÔååÍ-D/ÛSJOkáòXÚ®ùªÝâúVÛxzÉ .øtèïÃ< ·ÙnCn»-?ßv ÙäîvE ùµJ.ÿÚçÉåsÔ5->£¼K%-gsXÚ¦:
+Ïü¼®¼¡ÕÏSîn×èkNZææ\¿ïëßÒª*ãë_T95R¼_/²9x²
+íÙÎ
Ãbn¸¡.aZý
*àqÊjI&çJ
+F×Q&n²ñÕõM~AÖ6¨ç
+yVghþeY|Û^hB§¡w÷_ÞøüìòÏý:ó³´5ïÌß7Ì*ïqÊ0úøÊSvîLíQYÙÈMO¯ÇÅåFwê¤L rO½^x±X¦Ó¿%Ķ\>8Ø)ãlBAgÁD2®VÏ&´zÎDëåeöÓ²SCJJ®µÙ1LäØÑ,åÃíGée¯¶wdûý|¦AËÊ>W$˽Páî àÕÅùJîÅð«bMufcrÏË;8d$Î
+¥&Jr.Ëò/µz¾d§X¯*°dÓê8 Ú&=+õD®¢µù¥F0hÕ,Àv.ÈFaðCè!
+òHNÏ/OÍktæûM'úËÄÒè`ÏêÑ1!M½ô·×Nl_µûl@]ÆɼìîùåµEuüµµj÷ÙÞwØNR\rnï3WòãáN·o
+>û|Øæêê&eÿ>?2vô¦¯¾¹ àýùÎzzɲ&?ñçG=»ÿ8ß`0²¹\VsëéOu»ØÐ D/þì Ìõ÷w¸íU¥ß-½¶¡A+îßç/zõXúNDøâÏþøý|Zî<J¦,²¶4£*hnÄÒO¿°ö#{WiÁôo òùã)¯váÐUÞþi¾ØApÃé}ì_Wë5;xñ§Kú{¦k"¥µmЧ¿±²2¯ÆëÝÈ¥_Îøñ¹]|rzÃ¥ÐvxÍøRgÓÐ×va;d«ðP/BÉü§KHÍ+óyzáºy\Na>;xÃ2
ùºÔM{¬Ûºo×{ùí§«\N·³ýó²#üË=¾õÛÇÃb:{¼Ýv>qø¾QÙ?óùúùvbA¹Þ`ä xS¯}Ó>ïôßûîsßpÑü< PÑóîk-ç½0s¡ùqT{Í©3¯}qµRÌ°²æ_âl6C·nöÏÜÜDBAé(ÖÀ&óxÕGO¼²$ãj¥ØÏß¡¹~ L&зÜn×n®µ¾¼¬¢¼S-v¬Jùð<PÏþ0ê 4·§Õ©8bT§w[ÎYõÖ\óã.Cʾ¹<ó³ä2D!ÔÉÿwïh±\¨ÿèè¿\KEZL ]æñÈÑÁÅ£¿+¹Z)v ¼ñÔ^ÕËòæÎ2?ï<Яâó³¯.ª.¬ãWÕ<ÂëyBÎ
++!.~µL,Ðgþuc[öÚ·-¯7eù1Ã2múäéu °®µõ}ôìàp»ím¾uÙ½æG¾ùÇÛù㽩[`k[ßµ¼ý9ÞÞöw<ô§eo¦tëâê{©íQäêtÛ-nu÷:ÞÜÝN#w·Ãóë² ~Ù J))JÝ/ÐiêYz1hY½eЫ£^Ã2t,£QË2ôɨcLɨg¨ÉÀ2
+,j22YÔddXY`21X×ÿ1 at ióco7K¿óK£nÿóE·#!Æc2?&1eBL°Ã2e$e$ËÄ°ØF°cb¶aqcb±xFÍ5²8|##0±9£ª*WÌÁö!î?d!NÁ}^²ë1î»:K×ò(¨«¯ó=°bÂe` & 0HÇ@À\& bFÒ¼1¹ö:¹¶|ëó®!5}?Lúot:©ZUX ¬kW_{2Ç Ð<F2-c®ÏgQøßó: EvQpo3{³¡G?d-4R¹UIf'Ëõ~¶{n³,;Wtò¥ÚsíMl'Ë=7ãËöØÖåÃ4ªµo´Ç¶¬ ¶sA¶¯êEVRZÜïµFK×êØ°²u¸Ç!dU|t úø±ìî55j
»]îþfϹv+2tïþ³«wêñÚF½ÄÞUß©·WÒ:þ-ënÇÜÎeõl)¶sA6 B^P!~ý-ÓKªT^j^ºzÞcü+-]5HO/÷>²ÓÉîÝÝÊòýå§Ó3:wvújÈõÛ¡{ãànW;bVïÍ
+/*åp×Ñÿîæ\Ösbh¥kCÝ;~Y Í2õñJ
+÷sÝ3wù®w,]5ùkýôæ}ýúûU$$äýñû¹!Cÿ±d]ªsz7ßv0¸weÊìÈsÛ¯tÁàУ ÏñCÈ|]äMÌzfxNE®Å&R]Õ¤trTYºGYE^àÂÎ4×uóöõ¬-UyDëdéB÷÷øÈÊ ®IDAT!«@qé÷ª]ôد°jöÊKÿ7(ë£ã,]Ë£ìøêÁ§7^ÑX«vêÜßw_øÐÀK׺?¸ÇYÐÎÛ¹ foÎÞÑ/!>¿×ÒÇýô(Üf#ðáÀß^ùÙWR²êÕmC,]ÓýÒª*C+&;Bø®!KÀଥ´6´ÿllç `îÛ»z<1øÇe/éÑÃÓêoµÖ^Ü:)|"\RÊ;YºûE©ôêàï?d£ð!dUÞ·'fÏî´áß/»¤o?ß
+K×ó¨;ý÷eOóãŲÌøh¹ô=7/u6
+{})¥ô÷rFÈZá9~YÈûÎûiõ6 ÀÞéöÓëÅç²M®íQ¶kgêð¦&½ÝÏoüÐü¿¿"iï~³d]ª>;üÔºyû¤l.K£Viå.¤çÙnéºB÷B²zß¹¡ã¦°Ë8p.# `htàr7
ÞFê_H¼<g¾¥k°&ß\¹ÐÒ5 ~YÈ¡E/ýdéBÙ<ÇYBòÜö÷¤®!êÈ0ø!k¡çKFKêØ´MUÌ±ß§Ë !<K×%à¡^d(¥µÏ-nZºPÇF
+zh¬+å ËÒµ d üBí¦¼Rk9üÏ®ã!!z½ÛÇtp|©³iÄÌC%«gK±²IüjEÖ¨õÁÚ^®ã¡0iÔóÚý^«N¾±Úas2>hïíZ³ò<çó¡Öù}j¢ÀK×µ!RK×ÐñÜâFWK×êøL`lZ=[Zké:²¼¸!BÈF`ðCVÛ¹ BwÁYO$Çv.¡;Ò6U1ÇV?kí\Â;U Ö<·¸Q`é:B5衱¶ØÎÙ(ÜãBÈfÛ¹PJ±²IüB!l?B!Á!BÈF`ðCV¢8¿ëClçBÝ?d-LlÈdé"B¶sA¶Û¹ «@)~nq#ßÒu :6N
+
+5yÀv.ÈFá?B6C s7u¤Û¹ [
Á!BÈF`ðC!²üB!l?d!w/XºB¨#Ãà¬aáEê¡;Ó©kÉñµ/È!\K×%àoJd(¥UÏ-nľ\¡;2jªìª 8 ³t=µ7ÜãBÈfdî¦sQJ-]BÁ!BÈF`ðC!²üB!l?d°B!twüÕÀv.¡»Ñ©kIÜ_ÿ±Ãv.ÈVáoJd°B¨-ÚR]"JÀv.Èá?B6C s7~3®Û¹ [
Á!BÈF`ðC!²üB!l?d!ûb;Bè0ø!«AKêà°²uØÎYlçjlçlîñC!d3°²uüB!l?B!Á!BÈF`ðCV"OÚÿØÒu B?d-¾¿Bw¤S×Óë_b;d«°²
+ÒÊç7ârÐi5u¤²à T¶sA6÷ ²{/Óè·OPJ,]BÁ!BÈF`ðC!²üB!l?d°B!twüµÀv.¡»ÒiêÉM³%ØÎý;÷ÒDpünnn·s³©Yºþ(&id¡%E%EEB õ""_ôBzå«^TjÚ¤à ( }!á¡|±YSÔTD]yËyêÔmº9·æn¦[/|Ó¼§ØõÒû}Þ~ùÝqpÏ#VpØà8 @<Â!?îïÑ`æÇà8 Bð h¨4ÚÈùÊÞ)8Î,ü D~ "?
Øp×X;¨f35î±nªÙ{ ×÷N䦱¾&Âe3nL³ÂIëÑm Y15¬£ÚÄ`ÂamÜ&Zå_[Ñík«|rHxsXÛä-
+TÖÉfÁÍIë~tsÙc}M²}ïL´÷6
+nî±nÍÔlÞñ^íËkåµÏ/m~zPJ)ä;OFøûÃRÚHe_ßçFh#E.s¬ Æzì ´"ÃK>Þ÷õ2k-àÔ~6R$ÇÎòÇÎJh#EüA-ðJh#E²^&×|kÍcçµeÅi#E.Îüµy¯ °«lÊ)ËûPáÊ
õÁúññ¤Tm(óN¯?ÖjIÕ6.kï)D{Iiá¬üÓÚP{M&¡Lý¥-8ÇÓ×m*È]ûËø½f»$XÝ]xA`«ÎÀp<}ð2â~5[±hÏ.ØtÕ["«!iNñUÄóÝO_á²ÜC×5³®fshÉ'Ë-AÌé¤
ó²=Gn æªR<ïh¹°¦¯JùésùÇn:×·ý=MÀÃ(óßâÍý«
+~x¸éÇì72ÿÄíõÍò¡Zí6«
+NVLiVÃÇѧÚYxa&)EmuI³&UFV3-§$sMÃ3Òe7¨ M;ûÀÅxµûrfX§*Üy%å1môE0æwê¨ÛWZ±o³~¥°¼M^áXOaÙÝpLëy#éiH±noñ¥Z.Þ6bnI´vÕ'ýÌüáËÏC1sßÚ¤®úä/í;~åÅÒmrôÔÒU¿i~ƲPz½!jêôU; F¿f1¥Etå IEND®B`
\ No newline at end of file
Added: trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_module.c
===================================================================
--- trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_module.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_module.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,235 @@
+/*
+ MAPI Proxy
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 <mapiproxy/dcesrv_mapiproxy.h>
+#include "libmapiproxy.h"
+#include <util/debug.h>
+
+/**
+ \file dcesrv_mapiproxy_module.c
+
+ \brief mapiproxy modules management
+ */
+
+static struct mp_module {
+ struct mapiproxy_module *mp_module;
+} *mp_modules = NULL;
+
+int num_mp_modules;
+static struct mapiproxy_module_list *mpm_list = NULL;
+
+
+NTSTATUS mapiproxy_module_push(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx, void *r)
+{
+ struct mapiproxy_module_list *mpm;
+ const struct ndr_interface_table *table;
+ NTSTATUS status;
+
+ table = (const struct ndr_interface_table *)dce_call->context->iface->private;
+
+ for (mpm = mpm_list; mpm; mpm = mpm->next) {
+ if (mpm->module->endpoint &&
+ ((strcmp(mpm->module->endpoint, "any") == 0) ||
+ (table->name && (strcmp(table->name, mpm->module->endpoint) == 0)))) {
+ if (mpm->module->push) {
+ status = mpm->module->push(dce_call, mem_ctx, r);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+NTSTATUS mapiproxy_module_ndr_pull(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx, struct ndr_pull *pull)
+{
+ struct mapiproxy_module_list *mpm;
+ const struct ndr_interface_table *table;
+ NTSTATUS status;
+
+ table = (const struct ndr_interface_table *)dce_call->context->iface->private;
+
+ for (mpm = mpm_list; mpm; mpm = mpm->next) {
+ if (mpm->module->endpoint &&
+ ((strcmp(mpm->module->endpoint, "any") == 0) ||
+ (table->name && (strcmp(table->name, mpm->module->endpoint) == 0)))) {
+ if (mpm->module->ndr_pull) {
+ status = mpm->module->ndr_pull(dce_call, mem_ctx, pull);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+NTSTATUS mapiproxy_module_pull(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx, void *r)
+{
+ struct mapiproxy_module_list *mpm;
+ const struct ndr_interface_table *table;
+ NTSTATUS status;
+
+ table = (const struct ndr_interface_table *)dce_call->context->iface->private;
+
+ for (mpm = mpm_list; mpm; mpm = mpm->next) {
+ if (mpm->module->endpoint &&
+ ((strcmp(mpm->module->endpoint, "any") == 0) ||
+ (table->name && (strcmp(table->name, mpm->module->endpoint) == 0)))) {
+ if (mpm->module->pull) {
+ status = mpm->module->pull(dce_call, mem_ctx, r);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+NTSTATUS mapiproxy_module_dispatch(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx, void *r,
+ struct mapiproxy *mapiproxy)
+{
+ struct mapiproxy_module_list *mpm;
+ const struct ndr_interface_table *table;
+ NTSTATUS status;
+
+ table = (const struct ndr_interface_table *)dce_call->context->iface->private;
+
+ for (mpm = mpm_list; mpm; mpm = mpm->next) {
+ if (mpm->module->endpoint &&
+ ((strcmp(mpm->module->endpoint, "any") == 0) ||
+ (table->name && (strcmp(table->name, mpm->module->endpoint) == 0)))) {
+ if (mpm->module->dispatch) {
+ status = mpm->module->dispatch(dce_call, mem_ctx, r, mapiproxy);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+NTSTATUS mapiproxy_module_unbind(struct server_id server_id, uint32_t context_id)
+{
+ struct mapiproxy_module_list *mpm;
+ NTSTATUS status;
+
+ for (mpm = mpm_list; mpm; mpm = mpm->next) {
+ if (mpm->module->unbind) {
+ status = mpm->module->unbind(server_id, context_id);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+extern NTSTATUS mapiproxy_module_register(const void *_mp_module)
+{
+ const struct mapiproxy_module *mp_module =_mp_module;
+
+ mp_modules = realloc_p(mp_modules, struct mp_module, num_mp_modules + 1);
+ if (!mp_modules) {
+ smb_panic("out of memory in mapiproxy_register");
+ }
+
+ mp_modules[num_mp_modules].mp_module = smb_xmemdup(mp_module, sizeof (*mp_module));
+ mp_modules[num_mp_modules].mp_module->name = smb_xstrdup(mp_module->name);
+
+ num_mp_modules++;
+
+ DEBUG(3, ("MAPIPROXY module '%s' registered\n", mp_module->name));
+
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS mapiproxy_module_load(struct dcesrv_context *dce_ctx)
+{
+ char **modules;
+ struct mapiproxy_module_list *module;
+ int i;
+ NTSTATUS status;
+
+ /* Fetch the module list from smb.conf */
+ modules = str_list_make(dce_ctx, lp_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "modules"), NULL);
+
+ /* Add modules to the list */
+ for (i = 0; modules[i]; i++) {
+ module = talloc_zero(dce_ctx, struct mapiproxy_module_list);
+ module->module = mapiproxy_module_byname(modules[i]);
+ if (module->module) {
+ DLIST_ADD_END(mpm_list, module, struct mapiproxy_module_list *);
+ DEBUG(3, ("MAPIPROXY module '%s' loaded\n", modules[i]));
+ if (module->module->init) {
+ status = module->module->init(dce_ctx);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+ } else {
+ DEBUG(0, ("MAPIPROXY module '%s' not found\n", modules[i]));
+ }
+ }
+
+ for (module = mpm_list; module; module = module->next) {
+ DEBUG(3, ("mapiproxy_module_load '%s' (%s)\n", module->module->name, module->module->description));
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+_PUBLIC_ NTSTATUS mapiproxy_module_init(struct dcesrv_context *dce_ctx)
+{
+ init_module_fn *mpm;
+ NTSTATUS ret;
+
+ mpm = load_samba_modules(NULL, dce_ctx->lp_ctx, "dcerpc_mapiproxy");
+
+ run_init_functions(mpm);
+ talloc_free(mpm);
+
+ ret = mapiproxy_module_load(dce_ctx);
+
+ return ret;
+}
+
+const struct mapiproxy_module *mapiproxy_module_byname(const char *name)
+{
+ int i;
+
+ if (!name) return NULL;
+
+ for (i = 0; i < num_mp_modules; i++) {
+ if (strcmp(mp_modules[i].mp_module->name, name) == 0) {
+ return mp_modules[i].mp_module;
+ }
+ }
+
+ return NULL;
+}
Added: trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_server.c
===================================================================
--- trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_server.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_server.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,362 @@
+/*
+ MAPI Proxy
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 <mapiproxy/dcesrv_mapiproxy.h>
+#include "libmapiproxy.h"
+#include <util/debug.h>
+
+/**
+ \file dcesrv_mapiproxy_server.c
+
+ \brief mapiproxy server modules management
+ */
+
+static struct server_module {
+ struct mapiproxy_module *server_module;
+} *server_modules = NULL;
+
+int num_server_modules;
+static struct mapiproxy_module_list *server_list = NULL;
+
+static TDB_CONTEXT *emsabp_tdb_ctx = NULL;
+static void *openchange_ldb_ctx = NULL;
+
+NTSTATUS mapiproxy_server_dispatch(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx, void *r,
+ struct mapiproxy *mapiproxy)
+{
+ struct mapiproxy_module_list *server;
+ const struct ndr_interface_table *table;
+ NTSTATUS status;
+
+ table = (const struct ndr_interface_table *)dce_call->context->iface->private;
+
+ for (server = server_list; server; server = server->next) {
+ if (server->module->endpoint && table->name &&
+ !strcmp(table->name, server->module->endpoint)) {
+ if (server->module->dispatch) {
+ mapiproxy->norelay = true;
+ status = server->module->dispatch(dce_call, mem_ctx, r, mapiproxy);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+NTSTATUS mapiproxy_server_unbind(struct server_id server_id, uint32_t context_id)
+{
+ struct mapiproxy_module_list *server;
+ NTSTATUS status;
+
+ for (server = server_list; server; server = server->next) {
+ if (server->module->unbind) {
+ status = server->module->unbind(server_id, context_id);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+extern NTSTATUS mapiproxy_server_register(const void *_server_module)
+{
+ const struct mapiproxy_module *server_module = _server_module;
+
+ server_modules = realloc_p(server_modules, struct server_module, num_server_modules + 1);
+ if (!server_modules) {
+ smb_panic("out of memory in mapiproxy_server_register");
+ }
+
+ server_modules[num_server_modules].server_module = smb_xmemdup(server_module, sizeof (*server_module));
+ server_modules[num_server_modules].server_module->name = smb_xstrdup(server_module->name);
+
+ num_server_modules++;
+
+ DEBUG(3, ("MAPIPROXY server '%s' registered\n", server_module->name));
+
+ return NT_STATUS_OK;
+}
+
+
+_PUBLIC_ bool mapiproxy_server_loaded(const char *endpoint)
+{
+ struct mapiproxy_module_list *server;
+
+ if (!endpoint) return false;
+
+ for (server = server_list; server; server = server->next) {
+ if (server->module->endpoint && !strcmp(endpoint, server->module->endpoint)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+static NTSTATUS mapiproxy_server_overwrite(TALLOC_CTX *mem_ctx, const char *name, const char *endpoint)
+{
+ struct mapiproxy_module_list *server;
+ struct mapiproxy_module_list *server_load;
+
+ if (!name) return NT_STATUS_NOT_FOUND;
+ if (!endpoint) return NT_STATUS_NOT_FOUND;
+
+ /* Step 0. Ensure given module matches with endpoint */
+ server_load = talloc_zero(mem_ctx, struct mapiproxy_module_list);
+ server_load->module = mapiproxy_server_byname(name);
+ if (!server_load->module) {
+ DEBUG(0, ("MAPIPROXY ERROR: couldn't load server '%s'\n", name));
+ talloc_free(server_load);
+ return NT_STATUS_NOT_FOUND;
+ } else {
+ if (strcmp(server_load->module->endpoint, endpoint)) {
+ DEBUG(0, ("MAPIPROXY ERROR: %s endpoint expected for %s but %s found!\n",
+ endpoint, server_load->module->name, server_load->module->endpoint));
+ talloc_free(server_load);
+ return NT_STATUS_NOT_FOUND;
+ }
+ }
+
+ /* Step 1. Seek if this module has already been loaded */
+ for (server = server_list; server; server = server->next) {
+ if (!strcmp(server->module->name, name) &&
+ !strcmp(server->module->endpoint, endpoint)) {
+ DEBUG(0, ("MAPIPROXY: server '%s' already loaded - skipped\n", name));
+ talloc_free(server_load);
+ return NT_STATUS_OK;
+ }
+ }
+
+ /* Step 2. Delete any loaded server matching given endpoint */
+ for (server = server_list; server; server = server->next) {
+ if (!strcmp(server->module->endpoint, endpoint)) {
+ DLIST_REMOVE(server_list, server);
+ talloc_free(server);
+ }
+ }
+
+ /* Step 3. Load custom server */
+ DLIST_ADD_END(server_list, server_load, struct mapiproxy_module_list *);
+
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS mapiproxy_server_load(struct dcesrv_context *dce_ctx)
+{
+ NTSTATUS status;
+ struct mapiproxy_module_list *server;
+ bool server_mode;
+ int i;
+ const char *nspi;
+ const char *emsmdb;
+ const char *rfr;
+ const char *server_name[] = { NDR_EXCHANGE_NSP_NAME,
+ NDR_EXCHANGE_EMSMDB_NAME,
+ NDR_EXCHANGE_DS_RFR_NAME, NULL };
+
+ /* Check server mode */
+ server_mode = lp_parm_bool(dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "server", false);
+ DEBUG(0, ("MAPIPROXY server mode %s\n", (server_mode == false) ? "disabled" : "enabled"));
+
+ if (server_mode == true) {
+ DEBUG(0, ("MAPIPROXY proxy mode disabled\n"));
+
+ for (i = 0; server_name[i]; i++) {
+ server = talloc_zero(dce_ctx, struct mapiproxy_module_list);
+ server->module = mapiproxy_server_bystatus(server_name[i], MAPIPROXY_DEFAULT);
+ if (server->module) {
+ DLIST_ADD_END(server_list, server, struct mapiproxy_module_list *);
+ } else {
+ DEBUG(0, ("MAPIPROXY ERROR: couldn't load server '%s'\n", server_name[i]));
+ }
+ }
+ }
+
+ /* Check for override/custom NSPI server */
+ nspi = lp_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "nspi_server");
+ mapiproxy_server_overwrite(dce_ctx, nspi, NDR_EXCHANGE_NSP_NAME);
+
+ /* Check for override/custom EMSMDB server */
+ emsmdb = lp_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "emsmdb_server");
+ mapiproxy_server_overwrite(dce_ctx, emsmdb, NDR_EXCHANGE_EMSMDB_NAME);
+
+ /* Check for override/custom RFR server */
+ rfr = lp_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "rfr_server");
+ mapiproxy_server_overwrite(dce_ctx, rfr, NDR_EXCHANGE_DS_RFR_NAME);
+
+ for (server = server_list; server; server = server->next) {
+ DEBUG(3, ("mapiproxy_server_load '%s' (%s)\n",
+ server->module->name, server->module->description));
+ if (server->module->init) {
+ status = server->module->init(dce_ctx);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Initialize mapiproxy servers modules
+
+ \param dce_ctx pointer to the connection context
+
+ \return NT_STATUS_OK on success otherwise NT error
+ */
+_PUBLIC_ NTSTATUS mapiproxy_server_init(struct dcesrv_context *dce_ctx)
+{
+ init_module_fn *servers;
+ NTSTATUS ret;
+
+ servers = load_samba_modules(NULL, dce_ctx->lp_ctx, "dcerpc_mapiproxy_server");
+
+ run_init_functions(servers);
+ talloc_free(servers);
+
+ ret = mapiproxy_server_load(dce_ctx);
+
+ return ret;
+}
+
+
+const struct mapiproxy_module *mapiproxy_server_bystatus(const char *name, enum mapiproxy_status status)
+{
+ int i;
+
+ if (!name) return NULL;
+
+ for (i = 0; i < num_server_modules; i++) {
+ if ((strcmp(server_modules[i].server_module->name, name) == 0) &&
+ (server_modules[i].server_module->status == status)) {
+ return server_modules[i].server_module;
+ }
+ }
+
+ return NULL;
+}
+
+
+const struct mapiproxy_module *mapiproxy_server_byname(const char *name)
+{
+ int i;
+
+ if (!name) return NULL;
+
+ for (i = 0; i < num_server_modules; i++) {
+ if ((strcmp(server_modules[i].server_module->name, name) == 0)) {
+ return server_modules[i].server_module;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ \details Initialize an EMSABP TDB context available to all
+ instances when Samba is not run in single mode.
+
+ \param lp_ctx pointer to the loadparm context
+
+ \note TDB database can't be opened twice with O_RDWR flags. We
+ ensure here we have a general context initialized, which we'll
+ reopen within forked instances
+
+ return Allocated TDB context on success, otherwise NULL
+ */
+_PUBLIC_ TDB_CONTEXT *mapiproxy_server_emsabp_tdb_init(struct loadparm_context *lp_ctx)
+{
+ char *tdb_path;
+ TALLOC_CTX *mem_ctx;
+
+ if (emsabp_tdb_ctx) return emsabp_tdb_ctx;
+
+ mem_ctx = talloc_named(NULL, 0, "mapiproxy_server_emsabp_tdb_init");
+ if (!mem_ctx) return NULL;
+
+ /* Step 0. Retrieve a TDB context pointer on the emsabp_tdb database */
+ tdb_path = talloc_asprintf(mem_ctx, "%s/%s", lp_private_dir(lp_ctx), EMSABP_TDB_NAME);
+ emsabp_tdb_ctx = tdb_open(tdb_path, 0, 0, O_RDWR|O_CREAT, 0600);
+ talloc_free(tdb_path);
+ if (!emsabp_tdb_ctx) {
+ DEBUG(3, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, strerror(errno)));
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ talloc_free(mem_ctx);
+
+ return emsabp_tdb_ctx;
+}
+
+
+/**
+ \details Initialize an openchange LDB context available to all
+ mapiproxy instances. This LDB context points on the OpenChange
+ dispatcher database used within emsmdb default provider.
+
+ \param lp_ctx pointer to the loadparm context
+
+ \note The memory context is not free'd leading and causes a loss
+ record.
+
+ \return Allocated LDB context on success, otherwise NULL
+ */
+_PUBLIC_ void *mapiproxy_server_openchange_ldb_init(struct loadparm_context *lp_ctx)
+{
+ char *ldb_path;
+ TALLOC_CTX *mem_ctx;
+ struct tevent_context *ev;
+ int ret;
+
+ /* Sanity checks */
+ if (openchange_ldb_ctx) return openchange_ldb_ctx;
+
+ ev = tevent_context_init(talloc_autofree_context());
+ if (!ev) return NULL;
+
+ mem_ctx = talloc_named(NULL, 0, "openchange_ldb_init");
+ if (!mem_ctx) return NULL;
+
+ /* Step 0. Retrieve a LDB context pointer on openchange.ldb database */
+ ldb_path = talloc_asprintf(mem_ctx, "%s/%s", lp_private_dir(lp_ctx), OPENCHANGE_LDB_NAME);
+ openchange_ldb_ctx = ldb_init(mem_ctx, ev);
+ if (!openchange_ldb_ctx) {
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ ret = ldb_connect(openchange_ldb_ctx, ldb_path, 0, NULL);
+ talloc_free(ldb_path);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ return openchange_ldb_ctx;
+}
Added: trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_session.c
===================================================================
--- trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_session.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapiproxy/dcesrv_mapiproxy_session.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,194 @@
+/*
+ MAPI Proxy
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 <mapiproxy/dcesrv_mapiproxy.h>
+#include "libmapiproxy.h"
+
+/**
+ \file dcesrv_mapiproxy_session.c
+
+ \brief session API for mapiproxy modules
+ */
+
+
+/**
+ \details Create and return an allocated pointer to a mpm session
+
+ \param mem_ctx pointer to the memory context
+ \param server_id reference to the session context server identifier
+ structure
+ \param context_id reference to the context identifier
+
+ \return Pointer to an allocated mpm_session structure on success,
+ otherwise NULL
+ */
+struct mpm_session *mpm_session_new(TALLOC_CTX *mem_ctx,
+ struct server_id server_id,
+ uint32_t context_id)
+{
+ struct mpm_session *session = NULL;
+
+ if (!mem_ctx) return NULL;
+
+ session = talloc_zero(mem_ctx, struct mpm_session);
+ if (!session) return NULL;
+
+ session->server_id.id = server_id.id;
+ session->server_id.id2 = server_id.id2;
+ session->server_id.node = server_id.node;
+ session->context_id = context_id;
+ session->destructor = NULL;
+ session->private_data = NULL;
+
+ return session;
+}
+
+
+/**
+ \details Create and return an allocated pointer to a mpm session
+
+ \param mem_ctx pointer to the memory context
+ \param dce_call pointer to the session context
+
+ \return Pointer to an allocated mpm_session structure on success,
+ otherwise NULL
+ */
+struct mpm_session *mpm_session_init(TALLOC_CTX *mem_ctx,
+ struct dcesrv_call_state *dce_call)
+{
+ if (!mem_ctx) return NULL;
+ if (!dce_call) return NULL;
+ if (!dce_call->conn) return NULL;
+ if (!dce_call->context) return NULL;
+
+ return mpm_session_new(mem_ctx, dce_call->conn->server_id,
+ dce_call->context->context_id);
+}
+
+
+/**
+ \details Set the mpm session destructor
+
+ \param session pointer to the mpm session context
+ \param destructor pointer to the destructor function
+
+ \return true on success, otherwise false
+ */
+bool mpm_session_set_destructor(struct mpm_session *session,
+ bool (*destructor)(void *))
+{
+ if (!session) return false;
+ if (!destructor) return false;
+
+ session->destructor = destructor;
+
+ return true;
+}
+
+
+/**
+ \details Set the mpm session pointer on private data
+
+ \param session pointer to the mpm session context
+ \param private_data generic pointer on private data
+
+ \return true on success, otherwise false
+ */
+bool mpm_session_set_private_data(struct mpm_session *session,
+ void *private_data)
+{
+ if (!session) return false;
+
+ session->private_data = private_data;
+
+ return true;
+}
+
+
+/**
+ \details Release a mapiproxy session context
+
+ \param session pointer to the mpm session context
+
+ \return true on success, otherwise false
+ */
+bool mpm_session_release(struct mpm_session *session)
+{
+ bool ret;
+
+ if (!session) return false;
+
+ if (session->destructor) {
+ ret = session->destructor(session->private_data);
+ if (ret == false) return ret;
+ }
+
+ talloc_free(session);
+
+ return true;
+}
+
+
+/**
+ \details Compare the mpm session with the session context one
+
+ \param session pointer to the mapiproxy module session
+ \param sid reference to a server_id structure to compare
+ \param context_id the connection context id to compare
+ */
+bool mpm_session_cmp_sub(struct mpm_session *session,
+ struct server_id sid,
+ uint32_t context_id)
+{
+ if (!session) return false;
+
+ if ((session->server_id.id == sid.id) &&
+ (session->server_id.id2 == sid.id2) &&
+ (session->server_id.node == sid.node) &&
+ (session->context_id == context_id)) {
+ return true;
+ }
+
+
+ return false;
+}
+
+
+/**
+ \details Compare the mpm session with the session context one
+
+ This function is a wrapper on mpm_session_cmp_sub
+
+ \param session pointer to the mapiproxy module session
+ \param dce_call pointer to the session context
+
+ \return true on success, otherwise false
+
+ \sa mpm_session_cmp_sub
+ */
+bool mpm_session_cmp(struct mpm_session *session,
+ struct dcesrv_call_state *dce_call)
+{
+ if (!session || !dce_call) return false;
+
+ return mpm_session_cmp_sub(session, dce_call->conn->server_id,
+ dce_call->context->context_id);
+}
Added: trunk/openchange/mapiproxy/libmapiproxy/entryid.c
===================================================================
--- trunk/openchange/mapiproxy/libmapiproxy/entryid.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapiproxy/entryid.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,133 @@
+/*
+ OpenChange Server implementation
+
+ EMSMDBP: EMSMDB Provider implementation
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file entryid.c
+
+ \brief EntryID convenient routines
+ */
+
+#include <mapiproxy/dcesrv_mapiproxy.h>
+#include "libmapiproxy.h"
+#include <libmapi/libmapi.h>
+#include <libmapi/proto_private.h>
+
+/**
+ \details Build an Address Book EntryID from a legacyExchangeDN
+
+ \param mem_ctx pointer to the memory context
+ \param legacyExchangeDN
+ */
+_PUBLIC_ enum MAPISTATUS entryid_set_AB_EntryID(TALLOC_CTX *mem_ctx,
+ const char *legacyExchangeDN,
+ struct SBinary_short *bin)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!legacyExchangeDN, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!bin, MAPI_E_INVALID_PARAMETER, NULL);
+
+ bin->cb = 28 + strlen(legacyExchangeDN) + 1;
+ bin->lpb = talloc_array(mem_ctx, uint8_t, bin->cb);
+
+ /* Fill EntryID: FIXME we should use PermanentEntryID here */
+ memset(bin->lpb, 0, bin->cb);
+ memcpy(&bin->lpb[4], GUID_NSPI, 16);
+ bin->lpb[20] = 0x1;
+ memcpy(bin->lpb + 28, legacyExchangeDN, strlen(legacyExchangeDN));
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Build a folder EntryID
+
+ \param mem_ctx pointer to the memory context
+ \param MailboxGuid pointer to the Mailbox Guid
+ \param ReplGuid pointer to the Replica Guid
+ \param FolderType the type of folder
+ \param fid the folder identifier
+ \param rbin the Binary_r structure where the function stores results
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_INVALID_PARAMETER
+ */
+_PUBLIC_ enum MAPISTATUS entryid_set_folder_EntryID(TALLOC_CTX *mem_ctx,
+ struct GUID *MailboxGuid,
+ struct GUID *ReplGuid,
+ uint16_t FolderType,
+ uint64_t fid,
+ struct Binary_r **rbin)
+{
+ struct Binary_r *bin;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!MailboxGuid, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ReplGuid, MAPI_E_INVALID_PARAMETER, NULL);
+
+ bin = talloc_zero(mem_ctx, struct Binary_r);
+
+ bin->cb = 46;
+ bin->lpb = talloc_array(mem_ctx, uint8_t, bin->cb);
+
+ /* 4 bytes: EntryID flags set to 0 */
+ memset(bin->lpb, 0, bin->cb);
+
+ /* 16 bytes: MailboxGuid */
+ bin->lpb[4] = (MailboxGuid->time_low & 0xFF);
+ bin->lpb[5] = ((MailboxGuid->time_low >> 8) & 0xFF);
+ bin->lpb[6] = ((MailboxGuid->time_low >> 16) & 0xFF);
+ bin->lpb[7] = ((MailboxGuid->time_low >> 24) & 0xFF);
+ bin->lpb[8] = (MailboxGuid->time_mid & 0xFF);
+ bin->lpb[9] = ((MailboxGuid->time_mid >> 8) & 0xFF);
+ bin->lpb[10] = (MailboxGuid->time_hi_and_version & 0xFF);
+ bin->lpb[11] = ((MailboxGuid->time_hi_and_version >> 8) & 0xFF);
+ memcpy(&bin->lpb[12], MailboxGuid->clock_seq, sizeof (uint8_t) * 2);
+ memcpy(&bin->lpb[14], MailboxGuid->node, sizeof (uint8_t) * 6);
+
+ /* 2 bytes: FolderType */
+ bin->lpb[20] = (FolderType & 0xFF);
+ bin->lpb[21] = ((FolderType >> 8) & 0xFF);
+
+ /* 16 bytes: ReplGuid */
+ bin->lpb[22] = (ReplGuid->time_low & 0xFF);
+ bin->lpb[23] = ((ReplGuid->time_low >> 8) & 0xFF);
+ bin->lpb[24] = ((ReplGuid->time_low >> 16) & 0xFF);
+ bin->lpb[25] = ((ReplGuid->time_low >> 24) & 0xFF);
+ bin->lpb[26] = (ReplGuid->time_mid & 0xFF);
+ bin->lpb[27] = ((ReplGuid->time_mid >> 8) & 0xFF);
+ bin->lpb[28] = (ReplGuid->time_hi_and_version & 0xFF);
+ bin->lpb[29] = ((ReplGuid->time_hi_and_version >> 8) & 0xFF);
+ memcpy(&bin->lpb[30], ReplGuid->clock_seq, sizeof (uint8_t) * 2);
+ memcpy(&bin->lpb[32], ReplGuid->node, sizeof (uint8_t) * 6);
+
+ /* 8 bytes: FolderID, first byte unset */
+ bin->lpb[39] = ((fid >> 8) & 0xFF);
+ bin->lpb[40] = ((fid >> 16) & 0xFF);
+ bin->lpb[41] = ((fid >> 24) & 0xFF);
+ bin->lpb[42] = ((fid >> 32) & 0xFF);
+ bin->lpb[43] = ((fid >> 40) & 0xFF);
+ bin->lpb[44] = ((fid >> 48) & 0xFF);
+ bin->lpb[45] = ((fid >> 56) & 0xFF);
+
+ *rbin = bin;
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/mapiproxy/libmapiproxy/libmapiproxy.h
===================================================================
--- trunk/openchange/mapiproxy/libmapiproxy/libmapiproxy.h (rev 0)
+++ trunk/openchange/mapiproxy/libmapiproxy/libmapiproxy.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,230 @@
+/*
+ MAPI Proxy
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008-2009
+
+ 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 __LIBMAPIPROXY_H__
+#define __LIBMAPIPROXY_H__
+
+#include <signal.h>
+#include <dcerpc_server.h>
+#include <talloc.h>
+#include <tevent.h>
+#include <tdb.h>
+#include <ldb.h>
+#include <ldb_errors.h>
+#include <libmapi/dlinklist.h>
+#include <fcntl.h>
+#include <errno.h>
+
+struct mapiproxy {
+ bool norelay;
+ bool ahead;
+};
+
+
+enum mapiproxy_status {
+ MAPIPROXY_DEFAULT = 0x0,
+ MAPIPROXY_CUSTOM = 0x1
+};
+
+
+struct mapiproxy_module {
+ enum mapiproxy_status status;
+ const char *name;
+ const char *description;
+ const char *endpoint;
+ NTSTATUS (*init)(struct dcesrv_context *);
+ NTSTATUS (*push)(struct dcesrv_call_state *, TALLOC_CTX *, void *);
+ NTSTATUS (*ndr_pull)(struct dcesrv_call_state *, TALLOC_CTX *, struct ndr_pull *);
+ NTSTATUS (*pull)(struct dcesrv_call_state *, TALLOC_CTX *, void *);
+ NTSTATUS (*dispatch)(struct dcesrv_call_state *, TALLOC_CTX *, void *, struct mapiproxy *);
+ NTSTATUS (*unbind)(struct server_id, uint32_t);
+};
+
+
+struct mapiproxy_module_list {
+ const struct mapiproxy_module *module;
+ struct mapiproxy_module_list *prev;
+ struct mapiproxy_module_list *next;
+};
+
+
+struct mpm_session {
+ struct server_id server_id;
+ uint32_t context_id;
+ bool (*destructor)(void *);
+ void *private_data;
+};
+
+
+struct auth_serversupplied_info
+{
+ struct dom_sid *account_sid;
+ struct dom_sid *primary_group_sid;
+
+ size_t n_domain_groups;
+ struct dom_sid **domain_groups;
+
+ DATA_BLOB user_session_key;
+ DATA_BLOB lm_session_key;
+
+ const char *account_name;
+ const char *domain_name;
+
+ const char *full_name;
+ const char *logon_script;
+ const char *profile_path;
+ const char *home_directory;
+ const char *home_drive;
+ const char *logon_server;
+
+ NTTIME last_logon;
+ NTTIME last_logoff;
+ NTTIME acct_expiry;
+ NTTIME last_password_change;
+ NTTIME allow_password_change;
+ NTTIME force_password_change;
+
+ uint16_t logon_count;
+ uint16_t bad_password_count;
+
+ uint32_t acct_flags;
+
+ bool authenticated;
+};
+
+
+struct mapi_handles {
+ uint32_t handle;
+ uint32_t parent_handle;
+ void *private_data;
+ int systemfolder;
+ struct mapi_handles *prev;
+ struct mapi_handles *next;
+};
+
+
+struct mapi_handles_context {
+ TDB_CONTEXT *tdb_ctx;
+ uint32_t last_handle;
+ struct mapi_handles *handles;
+};
+
+
+#define MAPI_HANDLES_RESERVED 0xFFFFFFFF
+#define MAPI_HANDLES_ROOT "root"
+#define MAPI_HANDLES_NULL "null"
+
+
+/**
+ EMSABP server defines
+ */
+#define EMSABP_TDB_NAME "emsabp_tdb.tdb"
+
+/**
+ Represents the NSPI Protocol in Permanent Entry IDs.
+ */
+static const uint8_t GUID_NSPI[] = {
+0xDC, 0xA7, 0x40, 0xC8, 0xC0, 0x42, 0x10, 0x1A, 0xB4, 0xB9,
+0x08, 0x00, 0x2B, 0x2F, 0xE1, 0x82
+};
+
+
+#define OPENCHANGE_LDB_NAME "openchange.ldb"
+
+#define NTLM_AUTH_IS_OK(dce_call) \
+(dce_call->conn->auth_state.session_info->server_info->authenticated == true)
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+__BEGIN_DECLS
+
+/* definitions from dcesrv_mapiproxy_module.c */
+NTSTATUS mapiproxy_module_register(const void *);
+NTSTATUS mapiproxy_module_init(struct dcesrv_context *);
+
+NTSTATUS mapiproxy_module_push(struct dcesrv_call_state *, TALLOC_CTX *, void *);
+NTSTATUS mapiproxy_module_pull(struct dcesrv_call_state *, TALLOC_CTX *, void *);
+NTSTATUS mapiproxy_module_ndr_pull(struct dcesrv_call_state *, TALLOC_CTX *, struct ndr_pull *);
+NTSTATUS mapiproxy_module_dispatch(struct dcesrv_call_state *, TALLOC_CTX *, void *, struct mapiproxy *);
+NTSTATUS mapiproxy_module_unbind(struct server_id, uint32_t);
+
+const struct mapiproxy_module *mapiproxy_module_byname(const char *);
+
+/* definitions from dcesrv_mapiproxy_server.c */
+NTSTATUS mapiproxy_server_register(const void *);
+NTSTATUS mapiproxy_server_init(struct dcesrv_context *);
+NTSTATUS mapiproxy_server_unbind(struct server_id, uint32_t);
+NTSTATUS mapiproxy_server_dispatch(struct dcesrv_call_state *, TALLOC_CTX *, void *, struct mapiproxy *);
+bool mapiproxy_server_loaded(const char *);
+
+const struct mapiproxy_module *mapiproxy_server_bystatus(const char *, enum mapiproxy_status);
+const struct mapiproxy_module *mapiproxy_server_byname(const char *);
+
+TDB_CONTEXT *mapiproxy_server_emsabp_tdb_init(struct loadparm_context *);
+void *mapiproxy_server_openchange_ldb_init(struct loadparm_context *);
+
+/* definitions from dcesrv_mapiproxy_session. c */
+struct mpm_session *mpm_session_new(TALLOC_CTX *, struct server_id, uint32_t);
+struct mpm_session *mpm_session_init(TALLOC_CTX *, struct dcesrv_call_state *);
+bool mpm_session_set_destructor(struct mpm_session *, bool (*destructor)(void *));
+bool mpm_session_set_private_data(struct mpm_session *, void *);
+bool mpm_session_release(struct mpm_session *);
+bool mpm_session_cmp_sub(struct mpm_session *, struct server_id, uint32_t);
+bool mpm_session_cmp(struct mpm_session *, struct dcesrv_call_state *);
+
+/* definitions from openchangedb.c */
+enum MAPISTATUS openchangedb_get_SystemFolderID(void *, char *, uint32_t, uint64_t *);
+enum MAPISTATUS openchangedb_get_MailboxGuid(void *, char *, struct GUID *);
+enum MAPISTATUS openchangedb_get_MailboxReplica(void *, char *, uint16_t *, struct GUID *);
+enum MAPISTATUS openchangedb_get_mapistoreURI(TALLOC_CTX *, void *, uint64_t, char **);
+enum MAPISTATUS openchangedb_get_ReceiveFolder(TALLOC_CTX *, void *, const char *, const char *, uint64_t *, const char **);
+enum MAPISTATUS openchangedb_lookup_folder_property(void *, uint32_t, uint64_t);
+enum MAPISTATUS openchangedb_get_folder_property(TALLOC_CTX *, void *, char *, uint32_t, uint64_t, void **);
+
+/* definitions from auto-generated openchangedb_property.c */
+const char *openchangedb_property_get_attribute(uint32_t);
+
+/* definitions from mapi_handles.c */
+struct mapi_handles_context *mapi_handles_init(TALLOC_CTX *);
+enum MAPISTATUS mapi_handles_release(struct mapi_handles_context *);
+enum MAPISTATUS mapi_handles_search(struct mapi_handles_context *, uint32_t, struct mapi_handles **);
+enum MAPISTATUS mapi_handles_add(struct mapi_handles_context *, uint32_t, struct mapi_handles **);
+enum MAPISTATUS mapi_handles_delete(struct mapi_handles_context *, uint32_t);
+enum MAPISTATUS mapi_handles_get_private_data(struct mapi_handles *, void **);
+enum MAPISTATUS mapi_handles_set_private_data(struct mapi_handles *, void *);
+enum MAPISTATUS mapi_handles_get_systemfolder(struct mapi_handles *, int *);
+enum MAPISTATUS mapi_handles_set_systemfolder(struct mapi_handles *, int);
+
+/* definitions from entryid.c */
+enum MAPISTATUS entryid_set_AB_EntryID(TALLOC_CTX *, const char *, struct SBinary_short *);
+enum MAPISTATUS entryid_set_folder_EntryID(TALLOC_CTX *, struct GUID *, struct GUID *, uint16_t, uint64_t, struct Binary_r **);
+
+__END_DECLS
+
+#endif /* ! __LIBMAPIPROXY_H__ */
Added: trunk/openchange/mapiproxy/libmapiproxy/mapi_handles.c
===================================================================
--- trunk/openchange/mapiproxy/libmapiproxy/mapi_handles.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapiproxy/mapi_handles.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,544 @@
+/*
+ OpenChange Server implementation
+
+ MAPI handles API implementation
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file mapi_handles.c
+
+ \brief API for MAPI handles management
+ */
+
+#include <mapiproxy/dcesrv_mapiproxy.h>
+#include <libmapi/libmapi.h>
+#include <libmapi/proto_private.h>
+#include "libmapiproxy.h"
+
+
+/**
+ \details Initialize MAPI handles context
+
+ \param mem_ctx pointer to the memory context
+
+ \return Allocated MAPI handles context on success, otherwise NULL
+ */
+_PUBLIC_ struct mapi_handles_context *mapi_handles_init(TALLOC_CTX *mem_ctx)
+{
+ struct mapi_handles_context *handles_ctx;
+
+ /* Step 1. Initialize the context */
+ handles_ctx = talloc_zero(mem_ctx, struct mapi_handles_context);
+ if (!handles_ctx) return NULL;
+
+ /* Step 2. Initialize the TDB context */
+ handles_ctx->tdb_ctx = tdb_open(NULL, 0, TDB_INTERNAL, O_RDWR|O_CREAT, 0600);
+
+ /* Step 3. Initialize the handles list */
+ handles_ctx->handles = NULL;
+
+ /* Step 4. Set last_handle to the first valid value */
+ handles_ctx->last_handle = 1;
+
+ return handles_ctx;
+}
+
+
+/**
+ \details Release MAPI handles context
+
+ \param handles_ctx pointer to the MAPI handles context
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS mapi_handles_release(struct mapi_handles_context *handles_ctx)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!handles_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+
+ tdb_close(handles_ctx->tdb_ctx);
+ talloc_free(handles_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Search for a record in the TDB database
+
+ \param handles_ctx pointer to the MAPI handles context
+ \param handle MAPI handle to lookup
+ \param rec pointer to the MAPI handle structure the function
+ returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS mapi_handles_search(struct mapi_handles_context *handles_ctx,
+ uint32_t handle, struct mapi_handles **rec)
+{
+ TALLOC_CTX *mem_ctx;
+ TDB_DATA key;
+ TDB_DATA dbuf;
+ struct mapi_handles *el;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!handles_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!handles_ctx->tdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(handle == MAPI_HANDLES_RESERVED, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!rec, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "mapi_handles_search");
+
+ /* Step 1. Search for the handle within TDB database */
+ key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%x", handle);
+ key.dsize = strlen((const char *)key.dptr);
+
+ dbuf = tdb_fetch(handles_ctx->tdb_ctx, key);
+ talloc_free(key.dptr);
+ OPENCHANGE_RETVAL_IF(!dbuf.dptr, MAPI_E_NOT_FOUND, mem_ctx);
+ OPENCHANGE_RETVAL_IF(!dbuf.dsize, MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Ensure this is not a free'd record */
+ OPENCHANGE_RETVAL_IF(!strncmp((char *)dbuf.dptr, MAPI_HANDLES_NULL, dbuf.dsize),
+ MAPI_E_NOT_FOUND, mem_ctx);
+ free(dbuf.dptr);
+
+ /* Step 2. Return the record within the double chained list */
+ for (el = handles_ctx->handles; el; el = el->next) {
+ if (el->handle == handle) {
+ *rec = el;
+ return MAPI_E_SUCCESS;
+ }
+ }
+
+ return MAPI_E_CORRUPT_STORE;
+}
+
+
+/**
+ \details Set a TDB record data as null meaning it can be reused in
+ the future.
+
+ \param handles_ctx pointer to the MAPI handles context
+ \param handle handle key value to free
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+static enum MAPISTATUS mapi_handles_tdb_free(struct mapi_handles_context *handles_ctx,
+ uint32_t handle)
+{
+ TALLOC_CTX *mem_ctx;
+ TDB_DATA key;
+ TDB_DATA dbuf;
+ int ret;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!handles_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!handles_ctx->tdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(handle == MAPI_HANDLES_RESERVED, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "mapi_handles_tdb_free");
+
+ key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%x", handle);
+ key.dsize = strlen((const char *)key.dptr);
+
+ /* Step 1. Makes sure the record exists */
+ ret = tdb_exists(handles_ctx->tdb_ctx, key);
+ OPENCHANGE_RETVAL_IF(!ret, MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Step 2. Update existing record */
+ dbuf.dptr = (unsigned char *)MAPI_HANDLES_NULL;
+ dbuf.dsize = strlen(MAPI_HANDLES_NULL);
+
+ ret = tdb_store(handles_ctx->tdb_ctx, key, dbuf, TDB_MODIFY);
+ if (ret == -1) {
+ DEBUG(3, ("[%s:%d]: Unable to create 0x%x record: %s\n", __FUNCTION__, __LINE__,
+ handle, tdb_errorstr(handles_ctx->tdb_ctx)));
+
+ talloc_free(mem_ctx);
+ return MAPI_E_CORRUPT_STORE;
+ }
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Update a TDB record
+
+
+ */
+static enum MAPISTATUS mapi_handles_tdb_update(struct mapi_handles_context *handles_ctx,
+ uint32_t handle, uint32_t container_handle)
+{
+ TALLOC_CTX *mem_ctx;
+ TDB_DATA key;
+ TDB_DATA dbuf;
+ int ret;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!handles_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!handles_ctx->tdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!handle, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "mapi_handles_tdb_update");
+
+ key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%x", handle);
+ key.dsize = strlen((const char *)key.dptr);
+
+ /* Step 1. Makes sure the record exists */
+ ret = tdb_exists(handles_ctx->tdb_ctx, key);
+ OPENCHANGE_RETVAL_IF(!ret, MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Step 2. Update record */
+ dbuf.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%x", container_handle);
+ dbuf.dsize = strlen((const char *)dbuf.dptr);
+
+ ret = tdb_store(handles_ctx->tdb_ctx, key, dbuf, TDB_MODIFY);
+ if (ret == -1) {
+ DEBUG(3, ("[%s:%d]: Unable to update 0x%x record: %s\n", __FUNCTION__, __LINE__,
+ handle, tdb_errorstr(handles_ctx->tdb_ctx)));
+
+ talloc_free(mem_ctx);
+ return MAPI_E_CORRUPT_STORE;
+ }
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Traverse TDB database and search for the first record
+ which dbuf value is "null" string.
+
+ \param tdb_ctx pointer to the TDB context
+ \param key the current TDB key
+ \param dbuf the current TDB value
+ \param state pointer on private data
+
+ \return 1 when a free record is found, otherwise 0
+*/
+static int mapi_handles_traverse_null(TDB_CONTEXT *tdb_ctx,
+ TDB_DATA key, TDB_DATA dbuf,
+ void *state)
+{
+ TALLOC_CTX *mem_ctx;
+ uint32_t *handle = (uint32_t *) state;
+ char *handle_str = NULL;
+
+ if (dbuf.dptr && !strncmp((const char *)dbuf.dptr, MAPI_HANDLES_NULL, dbuf.dsize)) {
+ mem_ctx = talloc_named(NULL, 0, "mapi_handles_traverse_null");
+ handle_str = talloc_strndup(mem_ctx, (char *)key.dptr, key.dsize);
+ *handle = strtol((const char *) handle_str, NULL, 16);
+ talloc_free(handle_str);
+ talloc_free(mem_ctx);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/**
+ \details Add a handles to the database and return a pointer on
+ created record
+
+ \param handles_ctx pointer to the MAPI handles context
+ \param container_handle the container handle if available
+ \param rec pointer on pointer to the MAPI handle structure the function
+ returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS mapi_handles_add(struct mapi_handles_context *handles_ctx,
+ uint32_t container_handle, struct mapi_handles **rec)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ TDB_DATA key;
+ TDB_DATA dbuf;
+ uint32_t handle = 0;
+ struct mapi_handles *el;
+ int ret;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!handles_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!handles_ctx->tdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(handle == MAPI_HANDLES_RESERVED, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!rec, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "mapi_handles_add");
+
+ /* Step 1. Seek the TDB database for the first free record */
+ ret = tdb_traverse(handles_ctx->tdb_ctx, mapi_handles_traverse_null, (void *)&handle);
+ if (ret > -1 && handle > 0) {
+ DEBUG(0, ("We have found free record 0x%x\n", handle));
+ retval = mapi_handles_tdb_update(handles_ctx, handle, container_handle);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ el = talloc_zero((TALLOC_CTX *)handles_ctx, struct mapi_handles);
+ if (!el) {
+ mapi_handles_tdb_free(handles_ctx, handle);
+ OPENCHANGE_RETVAL_IF(!el, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+ }
+
+ el->handle = handle;
+ el->parent_handle = container_handle;
+ el->private_data = NULL;
+ *rec = el;
+ DLIST_ADD_END(handles_ctx->handles, el, struct mapi_handles *);
+
+ return MAPI_E_SUCCESS;
+ }
+
+ /* Step 2. If no record is available, create a new one */
+ key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%x", handles_ctx->last_handle);
+ key.dsize = strlen((const char *)key.dptr);
+
+ if (container_handle) {
+ dbuf.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%x", container_handle);
+ dbuf.dsize = strlen((const char *)dbuf.dptr);
+ } else {
+ dbuf.dptr = (unsigned char *) MAPI_HANDLES_ROOT;
+ dbuf.dsize = strlen(MAPI_HANDLES_ROOT);
+ }
+
+ ret = tdb_store(handles_ctx->tdb_ctx, key, dbuf, TDB_INSERT);
+ if (ret == -1) {
+ DEBUG(3, ("[%s:%d]: Unable to create 0x%x record: %s\n", __FUNCTION__, __LINE__,
+ handles_ctx->last_handle, tdb_errorstr(handles_ctx->tdb_ctx)));
+ talloc_free(mem_ctx);
+
+ return MAPI_E_CORRUPT_STORE;
+ }
+
+ el = talloc_zero((TALLOC_CTX *)handles_ctx, struct mapi_handles);
+ if (!el) {
+ mapi_handles_tdb_free(handles_ctx, handles_ctx->last_handle);
+ OPENCHANGE_RETVAL_IF(!el, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
+ }
+
+ el->handle = handles_ctx->last_handle;
+ el->parent_handle = container_handle;
+ el->private_data = NULL;
+ el->systemfolder = -1;
+ *rec = el;
+ DLIST_ADD_END(handles_ctx->handles, el, struct mapi_handles *);
+
+ handles_ctx->last_handle += 1;
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Get the private data associated to a MAPI handle
+
+ \param handle pointer to the MAPI handle structure
+ \param private_data pointer on pointer to the private data the
+ function returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
+ */
+_PUBLIC_ enum MAPISTATUS mapi_handles_get_private_data(struct mapi_handles *handle, void **private_data)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!handle, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!private_data, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!handle->private_data, MAPI_E_NOT_FOUND, NULL);
+
+ *private_data = handle->private_data;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Set the private data associated to a MAPI handle
+
+ \param handle pointer to the MAPI handle structure
+ \param private_data pointer to the private data to associate to the
+ MAPI handle
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS mapi_handles_set_private_data(struct mapi_handles *handle, void *private_data)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!handle, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(handle->private_data, MAPI_E_UNABLE_TO_COMPLETE, NULL);
+
+ handle->private_data = private_data;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Get the system folder identifier associated to a MAPI handle
+
+ \param handle pointer to the MAPI handle structure
+ \param systemFolderIdx pointer to the system folder index to retrieve
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND.
+ */
+_PUBLIC_ enum MAPISTATUS mapi_handles_get_systemfolder(struct mapi_handles *handle, int *systemfolder)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!handle, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!systemfolder, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(handle->systemfolder == -1, MAPI_E_NOT_FOUND, NULL);
+
+ *systemfolder = handle->systemfolder;
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Set the system folder identifier associated to a MAPI handle
+
+ \param handle pointer to the MAPI handle structure
+ \param systemFolderIdx the system folder index to set
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS mapi_handles_set_systemfolder(struct mapi_handles *handle, int systemfolder)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!handle, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(handle->systemfolder != -1, MAPI_E_UNABLE_TO_COMPLETE, NULL);
+
+ handle->systemfolder = systemfolder;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+struct mapi_handles_private {
+ struct mapi_handles_context *handles_ctx;
+ uint32_t container_handle;
+};
+
+/**
+ \details Traverse TDB database and search for records
+ which dbuf value is set to state.
+
+ \param tdb_ctx pointer to the TDB context
+ \param key the current TDB key
+ \param dbuf the current TDB value
+ \param state pointer on private data
+
+ \return 1 when a free record is found, otherwise 0
+*/
+static int mapi_handles_traverse_delete(TDB_CONTEXT *tdb_ctx,
+ TDB_DATA key, TDB_DATA dbuf,
+ void *state)
+{
+ TALLOC_CTX *mem_ctx;
+ struct mapi_handles_private *handles_private = (struct mapi_handles_private *) state;
+ uint32_t handle;
+ char *container_handle_str = NULL;
+ char *handle_str = NULL;
+
+ mem_ctx = talloc_named(NULL, 0, "mapi_handles_traverse_delete");
+ container_handle_str = talloc_asprintf(mem_ctx, "0x%x", handles_private->container_handle);
+
+ if (dbuf.dptr && !strncmp((const char *)dbuf.dptr, container_handle_str, dbuf.dsize)) {
+ handle_str = talloc_strndup(mem_ctx, (char *)key.dptr, key.dsize);
+ handle = strtol((const char *) handle_str, NULL, 16);
+ talloc_free(handle_str);
+ mapi_handles_delete(handles_private->handles_ctx, handle);
+ }
+
+ talloc_free(container_handle_str);
+ talloc_free(mem_ctx);
+
+ return 0;
+}
+
+
+
+/**
+ \details Remove the MAPI handle referenced by the handle parameter
+ from the double chained list and mark its associated TDB record as
+ null
+
+ \param handles_ctx pointer to the MAPI handles context
+ \param handle the handle to delete
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS mapi_handles_delete(struct mapi_handles_context *handles_ctx,
+ uint32_t handle)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ TDB_DATA key;
+ struct mapi_handles *el;
+ struct mapi_handles_private handles_private;
+ int ret;
+ bool found = false;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!handles_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!handles_ctx->tdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(handle == MAPI_HANDLES_RESERVED, MAPI_E_INVALID_PARAMETER, NULL);
+
+ DEBUG(4, ("[%s:%d]: Deleting MAPI handle 0x%x\n", __FUNCTION__, __LINE__, handle));
+
+ mem_ctx = talloc_named(NULL, 0, "mapi_handles_delete");
+
+ key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%x", handle);
+ key.dsize = strlen((const char *)key.dptr);
+
+ /* Step 1. Make sure the record exists */
+ ret = tdb_exists(handles_ctx->tdb_ctx, key);
+ OPENCHANGE_RETVAL_IF(!ret, MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Step 2. Delete this record from the double chained list */
+ for (el = handles_ctx->handles; el; el = el->next) {
+ if (el->handle == handle) {
+ DLIST_REMOVE(handles_ctx->handles, el);
+ talloc_free(el);
+ found = true;
+ }
+ }
+ /* This case should never occur */
+ OPENCHANGE_RETVAL_IF(found == false, MAPI_E_CORRUPT_STORE, mem_ctx);
+
+ /* Step 3. Free this record within the TDB database */
+ retval = mapi_handles_tdb_free(handles_ctx, handle);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ /* Step 4. Delete hierarchy of children */
+ handles_private.handles_ctx = handles_ctx;
+ handles_private.container_handle = handle;
+ ret = tdb_traverse(handles_ctx->tdb_ctx, mapi_handles_traverse_delete, (void *)&handles_private);
+
+ talloc_free(mem_ctx);
+
+ DEBUG(4, ("[%s:%d]: Deleting MAPI handle 0x%x COMPLETE\n", __FUNCTION__, __LINE__, handle));
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/mapiproxy/libmapiproxy/openchangedb.c
===================================================================
--- trunk/openchange/mapiproxy/libmapiproxy/openchangedb.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapiproxy/openchangedb.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,503 @@
+/*
+ OpenChange Server implementation
+
+ EMSMDBP: EMSMDB Provider implementation
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file openchangedb.c
+
+ \brief OpenChange Dispatcher database routines
+ */
+
+#include <mapiproxy/dcesrv_mapiproxy.h>
+#include "libmapiproxy.h"
+#include <libmapi/libmapi.h>
+#include <libmapi/proto_private.h>
+#include <libmapi/defs_private.h>
+
+/**
+ \details Retrieve the mailbox FolderID for given recipient from
+ openchange dispatcher database
+
+ \param ldb_ctx pointer to the OpenChange LDB context
+ \param recipient the mailbox username
+ \param SystemIdx the system folder index
+ \param FolderId pointer to the folder identifier the function returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS openchangedb_get_SystemFolderID(void *ldb_ctx,
+ char *recipient, uint32_t SystemIdx,
+ uint64_t *FolderId)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_result *res = NULL;
+ char *ldb_filter;
+ const char * const attrs[] = { "*", NULL };
+ int ret;
+ const char *dn;
+ struct ldb_dn *ldb_dn = NULL;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!recipient, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!FolderId, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "get_SystemFolderID");
+
+ /* Step 1. Search Mailbox Root DN */
+ ldb_filter = talloc_asprintf(mem_ctx, "CN=%s", recipient);
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
+ LDB_SCOPE_SUBTREE, attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Step 2. If Mailbox root folder, check for FolderID within current record */
+ if (SystemIdx == 0x1) {
+ *FolderId = ldb_msg_find_attr_as_int64(res->msgs[0], "PidTagFolderId", 0);
+ OPENCHANGE_RETVAL_IF(!*FolderId, MAPI_E_CORRUPT_STORE, mem_ctx);
+
+ talloc_free(mem_ctx);
+ return MAPI_E_SUCCESS;
+ }
+
+ dn = ldb_msg_find_attr_as_string(res->msgs[0], "distinguishedName", NULL);
+ OPENCHANGE_RETVAL_IF(!dn, MAPI_E_CORRUPT_STORE, mem_ctx);
+
+ /* Step 3. Search FolderID */
+ ldb_dn = ldb_dn_new(mem_ctx, ldb_ctx, dn);
+ OPENCHANGE_RETVAL_IF(!ldb_dn, MAPI_E_CORRUPT_STORE, mem_ctx);
+ talloc_free(res);
+
+ ldb_filter = talloc_asprintf(mem_ctx, "(&(objectClass=systemfolder)(SystemIdx=%d))", SystemIdx);
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_dn, LDB_SCOPE_SUBTREE, attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
+
+ *FolderId = ldb_msg_find_attr_as_int64(res->msgs[0], "PidTagFolderId", 0);
+ OPENCHANGE_RETVAL_IF(!*FolderId, MAPI_E_CORRUPT_STORE, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve the mailbox GUID for given recipient from
+ openchange dispatcher database
+
+ \param ldb_ctx pointer to the OpenChange LDB context
+ \param recipient the mailbox username
+ \param MailboxGUID pointer to the mailbox GUID the function returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS openchangedb_get_MailboxGuid(void *ldb_ctx,
+ char *recipient,
+ struct GUID *MailboxGUID)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_result *res = NULL;
+ char *ldb_filter;
+ const char *guid;
+ const char * const attrs[] = { "*", NULL };
+ int ret;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!recipient, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!MailboxGUID, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "get_MailboxGuid");
+
+ /* Step 1. Search Mailbox DN */
+ ldb_filter = talloc_asprintf(mem_ctx, "CN=%s", recipient);
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
+ LDB_SCOPE_SUBTREE, attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Step 2. Retrieve MailboxGUID attribute's value */
+ guid = ldb_msg_find_attr_as_string(res->msgs[0], "MailboxGUID", NULL);
+ OPENCHANGE_RETVAL_IF(!guid, MAPI_E_CORRUPT_STORE, mem_ctx);
+
+ GUID_from_string(guid, MailboxGUID);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve the mailbox replica identifier and GUID for given
+ recipient from openchange dispatcher database
+
+ \param ldb_ctx pointer to the OpenChange LDB context
+ \param recipient the mailbox username
+ \param ReplID pointer to the replica identifier the function returns
+ \param ReplGUID pointer to the replica GUID the function returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS openchangedb_get_MailboxReplica(void *ldb_ctx,
+ char *recipient, uint16_t *ReplID,
+ struct GUID *ReplGUID)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_result *res = NULL;
+ char *ldb_filter;
+ const char *guid;
+ const char * const attrs[] = { "*", NULL };
+ int ret;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!recipient, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ReplID, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ReplGUID, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "get_MailboxReplica");
+
+ /* Step 1. Search Mailbox DN */
+ ldb_filter = talloc_asprintf(mem_ctx, "CN=%s", recipient);
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
+ LDB_SCOPE_SUBTREE, attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Step 2. Retrieve ReplicaID attribute's value */
+ *ReplID = ldb_msg_find_attr_as_int(res->msgs[0], "ReplicaID", 0);
+
+ /* Step 3/ Retrieve ReplicaGUID attribute's value */
+ guid = ldb_msg_find_attr_as_string(res->msgs[0], "ReplicaGUID", 0);
+ OPENCHANGE_RETVAL_IF(!guid, MAPI_E_CORRUPT_STORE, mem_ctx);
+
+ GUID_from_string(guid, ReplGUID);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve the mapistore URI associated to a mailbox system
+ folder.
+
+ \param parent_ctx pointer to the memory context
+ \param ldb_ctx pointer to the openchange LDB context
+ \param fid the Folder identifier to search for
+ \param mapistoreURL pointer on pointer to the mapistore URI the
+ function returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
+ */
+_PUBLIC_ enum MAPISTATUS openchangedb_get_mapistoreURI(TALLOC_CTX *parent_ctx,
+ void *ldb_ctx,
+ uint64_t fid,
+ char **mapistoreURL)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_result *res = NULL;
+ char *ldb_filter;
+ const char * const attrs[] = { "*", NULL };
+ int ret;
+
+ mem_ctx = talloc_named(NULL, 0, "get_mapistoreURI");
+
+ ldb_filter = talloc_asprintf(mem_ctx, "(PidTagFolderId=0x%.16"PRIx64")", fid);
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
+ LDB_SCOPE_SUBTREE, attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
+
+ *mapistoreURL = talloc_strdup(parent_ctx, ldb_msg_find_attr_as_string(res->msgs[0], "mapistore_uri", NULL));
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve the Explicit message class and Folder identifier
+ associated to the MessageClass search pattern.
+
+ \param parent_ctx pointer to the memory context
+ \param ldb_ctx pointer to the openchange LDB context
+ \param recipient pointer to the mailbox's username
+ \param MessageClass substring to search for
+ \param fid pointer to the folder identifier the function returns
+ \param ExplicitMessageClass pointer on pointer to the complete
+ message class the function returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
+ */
+_PUBLIC_ enum MAPISTATUS openchangedb_get_ReceiveFolder(TALLOC_CTX *parent_ctx,
+ void *ldb_ctx,
+ const char *recipient,
+ const char *MessageClass,
+ uint64_t *fid,
+ const char **ExplicitMessageClass)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_result *res = NULL;
+ struct ldb_dn *dn;
+ struct ldb_message_element *ldb_element;
+ char *dnstr;
+ char *ldb_filter;
+ const char * const attrs[] = { "*", NULL };
+ int ret;
+ int i;
+ int length;
+
+ mem_ctx = talloc_named(NULL, 0, "get_ReceiveFolder");
+
+ /* Step 1. Search Mailbox DN */
+ ldb_filter = talloc_asprintf(mem_ctx, "CN=%s", recipient);
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
+ LDB_SCOPE_SUBTREE, attrs, ldb_filter);
+ talloc_free(ldb_filter);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
+
+ dnstr = talloc_strdup(mem_ctx, ldb_msg_find_attr_as_string(res->msgs[0], "distinguishedName", NULL));
+ OPENCHANGE_RETVAL_IF(!dnstr, MAPI_E_NOT_FOUND, mem_ctx);
+
+ talloc_free(res);
+
+ /* Step 2. Search for MessageClass substring within user's mailbox */
+ dn = ldb_dn_new(mem_ctx, ldb_ctx, dnstr);
+ talloc_free(dnstr);
+
+ ldb_filter = talloc_asprintf(mem_ctx, "(PidTagMessageClass=%s*)", MessageClass);
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, dn, LDB_SCOPE_SUBTREE, attrs, ldb_filter);
+ talloc_free(ldb_filter);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
+
+ *fid = ldb_msg_find_attr_as_uint64(res->msgs[0], "PidTagFolderId", 0x0);
+
+ /* Step 3. Find the longest ExplicitMessageClass matching MessageClass */
+ ldb_element = ldb_msg_find_element(res->msgs[0], "PidTagMessageClass");
+ for (i = 0, length = 0; i < ldb_element[0].num_values; i++) {
+ if (!strncasecmp(MessageClass, (char *)ldb_element->values[i].data,
+ strlen((char *)ldb_element->values[i].data)) &&
+ strlen((char *)ldb_element->values[i].data) > length) {
+
+ if (*ExplicitMessageClass && strcmp(*ExplicitMessageClass, "")) {
+ talloc_free((char *)*ExplicitMessageClass);
+ }
+
+ if (MessageClass && !strcmp(MessageClass, "All")) {
+ *ExplicitMessageClass = "";
+ } else {
+ *ExplicitMessageClass = talloc_strdup(parent_ctx, (char *)ldb_element->values[i].data);
+ }
+ length = strlen((char *)ldb_element->values[i].data);
+ }
+ }
+ OPENCHANGE_RETVAL_IF(!*ExplicitMessageClass, MAPI_E_NOT_FOUND, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Check if a property exists within an openchange dispatcher
+ database record
+
+ \param ldb_ctx pointer to the openchange LDB context
+ \param proptag the MAPI property tag to lookup
+ \param fid the record folder identifier
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
+ */
+_PUBLIC_ enum MAPISTATUS openchangedb_lookup_folder_property(void *ldb_ctx,
+ uint32_t proptag,
+ uint64_t fid)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_result *res = NULL;
+ char *ldb_filter;
+ const char * const attrs[] = { "*", NULL };
+ const char *PidTagAttr = NULL;
+ int ret;
+
+ mem_ctx = talloc_named(NULL, 0, "get_folder_property");
+
+ /* Step 1. Find PidTagFolderId record */
+ ldb_filter = talloc_asprintf(mem_ctx, "(PidTagFolderId=0x%.16"PRIx64")", fid);
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
+ LDB_SCOPE_SUBTREE, attrs, ldb_filter);
+ talloc_free(ldb_filter);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Step 2. Convert proptag into PidTag attribute */
+ PidTagAttr = openchangedb_property_get_attribute(proptag);
+
+ /* Step 3. Search for attribute */
+ OPENCHANGE_RETVAL_IF(!ldb_msg_find_element(res->msgs[0], PidTagAttr), MAPI_E_NOT_FOUND, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve a special MAPI property from a folder record
+
+ \param mem_ctx pointer to the memory context
+ \param ldb_ctx pointer to the OpenChange LDB context
+ \param recipient the mailbox username
+ \param res pointer to the LDB result
+ \param proptag the MAPI property tag to lookup
+ \param PidTagAttr the mapped MAPI property name
+
+ \return pointer to valid data on success, otherwise NULL
+ */
+static void *openchangedb_get_folder_special_property(TALLOC_CTX *mem_ctx,
+ void *ldb_ctx,
+ char *recipient,
+ struct ldb_result *res,
+ uint32_t proptag,
+ const char *PidTagAttr)
+{
+ enum MAPISTATUS retval;
+ struct GUID MailboxGUID;
+ struct GUID ReplGUID;
+ uint16_t ReplID;
+ struct Binary_r *bin;
+ uint16_t FolderType;
+ uint64_t FolderId;
+ const char *tmp;
+
+ switch (proptag) {
+ case PR_IPM_APPOINTMENT_ENTRYID:
+ case PR_IPM_CONTACT_ENTRYID:
+ case PR_IPM_JOURNAL_ENTRYID:
+ case PR_IPM_NOTE_ENTRYID:
+ case PR_IPM_TASK_ENTRYID:
+ case PR_REMINDERS_ONLINE_ENTRYID:
+ case PR_IPM_DRAFTS_ENTRYID:
+ retval = openchangedb_get_MailboxGuid(ldb_ctx, recipient, &MailboxGUID);
+ retval = openchangedb_get_MailboxReplica(ldb_ctx, recipient, &ReplID, &ReplGUID);
+ FolderType = (uint16_t) ldb_msg_find_attr_as_int(res->msgs[0], "FolderType", 0x1);
+
+ tmp = ldb_msg_find_attr_as_string(res->msgs[0], PidTagAttr, NULL);
+ FolderId = strtoul(tmp, NULL, 16);
+ retval = entryid_set_folder_EntryID(mem_ctx, &MailboxGUID, &ReplGUID, FolderType, FolderId, &bin);
+ return (void *)bin;
+ break;
+ }
+
+ return NULL;
+}
+
+
+/**
+ \details Retrieve a MAPI property value from a folder record
+
+ \param parent_ctx pointer to the memory context
+ \param ldb_ctx pointer to the openchange LDB context
+ \param recipient the mailbox username
+ \param proptag the MAPI property tag to retrieve value for
+ \param fid the record folder identifier
+ \param data pointer on pointer to the data the function returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
+ */
+_PUBLIC_ enum MAPISTATUS openchangedb_get_folder_property(TALLOC_CTX *parent_ctx,
+ void *ldb_ctx,
+ char *recipient,
+ uint32_t proptag,
+ uint64_t fid,
+ void **data)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_result *res = NULL;
+ char *ldb_filter;
+ const char * const attrs[] = { "*", NULL };
+ const char *PidTagAttr = NULL;
+ int ret;
+ const char *str;
+ uint64_t *d;
+ uint32_t l;
+ int *b;
+
+ mem_ctx = talloc_named(NULL, 0, "get_folder_property");
+
+ /* Step 1. Find PidTagFolderId record */
+ ldb_filter = talloc_asprintf(mem_ctx, "(PidTagFolderId=0x%.16"PRIx64")", fid);
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
+ LDB_SCOPE_SUBTREE, attrs, ldb_filter);
+ talloc_free(ldb_filter);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Step 2. Convert proptag into PidTag attribute */
+ PidTagAttr = openchangedb_property_get_attribute(proptag);
+ OPENCHANGE_RETVAL_IF(!PidTagAttr, MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Step 3. Ensure the element exists */
+ OPENCHANGE_RETVAL_IF(!ldb_msg_find_element(res->msgs[0], PidTagAttr), MAPI_E_NOT_FOUND, mem_ctx);
+
+ /* Step 4. Check if this is a "special property" */
+ *data = openchangedb_get_folder_special_property(parent_ctx, ldb_ctx, recipient, res, proptag, PidTagAttr);
+ OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, mem_ctx);
+
+ /* Step 5. If this is not a "special property" */
+ switch (proptag & 0xFFFF) {
+ case PT_BOOLEAN:
+ b = talloc_zero(parent_ctx, int);
+ *b = ldb_msg_find_attr_as_bool(res->msgs[0], PidTagAttr, 0x0);
+ *data = (void *)b;
+ break;
+ case PT_LONG:
+ l = ldb_msg_find_attr_as_int(res->msgs[0], PidTagAttr, 0x0);
+ *data = (void *)&l;
+ break;
+ case PT_I8:
+ str = ldb_msg_find_attr_as_string(res->msgs[0], PidTagAttr, 0x0);
+ d = talloc_zero(parent_ctx, uint64_t);
+ *d = strtoull(str, NULL, 16);
+ *data = (void *)d;
+ break;
+ case PT_STRING8:
+ case PT_UNICODE:
+ str = ldb_msg_find_attr_as_string(res->msgs[0], PidTagAttr, NULL);
+ *data = (char *) talloc_strdup(parent_ctx, str);
+ break;
+ default:
+ talloc_free(mem_ctx);
+ DEBUG(0, ("[%s:%d] Property Type 0x%.4x not supported\n", __FUNCTION__, __LINE__, (proptag & 0xFFFF)));
+ return MAPI_E_NOT_FOUND;
+ }
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/mapiproxy/libmapiproxy.pc.in
===================================================================
--- trunk/openchange/mapiproxy/libmapiproxy.pc.in (rev 0)
+++ trunk/openchange/mapiproxy/libmapiproxy.pc.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,15 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@prefix@/share
+datadir=@datadir@
+
+Name: MAPIPROXY
+Description: MAPI Proxy and Server Module Library
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lmapiproxy
+Libs.private: @LIBS@
+Cflags: -I${includedir}
+Requires: talloc dcerpc ndr ldb
+Requires.private: samba-hostconfig
Added: trunk/openchange/mapiproxy/libmapiserver/libmapiserver.h
===================================================================
--- trunk/openchange/mapiproxy/libmapiserver/libmapiserver.h (rev 0)
+++ trunk/openchange/mapiproxy/libmapiserver/libmapiserver.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,109 @@
+/*
+ libmapiserver - MAPI library for Server side
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 __LIBMAPISERVER_H__
+#define __LIBMAPISERVER_H__
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <dcerpc.h>
+#include <param.h>
+
+#include <gen_ndr/exchange.h>
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+#define SIZE_DFLT_MAPI_RESPONSE 6
+
+/* Rops default and static size */
+
+/**
+ \details OpenFolderRop has fixed response size for
+ -# HasRules: uint8_t
+ -# IsGhosted: uint8_t
+ */
+#define SIZE_DFLT_ROPOPENFOLDER 2
+
+/**
+ \details GetPropertiesSpecificRop has fixed response size for:
+ -# layout: uint8_t
+ */
+#define SIZE_DFLT_ROPGETPROPERTIESSPECIFIC 1
+
+/**
+ \details GetReceiveFolder has fixed response size for:
+ -# folder_id: uint64_t
+ */
+#define SIZE_DFLT_ROPGETRECEIVEFOLDER 8
+
+/**
+ \details LogonRop has a fixed size for mailbox:
+ -# LogonFlags: uint8_t
+ -# FolderIDs: uint64_t * 13
+ -# ResponseFlags: uint8_t
+ -# MailboxGUID: sizeof (struct GUID)
+ -# ReplID: uint16_t
+ -# ReplGUID: sizeof (struct GUID)
+ -# LogonTime: uint8_t * 6 + uint16_t
+ -# GwartTime: uint64_t
+ -# StoreState: uint32_t
+ */
+#define SIZE_DFLT_ROPLOGON_MAILBOX 160
+
+#define SIZE_NULL_TRANSACTION 2
+
+__BEGIN_DECLS
+
+/* definitions from libmapiserver_oxcfold.c */
+uint16_t libmapiserver_RopOpenFolder_size(struct EcDoRpc_MAPI_REPL *);
+
+/* definitions from libmapiserver_oxcnotif.c */
+uint16_t libmapiserver_RopRegisterNotification_size(void);
+
+/* definitions from libmapiserver_oxcprpt.c */
+uint16_t libmapiserver_RopGetPropertiesSpecific_size(struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *);
+int libmapiserver_push_property(TALLOC_CTX *, struct smb_iconv_convenience *, uint32_t, const void *, DATA_BLOB *, uint8_t);
+
+/* definitions from libmapiserver_oxcstor.c */
+uint16_t libmapiserver_RopLogon_size(struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *);
+uint16_t libmapiserver_RopRelease_size(void);
+uint16_t libmapiserver_RopGetReceiveFolder_size(struct EcDoRpc_MAPI_REPL *);
+
+__END_DECLS
+
+#endif /* ! __LIBMAPISERVER_H__ */
Added: trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcfold.c
===================================================================
--- trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcfold.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcfold.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,50 @@
+/*
+ libmapiserver - MAPI library for Server side
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file libmapiserver_oxcfold.c
+
+ \brief OXCFOLD Rops
+ */
+
+#include "libmapiserver.h"
+
+/**
+ \details Calculate OpenFolder Rop size
+
+ \param response pointer to the OpenFolder EcDoRpc_MAPI_REPL
+ structure
+
+ \return Size of OpenFolder response
+ */
+_PUBLIC_ uint16_t libmapiserver_RopOpenFolder_size(struct EcDoRpc_MAPI_REPL *response)
+{
+ uint16_t size = SIZE_DFLT_MAPI_RESPONSE;
+
+ if (!response) {
+ return size;
+ }
+
+ size += SIZE_DFLT_ROPOPENFOLDER;
+
+ /* No ghosted folder for the moment */
+ return size;
+}
Added: trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcnotif.c
===================================================================
--- trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcnotif.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcnotif.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,38 @@
+/*
+ libmapiserver - MAPI library for Server side
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file libmapiserver_oxcfold.c
+
+ \brief OXCNOTIF Rops
+ */
+
+#include "libmapiserver.h"
+
+/**
+ \details Calculate RegisterNotification Rop size
+
+ \return Size of RegisterNotification response
+ */
+_PUBLIC_ uint16_t libmapiserver_RopRegisterNotification_size(void)
+{
+ return SIZE_DFLT_MAPI_RESPONSE;
+}
Added: trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcprpt.c
===================================================================
--- trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcprpt.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcprpt.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,151 @@
+/*
+ libmapiserver - MAPI library for Server side
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file libmapiserver_oxcprpt.c
+
+ \brief OXCPRPT Rops
+ */
+
+#include "libmapiserver.h"
+#include <libmapi/mapidefs.h>
+#include <gen_ndr/ndr_exchange.h>
+
+#include <util/debug.h>
+
+/**
+ \details Calculate GetPropertiesSpecific Rop size
+
+ \param request pointer to the GetPropertiesSpecific EcDoRpc_MAPI_REQ structure
+ \param response pointer to the GetPropertiesSpecific EcDoRpc_MAPI_REPL structure
+
+ \return Size of GetPropsSpecific response
+ */
+_PUBLIC_ uint16_t libmapiserver_RopGetPropertiesSpecific_size(struct EcDoRpc_MAPI_REQ *request,
+ struct EcDoRpc_MAPI_REPL *response)
+{
+ uint16_t size = SIZE_DFLT_MAPI_RESPONSE;
+
+ if (!response) {
+ return size;
+ }
+
+ size += SIZE_DFLT_ROPGETPROPERTIESSPECIFIC;
+ size += response->u.mapi_GetProps.prop_data.length;
+
+ return size;
+}
+
+
+/**
+ \details Add a property value to a DATA blob. This convenient
+ function should be used when creating a GetPropertiesSpecific reply
+ response blob.
+
+ \param mem_ctx pointer to the memory context
+ \param iconv_convenience pointer to the iconv_convenience context
+ \param property the property tag which value is meant to be
+ appended to the blob
+ \param value generic pointer on the property value
+ \param blob the data blob the function uses to return the blob
+ \param layout whether values should be prefixed by a layout
+
+ \note blob.length must be set to 0 before this function is called
+ the first time. Also the function only supports a limited set of
+ property types at the moment.
+
+ \return 0 on success;
+ */
+_PUBLIC_ int libmapiserver_push_property(TALLOC_CTX *mem_ctx,
+ struct smb_iconv_convenience *iconv_convenience,
+ uint32_t property,
+ const void *value,
+ DATA_BLOB *blob,
+ uint8_t layout)
+{
+ struct ndr_push *ndr;
+
+ ndr = ndr_push_init_ctx(mem_ctx, iconv_convenience);
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ ndr->offset = 0;
+ if (blob->length) {
+ talloc_free(ndr->data);
+ ndr->data = blob->data;
+ ndr->offset = blob->length;
+ }
+
+ /* Step 1. Set the layout */
+ if (layout) {
+ switch (property & 0xFFFF) {
+ case PT_ERROR:
+ ndr_push_uint8(ndr, NDR_SCALARS, PT_ERROR);
+ break;
+ default:
+ ndr_push_uint8(ndr, NDR_SCALARS, 0x0);
+ }
+ }
+
+ /* Step 2. Push property data if supported */
+ switch (property & 0xFFFF) {
+ case PT_I2:
+ ndr_push_uint16(ndr, NDR_SCALARS, *(uint16_t *) value);
+ break;
+ case PT_LONG:
+ case PT_ERROR:
+ case PT_OBJECT:
+ ndr_push_uint32(ndr, NDR_SCALARS, *(uint32_t *) value);
+ break;
+ case PT_DOUBLE:
+ case PT_I8:
+ ndr_push_dlong(ndr, NDR_SCALARS, *(uint64_t *) value);
+ break;
+ case PT_BOOLEAN:
+ ndr_push_uint8(ndr, NDR_SCALARS, *(uint8_t *) value);
+ break;
+ case PT_STRING8:
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_STR_ASCII);
+ ndr_push_string(ndr, NDR_SCALARS, (char *) value);
+ break;
+ case PT_UNICODE:
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ ndr_push_string(ndr, NDR_SCALARS, (char *) value);
+ break;
+ case PT_BINARY:
+ ndr_push_SBinary_short(ndr, NDR_SCALARS, (struct SBinary_short *) value);
+ break;
+ case PT_CLSID:
+ ndr_push_GUID(ndr, NDR_SCALARS, (struct GUID *) value);
+ break;
+ case PT_SYSTIME:
+ ndr_push_FILETIME(ndr, NDR_SCALARS, (struct FILETIME *) value);
+ break;
+ default:
+ break;
+ }
+
+ /* Step 3. Steal ndr context */
+ blob->data = ndr->data;
+ talloc_steal(mem_ctx, blob->data);
+ blob->length = ndr->offset;
+
+ talloc_free(ndr);
+ return 0;
+}
Added: trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcstor.c
===================================================================
--- trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcstor.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapiserver/libmapiserver_oxcstor.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,78 @@
+/*
+ libmapiserver - MAPI library for Server side
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file libmapiserver_oxcstor.c
+
+ \brief OXCSTOR Rops
+ */
+
+#include "libmapiserver.h"
+#include <string.h>
+
+/**
+ \details Calculate Logon Rop size
+
+ \param request pointer to the Logon EcDoRpc_MAPI_REQ structure
+ \param response pointer to the Logon EcDoRpc_MAPI_REPL structure
+
+ \return Size of Logon response
+ */
+_PUBLIC_ uint16_t libmapiserver_RopLogon_size(struct EcDoRpc_MAPI_REQ *request,
+ struct EcDoRpc_MAPI_REPL *response)
+{
+ uint16_t size = SIZE_DFLT_MAPI_RESPONSE;
+
+ if (!response) {
+ return size;
+ }
+
+ switch (request->u.mapi_Logon.LogonFlags) {
+ case LogonPrivate:
+ size += SIZE_DFLT_ROPLOGON_MAILBOX;
+ break;
+ default:
+ break;
+ }
+
+ return size;
+}
+
+
+_PUBLIC_ uint16_t libmapiserver_RopRelease_size(void)
+{
+ return SIZE_NULL_TRANSACTION;
+}
+
+
+_PUBLIC_ uint16_t libmapiserver_RopGetReceiveFolder_size(struct EcDoRpc_MAPI_REPL *response)
+{
+ uint16_t size = SIZE_DFLT_MAPI_RESPONSE;
+
+ if (!response || response->error_code != MAPI_E_SUCCESS) {
+ return size;
+ }
+
+ size += SIZE_DFLT_ROPGETRECEIVEFOLDER;
+ size += strlen(response->u.mapi_GetReceiveFolder.MessageClass) + 1;
+
+ return size;
+}
Added: trunk/openchange/mapiproxy/libmapiserver.pc.in
===================================================================
--- trunk/openchange/mapiproxy/libmapiserver.pc.in (rev 0)
+++ trunk/openchange/mapiproxy/libmapiserver.pc.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@prefix@/share
+datadir=@datadir@
+
+Name: MAPISERVER
+Description: Server side MAPI library
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lmapiserver
+Libs.private: @LIBS@
+Cflags: -I${includedir}
+Requires: talloc
Added: trunk/openchange/mapiproxy/libmapistore/backends/mapistore_sqlite3.c
===================================================================
--- trunk/openchange/mapiproxy/libmapistore/backends/mapistore_sqlite3.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapistore/backends/mapistore_sqlite3.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,126 @@
+/*
+ OpenChange Storage Abstraction Layer library
+ MAPIStore SQLite backend
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 "mapistore_sqlite3.h"
+
+
+/**
+ \details Initialize sqlite3 mapistore backend
+
+ \return MAPISTORE_SUCCESS on success
+ */
+static int sqlite3_init(void)
+{
+ DEBUG(0, ("sqlite3 backend initialized\n"));
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Create a connection context to the sqlite3 backend
+
+ \param mem_ctx pointer to the memory context
+ \param uri pointer to the database path
+ \param context_id pointer to the context identifier the function
+ returns
+
+ \return MAPISTORE_SUCCESS on success
+ */
+static int sqlite3_create_context(TALLOC_CTX *mem_ctx, const char *uri, void **private_data)
+{
+ struct sqlite3_context *sqlite_ctx;
+ sqlite3 *db;
+ int ret;
+
+ DEBUG(0, ("[%s:%d]\n", __FUNCTION__, __LINE__));
+
+ ret = sqlite3_open(uri, &db);
+ if (ret) {
+ DEBUG(3, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__,
+ sqlite3_errmsg(db)));
+ sqlite3_close(db);
+ return -1;
+ }
+
+ sqlite_ctx = talloc_zero(mem_ctx, struct sqlite3_context);
+ sqlite_ctx->db = db;
+ sqlite_ctx->private_data = NULL;
+
+ *private_data = (void *)sqlite_ctx;
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Delete a connection context from the sqlite3 backend
+
+ \return MAPISTORE_SUCCESS on success
+ */
+static int sqlite3_delete_context(void *private_data)
+{
+ struct sqlite3_context *sqlite_ctx = (struct sqlite3_context *)private_data;
+ int ret;
+
+ DEBUG(5, ("[%s:%d]\n", __FUNCTION__, __LINE__));
+
+ if (!private_data) {
+ return MAPISTORE_SUCCESS;
+ }
+
+ ret = sqlite3_close(sqlite_ctx->db);
+ if (ret) return MAPISTORE_ERROR;
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Entry point for mapistore SQLite backend
+
+ \return MAPISTORE_SUCCESS on success, otherwise -1
+ */
+int mapistore_init_backend(void)
+{
+ struct mapistore_backend backend;
+ int ret;
+
+ /* Fill in our name */
+ backend.name = "sqlite3";
+ backend.description = "mapistore sqlite3 backend";
+ backend.namespace = "sqlite://";
+
+ /* Fill in all the operations */
+ backend.init = sqlite3_init;
+ backend.create_context = sqlite3_create_context;
+ backend.delete_context = sqlite3_delete_context;
+
+ /* Register ourselves with the MAPIPROXY subsystem */
+ ret = mapistore_backend_register(&backend);
+ if (ret != MAPISTORE_SUCCESS) {
+ DEBUG(0, ("Failed to register the '%s' mapistore backend!\n", backend.name));
+ return ret;
+ }
+
+ return MAPISTORE_SUCCESS;
+}
Added: trunk/openchange/mapiproxy/libmapistore/backends/mapistore_sqlite3.h
===================================================================
--- trunk/openchange/mapiproxy/libmapistore/backends/mapistore_sqlite3.h (rev 0)
+++ trunk/openchange/mapiproxy/libmapistore/backends/mapistore_sqlite3.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,43 @@
+/*
+ OpenChange Storage Abstraction Layer library
+ MAPIStore SQLite backend
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 __MAPISTORE_SQLITE3_H
+#define __MAPISTORE_SQLITE3_H
+
+#include <mapiproxy/libmapistore/mapistore.h>
+#include <mapiproxy/libmapistore/mapistore_errors.h>
+#include <libmapi/dlinklist.h>
+#include <sqlite3.h>
+
+struct sqlite3_context {
+ sqlite3 *db;
+ void *private_data;
+};
+
+
+__BEGIN_DECLS
+
+int mapistore_init_backend(void);
+
+__END_DECLS
+
+#endif /* ! __MAPISTORE_SQLITE3_H */
Added: trunk/openchange/mapiproxy/libmapistore/mapistore.h
===================================================================
--- trunk/openchange/mapiproxy/libmapistore/mapistore.h (rev 0)
+++ trunk/openchange/mapiproxy/libmapistore/mapistore.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,110 @@
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 __MAPISTORE_H
+#define __MAPISTORE_H
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#ifndef _PUBLIC_
+#define _PUBLIC_
+#endif
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <tdb.h>
+#include <talloc.h>
+#include <util/debug.h>
+
+#define MAPISTORE_SUCCESS 0
+
+typedef int (*init_backend_fn) (void);
+
+#define MAPISTORE_INIT_MODULE "mapistore_init_backend"
+
+struct mapistore_backend {
+ const char *name;
+ const char *description;
+ const char *namespace;
+
+ int (*init)(void);
+ int (*create_context)(TALLOC_CTX *, const char *, void **);
+ int (*delete_context)(void *);
+};
+
+struct backend_context {
+ const struct mapistore_backend *backend;
+ void *private_data;
+ uint32_t context_id;
+};
+
+struct backend_context_list {
+ struct backend_context *ctx;
+ struct backend_context_list *prev;
+ struct backend_context_list *next;
+};
+
+struct processing_context;
+
+struct mapistore_context {
+ struct processing_context *processing_ctx;
+ struct backend_context_list *context_list;
+};
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+__BEGIN_DECLS
+
+/* definitions from mapistore_interface.c */
+struct mapistore_context *mapistore_init(TALLOC_CTX *, const char *);
+int mapistore_release(struct mapistore_context *);
+int mapistore_add_context(struct mapistore_context *, const char *uri, uint32_t *);
+int mapistore_del_context(struct mapistore_context *, uint32_t);
+const char *mapistore_errstr(int);
+
+/* definitions from mapistore_processing.c */
+int mapistore_set_mapping_path(const char *);
+
+/* definitions from mapistore_backend.c */
+extern int mapistore_backend_register(const void *);
+const char *mapistore_backend_get_installdir(void);
+init_backend_fn *mapistore_backend_load(TALLOC_CTX *, const char *);
+
+bool mapistore_backend_run_init(init_backend_fn *);
+
+__END_DECLS
+
+#endif /* ! __MAPISTORE_H */
Added: trunk/openchange/mapiproxy/libmapistore/mapistore_backend.c
===================================================================
--- trunk/openchange/mapiproxy/libmapistore/mapistore_backend.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapistore/mapistore_backend.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,307 @@
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Note: init and load functions have been copied from
+ samba4/source4/param/util.c initially wrote by Jelmer.
+
+ Copyright (C) Jelmer Vernooij 2005-2007
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 <sys/types.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <dirent.h>
+
+#include "mapistore.h"
+#include "mapistore_errors.h"
+#include "mapistore_private.h"
+#include <libmapi/dlinklist.h>
+
+#include <util.h>
+#include <util/debug.h>
+
+/**
+ \file mapistore_backend.c
+
+ \brief mapistore backends management API
+ */
+
+
+static struct mstore_backend {
+ struct mapistore_backend *backend;
+} *backends = NULL;
+
+int num_backends;
+
+
+/**
+ \details Register mapistore backends
+
+ \param _backend pointer to the mapistore backend to register
+
+ \return MAPISTORE_SUCCESS on success
+ */
+_PUBLIC_ extern int mapistore_backend_register(const void *_backend)
+{
+ const struct mapistore_backend *backend = _backend;
+
+ backends = realloc_p(backends, struct mstore_backend, num_backends + 1);
+ if (!backends) {
+ smb_panic("out of memory in mapistore_backend_register");
+ }
+
+ backends[num_backends].backend = smb_xmemdup(backend, sizeof (*backend));
+ backends[num_backends].backend->name = smb_xstrdup(backend->name);
+
+ num_backends++;
+
+ DEBUG(3, ("MAPISTORE backend '%s' registered\n", backend->name));
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Return the full path where mapistore backends are
+ installed.
+
+ \return Pointer to the full path where backends are installed.
+ */
+_PUBLIC_ const char *mapistore_backend_get_installdir(void)
+{
+ return MAPISTORE_BACKEND_INSTALLDIR;
+}
+
+
+/**
+ \details Obtain the backend init function from a shared library
+ file
+
+ \param path full path to the backend shared library
+
+ \return Pointer to the initialization function on success,
+ otherwise NULL.
+ */
+static init_backend_fn load_backend(const char *path)
+{
+ void *handle;
+ void *init_fn;
+
+ handle = dlopen(path, RTLD_NOW);
+ if (handle == NULL) {
+ DEBUG(0, ("Unable to open %s: %s\n", path, dlerror()));
+ return NULL;
+ }
+
+ init_fn = dlsym(handle, MAPISTORE_INIT_MODULE);
+
+ if (init_fn == NULL) {
+ DEBUG(0, ("Unable to find %s() in %s: %s\n",
+ MAPISTORE_INIT_MODULE, path, dlerror()));
+ DEBUG(1, ("Loading mapistore backend '%s' failed\n", path));
+ dlclose(handle);
+ return NULL;
+ }
+
+ return (init_backend_fn) init_fn;
+}
+
+
+/**
+ \details Load backends from specified directory
+
+ \param mem_ctx pointer to the memory context
+ \param pointer to the backends shared library folder
+
+ \return allocated array of functions pointers to initialization
+ functions on success, otherwise NULL.
+ */
+static init_backend_fn *load_backends(TALLOC_CTX *mem_ctx, const char *path)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char *filename;
+ int success = 0;
+ init_backend_fn *ret;
+
+ ret = talloc_array(mem_ctx, init_backend_fn, 2);
+ ret[0] = NULL;
+
+ dir = opendir(path);
+ if (dir == NULL) {
+ talloc_free(ret);
+ return NULL;
+ }
+
+ while ((entry = readdir(dir))) {
+ if (ISDOT(entry->d_name) || ISDOTDOT(entry->d_name)) {
+ continue;
+ }
+
+ filename = talloc_asprintf(mem_ctx, "%s/%s", path, entry->d_name);
+ ret[success] = load_backend(filename);
+ if (ret[success]) {
+ ret = talloc_realloc(mem_ctx, ret, init_backend_fn, success + 2);
+ success++;
+ ret[success] = NULL;
+ }
+
+ talloc_free(filename);
+ }
+
+ closedir(dir);
+
+ return ret;
+}
+
+
+/**
+ \details Load the initialization functions from backends DSO
+
+ \param mem_ctx pointer to the memory context
+ \param path pointer to the backend's DSO folder
+
+ \return allocated array of functions pointers to initialization
+ functions on success, otherwise NULL.
+ */
+_PUBLIC_ init_backend_fn *mapistore_backend_load(TALLOC_CTX *mem_ctx, const char *path)
+{
+ if (!path) {
+ path = mapistore_backend_get_installdir();
+ }
+
+ return load_backends(mem_ctx, path);
+}
+
+
+/**
+ \details Run specified initialization functions.
+
+ \param fns pointer to an array of mapistore backends initialization
+ functions
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapistore_backend_run_init(init_backend_fn *fns)
+{
+ int i;
+ bool ret = true;
+
+ if (fns == NULL) {
+ return true;
+ }
+
+ for (i = 0; fns[i]; i++) {
+ ret &= (bool)fns[i]();
+ }
+
+ return ret;
+}
+
+
+/**
+ \details Initialize mapistore backends
+
+ \param mem_ctx pointer to the memory context
+ \param path pointer to folder where mapistore backends are
+ installed
+
+ \return MAPISTORE_SUCCESS on success, otherwise
+ MAPISTORE_ERR_BACKEND_INIT
+ */
+int mapistore_backend_init(TALLOC_CTX *mem_ctx, const char *path)
+{
+ init_backend_fn *ret;
+ bool status;
+ int retval;
+ int i;
+
+ ret = mapistore_backend_load(mem_ctx, path);
+ status = mapistore_backend_run_init(ret);
+ talloc_free(ret);
+
+ for (i = 0; i < num_backends; i++) {
+ if (backends[i].backend) {
+ DEBUG(3, ("MAPISTORE backend '%s' loaded\n", backends[i].backend->name));
+ retval = backends[i].backend->init();
+ }
+ }
+
+ return (status != true) ? MAPISTORE_SUCCESS : MAPISTORE_ERR_BACKEND_INIT;
+}
+
+
+/**
+ \details Create backend context
+
+ \param mem_ctx pointer to the memory context
+ \param namespace the backend namespace
+ \param uri the backend parameters which can be passes inline
+
+ \return a valid backend_context pointer on success, otherwise NULL
+ */
+struct backend_context *mapistore_backend_create_context(TALLOC_CTX *mem_ctx, const char *namespace,
+ const char *uri)
+{
+ struct backend_context *context;
+ int retval;
+ bool found;
+ void *private_data = NULL;
+ int i;
+
+ DEBUG(0, ("namespace is %s and backend_uri is '%s'\n", namespace, uri));
+ for (i = 0; i < num_backends; i++) {
+ if (backends[i].backend->namespace &&
+ !strcmp(namespace, backends[i].backend->namespace)) {
+ found = true;
+ retval = backends[i].backend->create_context(mem_ctx, uri, &private_data);
+ if (retval != MAPISTORE_SUCCESS) {
+ return NULL;
+ }
+
+ break;
+ }
+ }
+ if (found == false) {
+ DEBUG(0, ("MAPISTORE: no backend with namespace '%s' is available\n", namespace));
+ return NULL;
+ }
+
+ context = talloc_zero(mem_ctx, struct backend_context);
+ context->backend = backends[i].backend;
+ context->private_data = private_data;
+ talloc_steal(context, context->private_data);
+
+ return context;
+}
+
+
+/**
+ \details Delete a context from the specified backend
+
+ \param bctx pointer to the backend context
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ int mapistore_backend_delete_context(struct backend_context *bctx)
+{
+ if (!bctx->backend->delete_context) return MAPISTORE_ERROR;
+
+ return bctx->backend->delete_context(bctx->private_data);
+}
Added: trunk/openchange/mapiproxy/libmapistore/mapistore_errors.h
===================================================================
--- trunk/openchange/mapiproxy/libmapistore/mapistore_errors.h (rev 0)
+++ trunk/openchange/mapiproxy/libmapistore/mapistore_errors.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,109 @@
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file mapistore_errors.h
+
+ \brief Thie header providers a set of result codes for MAPISTORE
+ function calls.
+ */
+
+#ifndef __MAPISTORE_ERRORS_H
+#define __MAPISTORE_ERRORS_H
+
+/**
+ The function call succeeded.
+ */
+#define MAPISTORE_SUCCESS 0
+
+/**
+ The function call failed for some non-specific reason.
+ */
+#define MAPISTORE_ERROR 1
+
+/**
+ The function call failed because it was unable to allocate the
+ memory required by underlying operations.
+ */
+#define MAPISTORE_ERR_NO_MEMORY 2
+
+/**
+ The function call failed because underlying context has already
+ been initialized
+ */
+#define MAPISTORE_ERR_ALREADY_INITIALIZED 3
+
+/**
+ The function call failed because context has not been initialized.
+ */
+#define MAPISTORE_ERR_NOT_INITIALIZED 4
+
+/**
+ The function call failed because an internal mapistore storage
+ component has corrupted data.
+ */
+#define MAPISTORE_ERR_CORRUPTED 5
+
+/**
+ The function call failed because one of the function parameters is
+ invalid
+ */
+#define MAPISTORE_ERR_INVALID_PARAMETER 6
+
+/**
+ The function call failed because the directory doesn't exist
+ */
+#define MAPISTORE_ERR_NO_DIRECTORY 7
+
+/**
+ The function call failed because the underlying function couldn't
+ open a database.
+ */
+#define MAPISTORE_ERR_DATABASE_INIT 8
+
+/**
+ The function call failed because the underlying function didn't run
+ a database operation successfully.
+ */
+#define MAPISTORE_ERR_DATABASE_OPS 9
+
+/**
+ The function failed to register a storage backend
+ */
+#define MAPISTORE_ERR_BACKEND_REGISTER 10
+
+/**
+ One of more storage backend initialization functions failed to
+ complete successfully.
+ */
+#define MAPISTORE_ERR_BACKEND_INIT 11
+
+/**
+ The function failed because mapistore failed to create a context
+ */
+#define MAPISTORE_ERR_CONTEXT_FAILED 12
+
+/**
+ The function failed because the provided namespace is invalid
+ */
+#define MAPISTORE_ERR_INVALID_NAMESPACE 13
+
+#endif /* ! __MAPISTORE_ERRORS_H */
Added: trunk/openchange/mapiproxy/libmapistore/mapistore_interface.c
===================================================================
--- trunk/openchange/mapiproxy/libmapistore/mapistore_interface.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapistore/mapistore_interface.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,234 @@
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 "mapistore.h"
+#include "mapistore_errors.h"
+#include "mapistore_private.h"
+#include <libmapi/dlinklist.h>
+
+#include <string.h>
+
+/**
+ \details Initialize the mapistore context
+
+ \param mem_ctx pointer to the memory context
+
+ \return allocate mapistore context on success, otherwise NULL
+ */
+_PUBLIC_ struct mapistore_context *mapistore_init(TALLOC_CTX *mem_ctx, const char *path)
+{
+ int retval;
+ struct mapistore_context *mstore_ctx;
+
+ mstore_ctx = talloc_zero(mem_ctx, struct mapistore_context);
+ if (!mstore_ctx) {
+ return NULL;
+ }
+
+ mstore_ctx->processing_ctx = talloc_zero(mstore_ctx, struct processing_context);
+
+ retval = mapistore_init_mapping_context(mstore_ctx->processing_ctx);
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(5, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, mapistore_errstr(retval)));
+ talloc_free(mstore_ctx);
+ return NULL;
+ }
+
+ retval = mapistore_backend_init(mstore_ctx, path);
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(5, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, mapistore_errstr(retval)));
+ talloc_free(mstore_ctx);
+ return NULL;
+ }
+
+ mstore_ctx->context_list = NULL;
+
+ return mstore_ctx;
+}
+
+
+/**
+ \details Release the mapistore context and destroy any data
+ associated
+
+ \param mstore_ctx pointer to the mapistore context
+
+ \note The function needs to rely on talloc destructors which is not
+ implemented in code yet.
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ int mapistore_release(struct mapistore_context *mstore_ctx)
+{
+ if (!mstore_ctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+
+ talloc_free(mstore_ctx->processing_ctx);
+ talloc_free(mstore_ctx->context_list);
+ talloc_free(mstore_ctx);
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Add a new connection context to mapistore
+
+ \param mstore_ctx pointer to the mapistore context
+ \param uri the connection context URI
+ \param pointer to the context identifier the function returns
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ int mapistore_add_context(struct mapistore_context *mstore_ctx,
+ const char *uri, uint32_t *context_id)
+{
+ TALLOC_CTX *mem_ctx;
+ int retval;
+ struct backend_context *backend_ctx;
+ struct backend_context_list *backend_list;
+ char *namespace;
+ char *namespace_start;
+ char *backend_uri;
+
+ /* Step 1. Perform Sanity Checks on URI */
+ if (!uri || strlen(uri) < 4) {
+ return MAPISTORE_ERR_INVALID_NAMESPACE;
+ }
+
+ mem_ctx = talloc_named(NULL, 0, "mapistore_add_context");
+ namespace = talloc_strdup(mem_ctx, uri);
+ namespace_start = namespace;
+ namespace = strchr(namespace, ':');
+ if (!namespace) {
+ DEBUG(0, ("[%s:%d]: Error - Invalid namespace '%s'\n", __FUNCTION__, __LINE__, namespace_start));
+ talloc_free(mem_ctx);
+ return MAPISTORE_ERR_INVALID_NAMESPACE;
+ }
+
+ if (namespace[1] && namespace[1] == '/' &&
+ namespace[2] && namespace[2] == '/' &&
+ namespace[3]) {
+ backend_uri = talloc_strdup(mem_ctx, &namespace[3]);
+ namespace[3] = '\0';
+ backend_ctx = mapistore_backend_create_context((TALLOC_CTX *)mstore_ctx, namespace_start, backend_uri);
+ if (!backend_ctx) {
+ return MAPISTORE_ERR_CONTEXT_FAILED;
+ }
+
+ backend_list = talloc_zero((TALLOC_CTX *) mstore_ctx, struct backend_context_list);
+ talloc_steal(backend_list, backend_ctx);
+ backend_list->ctx = backend_ctx;
+ retval = mapistore_get_context_id(mstore_ctx->processing_ctx, &backend_list->ctx->context_id);
+ if (retval != MAPISTORE_SUCCESS) {
+ talloc_free(mem_ctx);
+ return MAPISTORE_ERR_CONTEXT_FAILED;
+ }
+ *context_id = backend_list->ctx->context_id;
+ DLIST_ADD_END(mstore_ctx->context_list, backend_list, struct backend_context_list *);
+
+ } else {
+ DEBUG(0, ("[%s:%d]: Error - Invalid URI '%s'\n", __FUNCTION__, __LINE__, uri));
+ talloc_free(mem_ctx);
+ return MAPISTORE_ERR_INVALID_NAMESPACE;
+ }
+
+ talloc_free(mem_ctx);
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Delete an existing connection context from mapistore
+
+ \param mstore_ctx pointer to the mapistore context
+ \param context_id the context identifier referencing the context to
+ delete
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ int mapistore_del_context(struct mapistore_context *mstore_ctx,
+ uint32_t context_id)
+{
+ struct backend_context_list *el;
+ int retval;
+ bool found = false;
+
+ /* Sanity checks */
+ if (!mstore_ctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+ if (!mstore_ctx->processing_ctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+ if (!mstore_ctx->context_list) return MAPISTORE_ERR_NOT_INITIALIZED;
+
+ /* Step 0. Ensure the context exists */
+ for (el = mstore_ctx->context_list; el; el = el->next) {
+ if (el->ctx && el->ctx->context_id == context_id) {
+ found = true;
+ break;
+ }
+ }
+ if (found == false) return MAPISTORE_ERR_INVALID_PARAMETER;
+
+ /* Step 1. Delete the context within backend */
+ retval = mapistore_backend_delete_context(el->ctx);
+ if (retval) return retval;
+
+ /* Step 2. Delete the context from the processing layer */
+
+ /* Step 2. Add the free'd context id to the free list */
+ retval = mapistore_free_context_id(mstore_ctx->processing_ctx, context_id);
+ return retval;
+}
+
+
+/**
+ \details return a string explaining what a mapistore error constant
+ means.
+
+ \param mapistore_err the mapistore error constant
+
+ \return constant string
+ */
+_PUBLIC_ const char *mapistore_errstr(int mapistore_err)
+{
+ switch (mapistore_err) {
+ case MAPISTORE_SUCCESS:
+ return "Success";
+ case MAPISTORE_ERROR:
+ return "Non-specific error";
+ case MAPISTORE_ERR_NO_MEMORY:
+ return "No memory available";
+ case MAPISTORE_ERR_ALREADY_INITIALIZED:
+ return "Already initialized";
+ case MAPISTORE_ERR_NOT_INITIALIZED:
+ return "Not initialized";
+ case MAPISTORE_ERR_NO_DIRECTORY:
+ return "No such file or directory";
+ case MAPISTORE_ERR_DATABASE_INIT:
+ return "Database initialization failed";
+ case MAPISTORE_ERR_DATABASE_OPS:
+ return "database operation failed";
+ case MAPISTORE_ERR_BACKEND_REGISTER:
+ return "storage backend registration failed";
+ case MAPISTORE_ERR_BACKEND_INIT:
+ return "storage backend initialization failed";
+ }
+
+ return "Unknown error";
+}
Added: trunk/openchange/mapiproxy/libmapistore/mapistore_private.h
===================================================================
--- trunk/openchange/mapiproxy/libmapistore/mapistore_private.h (rev 0)
+++ trunk/openchange/mapiproxy/libmapistore/mapistore_private.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,116 @@
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 __MAPISTORE_PRIVATE_H__
+#define __MAPISTORE_PRIVATE_H__
+
+#ifndef ISDOT
+#define ISDOT(path) ( \
+ *((const char *)(path)) == '.' && \
+ *(((const char *)(path)) + 1) == '\0' \
+ )
+#endif
+
+#ifndef ISDOTDOT
+#define ISDOTDOT(path) ( \
+ *((const char *)(path)) == '.' && \
+ *(((const char *)(path)) + 1) == '.' && \
+ *(((const char *)(path)) + 2) == '\0' \
+ )
+#endif
+
+
+struct tdb_wrap {
+ struct tdb_context *tdb;
+ const char *name;
+ struct tdb_wrap *prev;
+ struct tdb_wrap *next;
+};
+
+/**
+ Identifier mapping context.
+
+ This structure stores PR_MID and PR_FID identifiers to backend
+ identifiers mapping. It points on 2 databases, one with "in use"
+ identifiers and another one with a list of "free identifiers" which
+ are added when an object is deleted, moved, etc.
+
+ The last_id structure member references the last identifier value
+ which got created. There is no identifier available with a value
+ higher than last_id.
+ */
+struct id_mapping_context {
+ struct tdb_wrap *used_ctx;
+ struct tdb_wrap *free_ctx;
+ uint64_t last_id;
+};
+
+
+/**
+ Free context identifier list
+
+ This structure is a double chained list storing unused context
+ identifiers.
+ */
+struct context_id_list {
+ uint32_t context_id;
+ struct context_id_list *prev;
+ struct context_id_list *next;
+};
+
+
+struct processing_context {
+ struct id_mapping_context *mapping_ctx;
+ struct context_id_list *free_ctx;
+ uint32_t last_context_id;
+ uint64_t dflt_start_id;
+};
+
+
+/**
+ The database name where in use ID mappings are stored
+ */
+#define MAPISTORE_DB_LAST_ID_KEY "mapistore_last_id"
+#define MAPISTORE_DB_LAST_ID_VAL 0x15000
+
+#define MAPISTORE_DB_NAME_USED_ID "mapistore_id_mapping_used.tdb"
+#define MAPISTORE_DB_NAME_FREE_ID "mapistore_id_mapping_free.tdb"
+
+__BEGIN_DECLS
+
+/* definitions from mapistore_processing.c */
+const char *mapistore_get_mapping_path(void);
+int mapistore_init_mapping_context(struct processing_context *);
+int mapistore_get_context_id(struct processing_context *, uint32_t *);
+int mapistore_free_context_id(struct processing_context *, uint32_t);
+
+
+/* definitions from mapistore_backend.c */
+int mapistore_backend_init(TALLOC_CTX *, const char *);
+struct backend_context *mapistore_backend_create_context(TALLOC_CTX *, const char *, const char *);
+int mapistore_backend_delete_context(struct backend_context *);
+
+/* definitions from mapistore_tdb_wrap.c */
+struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *, const char *, int, int, int, mode_t);
+
+__END_DECLS
+
+#endif /* ! __MAPISTORE_PRIVATE_H__ */
Added: trunk/openchange/mapiproxy/libmapistore/mapistore_processing.c
===================================================================
--- trunk/openchange/mapiproxy/libmapistore/mapistore_processing.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapistore/mapistore_processing.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,247 @@
+/*
+ OpenChange Storage Abstraction Layer library
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 <sys/types.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "mapistore.h"
+#include "mapistore_errors.h"
+#include "mapistore_private.h"
+#include <libmapi/dlinklist.h>
+#include <libmapi/defs_private.h>
+
+#include <tdb.h>
+
+char *mapping_path = NULL;
+
+/**
+ \details Set the mapping path
+
+ \param path pointer to the mapping path
+
+ \note The mapping path can be set unless id_mapping_context is
+ initialized. If path is NULL and mapping path is not yet
+ initialized, then mapping_path will be reset to its default value
+ when the initialization routine is called.
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ int mapistore_set_mapping_path(const char *path)
+{
+ TALLOC_CTX *mem_ctx;
+ DIR *dir;
+
+ /* Case 1. Path is set to NULL */
+ if (!path) {
+ if (mapping_path) {
+ talloc_free(mapping_path);
+ }
+ mapping_path = NULL;
+ return MAPISTORE_SUCCESS;
+ }
+
+ if (mapping_path) {
+ talloc_free(mapping_path);
+ }
+
+ /* Case 2. path is initialized */
+
+ /* Step 1. Check if path is valid path */
+ dir = opendir(path);
+ if (!dir) {
+ return MAPISTORE_ERR_NO_DIRECTORY;
+ }
+
+ /* Step 2. TODO: Check for write permissions */
+
+ mem_ctx = talloc_autofree_context();
+ mapping_path = talloc_strdup(mem_ctx, path);
+ return MAPISTORE_SUCCESS;
+}
+
+/**
+ \details Return the current mapping path
+
+ \return pointer to the mapping path.
+ */
+const char *mapistore_get_mapping_path(void)
+{
+ return (!mapping_path) ? MAPISTORE_MAPPING_PATH : (const char *)mapping_path;
+}
+
+
+/**
+ \details Initialize the ID mapping context or return the existing
+ one if already initialized.
+
+ \param pctx pointer to the processing context
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+int mapistore_init_mapping_context(struct processing_context *pctx)
+{
+ TDB_DATA key;
+ TDB_DATA dbuf;
+ TALLOC_CTX *mem_ctx;
+ char *dbpath;
+ uint64_t last_id;
+ char *tmp_buf;
+ int ret;
+
+ if (!pctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+ if (pctx->mapping_ctx) return MAPISTORE_ERR_ALREADY_INITIALIZED;
+
+ pctx->mapping_ctx = talloc_zero(pctx, struct id_mapping_context);
+ if (!pctx->mapping_ctx) return MAPISTORE_ERR_NO_MEMORY;
+
+ mem_ctx = talloc_named(NULL, 0, "mapistore_init_mapping_context");
+
+ /* Step 1. Open/Create the used ID database */
+ if (!pctx->mapping_ctx->used_ctx) {
+ dbpath = talloc_asprintf(mem_ctx, "%s/%s", mapistore_get_mapping_path(), MAPISTORE_DB_NAME_USED_ID);
+ pctx->mapping_ctx->used_ctx = tdb_wrap_open(pctx, dbpath, 0, 0, O_RDWR|O_CREAT, 0600);
+ talloc_free(dbpath);
+ if (!pctx->mapping_ctx->used_ctx) {
+ DEBUG(3, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, strerror(errno)));
+ talloc_free(mem_ctx);
+ talloc_free(pctx->mapping_ctx);
+ return MAPISTORE_ERR_DATABASE_INIT;
+ }
+ }
+
+ /* Step 2. Open/Create the free ID database */
+ if (!pctx->mapping_ctx->free_ctx) {
+ dbpath = talloc_asprintf(mem_ctx, "%s/%s", mapistore_get_mapping_path(), MAPISTORE_DB_NAME_FREE_ID);
+ pctx->mapping_ctx->free_ctx = tdb_wrap_open(pctx, dbpath, 0, 0, O_RDWR|O_CREAT, 0600);
+ talloc_free(dbpath);
+ if (!pctx->mapping_ctx->free_ctx) {
+ DEBUG(3, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, strerror(errno)));
+ talloc_free(mem_ctx);
+ talloc_free(pctx->mapping_ctx);
+ return MAPISTORE_ERR_DATABASE_INIT;
+ }
+ }
+
+ /* Step 3. Retrieve the last ID value */
+ key.dptr = (unsigned char *) MAPISTORE_DB_LAST_ID_KEY;
+ key.dsize = strlen(MAPISTORE_DB_LAST_ID_KEY);
+
+ dbuf = tdb_fetch(pctx->mapping_ctx->used_ctx->tdb, key);
+
+ /* If the record doesn't exist, insert it */
+ if (!dbuf.dptr || !dbuf.dsize) {
+ dbuf.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%"PRIx64, (uint64_t) MAPISTORE_DB_LAST_ID_VAL);
+ dbuf.dsize = strlen((const char *) dbuf.dptr);
+ last_id = MAPISTORE_DB_LAST_ID_VAL;
+
+ ret = tdb_store(pctx->mapping_ctx->used_ctx->tdb, key, dbuf, TDB_INSERT);
+ talloc_free(dbuf.dptr);
+ if (ret == -1) {
+ DEBUG(3, ("[%s:%d]: Unable to create %s record: %s\n", __FUNCTION__, __LINE__,
+ MAPISTORE_DB_LAST_ID_KEY, tdb_errorstr(pctx->mapping_ctx->used_ctx->tdb)));
+ talloc_free(mem_ctx);
+ talloc_free(pctx->mapping_ctx);
+
+ return MAPISTORE_ERR_DATABASE_OPS;
+ }
+
+ } else {
+ tmp_buf = talloc_strndup(mem_ctx, (char *)dbuf.dptr, dbuf.dsize);
+ free(dbuf.dptr);
+ last_id = strtoull(tmp_buf, NULL, 16);
+ talloc_free(tmp_buf);
+ }
+
+ pctx->mapping_ctx->last_id = last_id;
+
+ talloc_free(mem_ctx);
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Return an unused or new context identifier
+
+ \param pctx pointer to the processing context
+ \param context_id pointer to the context identifier the function
+ returns
+
+ \return a non zero context identifier on success, otherwise 0.
+ */
+int mapistore_get_context_id(struct processing_context *pctx, uint32_t *context_id)
+{
+ struct context_id_list *el;
+
+ /* Sanity checks */
+ if (!pctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+
+ /* Step 1. The free context list doesn't exist yet */
+ if (!pctx->free_ctx) {
+ pctx->last_context_id++;
+ *context_id = pctx->last_context_id;
+ }
+
+ /* Step 2. We have a free list */
+ for (el = pctx->free_ctx; el; el = el->next) {
+ if (el->context_id) {
+ *context_id = el->context_id;
+ DLIST_REMOVE(pctx->free_ctx, el);
+ break;
+ }
+ }
+
+ return MAPISTORE_SUCCESS;
+}
+
+
+/**
+ \details Add a context identifier to the list
+
+ \param pctx pointer to the processing context
+ \param context_id the identifier referencing the context to free
+
+ \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
+ */
+int mapistore_free_context_id(struct processing_context *pctx, uint32_t context_id)
+{
+ struct context_id_list *el;
+
+ /* Sanity checks */
+ if (!pctx) return MAPISTORE_ERR_NOT_INITIALIZED;
+
+ /* Step 1. Ensure the list is not corrupted */
+ for (el = pctx->free_ctx; el; el = el->next) {
+ if (el->context_id == context_id) {
+ return MAPISTORE_ERR_CORRUPTED;
+ }
+ }
+
+ /* Step 2. Create the element and add it to the list */
+ el = talloc_zero((TALLOC_CTX *)pctx, struct context_id_list);
+ el->context_id = context_id;
+ DLIST_ADD_END(pctx->free_ctx, el, struct context_id_list *);
+
+ return MAPISTORE_SUCCESS;
+}
Added: trunk/openchange/mapiproxy/libmapistore/mapistore_tdb_wrap.c
===================================================================
--- trunk/openchange/mapiproxy/libmapistore/mapistore_tdb_wrap.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapistore/mapistore_tdb_wrap.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,132 @@
+/*
+ Unix SMB/CIFS implementation.
+ TDB wrap functions
+
+ Copyright (C) Andrew Tridgell 2004
+ Copyright (C) Jelmer Vernooij <jelmer at samba.org> 2007
+
+ 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 <stdio.h>
+#include <string.h>
+
+#include "mapistore.h"
+#include "mapistore_errors.h"
+#include "mapistore_private.h"
+#include <libmapi/dlinklist.h>
+
+static struct tdb_wrap *tdb_list;
+
+/* destroy the last connection to a tdb */
+static int tdb_wrap_destructor(struct tdb_wrap *w)
+{
+ tdb_close(w->tdb);
+ DLIST_REMOVE(tdb_list, w);
+ return 0;
+}
+
+/*
+ Log tdb messages via DEBUG().
+*/
+static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level,
+ const char *format, ...) PRINTF_ATTRIBUTE(3,4);
+
+static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level,
+ const char *format, ...)
+{
+ va_list ap;
+ char *ptr = NULL;
+ int dl;
+ int ret;
+
+ va_start(ap, format);
+ ret = vasprintf(&ptr, format, ap);
+ va_end(ap);
+
+ switch (level) {
+ case TDB_DEBUG_FATAL:
+ dl = 0;
+ break;
+ case TDB_DEBUG_ERROR:
+ dl = 1;
+ break;
+ case TDB_DEBUG_WARNING:
+ dl = 2;
+ break;
+ case TDB_DEBUG_TRACE:
+ dl = 5;
+ break;
+ default:
+ dl = 0;
+ }
+
+ if (ptr != NULL) {
+ const char *name = tdb_name(tdb);
+ DEBUG(dl, ("tdb(%s): %s", name ? name : "unnamed", ptr));
+ free(ptr);
+ }
+}
+
+
+/**
+ \details wrapped connection to a tdb database
+
+ \param mem_ctx pointer to the memory context
+ \param name tdb database name
+ \param hash_size the hash size
+ \param tdb_flags TDB flags
+ \param open_flags open flags
+ \param mode
+
+ \note to close just talloc_free() the tdb_wrap pointer
+
+ \return pointer to an allocated tdb_wrap structure on success,
+ otherwise NULL
+ */
+struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, const char *name,
+ int hash_size, int tdb_flags,
+ int open_flags, mode_t mode)
+{
+ struct tdb_wrap *w;
+ struct tdb_logging_context log_ctx;
+
+ log_ctx.log_fn = tdb_wrap_log;
+
+ for (w = tdb_list; w; w = w->next) {
+ if (strcmp(name, w->name) == 0) {
+ return talloc_reference(mem_ctx, w);
+ }
+ }
+
+ w = talloc(mem_ctx, struct tdb_wrap);
+ if (w == NULL) {
+ return NULL;
+ }
+
+ w->name = talloc_strdup(w, name);
+
+ w->tdb = tdb_open_ex(name, hash_size, tdb_flags,
+ open_flags, mode, &log_ctx, NULL);
+ if (w->tdb == NULL) {
+ talloc_free(w);
+ return NULL;
+ }
+
+ talloc_set_destructor(w, tdb_wrap_destructor);
+
+ DLIST_ADD(tdb_list, w);
+
+ return w;
+}
Added: trunk/openchange/mapiproxy/libmapistore/tests/mapistore_test.c
===================================================================
--- trunk/openchange/mapiproxy/libmapistore/tests/mapistore_test.c (rev 0)
+++ trunk/openchange/mapiproxy/libmapistore/tests/mapistore_test.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,112 @@
+/*
+ OpenChange Storage Abstraction Layer library test tool
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 "mapiproxy/libmapistore/mapistore.h"
+#include <talloc.h>
+#include <core/ntstatus.h>
+#include <samba/popt.h>
+#include <param.h>
+#include <util/debug.h>
+
+/**
+ \file mapistore_test.c
+
+ \brief Test mapistore implementation
+ */
+
+
+int main(int argc, const char *argv[])
+{
+ TALLOC_CTX *mem_ctx;
+ int retval;
+ struct mapistore_context *mstore_ctx;
+ struct loadparm_context *lp_ctx;
+ poptContext pc;
+ int opt;
+ const char *opt_debug = NULL;
+ uint32_t context_id = 0;
+ uint32_t context_id2 = 0;
+
+ enum { OPT_DEBUG=1000 };
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "debuglevel", 'd', POPT_ARG_STRING, NULL, OPT_DEBUG, "set the debug level", NULL },
+ { NULL, 0, 0, NULL, 0, NULL, NULL }
+ };
+
+ mem_ctx = talloc_named(NULL, 0, "mapistore_test");
+ lp_ctx = loadparm_init(mem_ctx);
+ lp_load_default(lp_ctx);
+ setup_logging(NULL, DEBUG_STDOUT);
+
+ pc = poptGetContext("mapistore_test", argc, argv, long_options, 0);
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_DEBUG:
+ opt_debug = poptGetOptArg(pc);
+ break;
+ }
+ }
+
+ poptFreeContext(pc);
+
+ if (opt_debug) {
+ lp_set_cmdline(lp_ctx, "log level", opt_debug);
+ }
+
+ retval = mapistore_set_mapping_path("/tmp");
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(0, ("%s\n", mapistore_errstr(retval)));
+ exit (1);
+ }
+
+ mstore_ctx = mapistore_init(mem_ctx, NULL);
+ if (!mstore_ctx) {
+ DEBUG(0, ("%s\n", mapistore_errstr(retval)));
+ exit (1);
+ }
+
+ retval = mapistore_add_context(mstore_ctx, "sqlite:///tmp/test.db", &context_id);
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(0, ("%s\n", mapistore_errstr(retval)));
+ exit (1);
+ }
+
+ retval = mapistore_add_context(mstore_ctx, "sqlite:///tmp/test2.db", &context_id2);
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(0, ("%s\n", mapistore_errstr(retval)));
+ exit (1);
+ }
+
+ DEBUG(0, ("Context ID: [1] = %d and [2] = %d\n", context_id, context_id2));
+
+ retval = mapistore_del_context(mstore_ctx, context_id);
+ retval = mapistore_del_context(mstore_ctx, context_id2);
+
+ retval = mapistore_release(mstore_ctx);
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(0, ("%s\n", mapistore_errstr(retval)));
+ exit (1);
+ }
+
+ return 0;
+}
Added: trunk/openchange/mapiproxy/libmapistore.pc.in
===================================================================
--- trunk/openchange/mapiproxy/libmapistore.pc.in (rev 0)
+++ trunk/openchange/mapiproxy/libmapistore.pc.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@prefix@/share
+datadir=@datadir@
+
+Name: MAPISTORE
+Description: MAPI Storage Abstraction Layer library
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lmapistore
+Libs.private: @LIBS@
+Cflags: -I${includedir}
+Requires: talloc tdb
Added: trunk/openchange/mapiproxy/modules/mpm_cache.c
===================================================================
--- trunk/openchange/mapiproxy/modules/mpm_cache.c (rev 0)
+++ trunk/openchange/mapiproxy/modules/mpm_cache.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1174 @@
+/*
+ MAPI Proxy - Cache module
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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/>.
+ */
+
+/**
+ \file mpm_cache.c
+
+ \brief Cache messages and attachments so we can reduce WAN traffic
+ */
+
+#include <libmapi/libmapi.h>
+#include <libmapi/defs_private.h>
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/libmapiproxy/libmapiproxy.h"
+#include "mapiproxy/modules/mpm_cache.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <time.h>
+
+struct mpm_cache *mpm = NULL;
+
+/**
+ \details Find the position of the given MAPI call in a serialized
+ MAPI request.
+
+ If the request includes a Release call, then request and replies
+ indexes for other calls will mismatch.
+
+ \param opnum The MAPI opnum to seek
+ \param mapi_req Pointer to the MAPI request calls array
+
+ \return On success, returns the call position, otherwise -1.
+ */
+static uint32_t cache_find_call_request_index(uint8_t opnum, struct EcDoRpc_MAPI_REQ *mapi_req)
+{
+ uint32_t i;
+
+ for (i = 0; mapi_req[i].opnum; i++) {
+ if (mapi_req[i].opnum == opnum) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ \details Dump time statistic between OpenStream and Release
+
+ This function monitors the effective time required to open, read
+ and close a stream.
+
+ \param stream the mpm_stream entry
+ */
+static void cache_dump_stream_stat(struct mpm_stream *stream)
+{
+ TALLOC_CTX *mem_ctx;
+ struct timeval tv_end;
+ uint64_t sec;
+ uint64_t usec;
+ char *name;
+ const char *stage;
+
+ mem_ctx = (TALLOC_CTX *)mpm;
+
+ if (stream->attachment) {
+ name = talloc_asprintf(mem_ctx, "0x%"PRIx64"/0x%"PRIx64"/%d",
+ stream->attachment->message->FolderId,
+ stream->attachment->message->MessageId,
+ stream->attachment->AttachmentID);
+ } else if (stream->message) {
+ name = talloc_asprintf(mem_ctx, "0x%"PRIx64"/0x%"PRIx64,
+ stream->message->FolderId,
+ stream->message->MessageId);
+ } else {
+ return;
+ }
+
+ gettimeofday(&tv_end, NULL);
+ sec = tv_end.tv_sec - stream->tv_start.tv_sec;
+ if ((tv_end.tv_usec - stream->tv_start.tv_usec) < 0) {
+ sec -= 1;
+ usec = tv_end.tv_usec + stream->tv_start.tv_usec;
+ while (usec > 1000000) {
+ usec -= 1000000;
+ sec += 1;
+ }
+ } else {
+ usec = tv_end.tv_usec - stream->tv_start.tv_usec;
+ }
+
+ if (stream->ahead == true) {
+ stage = "[read ahead]";
+ } else if ((stream->ahead == false) && (stream->cached == true)) {
+ stage = "[cached mode]";
+ } else {
+ stage = "[non cached]";
+ }
+
+ DEBUG(1, ("STATISTIC: %-20s %s The difference is %ld seconds %ld microseconds\n",
+ stage, name, (long int)sec, (long int)usec));
+ talloc_free(name);
+}
+
+
+/**
+ \details
+
+ 1. close the existing FILE *
+ 2. build complete file path
+ 3. replace __FILE__ arguments with complete file path
+ 4. call execve
+ 5. stat the sync'd file
+ 6. open the stream again
+ 7. mark the file as cached
+
+ \param stream pointer on the mpm_stream entry
+ */
+static NTSTATUS cache_exec_sync_cmd(struct mpm_stream *stream)
+{
+ uint32_t i;
+ int ret = 0;
+ char **args;
+ struct stat sb;
+ pid_t pid;
+ int status;
+
+ mpm_cache_stream_close(stream);
+
+ for (i = 0; mpm->sync_cmd[i]; i++);
+
+ args = talloc_array((TALLOC_CTX *)mpm, char *, i + 1);
+
+ for (i = 0; mpm->sync_cmd[i]; i++){
+ if (strstr(mpm->sync_cmd[i], "__FILE__")) {
+ args[i] = string_sub_talloc((TALLOC_CTX *)args, mpm->sync_cmd[i], "__FILE__", stream->filename);
+ } else {
+ args[i] = talloc_strdup((TALLOC_CTX *)args, mpm->sync_cmd[i]);
+ }
+ }
+ args[i] = NULL;
+
+ for (i = 0; args[i]; i++){
+ DEBUG(0, ("'%s' ", args[i]));
+ }
+ DEBUG(0, ("\n"));
+
+ switch(pid = fork()) {
+ case -1:
+ DEBUG(0, ("Failed to fork\n"));
+ break;
+ case 0:
+ ret = execve(args[0], args, NULL);
+ break;
+ default:
+ wait(&status);
+ break;
+ }
+ talloc_free(args);
+ if (ret == -1) {
+ perror("execve: ");
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ stat(stream->filename, &sb);
+ if (sb.st_size != stream->StreamSize) {
+ DEBUG(0, ("Sync'd file size is 0x%x and 0x%x was expected\n",
+ (uint32_t)sb.st_size, stream->StreamSize));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ mpm_cache_stream_open(mpm, stream);
+ stream->cached = true;
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Track down Release calls and update the mpm_cache global
+ list - removing associated entries.
+
+ This function recursively remove child entries whenever necessary.
+
+ \param dce_call pointer to the session context
+ \param EcDoRpc pointer to the EcDoRpc operation
+ \param handle_idx the handle to track down
+
+ \return NT_STATUS_OK
+ */
+static NTSTATUS cache_pull_Release(struct dcesrv_call_state *dce_call,
+ struct EcDoRpc *EcDoRpc,
+ uint32_t handle_idx)
+{
+ struct mpm_message *message;
+ struct mpm_attachment *attach;
+ struct mpm_stream *stream;
+
+ /* Look over messages */
+ for (message = mpm->messages; message; message = message->next) {
+ if ((mpm_session_cmp(message->session, dce_call) == true) &&
+ (EcDoRpc->in.mapi_request->handles[handle_idx] == message->handle)) {
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Del: Message 0x%"PRIx64" 0x%"PRIx64": 0x%x\n",
+ MPM_LOCATION, MPM_SESSION(message), message->FolderId,
+ message->MessageId, message->handle));
+
+ /* Loop over children attachments */
+ attach = mpm->attachments;
+ while (attach) {
+ if ((mpm_session_cmp(attach->session, dce_call) == true) &&
+ (message->handle == attach->parent_handle)) {
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Del recursive 1: Attachment %d: 0x%x\n", MPM_LOCATION,
+ MPM_SESSION(attach), attach->AttachmentID, attach->handle));
+
+ /* Loop over children streams */
+ stream = mpm->streams;
+ while (stream) {
+ if ((mpm_session_cmp(stream->session, dce_call) == true) &&
+ (attach->handle == stream->parent_handle)) {
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Del recursive 1-2: Stream 0x%x\n",
+ MPM_LOCATION, MPM_SESSION(stream), stream->handle));
+ mpm_session_release(stream->session);
+ mpm_cache_stream_close(stream);
+ talloc_free(stream->filename);
+ DLIST_REMOVE(mpm->streams, stream);
+ talloc_free(stream);
+ stream = mpm->streams;
+ } else {
+ stream = stream->next;
+ }
+ }
+
+ mpm_session_release(attach->session);
+ DLIST_REMOVE(mpm->attachments, attach);
+ talloc_free(attach);
+ attach = mpm->attachments;
+ } else {
+ attach = attach->next;
+ }
+ }
+
+ /* Look over children streams */
+ stream = mpm->streams;
+ while (stream) {
+ if ((mpm_session_cmp(stream->session, dce_call) == true) &&
+ (message->handle == stream->parent_handle)) {
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Del recursive 1: Stream 0x%x\n",
+ MPM_LOCATION, MPM_SESSION(stream), stream->handle));
+ mpm_session_release(stream->session);
+ mpm_cache_stream_close(stream);
+ DLIST_REMOVE(mpm->streams, stream);
+ talloc_free(stream->filename);
+ talloc_free(stream);
+ stream = mpm->streams;
+ } else {
+ stream = stream->next;
+ }
+ }
+
+ mpm_session_release(message->session);
+ DLIST_REMOVE(mpm->messages, message);
+ talloc_free(message);
+ return NT_STATUS_OK;
+ }
+ }
+
+ /* Look over attachments */
+ for (attach = mpm->attachments; attach; attach = attach->next) {
+ if ((mpm_session_cmp(attach->session, dce_call) == true) &&
+ (EcDoRpc->in.mapi_request->handles[handle_idx] == attach->handle)) {
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Del: Attachment %d: 0x%x\n", MPM_LOCATION,
+ MPM_SESSION(attach), attach->AttachmentID, attach->handle));
+
+
+ /* Loop over children streams */
+ stream = mpm->streams;
+ while (stream) {
+ if ((mpm_session_cmp(stream->session, dce_call) == true) &&
+ (attach->handle == stream->parent_handle)) {
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Del recursive 2: Stream 0x%x\n",
+ MPM_LOCATION, MPM_SESSION(stream), stream->handle));
+ mpm_session_release(stream->session);
+ mpm_cache_stream_close(stream);
+ DLIST_REMOVE(mpm->streams, stream);
+ talloc_free(stream->filename);
+ talloc_free(stream);
+ stream = mpm->streams;
+ } else {
+ stream = stream->next;
+ }
+ }
+
+ mpm_session_release(attach->session);
+ DLIST_REMOVE(mpm->attachments, attach);
+ talloc_free(attach);
+ return NT_STATUS_OK;
+ }
+ }
+
+ /* Look over streams */
+ for (stream = mpm->streams; stream; stream = stream->next) {
+ if ((mpm_session_cmp(stream->session, dce_call) == true) &&
+ (EcDoRpc->in.mapi_request->handles[handle_idx] == stream->handle)) {
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Del: Stream 0x%x\n", MPM_LOCATION,
+ MPM_SESSION(stream), stream->handle));
+ mpm_session_release(stream->session);
+ mpm_cache_stream_close(stream);
+ DLIST_REMOVE(mpm->streams, stream);
+ talloc_free(stream->filename);
+ talloc_free(stream);
+ return NT_STATUS_OK;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Monitor OpenMessage requests and register a message in the
+ mpm_messages list.
+
+ This is the first step for message registration:
+ * set Folder ID and Message ID
+ * set the handle to 0xFFFFFFFF
+ * Insert the message to the list
+
+ \param dce_call pointer to the session context
+ \param mem_ctx the memory context
+ \param request reference to the OpenMessage request
+
+ \return NT_STATUS_OK on success
+ */
+static NTSTATUS cache_pull_OpenMessage(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct OpenMessage_req request)
+{
+ struct mpm_message *message;
+
+ /* Check if the message has already been registered */
+ for (message = mpm->messages; message; message = message->next) {
+ if ((mpm_session_cmp(message->session, dce_call) == true) &&
+ (request.FolderId == message->FolderId) &&
+ (request.MessageId == message->MessageId)) {
+ DLIST_REMOVE(mpm->messages, message);
+ }
+ }
+
+ message = talloc((TALLOC_CTX *)mpm, struct mpm_message);
+ NT_STATUS_HAVE_NO_MEMORY(message);
+
+ message->session = mpm_session_init((TALLOC_CTX *)mpm, dce_call);
+ NT_STATUS_HAVE_NO_MEMORY(message->session);
+
+ message->FolderId = request.FolderId;
+ message->MessageId = request.MessageId;
+ message->handle = 0xFFFFFFFF;
+
+ DLIST_ADD_END(mpm->messages, message, struct mpm_message *);
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Monitor OpenMessage replies and store OpenMessage MAPI
+ handle.
+
+ This is the second step for message registration:
+
+ * Seek for a given FolderId/MessageId in the mpm_message list
+
+ * If a match is found (expected) and MAPI retval is set to
+ MAPI_E_SUCCESS, update the handle field for the element and
+ commit this message in the tdb store.
+
+ * If retval is different from MAPI_E_SUCCESS, then delete the
+ record
+
+
+ \param dce_call pointer to the session context
+ \param mapi_req reference to the OpenMessage MAPI request entry
+ \param mapi_repl reference to the OpenMessage MAPI response entry
+ \param EcDoRpc pointer to the current EcDoRpc operation
+
+ \return NT_STATUS_OK
+ */
+static NTSTATUS cache_push_OpenMessage(struct dcesrv_call_state *dce_call,
+ struct EcDoRpc_MAPI_REQ mapi_req,
+ struct EcDoRpc_MAPI_REPL mapi_repl,
+ struct EcDoRpc *EcDoRpc)
+{
+ struct mpm_message *el;
+ struct mapi_response *mapi_response;
+ struct OpenMessage_req request;
+
+ request = mapi_req.u.mapi_OpenMessage;
+
+ mapi_response = EcDoRpc->out.mapi_response;
+
+ for (el = mpm->messages; el; el = el->next) {
+ if ((el->FolderId == request.FolderId) && (el->MessageId == request.MessageId) &&
+ (mpm_session_cmp(el->session, dce_call) == true)) {
+ if (mapi_repl.error_code == MAPI_E_SUCCESS) {
+ mpm_cache_ldb_add_message((TALLOC_CTX *)mpm, mpm->ldb_ctx, el);
+ el->handle = mapi_response->handles[request.handle_idx];
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Add: Message 0x%"PRIx64" 0x%"PRIx64" 0x%x\n",
+ MPM_LOCATION, MPM_SESSION(el), el->FolderId, el->MessageId, el->handle));
+ } else {
+ DEBUG(0, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Del: Message OpenMessage returned %s\n",
+ MPM_LOCATION, MPM_SESSION(el), mapi_get_errstr(mapi_repl.error_code)));
+ DLIST_REMOVE(mpm->messages, el);
+ }
+ return NT_STATUS_OK;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Monitor OpenAttach requests and register an attachment in
+ the mpm_messages list.
+
+ This is the first step for attachment registration. This
+ function first ensures the attachment is not already registered,
+ otherwise delete it. It next creates the attachment entry in the
+ global mpm_message structure.
+
+ \param dce_call pointer to the session context
+ \param mem_ctx the memory context
+ \param mapi_req reference to the OpenAttach EcDoRpc_MAPI_REQ entry
+ \param EcDoRpc pointer to the EcDoRpc operation
+
+ \return NT_STATUS_OK on success, otherwise NT_STATUS_NO_MEMORY
+ */
+static NTSTATUS cache_pull_OpenAttach(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcDoRpc_MAPI_REQ mapi_req,
+ struct EcDoRpc *EcDoRpc)
+{
+ struct mpm_message *el;
+ struct mpm_attachment *attach;
+ struct mapi_request *mapi_request;
+ struct OpenAttach_req request;
+
+ mapi_request = EcDoRpc->in.mapi_request;
+ request = mapi_req.u.mapi_OpenAttach;
+
+ for (attach = mpm->attachments; attach; attach = attach->next) {
+ /* Check if the attachment has already been registered */
+ if ((mpm_session_cmp(attach->session, dce_call) == true) &&
+ (mapi_request->handles[mapi_req.handle_idx] == attach->parent_handle) && (request.AttachmentID == attach->AttachmentID)) {
+ DLIST_REMOVE(mpm->attachments, attach);
+ }
+ }
+
+ attach = talloc((TALLOC_CTX *)mpm, struct mpm_attachment);
+ NT_STATUS_HAVE_NO_MEMORY(attach);
+
+ attach->session = mpm_session_init((TALLOC_CTX *)mpm, dce_call);
+ NT_STATUS_HAVE_NO_MEMORY(attach->session);
+
+ attach->AttachmentID = request.AttachmentID;
+ attach->parent_handle = mapi_request->handles[mapi_req.handle_idx];
+ attach->handle = 0xFFFFFFFF;
+
+ for (el = mpm->messages; el; el = el->next) {
+ if ((mpm_session_cmp(el->session, dce_call) == true) && attach->parent_handle == el->handle) {
+ attach->message = el;
+ break;
+ }
+ }
+
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Add [1]: Attachment %d parent handle (0x%x) 0x%"PRIx64", 0x%"PRIx64" added to the list\n",
+ MPM_LOCATION, MPM_SESSION(attach), request.AttachmentID, attach->parent_handle,
+ attach->message->FolderId, attach->message->MessageId));
+ DLIST_ADD_END(mpm->attachments, attach, struct mpm_attachment *);
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Monitor OpenAttach replies and store OpenAttach MAPI
+ handle.
+
+ This is the second step for attachment registration:
+
+ * Seek for a given parent_handle/attachmentID in the
+ mpm_attachments list.
+
+ * if a match is found (expected) and MAPI retval is set to
+ MAPI_E_SUCCESS, update the handle parameter for the element and
+ commit this attachment in the tdb store.
+
+ * If retval is different from MAPI_E_SUCCESS, then delete the
+ element.
+
+ \param dce_call pointer to the session context
+ \param mapi_req reference to the OpenAttach request entry
+ \param mapi_repl reference to the OpenAttach MAPI response entry
+ \param EcDoRpc pointer to the current EcDoRpc operation
+
+ \return NT_STATUS_OK
+
+ */
+static NTSTATUS cache_push_OpenAttach(struct dcesrv_call_state *dce_call,
+ struct EcDoRpc_MAPI_REQ mapi_req,
+ struct EcDoRpc_MAPI_REPL mapi_repl,
+ struct EcDoRpc *EcDoRpc)
+{
+ struct mpm_attachment *el;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct OpenAttach_req request;
+
+ mapi_request = EcDoRpc->in.mapi_request;
+ mapi_response = EcDoRpc->out.mapi_response;
+ request = mapi_req.u.mapi_OpenAttach;
+
+ for (el = mpm->attachments; el; el = el->next) {
+ if ((mpm_session_cmp(el->session, dce_call) == true) &&
+ (mapi_request->handles[mapi_req.handle_idx] == el->parent_handle) &&
+ (request.AttachmentID == el->AttachmentID)) {
+ if (mapi_repl.error_code == MAPI_E_SUCCESS) {
+ el->handle = mapi_response->handles[request.handle_idx];
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Add [2]: Attachment %d with handle 0x%x and parent handle 0x%x\n",
+ MPM_LOCATION, MPM_SESSION(el), el->AttachmentID, el->handle, el->parent_handle));
+ mpm_cache_ldb_add_attachment((TALLOC_CTX *)mpm, mpm->ldb_ctx, el);
+ } else {
+ DEBUG(0, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Del: Attachment OpenAttach returned %s\n",
+ MPM_LOCATION, MPM_SESSION(el), mapi_get_errstr(mapi_repl.error_code)));
+ DLIST_REMOVE(mpm->attachments, el);
+ }
+ return NT_STATUS_OK;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Monitor OpenStream requests and register a stream in the
+ mpm_streams list.
+
+ We are only interested in monitoring streams related to attachments
+ or messages. This is the first step for stream registration:
+
+ * Look whether this stream inherits from a message or attachment
+ * Fill the stream element according to previous statement
+ * Add it to the mpm_stream list
+
+ \param dce_call pointer to the session context
+ \param mem_ctx the memory context
+ \param mapi_req reference to the OpenStream MAPI request
+ \param EcDoRpc pointer to the current EcDoRpc operation
+
+ \return NT_STATUS_OK on success, otherwise NT_STATUS_NO_MEMORY
+ */
+static NTSTATUS cache_pull_OpenStream(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcDoRpc_MAPI_REQ mapi_req,
+ struct EcDoRpc *EcDoRpc)
+{
+ struct mpm_stream *stream;
+ struct mpm_attachment *attach;
+ struct mpm_message *message;
+ struct mapi_request *mapi_request;
+ struct OpenStream_req request;
+
+ mapi_request = EcDoRpc->in.mapi_request;
+ request = mapi_req.u.mapi_OpenStream;
+
+ for (attach = mpm->attachments; attach; attach = attach->next) {
+ if ((mpm_session_cmp(attach->session, dce_call) == true) &&
+ mapi_request->handles[mapi_req.handle_idx] == attach->handle) {
+ stream = talloc((TALLOC_CTX *)mpm, struct mpm_stream);
+ NT_STATUS_HAVE_NO_MEMORY(stream);
+
+ stream->session = mpm_session_init((TALLOC_CTX *)mpm, dce_call);
+ NT_STATUS_HAVE_NO_MEMORY(stream->session);
+
+ stream->handle = 0xFFFFFFFF;
+ stream->parent_handle = attach->handle;
+ stream->PropertyTag = request.PropertyTag;
+ stream->StreamSize = 0;
+ stream->filename = NULL;
+ stream->attachment = attach;
+ stream->cached = false;
+ stream->message = NULL;
+ stream->ahead = (mpm->ahead == true) ? true : false;
+ gettimeofday(&stream->tv_start, NULL);
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Stream::attachment added 0x%x 0x%"PRIx64" 0x%"PRIx64"\n",
+ MPM_LOCATION, MPM_SESSION(stream), stream->parent_handle,
+ stream->attachment->message->FolderId, stream->attachment->message->MessageId));
+ DLIST_ADD_END(mpm->streams, stream, struct mpm_stream *);
+ return NT_STATUS_OK;
+ }
+ }
+
+ for (message = mpm->messages; message; message = message->next) {
+ if ((mpm_session_cmp(message->session, dce_call) == true) &&
+ mapi_request->handles[mapi_req.handle_idx] == message->handle) {
+ stream = talloc((TALLOC_CTX *)mpm, struct mpm_stream);
+ NT_STATUS_HAVE_NO_MEMORY(stream);
+
+ stream->session = mpm_session_init((TALLOC_CTX *)mpm, dce_call);
+ NT_STATUS_HAVE_NO_MEMORY(stream->session);
+
+ stream->handle = 0xFFFFFFFF;
+ stream->parent_handle = message->handle;
+ stream->PropertyTag = request.PropertyTag;
+ stream->StreamSize = 0;
+ stream->filename = NULL;
+ stream->attachment = NULL;
+ stream->cached = false;
+ stream->ahead = (mpm->ahead == true) ? true : false;
+ gettimeofday(&stream->tv_start, NULL);
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Stream::message added 0x%x\n",
+ MPM_LOCATION, MPM_SESSION(stream), stream->parent_handle));
+ stream->message = message;
+ DLIST_ADD_END(mpm->streams, stream, struct mpm_stream *);
+ return NT_STATUS_OK;
+ }
+ }
+
+ DEBUG(1, ("* [%s:%d] Stream: Not related to any attachment or message ?!?\n",
+ MPM_LOCATION));
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Monitor OpenStream replies and store the OpenStream MAPI
+ handle.
+
+ This is the second step for stream registration:
+
+ * Seek the parent_handle/PropertyTag couple in the mpm_streams
+ list.
+
+ * If a match is found (expected) and MAPI retval is set to
+ MAPI_E_SUCCESS, update the handle field and StreamSize parameters
+ for the element and commit this stream in the tdb store.
+
+ * If retval is different from MAPI_E_SUCCESS, then delete the
+ * element.
+
+ \param dce_call pointer to the session context
+ \param mapi_req reference to the OpenStream MAPI request entry
+ \param mapi_repl reference to the OpenStream MAPI response entry
+ \param EcDoRpc pointer to the current EcDoRpc operation
+
+ \return NT_STATUS_OK
+ */
+static NTSTATUS cache_push_OpenStream(struct dcesrv_call_state *dce_call,
+ struct EcDoRpc_MAPI_REQ mapi_req,
+ struct EcDoRpc_MAPI_REPL mapi_repl,
+ struct EcDoRpc *EcDoRpc)
+{
+ struct mpm_stream *el;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct OpenStream_req request;
+ struct OpenStream_repl response;
+
+ mapi_request = EcDoRpc->in.mapi_request;
+ mapi_response = EcDoRpc->out.mapi_response;
+ request = mapi_req.u.mapi_OpenStream;
+ response = mapi_repl.u.mapi_OpenStream;
+
+ for (el = mpm->streams; el; el = el->next) {
+ if ((mpm_session_cmp(el->session, dce_call) == true) &&
+ (mapi_request->handles[mapi_req.handle_idx] == el->parent_handle)) {
+ if (request.PropertyTag == el->PropertyTag) {
+ if (mapi_repl.error_code == MAPI_E_SUCCESS) {
+ el->handle = mapi_response->handles[request.handle_idx];
+ el->StreamSize = response.StreamSize;
+ DEBUG(2, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Add [2]: Stream for Property Tag 0x%x, handle 0x%x and size = %d\n",
+ MPM_LOCATION, MPM_SESSION(el), el->PropertyTag, el->handle, el->StreamSize));
+ mpm_cache_ldb_add_stream(mpm, mpm->ldb_ctx, el);
+ } else {
+ DEBUG(0, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Del: Stream OpenStream returned %s\n",
+ MPM_LOCATION, MPM_SESSION(el), mapi_get_errstr(mapi_repl.error_code)));
+ DLIST_REMOVE(mpm->streams, el);
+ }
+ return NT_STATUS_OK;
+ }
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Monitor ReadStream replies.
+
+ This function writes ReadStream data received from remote server
+ and associated to messages or attachments to the opened associated
+ file. This function only writes data if the file is not already
+ cached, otherwise it just returns.
+
+ \param dce_call pointer to the session context
+ \param mapi_req reference to the ReadStream MAPI request
+ \param mapi_repl reference to the ReadStream MAPI reply
+ \param EcDoRpc pointer to the current EcDoRpc operation
+
+ \return NT_STATUS_OK
+
+ \sa cache_dispatch
+ */
+static NTSTATUS cache_push_ReadStream(struct dcesrv_call_state *dce_call,
+ struct EcDoRpc_MAPI_REQ mapi_req,
+ struct EcDoRpc_MAPI_REPL mapi_repl,
+ struct EcDoRpc *EcDoRpc)
+{
+ struct mpm_stream *stream;
+ struct mapi_response *mapi_response;
+ struct ReadStream_repl response;
+ struct ReadStream_req request;
+
+ mapi_response = EcDoRpc->out.mapi_response;
+ response = mapi_repl.u.mapi_ReadStream;
+ request = mapi_req.u.mapi_ReadStream;
+
+ /* Check if the handle is registered */
+ for (stream = mpm->streams; stream; stream = stream->next) {
+ if ((mpm_session_cmp(stream->session, dce_call) == true) &&
+ mapi_response->handles[mapi_repl.handle_idx] == stream->handle) {
+ if (stream->fp && stream->cached == false) {
+ if (mpm->sync == true && stream->StreamSize > mpm->sync_min) {
+ cache_exec_sync_cmd(stream);
+ } else {
+ DEBUG(5, ("* [%s:%d] [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] %zd bytes from remove server\n",
+ MPM_LOCATION, MPM_SESSION(stream), response.data.length));
+ mpm_cache_stream_write(stream, response.data.length, response.data.data);
+ if (stream->offset == stream->StreamSize) {
+ if (response.data.length) {
+ cache_dump_stream_stat(stream);
+ }
+ }
+ }
+ } else if (stream->cached == true) {
+ /* This is managed by the dispatch routine */
+ }
+ return NT_STATUS_OK;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Analyze EcDoRpc MAPI requests
+
+ This function loops over EcDoRpc MAPI calls and search for the
+ opnums required by the cache module to monitor Stream traffic
+ properly.
+
+ \param dce_call the session context
+ \param mem_ctx the memory context
+ \param r generic pointer on EcDoRpc operation
+
+ \return NT_STATUS_OK
+ */
+static NTSTATUS cache_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
+{
+ struct EcDoRpc *EcDoRpc;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ uint32_t i;
+
+ if (dce_call->pkt.u.request.opnum != 0x2) {
+ return NT_STATUS_OK;
+ }
+
+ EcDoRpc = (struct EcDoRpc *) r;
+ if (!EcDoRpc) return NT_STATUS_OK;
+ if (!&(EcDoRpc->in)) return NT_STATUS_OK;
+ if (!EcDoRpc->in.mapi_request) return NT_STATUS_OK;
+ if (!EcDoRpc->in.mapi_request->mapi_req) return NT_STATUS_OK;
+
+ /* If this is an idle request, do not go further */
+ if (EcDoRpc->in.mapi_request->length == 2) {
+ return NT_STATUS_OK;
+ }
+
+ mapi_req = EcDoRpc->in.mapi_request->mapi_req;
+ for (i = 0; mapi_req[i].opnum; i++) {
+ switch (mapi_req[i].opnum) {
+ case op_MAPI_OpenMessage:
+ cache_pull_OpenMessage(dce_call, (TALLOC_CTX *)mpm, mapi_req[i].u.mapi_OpenMessage);
+ break;
+ case op_MAPI_OpenAttach:
+ cache_pull_OpenAttach(dce_call, (TALLOC_CTX *)mpm, mapi_req[i], EcDoRpc);
+ break;
+ case op_MAPI_OpenStream:
+ cache_pull_OpenStream(dce_call, (TALLOC_CTX *)mpm, mapi_req[i], EcDoRpc);
+ break;
+ case op_MAPI_Release:
+ cache_pull_Release(dce_call, EcDoRpc, mapi_req[i].handle_idx);
+ break;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Analyze EcDoRpc MAPI responses
+
+ This function loops over EcDoRpc MAPI calls and search for the
+ opnums required by the cache module to monitor Stream traffic
+ properly.
+
+ \param dce_call pointer to the session context
+ \param mem_ctx the memory context
+ \param r generic pointer on EcDoRpc operation
+
+ \return NT_STATUS_OK
+ */
+static NTSTATUS cache_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
+{
+ struct EcDoRpc *EcDoRpc;
+ struct EcDoRpc_MAPI_REPL *mapi_repl;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ uint32_t i;
+ uint32_t index;
+
+ if (dce_call->pkt.u.request.opnum != 0x2) {
+ return NT_STATUS_OK;
+ }
+
+ EcDoRpc = (struct EcDoRpc *) r;
+ if (!EcDoRpc) return NT_STATUS_OK;
+ if (!&(EcDoRpc->out)) return NT_STATUS_OK;
+ if (!EcDoRpc->out.mapi_response) return NT_STATUS_OK;
+ if (!EcDoRpc->out.mapi_response->mapi_repl) return NT_STATUS_OK;
+
+ /* If this is an idle request, do not got further */
+ if (EcDoRpc->out.mapi_response->length == 2) {
+ return NT_STATUS_OK;
+ }
+
+ mapi_repl = EcDoRpc->out.mapi_response->mapi_repl;
+ mapi_req = EcDoRpc->in.mapi_request->mapi_req;
+
+ for (i = 0; mapi_repl[i].opnum; i++) {
+ switch (mapi_repl[i].opnum) {
+ case op_MAPI_OpenMessage:
+ index = cache_find_call_request_index(op_MAPI_OpenMessage, mapi_req);
+ if (index == -1) break;
+ cache_push_OpenMessage(dce_call, mapi_req[index], mapi_repl[i], EcDoRpc);
+ break;
+ case op_MAPI_OpenAttach:
+ index = cache_find_call_request_index(op_MAPI_OpenAttach, mapi_req);
+ if (index == -1) break;
+ cache_push_OpenAttach(dce_call, mapi_req[index], mapi_repl[i], EcDoRpc);
+ break;
+ case op_MAPI_OpenStream:
+ index = cache_find_call_request_index(op_MAPI_OpenStream, mapi_req);
+ if (index == -1) break;
+ cache_push_OpenStream(dce_call, mapi_req[index], mapi_repl[i], EcDoRpc);
+ break;
+ case op_MAPI_ReadStream:
+ index = cache_find_call_request_index(op_MAPI_ReadStream, mapi_req);
+ if (index == -1) break;
+ cache_push_ReadStream(dce_call, mapi_req[index], mapi_repl[i], EcDoRpc);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Dispatch function.
+
+ This function avoids calling dcerpc_ndr_request - understand
+ forwarding client request to remove server - when the client is
+ reading a message/attachment stream available in the cache.
+
+ This function can also be used to loop over dcerpc_ndr_request and
+ perform a read-ahead operation.
+
+ \param dce_call the session context
+ \param mem_ctx the memory context
+ \param r pointer on EcDoRpc operation
+ \param mapiproxy pointer to a mapiproxy structure controlling
+ mapiproxy behavior.
+
+ \return NT_STATUS_OK
+ */
+static NTSTATUS cache_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ void *r, struct mapiproxy *mapiproxy)
+{
+ struct EcDoRpc *EcDoRpc;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct mpm_stream *stream;
+ uint32_t i;
+ uint32_t count;
+
+ if (dce_call->pkt.u.request.opnum != 0x2) {
+ return NT_STATUS_OK;
+ }
+
+ EcDoRpc = (struct EcDoRpc *) r;
+ if (!EcDoRpc->in.mapi_request->mapi_req) return NT_STATUS_OK;
+
+ /* If this is an idle request, do not got further */
+ if (EcDoRpc->in.mapi_request->length == 2) {
+ return NT_STATUS_OK;
+ }
+
+ mapi_request = EcDoRpc->in.mapi_request;
+ mapi_response = EcDoRpc->out.mapi_response;
+ mapi_req = mapi_request->mapi_req;
+
+ for (count = 0, i = 0; mapi_req[i].opnum; i++) {
+ switch (mapi_req[i].opnum) {
+ case op_MAPI_ReadStream:
+ count++;
+ break;
+ }
+ }
+
+ /* If we have more than count cached calls, forward to Exchange */
+ if (i > count) return NT_STATUS_OK;
+
+ for (i = 0; mapi_req[i].opnum; i++) {
+ switch (mapi_req[i].opnum) {
+ case op_MAPI_ReadStream:
+ {
+ struct ReadStream_req request;
+
+ request = mapi_req[i].u.mapi_ReadStream;
+ for (stream = mpm->streams; stream; stream = stream->next) {
+ if ((mpm_session_cmp(stream->session, dce_call) == true) &&
+ (mapi_request->handles[mapi_req[i].handle_idx] == stream->handle)) {
+ if (stream->cached == true) {
+ cached:
+ mapiproxy->norelay = true;
+ mapiproxy->ahead = false;
+ /* Create a fake ReadStream reply */
+ mapi_response->mapi_repl = talloc_array(mem_ctx, struct EcDoRpc_MAPI_REPL, i + 2);
+ mapi_response->mapi_repl[i].opnum = op_MAPI_ReadStream;
+ mapi_response->mapi_repl[i].handle_idx = mapi_req[i].handle_idx;
+ mapi_response->mapi_repl[i].error_code = MAPI_E_SUCCESS;
+ mapi_response->mapi_repl[i].u.mapi_ReadStream.data.length = 0;
+ mapi_response->mapi_repl[i].u.mapi_ReadStream.data.data = talloc_size(mem_ctx, request.ByteCount);
+ mpm_cache_stream_read(stream, (size_t) request.ByteCount,
+ &mapi_response->mapi_repl[i].u.mapi_ReadStream.data.length,
+ &mapi_response->mapi_repl[i].u.mapi_ReadStream.data.data);
+ if (stream->offset == stream->StreamSize) {
+ if (mapi_response->mapi_repl[i].u.mapi_ReadStream.data.length) {
+ cache_dump_stream_stat(stream);
+ }
+ }
+ DEBUG(5, ("* [%s:%d] %zd bytes read from cache\n", MPM_LOCATION,
+ mapi_response->mapi_repl[i].u.mapi_ReadStream.data.length));
+ mapi_response->handles = talloc_array(mem_ctx, uint32_t, 1);
+ mapi_response->handles[0] = stream->handle;
+ mapi_response->mapi_len = 0xE + mapi_response->mapi_repl[i].u.mapi_ReadStream.data.length;
+ mapi_response->length = mapi_response->mapi_len - 4;
+ *EcDoRpc->out.length = mapi_response->mapi_len;
+ EcDoRpc->out.size = EcDoRpc->in.size;
+ break;
+ } else if ((stream->cached == false) && (stream->ahead == true)) {
+ if (mapiproxy->ahead == true) {
+ mpm_cache_stream_write(stream,
+ mapi_response->mapi_repl[i].u.mapi_ReadStream.data.length,
+ mapi_response->mapi_repl[i].u.mapi_ReadStream.data.data);
+ /* When read ahead is over */
+ if (stream->offset == stream->StreamSize) {
+ cache_dump_stream_stat(stream);
+ mpm_cache_stream_reset(stream);
+ stream->cached = true;
+ stream->ahead = false;
+ goto cached;
+ }
+ } else {
+ mapiproxy->ahead = true;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details
+ */
+static NTSTATUS cache_unbind(struct server_id server_id, uint32_t context_id)
+{
+ struct mpm_message *message;
+ struct mpm_attachment *attach;
+ struct mpm_stream *stream;
+
+ /* Look over messages still attached to the session */
+ message = mpm->messages;
+ while (message) {
+ if ((mpm_session_cmp_sub(message->session, server_id, context_id) == true)) {
+ DEBUG(2, ("[%s:%d]: [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Message - 0x%"PRIx64"/0x%"PRIx64" handle(0x%x)\n",
+ MPM_LOCATION, MPM_SESSION(message), message->FolderId, message->MessageId,
+ message->handle));
+ mpm_session_release(message->session);
+ DLIST_REMOVE(mpm->messages, message);
+ talloc_free(message);
+ message = mpm->messages;
+ } else {
+ message = message->next;
+ }
+ }
+
+ /* Look over attachments still attached to the session */
+ attach = mpm->attachments;
+ while (attach) {
+ if ((mpm_session_cmp_sub(attach->session, server_id, context_id) == true)) {
+ DEBUG(2, ("[%s:%d]: [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Attachment - AttachmentID(0x%x) handle(0x%x)\n",
+ MPM_LOCATION, MPM_SESSION(attach), attach->AttachmentID, attach->handle));
+ mpm_session_release(attach->session);
+ DLIST_REMOVE(mpm->attachments, attach);
+ talloc_free(attach);
+ attach = mpm->attachments;
+ } else {
+ attach = attach->next;
+ }
+ }
+
+ stream = mpm->streams;
+ while (stream) {
+ if ((mpm_session_cmp_sub(stream->session, server_id, context_id) == true)) {
+ DEBUG(2, ("[%s:%d]: [s(0x%"PRIx64"-0x%x-0x%x),c(0x%x)] Stream - handle(0x%x)\n", MPM_LOCATION,
+ MPM_SESSION(stream), stream->handle));
+ mpm_session_release(stream->session);
+ mpm_cache_stream_close(stream);
+ talloc_free(stream->filename);
+ DLIST_REMOVE(mpm->streams, stream);
+ talloc_free(stream);
+ stream = mpm->streams;
+ } else {
+ stream = stream->next;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Initialize the cache module and retrieve configuration from
+ smb.conf
+
+ Possible smb.conf parameters:
+ * mpm_cache:database
+
+ \param dce_ctx the session context
+
+ \return NT_STATUS_OK on success otherwise
+ NT_STATUS_INVALID_PARAMETER, NT_STATUS_NO_MEMORY
+ */
+static NTSTATUS cache_init(struct dcesrv_context *dce_ctx)
+{
+ char *database;
+ struct loadparm_context *lp_ctx;
+ NTSTATUS status;
+
+ mpm = talloc_zero(dce_ctx, struct mpm_cache);
+ if (!mpm) return NT_STATUS_NO_MEMORY;
+ mpm->messages = NULL;
+ mpm->attachments = NULL;
+ mpm->streams = NULL;
+
+ mpm->ahead = lp_parm_bool(dce_ctx->lp_ctx, NULL, MPM_NAME, "ahead", false);
+ mpm->sync = lp_parm_bool(dce_ctx->lp_ctx, NULL, MPM_NAME, "sync", false);
+ mpm->sync_min = lp_parm_int(dce_ctx->lp_ctx, NULL, MPM_NAME, "sync_min", 500000);
+ mpm->sync_cmd = str_list_make(dce_ctx, lp_parm_string(dce_ctx->lp_ctx, NULL, MPM_NAME, "sync_cmd"), " ");
+ mpm->dbpath = lp_parm_string(dce_ctx->lp_ctx, NULL, MPM_NAME, "path");
+
+ if ((mpm->ahead == true) && mpm->sync) {
+ DEBUG(0, ("%s: cache:ahead and cache:sync are exclusive!\n", MPM_ERROR));
+ talloc_free(mpm);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!mpm->dbpath) {
+ DEBUG(0, ("%s: Missing mpm_cache:path parameter\n", MPM_ERROR));
+ talloc_free(mpm);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ database = talloc_asprintf(dce_ctx->lp_ctx, "tdb://%s/%s", mpm->dbpath, MPM_DB);
+ status = mpm_cache_ldb_createdb(dce_ctx, database, &mpm->ldb_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(database);
+ talloc_free(mpm);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ lp_ctx = loadparm_init(dce_ctx);
+ lp_load_default(lp_ctx);
+ dcerpc_init(lp_ctx);
+
+ talloc_free(database);
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Entry point for the cache mapiproxy module
+
+ \return NT_STATUS_OK on success, otherwise NTSTATUS error
+ */
+NTSTATUS samba_init_module(void)
+{
+ struct mapiproxy_module module;
+ NTSTATUS ret;
+
+ /* Fill in our name */
+ module.name = "cache";
+ module.description = "Cache MAPI messages and attachments";
+ module.endpoint = "exchange_emsmdb";
+
+ /* Fill in all the operations */
+ module.init = cache_init;
+ module.unbind = cache_unbind;
+ module.push = cache_push;
+ module.ndr_pull = NULL;
+ module.pull = cache_pull;
+ module.dispatch = cache_dispatch;
+
+ /* Register ourselves with the MAPIPROXY subsystem */
+ ret = mapiproxy_module_register(&module);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("Failed to register the 'cache' mapiproxy module!\n"));
+ return ret;
+ }
+
+ return ret;
+}
Added: trunk/openchange/mapiproxy/modules/mpm_cache.h
===================================================================
--- trunk/openchange/mapiproxy/modules/mpm_cache.h (rev 0)
+++ trunk/openchange/mapiproxy/modules/mpm_cache.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,124 @@
+/*
+ MAPI Proxy - Cache module
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 __MPM_CACHE_H
+#define __MPM_CACHE_H
+
+#include <stdio.h>
+
+#include <libmapi/dlinklist.h>
+#include <ldb_errors.h>
+#include <ldb.h>
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+struct mpm_message {
+ struct mpm_session *session;
+ uint32_t handle;
+ uint64_t FolderId;
+ uint64_t MessageId;
+ struct mpm_message *prev;
+ struct mpm_message *next;
+};
+
+struct mpm_attachment {
+ struct mpm_session *session;
+ uint32_t parent_handle;
+ uint32_t handle;
+ uint32_t AttachmentID;
+ struct mpm_message *message;
+ struct mpm_attachment *prev;
+ struct mpm_attachment *next;
+};
+
+/**
+ A stream can either be for a message or attachment
+ */
+struct mpm_stream {
+ struct mpm_session *session;
+ uint32_t parent_handle;
+ uint32_t handle;
+ enum MAPITAGS PropertyTag;
+ uint32_t StreamSize;
+ size_t offset;
+ FILE *fp;
+ char *filename;
+ bool cached;
+ bool ahead;
+ struct timeval tv_start;
+ struct mpm_attachment *attachment;
+ struct mpm_message *message;
+ struct mpm_stream *prev;
+ struct mpm_stream *next;
+};
+
+/* TODO: Make use of dce_ctx->context->context_id to differentiate sessions ? */
+
+struct mpm_cache {
+ struct ldb_context *ldb_ctx;
+ struct mpm_message *messages;
+ struct mpm_attachment *attachments;
+ struct mpm_stream *streams;
+ const char *dbpath;
+ bool ahead;
+ bool sync;
+ int sync_min;
+ char **sync_cmd;
+};
+
+__BEGIN_DECLS
+
+NTSTATUS samba_init_module(void);
+
+NTSTATUS mpm_cache_ldb_createdb(struct dcesrv_context *, const char *, struct ldb_context **);
+NTSTATUS mpm_cache_ldb_add_message(TALLOC_CTX *, struct ldb_context *, struct mpm_message *);
+NTSTATUS mpm_cache_ldb_add_attachment(TALLOC_CTX *, struct ldb_context *, struct mpm_attachment *);
+NTSTATUS mpm_cache_ldb_add_stream(struct mpm_cache *, struct ldb_context *, struct mpm_stream *);
+
+NTSTATUS mpm_cache_stream_open(struct mpm_cache *, struct mpm_stream *);
+NTSTATUS mpm_cache_stream_close(struct mpm_stream *);
+NTSTATUS mpm_cache_stream_write(struct mpm_stream *, uint16_t, uint8_t *);
+NTSTATUS mpm_cache_stream_read(struct mpm_stream *, size_t, size_t *, uint8_t **);
+NTSTATUS mpm_cache_stream_reset(struct mpm_stream *);
+
+__END_DECLS
+
+/*
+ * Defines
+ */
+
+#define MPM_NAME "mpm_cache"
+#define MPM_ERROR "[ERROR] mpm_cache:"
+#define MPM_DB "mpm_cache.ldb"
+#define MPM_DB_STORAGE "data"
+
+#define MPM_LOCATION __FUNCTION__, __LINE__
+#define MPM_SESSION(x) x->session->server_id.id, x->session->server_id.id2, x->session->server_id.node, x->session->context_id
+
+#endif /* __MPM_CACHE_H */
Added: trunk/openchange/mapiproxy/modules/mpm_cache_ldb.c
===================================================================
--- trunk/openchange/mapiproxy/modules/mpm_cache_ldb.c (rev 0)
+++ trunk/openchange/mapiproxy/modules/mpm_cache_ldb.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,371 @@
+/*
+ MAPI Proxy - Cache module
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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/>.
+ */
+
+/**
+ \file mpm_cache_ldb.c
+
+ \brief LDB routines for the cache module
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/libmapiproxy/libmapiproxy.h"
+#include "mapiproxy/modules/mpm_cache.h"
+#include <libmapi/defs_private.h>
+#include <util/debug.h>
+
+/**
+ \details Create the cache database
+
+ \param dce_ctx pointer to the session context
+ \param database the complete path to the tdb store
+ \param ldb_ctx pointer to pointer on the the LDB context
+
+ \return NT_STATUS_OK on success, otherwise NT_ERROR:
+ NT_STATUS_NO_MEMORY, NT_STATUS_NOT_FOUND.
+ */
+NTSTATUS mpm_cache_ldb_createdb(struct dcesrv_context *dce_ctx,
+ const char *database,
+ struct ldb_context **ldb_ctx)
+{
+ struct ldb_context *tmp_ctx;
+ struct tevent_context *ev;
+ int ret;
+
+ ev = tevent_context_init(dce_ctx);
+ if (!ev) return NT_STATUS_NO_MEMORY;
+
+ tmp_ctx = ldb_init(dce_ctx, ev);
+ if (!tmp_ctx) return NT_STATUS_NO_MEMORY;
+
+ ret = ldb_connect(tmp_ctx, database, 0, NULL);
+ if (ret != LDB_SUCCESS) {
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ *ldb_ctx = tmp_ctx;
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Add a folder record to the TDB store
+
+ \param mem_ctx pointer to the memory context
+ \param ldb_ctx pointer to the LDB context
+ \param FolderId the ID we will be using to uniquely create the
+ record
+
+ \return NT_STATUS_OK on success, otherwise NT_STATUS_NOT_FOUND
+ */
+static NTSTATUS mpm_cache_ldb_add_folder(TALLOC_CTX *mem_ctx,
+ struct ldb_context *ldb_ctx,
+ uint64_t FolderId)
+{
+ struct ldb_message *msg;
+ char *dn;
+ int ret;
+
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ dn = talloc_asprintf(mem_ctx, "CN=0x%"PRIx64",CN=Cache", FolderId);
+ msg->dn = ldb_dn_new(ldb_ctx, ldb_ctx, dn);
+ talloc_free(dn);
+ if (!msg->dn) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = ldb_add(ldb_ctx, msg);
+ if (ret != 0) {
+ DEBUG(0, ("* [%s:%d] Failed to modify record %s: %s\n",
+ MPM_LOCATION, ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(ldb_ctx)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Add a message record to the TDB store
+
+ \param mem_ctx pointer to the memory context
+ \param ldb_ctx pointer to the LDB context
+ \param message pointer to the mpm_message entry with the folder and
+ message ID
+
+ \return NT_STATUS_OK on success, otherwise a NT error
+ */
+NTSTATUS mpm_cache_ldb_add_message(TALLOC_CTX *mem_ctx,
+ struct ldb_context *ldb_ctx,
+ struct mpm_message *message)
+{
+ NTSTATUS status;
+ struct ldb_message *msg;
+ struct ldb_dn *dn;
+ struct ldb_result *res;
+ char *basedn;
+ int ret;
+
+ /* First check if the CN=Folder,CN=Cache entry exists */
+ basedn = talloc_asprintf(mem_ctx, "CN=0x%"PRIx64",CN=Cache", message->FolderId);
+ dn = ldb_dn_new(mem_ctx, ldb_ctx, basedn);
+ talloc_free(basedn);
+ if (!dn) return NT_STATUS_UNSUCCESSFUL;
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
+ if (ret == LDB_SUCCESS && !res->count) {
+ DEBUG(5, ("* [%s:%d] We have to create folder TDB record: CN=0x%"PRIx64",CN=Cache\n",
+ MPM_LOCATION, message->FolderId));
+ status = mpm_cache_ldb_add_folder(mem_ctx, ldb_ctx, message->FolderId);
+ if (!NT_STATUS_IS_OK(status)) return status;
+ }
+
+ /* Search if the message doesn't already exist */
+ basedn = talloc_asprintf(mem_ctx, "CN=0x%"PRIx64",CN=0x%"PRIx64",CN=Cache",
+ message->MessageId, message->FolderId);
+ dn = ldb_dn_new(mem_ctx, ldb_ctx, basedn);
+ talloc_free(basedn);
+ if (!dn) return NT_STATUS_UNSUCCESSFUL;
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
+ if (res->count) return NT_STATUS_OK;
+
+ /* Create the CN=Message,CN=Folder,CN=Cache */
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) return NT_STATUS_NO_MEMORY;
+
+ basedn = talloc_asprintf(mem_ctx, "CN=0x%"PRIx64",CN=0x%"PRIx64",CN=Cache",
+ message->MessageId, message->FolderId);
+ msg->dn = ldb_dn_new(ldb_ctx, ldb_ctx, basedn);
+ talloc_free(basedn);
+ if (!msg->dn) return NT_STATUS_NO_MEMORY;
+
+ ret = ldb_add(ldb_ctx, msg);
+ if (ret != 0) {
+ DEBUG(0, ("* [%s:%d] Failed to modify record %s: %s\n",
+ MPM_LOCATION, ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(ldb_ctx)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Add an attachment record to the TDB store
+
+ \param mem_ctx pointer to the memory context
+ \param ldb_ctx pointer to the LDB context
+ \param attach pointer to the mpm_attachment entry
+
+ \return NT_STATUS_OK on success, otherwise a NT error
+*/
+NTSTATUS mpm_cache_ldb_add_attachment(TALLOC_CTX *mem_ctx,
+ struct ldb_context *ldb_ctx,
+ struct mpm_attachment *attach)
+{
+ struct mpm_message *message;
+ struct ldb_message *msg;
+ struct ldb_dn *dn;
+ struct ldb_result *res;
+ char *basedn;
+ int ret;
+
+ message = attach->message;
+
+ /* Search if the attachment doesn't already exist */
+ basedn = talloc_asprintf(mem_ctx, "CN=%d,CN=0x%"PRIx64",CN=0x%"PRIx64",CN=Cache",
+ attach->AttachmentID, message->MessageId,
+ message->FolderId);
+ dn = ldb_dn_new(mem_ctx, ldb_ctx, basedn);
+ talloc_free(basedn);
+ if (!dn) return NT_STATUS_UNSUCCESSFUL;
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
+ if (ret == LDB_SUCCESS && res->count) return NT_STATUS_OK;
+
+ DEBUG(2, ("* [%s:%d] Create the attachment TDB record\n", MPM_LOCATION));
+
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) return NT_STATUS_NO_MEMORY;
+
+ basedn = talloc_asprintf(mem_ctx, "CN=%d,CN=0x%"PRIx64",CN=0x%"PRIx64",CN=Cache",
+ attach->AttachmentID, message->MessageId,
+ message->FolderId);
+ msg->dn = ldb_dn_new(ldb_ctx, ldb_ctx, basedn);
+ talloc_free(basedn);
+ if (!msg->dn) return NT_STATUS_NO_MEMORY;
+
+ ret = ldb_add(ldb_ctx, msg);
+ if (ret != 0) {
+ DEBUG(0, ("* [%s:%d] Failed to modify record %s: %s\n",
+ MPM_LOCATION, ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(ldb_ctx)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Add stream references to a message or attachment in the
+ TDB store
+
+ \param mpm pointer to the cache module general structure
+ \param ldb_ctx pointer to the LDB context
+ \param stream pointer to the mpm_stream entry
+
+ \return NT_STATUS_OK on success, otherwise NT error
+ */
+NTSTATUS mpm_cache_ldb_add_stream(struct mpm_cache *mpm,
+ struct ldb_context *ldb_ctx,
+ struct mpm_stream *stream)
+{
+ TALLOC_CTX *mem_ctx;
+ struct mpm_message *message;
+ struct mpm_attachment *attach;
+ struct ldb_message *msg;
+ struct ldb_dn *dn;
+ const char * const attrs[] = { "*", NULL };
+ struct ldb_result *res;
+ char *basedn = NULL;
+ char *attribute;
+ int ret;
+ uint32_t i;
+
+ mem_ctx = (TALLOC_CTX *) mpm;
+
+ if (stream->attachment) {
+ attach = stream->attachment;
+ message = attach->message;
+ } else if (stream->message) {
+ attach = NULL;
+ message = stream->message;
+ } else {
+ return NT_STATUS_OK;
+ }
+
+ /* This is a stream for an attachment */
+ if (stream->attachment) {
+ basedn = talloc_asprintf(mem_ctx, "CN=%d,CN=0x%"PRIx64",CN=0x%"PRIx64",CN=Cache",
+ attach->AttachmentID, message->MessageId,
+ message->FolderId);
+ dn = ldb_dn_new(mem_ctx, ldb_ctx, basedn);
+ talloc_free(basedn);
+ if (!dn) return NT_STATUS_UNSUCCESSFUL;
+
+ attribute = talloc_asprintf(mem_ctx, "(0x%x=*)", stream->PropertyTag);
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, dn, LDB_SCOPE_BASE, attrs,
+ attribute);
+ talloc_free(attribute);
+
+ if (ret == LDB_SUCCESS && res->count == 1) {
+ attribute = talloc_asprintf(mem_ctx, "0x%x", stream->PropertyTag);
+ basedn = (char *) ldb_msg_find_attr_as_string(res->msgs[0], attribute, NULL);
+ talloc_free(attribute);
+ DEBUG(2, ("* [%s:%d] Loading from cache 0x%x = %s\n", MPM_LOCATION,
+ stream->PropertyTag, basedn));
+ stream->filename = talloc_strdup(mem_ctx, basedn);
+ stream->cached = true;
+ stream->ahead = false;
+ mpm_cache_stream_open(mpm, stream);
+
+ return NT_STATUS_OK;
+ }
+
+ /* Otherwise create the stream with basedn above */
+ basedn = talloc_asprintf(mem_ctx, "CN=%d,CN=0x%"PRIx64",CN=0x%"PRIx64",CN=Cache",
+ attach->AttachmentID, message->MessageId,
+ message->FolderId);
+
+ DEBUG(2, ("* [%s:%d] Create the stream TDB record for attachment\n", MPM_LOCATION));
+ }
+
+ if (stream->message) {
+ basedn = talloc_asprintf(mem_ctx, "CN=0x%"PRIx64",CN=0x%"PRIx64",CN=Cache",
+ message->MessageId, message->FolderId);
+ dn = ldb_dn_new(mem_ctx, ldb_ctx, basedn);
+ talloc_free(basedn);
+ if (!dn) return NT_STATUS_UNSUCCESSFUL;
+
+ attribute = talloc_asprintf(mem_ctx, "(0x%x=*)", stream->PropertyTag);
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, dn, LDB_SCOPE_BASE, attrs, attribute);
+ talloc_free(attribute);
+
+ if (ret == LDB_SUCCESS && res->count == 1) {
+ attribute = talloc_asprintf(mem_ctx, "0x%x", stream->PropertyTag);
+ basedn = (char *) ldb_msg_find_attr_as_string(res->msgs[0], attribute, NULL);
+ talloc_free(attribute);
+ DEBUG(2, ("* [%s:%d] Loading from cache 0x%x = %s\n", MPM_LOCATION,
+ stream->PropertyTag, basedn));
+ stream->filename = talloc_strdup(mem_ctx, basedn);
+ stream->cached = true;
+ stream->ahead = false;
+ mpm_cache_stream_open(mpm, stream);
+
+ return NT_STATUS_OK;
+ }
+
+ /* Otherwise create the stream with basedn above */
+ basedn = talloc_asprintf(mem_ctx, "CN=0x%"PRIx64",CN=0x%"PRIx64",CN=Cache",
+ message->MessageId, message->FolderId);
+
+ DEBUG(2, ("* [%s:%d] Modify the message TDB record and append stream information\n",
+ MPM_LOCATION));
+ }
+
+ stream->cached = false;
+ mpm_cache_stream_open(mpm, stream);
+
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) return NT_STATUS_NO_MEMORY;
+
+ msg->dn = ldb_dn_new(ldb_ctx, ldb_ctx, basedn);
+ talloc_free(basedn);
+ if (!msg->dn) return NT_STATUS_NO_MEMORY;
+
+ attribute = talloc_asprintf(mem_ctx, "0x%x", stream->PropertyTag);
+ ldb_msg_add_fmt(msg, attribute, "%s", stream->filename);
+ talloc_free(attribute);
+
+ attribute = talloc_asprintf(mem_ctx, "0x%x_StreamSize", stream->PropertyTag);
+ ldb_msg_add_fmt(msg, attribute, "%d", stream->StreamSize);
+ talloc_free(attribute);
+
+ /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
+ for (i=0;i<msg->num_elements;i++) {
+ msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
+ }
+
+ ret = ldb_modify(ldb_ctx, msg);
+ if (ret != 0) {
+ DEBUG(0, ("* [%s:%d] Failed to modify record %s: %s\n",
+ MPM_LOCATION, ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(ldb_ctx)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
Added: trunk/openchange/mapiproxy/modules/mpm_cache_stream.c
===================================================================
--- trunk/openchange/mapiproxy/modules/mpm_cache_stream.c (rev 0)
+++ trunk/openchange/mapiproxy/modules/mpm_cache_stream.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,201 @@
+/*
+ MAPI Proxy - Cache module
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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/>.
+ */
+
+/**
+ \file mpm_cache_stream.c
+
+ \brief Storage routines for the cache module
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/libmapiproxy/libmapiproxy.h"
+#include "mapiproxy/modules/mpm_cache.h"
+#include <libmapi/defs_private.h>
+#include <util/debug.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <errno.h>
+
+/**
+ \details Create a file: message or attachment in the cache
+
+ If the stream is attached to an attachment: FolderID/MessageID/AttachmentID.stream
+ If the stream is attached to a message: FolderID/MessageID.stream
+
+ \param mpm pointer to the cache module general structure
+ \param stream pointer to the mpm_stream entry
+
+ \return Return a FILE pointer otherwise NULL
+ */
+NTSTATUS mpm_cache_stream_open(struct mpm_cache *mpm, struct mpm_stream *stream)
+{
+ TALLOC_CTX *mem_ctx;
+ char *file;
+ int ret;
+
+ mem_ctx = (TALLOC_CTX *) mpm;
+
+ if (stream->filename) {
+ stream->fp = fopen(stream->filename, "r");
+ stream->offset = 0;
+ return NT_STATUS_OK;
+ }
+
+ if (stream->message) {
+ /* Create the folder */
+ file = talloc_asprintf(mem_ctx, "%s/0x%"PRIx64, mpm->dbpath, stream->message->FolderId);
+ ret = mkdir(file, 0777);
+ talloc_free(file);
+ if ((ret == -1) && (errno != EEXIST)) return NT_STATUS_UNSUCCESSFUL;
+
+ /* Open the file */
+ file = talloc_asprintf(mem_ctx, "%s/0x%"PRIx64"/0x%"PRIx64".stream",
+ mpm->dbpath, stream->message->FolderId,
+ stream->message->MessageId);
+
+ DEBUG(2, ("* [%s:%d]: Opening Message stream %s\n", MPM_LOCATION, file));
+ stream->filename = talloc_strdup(mem_ctx, file);
+ stream->fp = fopen(file, "w+");
+ stream->offset = 0;
+ talloc_free(file);
+
+ return NT_STATUS_OK;
+ }
+
+ if (stream->attachment) {
+ /* Create the folders */
+ file = talloc_asprintf(mem_ctx, "%s/0x%"PRIx64, mpm->dbpath,
+ stream->attachment->message->FolderId);
+ ret = mkdir(file, 0777);
+ talloc_free(file);
+ if ((ret == -1) && (errno != EEXIST)) return NT_STATUS_UNSUCCESSFUL;
+
+ file = talloc_asprintf(mem_ctx, "%s/0x%"PRIx64"/0x%"PRIx64, mpm->dbpath,
+ stream->attachment->message->FolderId,
+ stream->attachment->message->MessageId);
+ ret = mkdir(file, 0777);
+ talloc_free(file);
+ if ((ret == -1) && (errno != EEXIST)) return NT_STATUS_UNSUCCESSFUL;
+
+ file = talloc_asprintf(mem_ctx, "%s/0x%"PRIx64"/0x%"PRIx64"/%d.stream",
+ mpm->dbpath,
+ stream->attachment->message->FolderId,
+ stream->attachment->message->MessageId,
+ stream->attachment->AttachmentID);
+
+ DEBUG(2, ("* [%s:%d]: Opening Attachment stream %s\n", MPM_LOCATION, file));
+ stream->filename = talloc_strdup(mem_ctx, file);
+ stream->fp = fopen(file, "w+");
+ stream->offset = 0;
+ talloc_free(file);
+
+ return NT_STATUS_OK;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Close the filesystem stream
+
+ \param stream pointer to the mpm_stream entry
+
+ \return NT_STATUS_OK on success, otherwise NT_STATUS_NOT_FOUND
+ */
+NTSTATUS mpm_cache_stream_close(struct mpm_stream *stream)
+{
+ if (stream && stream->fp) {
+ fclose(stream->fp);
+ stream->fp = NULL;
+ } else {
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Read input_size bytes from a local binary stream
+
+ \param stream pointer to the mpm_stream entry
+ \param input_size the number of bytes to read
+ \param length output pointer to the length effectively read from the
+ stream
+ \param data output pointer to the binary data read from the stream
+
+ \return NT_STATUS_OK
+ */
+NTSTATUS mpm_cache_stream_read(struct mpm_stream *stream, size_t input_size, size_t *length, uint8_t **data)
+{
+ fseek(stream->fp, stream->offset, SEEK_SET);
+ *length = fread(*data, sizeof (uint8_t), input_size, stream->fp);
+ stream->offset += *length;
+ DEBUG(5, ("* [%s:%d]: Current offset: 0x%zx\n", MPM_LOCATION,
+ stream->offset));
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Write length bytes to a local stream
+
+ \param stream pointer to the mpm_stream entry
+ \param length the data length to write to the stream
+ \param data pointer to the data to write to the stream
+
+ \return NT_STATUS_OK on success, otherwise NT_STATUS_UNSUCCESSFUL
+ */
+NTSTATUS mpm_cache_stream_write(struct mpm_stream *stream, uint16_t length, uint8_t *data)
+{
+ uint32_t WrittenSize;
+
+ fseek(stream->fp, stream->offset, SEEK_SET);
+ WrittenSize = fwrite(data, sizeof (uint8_t), length, stream->fp);
+ if (WrittenSize != length) {
+ DEBUG(0, ("* [%s:%d] WrittenSize != length\n", MPM_LOCATION));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ stream->offset += WrittenSize;
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Rewind a stream to the beginning
+
+ \param stream pointer to the mpm_stream entry
+
+ \return NT_STATUS_OK on success
+ */
+NTSTATUS mpm_cache_stream_reset(struct mpm_stream *stream)
+{
+ fseek(stream->fp, 0, SEEK_SET);
+ stream->offset = 0;
+
+ return NT_STATUS_OK;
+}
Added: trunk/openchange/mapiproxy/modules/mpm_downgrade.c
===================================================================
--- trunk/openchange/mapiproxy/modules/mpm_downgrade.c (rev 0)
+++ trunk/openchange/mapiproxy/modules/mpm_downgrade.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,148 @@
+/*
+ MAPI Proxy - Downgrade Module
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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/>.
+ */
+
+/**
+ \file mpm_downgrade.c
+
+ \brief Downgrade EMSMDB protocol version EcDoConnect/EcDoRpc
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/dcesrv_mapiproxy_proto.h"
+#include "mapiproxy/libmapiproxy/libmapiproxy.h"
+#include <util/debug.h>
+
+
+/**
+ \details This function replaces the store_version short array
+ returned by Exchange in EcDoConnect with a version matching
+ Exchange 2000. Otherwise Outlook tries to upgrade indefinitely.
+
+ \param dce_call pointer to the session context
+ \param r pointer to the EcDoConnect structure
+
+ \return true on success
+ */
+static bool downgrade_EcDoConnect(struct dcesrv_call_state *dce_call, struct EcDoConnect *r)
+{
+ r->out.rgwServerVersion[0] = 0x0006;
+ r->out.rgwServerVersion[1] = 0x1141;
+ r->out.rgwServerVersion[2] = 0x0005;
+
+ return true;
+}
+
+
+static NTSTATUS downgrade_push(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx, void *r)
+{
+ const struct ndr_interface_table *table;
+ uint16_t opnum;
+ const char *name;
+
+ table = (const struct ndr_interface_table *)dce_call->context->iface->private;
+ opnum = dce_call->pkt.u.request.opnum;
+ name = table->calls[opnum].name;
+
+ if (table->name && !strcmp(table->name, "exchange_emsmdb")) {
+ if (name && !strcmp(name, "EcDoConnect")) {
+ downgrade_EcDoConnect(dce_call, (struct EcDoConnect *)r);
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS downgrade_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull)
+{
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS downgrade_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
+{
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Returns the nca_op_rng_error DCERPC status code when
+ Outlook sends an EcDoConnectEx requrest.
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r generic pointer to EcDoConnectEx structure
+ \param mapiproxy pointer to the mapiproxy structure
+
+ \return NT_STATUS_NET_WRITE_FAULT when EcDoConnectEx is detected,
+ otherwise NT_STATUS_OK
+
+*/
+static NTSTATUS downgrade_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r,
+ struct mapiproxy *mapiproxy)
+{
+ const struct ndr_interface_table *table;
+ uint16_t opnum;
+
+ table = (const struct ndr_interface_table *)dce_call->context->iface->private;
+ opnum = dce_call->pkt.u.request.opnum;
+
+ if ((opnum == 0xA) && (table->name && !strcmp(table->name, "exchange_emsmdb"))) {
+ dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/**
+ \details Entry point for the downgrade mapiproxy module
+
+ \return NT_STATUS_OK on success, otherwise NTSTATUS error
+ */
+NTSTATUS samba_init_module(void)
+{
+ struct mapiproxy_module module;
+ NTSTATUS ret;
+
+ /* Fill in our name */
+ module.name = "downgrade";
+ module.description = "Downgrade EMSMDB protocol version EcDoConnect/EcDoRpc";
+ module.endpoint = "exchange_emsmdb";
+
+ /* Fill in all the operations */
+ module.init = NULL;
+ module.unbind = NULL;
+ module.push = downgrade_push;
+ module.ndr_pull = downgrade_ndr_pull;
+ module.pull = downgrade_pull;
+ module.dispatch = downgrade_dispatch;
+
+ /* Register ourselves with the MAPIPROXY subsystem */
+ ret = mapiproxy_module_register(&module);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("Failed to register the 'downgrade' mapiproxy module!\n"));
+ return ret;
+ }
+
+ return ret;
+}
Added: trunk/openchange/mapiproxy/modules/mpm_dummy.c
===================================================================
--- trunk/openchange/mapiproxy/modules/mpm_dummy.c (rev 0)
+++ trunk/openchange/mapiproxy/modules/mpm_dummy.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,101 @@
+/*
+ MAPI Proxy - Dummy Module
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/dcesrv_mapiproxy_proto.h"
+#include <util/debug.h>
+
+/**
+ \details Dummy init function which reads a parametric option from
+ smb.conf and display it on the log channel.
+ */
+static NTSTATUS dummy_init(struct dcesrv_context *dce_ctx)
+{
+ const char *test;
+
+ test = lp_parm_string(dce_ctx->lp_ctx, NULL, "mpm_dummy", "test");
+ if (test) {
+ DEBUG(0, ("Sample dummy string: %s\n", test));
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS dummy_unbind(struct server_id server_id, uint32_t context_id)
+{
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS dummy_push(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx, void *r)
+{
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS dummy_ndr_pull(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx, struct ndr_pull *ndr)
+{
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS dummy_pull(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx, void *r)
+{
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS dummy_dispatch(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx, void *r,
+ struct mapiproxy *mapiproxy)
+{
+ return NT_STATUS_OK;
+}
+
+
+NTSTATUS samba_init_module(void)
+{
+ struct mapiproxy_module module;
+ NTSTATUS ret;
+
+ /* Fill in our name */
+ module.name = "dummy";
+ module.description = "dummy MAPIPROXY module";
+ module.endpoint = "exchange_emsmdb";
+
+ /* Fill in all the operations */
+ module.init = dummy_init;
+ module.unbind = dummy_unbind;
+ module.push = dummy_push;
+ module.ndr_pull = dummy_ndr_pull;
+ module.pull = dummy_pull;
+ module.dispatch = dummy_dispatch;
+
+ /* Register ourselves with the MAPIPROXY subsytem */
+ ret = mapiproxy_module_register(&module);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("Failed to register 'dummy' mapiproxy module!\n"));
+ return ret;
+ }
+
+ return ret;
+}
Added: trunk/openchange/mapiproxy/modules/mpm_pack.c
===================================================================
--- trunk/openchange/mapiproxy/modules/mpm_pack.c (rev 0)
+++ trunk/openchange/mapiproxy/modules/mpm_pack.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,368 @@
+/*
+ MAPI Proxy - Unpack/Pack Module
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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/>.
+ */
+
+/**
+ \file mpm_pack.c
+
+ \brief Pack/Unpack specified MAPI calls into/from a custom MAPI call
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/libmapiproxy/libmapiproxy.h"
+#include <util/debug.h>
+
+#define MPM_NAME "mpm_pack"
+#define MPM_PACK_ERROR "[ERROR] mpm_pack:"
+
+NTSTATUS samba_init_module(void);
+
+static struct mpm_pack {
+ uint8_t *mapi_calls;
+ bool lasthop;
+} *mpm = NULL;
+
+
+static uint32_t proxypack(TALLOC_CTX *mem_ctx, struct EcDoRpc_MAPI_REQ *mapi_req,
+ struct ndr_push *ndr)
+{
+ struct proxypack_req request;
+ uint32_t size;
+
+ /* Fill in the proxypack operation */
+ size = 0;
+ request.bin.cb = ndr->offset;
+ size += sizeof (uint16_t);
+ request.bin.lpb = talloc_memdup(mem_ctx, ndr->data, ndr->offset);
+ size += ndr->offset;
+
+ /* Fill the MAPI_REQ request */
+ mapi_req->opnum = op_MAPI_proxypack;
+ mapi_req->logon_id = 0;
+ mapi_req->handle_idx = 0;
+ mapi_req->u.mapi_proxypack = request;
+ size += 5;
+
+ return size;
+}
+
+/**
+ \details unpack proxypack contents and restore the original EcDoRpc
+ request
+ */
+static bool unpack(TALLOC_CTX *mem_ctx, struct EcDoRpc *EcDoRpc)
+{
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct EcDoRpc_MAPI_REQ *mapi_newreq;
+ struct ndr_pull *ndr;
+ bool found;
+ uint32_t i;
+ uint8_t pos;
+ uint32_t count;
+ uint32_t nopack_count = 0;
+ uint32_t nopack_idx = 0;
+ uint32_t pack_idx = 0;
+
+ mapi_req = EcDoRpc->in.mapi_request->mapi_req;
+
+ /* Seek the unpack call */
+ for (i = 0, found = false; mapi_req[i].opnum; i++) {
+ if (mapi_req[i].opnum == op_MAPI_proxypack) {
+ found = true;
+ break;
+ }
+ }
+ /* Nothing to unpack */
+ if (found == false) return false;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_pull);
+ ndr->iconv_convenience = smb_iconv_convenience_init(mem_ctx, "CP850", "UTF8", true);
+
+ ndr->data_size = mapi_req[i].u.mapi_proxypack.bin.cb;
+ ndr->data = mapi_req[i].u.mapi_proxypack.bin.lpb;
+
+ for (nopack_count = 0; mapi_req[nopack_count].opnum; nopack_count++);
+
+ /* Merge unpacked and non packed calls < last packed call position */
+ mapi_newreq = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+ for (count = 0; ndr->offset != ndr->data_size; count++) {
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &pos));
+ if (pack_idx < pos) {
+ while (pack_idx < pos) {
+ if (nopack_idx >= nopack_count) break;
+
+ mapi_newreq = talloc_realloc(mem_ctx, mapi_newreq, struct EcDoRpc_MAPI_REQ, pack_idx + 2);
+ mapi_newreq[pack_idx] = mapi_req[nopack_idx];
+ nopack_idx++;
+ pack_idx++;
+ }
+ }
+
+ if (pos > pack_idx) {
+ pack_idx = pos;
+ }
+
+ mapi_newreq = talloc_realloc(mem_ctx, mapi_newreq, struct EcDoRpc_MAPI_REQ, pack_idx + 2);
+ NDR_CHECK(ndr_pull_EcDoRpc_MAPI_REQ(ndr, NDR_SCALARS, &mapi_newreq[pos]));
+ pack_idx++;
+ }
+
+ /* Append remaining non packed calls */
+ mapi_newreq[pack_idx].opnum = 0;
+ while (mapi_req[nopack_idx].opnum) {
+ if (nopack_idx > nopack_count) break;
+
+ if (mapi_req[nopack_idx].opnum != op_MAPI_proxypack) {
+ mapi_newreq = talloc_realloc(mem_ctx, mapi_newreq, struct EcDoRpc_MAPI_REQ, pack_idx + 2);
+ mapi_newreq[pack_idx] = mapi_req[nopack_idx];
+ pack_idx++;
+ mapi_newreq[pack_idx].opnum = 0;
+ }
+ nopack_idx++;
+ }
+
+ /* Update mapi_request length and mapi_req pointer */
+ EcDoRpc->in.mapi_request->mapi_len -= (5 + count);
+ EcDoRpc->in.mapi_request->length -= (5 + count);
+ EcDoRpc->in.mapi_request->mapi_req = mapi_newreq;
+
+ return true;
+}
+
+/**
+ \details pack EcDoRpc calls into proxypack
+ */
+static bool pack(TALLOC_CTX *mem_ctx, struct EcDoRpc *EcDoRpc)
+{
+ struct EcDoRpc_MAPI_REQ *mapi_req;
+ struct EcDoRpc_MAPI_REQ *mapi_newreq;
+ struct ndr_push *ndr;
+ struct ndr_push *nopack_ndr;
+ uint32_t size;
+ uint32_t handle_size;
+ uint32_t i, j;
+ uint32_t idx;
+ bool found;
+
+ mapi_req = EcDoRpc->in.mapi_request->mapi_req;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_push);
+ ndr->iconv_convenience = smb_iconv_convenience_init(mem_ctx, "CP850", "UTF8", true);
+
+ nopack_ndr = talloc_zero(mem_ctx, struct ndr_push);
+ nopack_ndr->iconv_convenience = smb_iconv_convenience_init(mem_ctx, "CP850", "UTF8", true);
+
+ mapi_newreq = talloc_array(mem_ctx, struct EcDoRpc_MAPI_REQ, 2);
+
+ for (i = 0, idx = 0; mapi_req[i].opnum; i++) {
+ found = false;
+ for (j = 0; mpm->mapi_calls[j]; j++) {
+ if (mapi_req[i].opnum == mpm->mapi_calls[j]) {
+ ndr_push_uint8(ndr, NDR_SCALARS, i);
+ ndr_push_EcDoRpc_MAPI_REQ(ndr, NDR_SCALARS, &mapi_req[i]);
+ found = true;
+ break;
+ }
+ }
+ if (found == false) {
+ mapi_newreq = talloc_realloc(mem_ctx, mapi_newreq, struct EcDoRpc_MAPI_REQ, idx + 2);
+ ndr_push_EcDoRpc_MAPI_REQ(nopack_ndr, NDR_SCALARS, &mapi_req[i]);
+ mapi_newreq[idx] = mapi_req[i];
+ idx++;
+ }
+ }
+
+ if (ndr->offset == 0) {
+ talloc_free(mapi_newreq);
+ talloc_free(nopack_ndr);
+ talloc_free(ndr);
+ return false;
+ }
+
+ DEBUG(3, ("============ non packed =============\n"));
+ dump_data(3, nopack_ndr->data, nopack_ndr->offset);
+ DEBUG(3, ("=====================================\n"));
+
+ DEBUG(3, ("\n============ packed =============\n"));
+ dump_data(3, ndr->data, ndr->offset);
+ DEBUG(3, ("=================================\n"));
+
+
+ /* Fill in the proxypack operation */
+ mapi_newreq = talloc_realloc(mem_ctx, mapi_newreq, struct EcDoRpc_MAPI_REQ, idx + 2);
+ size = proxypack(mem_ctx, &mapi_newreq[idx], ndr);
+ talloc_free(ndr);
+
+ if (!size) return false;
+
+ idx++;
+ mapi_newreq[idx].opnum = 0;
+
+ /* Recalculate the EcDoRpc request size */
+ handle_size = EcDoRpc->in.mapi_request->mapi_len - EcDoRpc->in.mapi_request->length;
+ EcDoRpc->in.mapi_request->mapi_len = nopack_ndr->offset + size + handle_size;
+ EcDoRpc->in.mapi_request->length = nopack_ndr->offset + size;
+
+ /* Replace EcDoRpc_MAPI_REQ */
+ talloc_free(EcDoRpc->in.mapi_request->mapi_req);
+ EcDoRpc->in.mapi_request->mapi_req = mapi_newreq;
+
+ /* Free memory */
+ talloc_free(nopack_ndr);
+
+ return true;
+}
+
+static NTSTATUS pack_push(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx, void *r)
+{
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS pack_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull)
+{
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details pack EcDoRpc MAPI requests
+
+ This function searches for MAPI opnums to pack in the requests,
+ add this opnums to the mapiproxy opnum DATA blob and refactor the
+ request to remove references to these calls in the original
+ request.
+ */
+static NTSTATUS pack_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
+{
+ struct EcDoRpc *EcDoRpc;
+ bool ret = false;
+
+ if (dce_call->pkt.u.request.opnum != 0x2) {
+ return NT_STATUS_OK;
+ }
+
+ EcDoRpc = (struct EcDoRpc *) r;
+ if (!EcDoRpc->in.mapi_request->mapi_req) return NT_STATUS_OK;
+
+ /* If this is an idle request, do not go further */
+ if (EcDoRpc->in.mapi_request->length == 2) {
+ return NT_STATUS_OK;
+ }
+
+ /* If this is not a last-hop */
+ if (mpm->lasthop == false) return NT_STATUS_OK;
+
+ ret = unpack(mem_ctx, EcDoRpc);
+ if (ret == false) {
+ ret = pack(mem_ctx, EcDoRpc);
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Initialize the pack module and retrieve configuration from
+ smb.conf.
+
+ Possible parameters:
+ * mpm_pack:opnums = 0x1, 0x2, 0x3
+ * mpm_pack:lasthop = true|false
+
+ */
+static NTSTATUS pack_init(struct dcesrv_context *dce_ctx)
+{
+ char **calls;
+ unsigned long opnum;
+ int i;
+ int j;
+ struct loadparm_context *lp_ctx;
+
+ /* Fetch the mapi call list from smb.conf */
+ calls = str_list_make(dce_ctx, lp_parm_string(dce_ctx->lp_ctx, NULL, MPM_NAME, "opnums"), NULL);
+
+ mpm = talloc_zero(dce_ctx, struct mpm_pack);
+ mpm->mapi_calls = talloc_zero(mpm, uint8_t);
+
+ for (i = 0; calls[i]; i++) {
+ opnum = strtol(calls[i], NULL, 16);
+ if (opnum <= 0 || opnum >= 0xFF) {
+ DEBUG(0, ("%s: invalid MAPI opnum 0x%.2x\n", MPM_PACK_ERROR, (uint32_t)opnum));
+ talloc_free(mpm);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ /* avoid duplicated opnums */
+ for (j = 0; j < i; j++) {
+ if (opnum == mpm->mapi_calls[j]) {
+ DEBUG(0, ("%s: duplicated opnum: 0x%.2x\n", MPM_PACK_ERROR, (uint32_t)opnum));
+ talloc_free(mpm);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ mpm->mapi_calls = talloc_realloc(mpm, mpm->mapi_calls, uint8_t, i + 2);
+ mpm->mapi_calls[i] = (uint8_t) opnum;
+ }
+ mpm->mapi_calls[i] = 0;
+
+ /* Fetch the lasthop parameter from smb.conf */
+ mpm->lasthop = lp_parm_bool(dce_ctx->lp_ctx, NULL, MPM_NAME, "lasthop", true);
+
+ lp_ctx = loadparm_init(dce_ctx);
+ lp_load_default(lp_ctx);
+ dcerpc_init(lp_ctx);
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Entry point for the pack mapiproxy module
+
+ \return NT_STATUS_OK on success, otherwise NTSTATUS error
+ */
+NTSTATUS samba_init_module(void)
+{
+ struct mapiproxy_module module;
+ NTSTATUS ret;
+
+ /* Fill in our name */
+ module.name = "pack";
+ module.description = "Pack specified MAPI calls into a custom MAPI call";
+ module.endpoint = "exchange_emsmdb";
+
+ /* Fill in all the operations */
+ module.init = pack_init;
+ module.unbind = NULL;
+ module.push = pack_push;
+ module.ndr_pull = pack_ndr_pull;
+ module.pull = pack_pull;
+ module.dispatch = NULL;
+
+ /* Register ourselves with the MAPIPROXY subsystem */
+ ret = mapiproxy_module_register(&module);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("Failed to register the 'pack' mapiproxy module!\n"));;
+ return ret;
+ }
+
+ return ret;
+}
Added: trunk/openchange/mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,627 @@
+/*
+ MAPI Proxy - Exchange EMSMDB Server
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file dcesrv_exchange_emsmdb.c
+
+ \brief OpenChange EMSMDB Server implementation
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "dcesrv_exchange_emsmdb.h"
+
+struct exchange_emsmdb_session *emsmdb_session = NULL;
+void *openchange_ldb_ctx = NULL;
+
+/**
+ \details exchange_emsmdb EcDoConnect (0x0) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcDoConnect request data
+
+ \note Session linking is not supported at the moment
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_EcDoConnect(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcDoConnect *r)
+{
+ struct emsmdbp_context *emsmdbp_ctx;
+ struct dcesrv_handle *handle;
+ struct policy_handle wire_handle;
+ struct exchange_emsmdb_session *session;
+ struct ldb_message *msg;
+ const char *cn;
+ const char *userDN;
+ char *dnprefix;
+
+ DEBUG(3, ("exchange_emsmdb: EcDoConnect (0x0)\n"));
+
+ /* Step 0. Ensure incoming use is authenticated */
+ if (!NTLM_AUTH_IS_OK(dce_call)) {
+ DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
+ failure:
+ wire_handle.handle_type = EXCHANGE_HANDLE_EMSMDB;
+ wire_handle.uuid = GUID_zero();
+ *r->out.handle = wire_handle;
+
+ r->out.pcmsPollsMax = talloc_zero(mem_ctx, uint32_t);
+ r->out.pcRetry = talloc_zero(mem_ctx, uint32_t);
+ r->out.pcmsRetryDelay = talloc_zero(mem_ctx, uint32_t);
+ r->out.picxr = talloc_zero(mem_ctx, uint32_t);
+ r->out.pullTimeStamp = talloc_zero(mem_ctx, uint32_t);
+
+ *r->out.pcmsPollsMax = 0;
+ *r->out.pcRetry = 0;
+ *r->out.pcmsRetryDelay = 0;
+ r->out.szDisplayName = NULL;
+ r->out.szDNPrefix = NULL;
+ r->out.rgwServerVersion[0] = 0;
+ r->out.rgwServerVersion[1] = 0;
+ r->out.rgwServerVersion[2] = 0;
+ r->out.rgwClientVersion[0] = 0;
+ r->out.rgwClientVersion[1] = 0;
+ r->out.rgwClientVersion[2] = 0;
+ *r->out.pullTimeStamp = 0;
+
+ r->out.result = MAPI_E_LOGON_FAILED;
+ return MAPI_E_LOGON_FAILED;
+ }
+
+ /* Step 1. Initialize the emsmdbp context */
+ emsmdbp_ctx = emsmdbp_init(dce_call->conn->dce_ctx->lp_ctx, openchange_ldb_ctx);
+ if (!emsmdbp_ctx) {
+ smb_panic("unable to initialize emsmdbp context");
+ OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_FAILONEPROVIDER, NULL);
+ }
+
+ /* Step 2. Check if incoming user belongs to the Exchange organization */
+ if (emsmdbp_verify_user(dce_call, emsmdbp_ctx) == false) {
+ talloc_free(emsmdbp_ctx);
+ goto failure;
+ }
+
+ /* Step 3. Check if input user DN belongs to the Exchange organization */
+ if (emsmdbp_verify_userdn(dce_call, emsmdbp_ctx, r->in.szUserDN, &msg) == false) {
+ talloc_free(emsmdbp_ctx);
+ goto failure;
+ }
+
+ emsmdbp_ctx->szUserDN = talloc_strdup(emsmdbp_ctx, r->in.szUserDN);
+
+ /* Step 4. Retrieve the display name of the user */
+ r->out.szDisplayName = ldb_msg_find_attr_as_string(msg, "displayName", NULL);
+ emsmdbp_ctx->szDisplayName = talloc_strdup(emsmdbp_ctx, r->out.szDisplayName);
+
+ /* Step 5. Retrieve the dinstinguished name of the server */
+ cn = ldb_msg_find_attr_as_string(msg, "cn", NULL);
+ userDN = ldb_msg_find_attr_as_string(msg, "legacyExchangeDN", NULL);
+ dnprefix = strstr(userDN, cn);
+ if (!dnprefix) {
+ talloc_free(emsmdbp_ctx);
+ goto failure;
+ }
+
+ *dnprefix = '\0';
+ r->out.szDNPrefix = strupper_talloc(mem_ctx, userDN);
+
+ /* Step 6. Fill EcDoConnect reply */
+ handle = dcesrv_handle_new(dce_call->context, EXCHANGE_HANDLE_EMSMDB);
+ OPENCHANGE_RETVAL_IF(!handle, MAPI_E_NOT_ENOUGH_RESOURCES, emsmdbp_ctx);
+
+ handle->data = (void *) emsmdbp_ctx;
+ *r->out.handle = handle->wire_handle;
+
+ r->out.pcmsPollsMax = talloc_zero(mem_ctx, uint32_t);
+ *r->out.pcmsPollsMax = EMSMDB_PCMSPOLLMAX;
+
+ r->out.pcRetry = talloc_zero(mem_ctx, uint32_t);
+ *r->out.pcRetry = EMSMDB_PCRETRY;
+
+ r->out.pcmsRetryDelay = talloc_zero(mem_ctx, uint32_t);
+ *r->out.pcmsRetryDelay = EMSMDB_PCRETRYDELAY;
+
+ r->out.picxr = talloc_zero(mem_ctx, uint32_t);
+ *r->out.picxr = 0;
+
+ r->out.rgwServerVersion[0] = 0x6;
+ r->out.rgwServerVersion[1] = 0x1141;
+ r->out.rgwServerVersion[2] = 0x5;
+
+ r->out.rgwClientVersion[0] = r->in.rgwClientVersion[0];
+ r->out.rgwClientVersion[1] = r->in.rgwClientVersion[1];
+ r->out.rgwClientVersion[2] = r->in.rgwClientVersion[2];
+
+ r->out.pullTimeStamp = talloc_zero(mem_ctx, uint32_t);
+ *r->out.pullTimeStamp = time(NULL);
+
+ r->out.result = MAPI_E_SUCCESS;
+
+ /* Step 7. Associate this emsmdbp context to the session */
+ session = talloc((TALLOC_CTX *)emsmdb_session, struct exchange_emsmdb_session);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_ENOUGH_RESOURCES, emsmdbp_ctx);
+
+ session->pullTimeStamp = *r->out.pullTimeStamp;
+ session->session = mpm_session_init((TALLOC_CTX *)emsmdb_session, dce_call);
+ OPENCHANGE_RETVAL_IF(!session->session, MAPI_E_NOT_ENOUGH_RESOURCES, emsmdbp_ctx);
+
+ mpm_session_set_private_data(session->session, (void *) emsmdbp_ctx);
+ mpm_session_set_destructor(session->session, emsmdbp_destructor);
+
+ DLIST_ADD_END(emsmdb_session, session, struct exchange_emsmdb_session *);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details exchange_emsmdb EcDoDisconnect (0x1) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcDoDisconnect request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_EcDoDisconnect(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcDoDisconnect *r)
+{
+ struct dcesrv_handle *h;
+ struct exchange_emsmdb_session *session;
+
+ DEBUG(3, ("exchange_emsmdb: EcDoDisconnect (0x1)\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;
+ }
+
+ /* Step 1. Retrieve handle and free if emsmdbp context and session are available */
+ h = dcesrv_handle_fetch(dce_call->context, r->in.handle, DCESRV_HANDLE_ANY);
+ if (h) {
+ for (session = emsmdb_session; session; session = session->next) {
+ if ((mpm_session_cmp(session->session, dce_call) == true)) {
+ DLIST_REMOVE(emsmdb_session, session);
+ mpm_session_release(session->session);
+ DEBUG(6, ("[%s:%d]: Session found and released\n", __FUNCTION__, __LINE__));
+ break;
+ }
+ }
+ }
+
+ r->out.result = MAPI_E_SUCCESS;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \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 dcesrv_handle *h;
+ struct emsmdbp_context *emsmdbp_ctx;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ enum MAPISTATUS retval;
+ uint32_t handles_length;
+ uint16_t size = 0;
+ uint32_t i;
+
+ 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;
+ }
+
+ h = dcesrv_handle_fetch(dce_call->context, r->in.handle, DCESRV_HANDLE_ANY);
+ emsmdbp_ctx = (struct emsmdbp_context *) h->data;
+
+ mapi_request = r->in.mapi_request;
+ mapi_response = talloc_zero(mem_ctx, struct mapi_response);
+ mapi_response->handles = mapi_request->handles;
+
+ /* Step 1. FIXME: Idle requests */
+ if (mapi_request->mapi_len <= 2) {
+ return MAPI_E_SUCCESS;
+ }
+
+ /* Step 2. Process serialized MAPI requests */
+ mapi_response->mapi_repl = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REPL);
+ for (i = 0; mapi_request->mapi_req[i].opnum != 0; i++) {
+ DEBUG(0, ("MAPI Rop: 0x%.2x\n", mapi_request->mapi_req[i].opnum));
+ mapi_response->mapi_repl = talloc_realloc(mem_ctx, mapi_response->mapi_repl,
+ struct EcDoRpc_MAPI_REPL, i + 2);
+ switch (mapi_request->mapi_req[i].opnum) {
+ case op_MAPI_Release:
+ retval = EcDoRpc_RopRelease(mem_ctx, emsmdbp_ctx,
+ &(mapi_request->mapi_req[i]),
+ mapi_request->handles, &size);
+ break;
+ case op_MAPI_OpenFolder:
+ retval = EcDoRpc_RopOpenFolder(mem_ctx, emsmdbp_ctx,
+ &(mapi_request->mapi_req[i]),
+ &(mapi_response->mapi_repl[i]),
+ mapi_response->handles, &size);
+ break;
+ case op_MAPI_GetProps:
+ retval = EcDoRpc_RopGetPropertiesSpecific(mem_ctx, emsmdbp_ctx,
+ &(mapi_request->mapi_req[i]),
+ &(mapi_response->mapi_repl[i]),
+ mapi_response->handles, &size);
+ break;
+ case op_MAPI_GetReceiveFolder:
+ retval = EcDoRpc_RopGetReceiveFolder(mem_ctx, emsmdbp_ctx,
+ &(mapi_request->mapi_req[i]),
+ &(mapi_response->mapi_repl[i]),
+ mapi_response->handles, &size);
+ break;
+ case op_MAPI_RegisterNotification:
+ retval = EcDoRpc_RopRegisterNotification(mem_ctx, emsmdbp_ctx,
+ &(mapi_request->mapi_req[i]),
+ &(mapi_response->mapi_repl[i]),
+ mapi_response->handles, &size);
+ break;
+ case op_MAPI_Logon:
+ retval = EcDoRpc_RopLogon(mem_ctx, emsmdbp_ctx,
+ &(mapi_request->mapi_req[i]),
+ &(mapi_response->mapi_repl[i]),
+ mapi_response->handles, &size);
+ break;
+ default:
+ DEBUG(1, ("MAPI Rop: 0x%.2x not implemented!\n",
+ mapi_request->mapi_req[i].opnum));
+ }
+ }
+
+ /* Step 3. Notifications/Pending calls should be processed here */
+ mapi_response->mapi_repl[i].opnum = 0;
+
+ /* Step 4. Fill mapi_response structure */
+ handles_length = mapi_request->mapi_len - mapi_request->length;
+ mapi_response->length = size + sizeof (mapi_response->length);
+ mapi_response->mapi_len = mapi_response->length + handles_length;
+
+ /* Step 5. Fill EcDoRpc reply */
+ r->out.handle = r->in.handle;
+ r->out.size = r->in.size;
+ r->out.offset = r->in.offset;
+ r->out.mapi_response = mapi_response;
+ r->out.length = talloc_zero(mem_ctx, uint16_t);
+ *r->out.length = mapi_response->mapi_len;
+
+ r->out.result = MAPI_E_SUCCESS;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details exchange_emsmdb EcGetMoreRpc (0x3) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcGetMoreRpc request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static void dcesrv_EcGetMoreRpc(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcGetMoreRpc *r)
+{
+ DEBUG(3, ("exchange_emsmdb: EcGetMoreRpc (0x3) not implemented\n"));
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_emsmdb EcRRegisterPushNotification (0x4) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcRRegisterPushNotification request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_EcRRegisterPushNotification(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcRRegisterPushNotification *r)
+{
+ DEBUG(3, ("exchange_emsmdb: EcRRegisterPushNotification (0x4) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_emsmdb EcRUnregisterPushNotification (0x5) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcRUnregisterPushNotification request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_EcRUnregisterPushNotification(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcRUnregisterPushNotification *r)
+{
+ DEBUG(3, ("exchange_emsmdb: EcRUnregisterPushNotification (0x5) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_emsmdb EcDummyRpc (0x6) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcDummyRpc request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static void dcesrv_EcDummyRpc(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcDummyRpc *r)
+{
+ DEBUG(3, ("exchange_emsmdb: EcDummyRpc (0x6) not implemented\n"));
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_emsmdb EcRGetDCName (0x7) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcRGetDCName request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static void dcesrv_EcRGetDCName(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcRGetDCName *r)
+{
+ DEBUG(3, ("exchange_emsmdb: EcRGetDCName (0x7) not implemented\n"));
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_emsmdb EcRNetGetDCName (0x8) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcRNetGetDCName request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static void dcesrv_EcRNetGetDCName(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcRNetGetDCName *r)
+{
+ DEBUG(3, ("exchange_emsmdb: EcRNetGetDCName (0x8) not implemented\n"));
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_emsmdb EcDoRpcExt (0x9) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcDoRpcExt request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static void dcesrv_EcDoRpcExt(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcDoRpcExt *r)
+{
+ DEBUG(3, ("exchange_emsmdb: EcDoRpcExt (0x9) not implemented\n"));
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_emsmdb EcDoConnectEx (0xA) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcDoConnectEx request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_EcDoConnectEx(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcDoConnectEx *r)
+{
+ DEBUG(3, ("exchange_emsmdb: EcDoConnectEx (0xA) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details Dispatch incoming EMSMDB call to the correct OpenChange
+ server function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r generic pointer on EMSMDB data
+ \param mapiproxy pointer to the mapiproxy structure controlling
+ mapiproxy behavior
+
+ \return NT_STATUS_OK;
+ */
+static NTSTATUS dcesrv_exchange_emsmdb_dispatch(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ void *r, struct mapiproxy *mapiproxy)
+{
+ enum MAPISTATUS retval;
+ const struct ndr_interface_table *table;
+ uint16_t opnum;
+
+ table = (const struct ndr_interface_table *) dce_call->context->iface->private;
+ opnum = dce_call->pkt.u.request.opnum;
+
+ /* Sanity checks */
+ if (!table) return NT_STATUS_UNSUCCESSFUL;
+ if (table->name && strcmp(table->name, NDR_EXCHANGE_EMSMDB_NAME)) return NT_STATUS_UNSUCCESSFUL;
+
+ switch (opnum) {
+ case NDR_ECDOCONNECT:
+ retval = dcesrv_EcDoConnect(dce_call, mem_ctx, (struct EcDoConnect *)r);
+ break;
+ case NDR_ECDODISCONNECT:
+ retval = dcesrv_EcDoDisconnect(dce_call, mem_ctx, (struct EcDoDisconnect *)r);
+ break;
+ case NDR_ECDORPC:
+ retval = dcesrv_EcDoRpc(dce_call, mem_ctx, (struct EcDoRpc *)r);
+ break;
+ case NDR_ECGETMORERPC:
+ dcesrv_EcGetMoreRpc(dce_call, mem_ctx, (struct EcGetMoreRpc *)r);
+ break;
+ case NDR_ECRREGISTERPUSHNOTIFICATION:
+ retval = dcesrv_EcRRegisterPushNotification(dce_call, mem_ctx, (struct EcRRegisterPushNotification *)r);
+ break;
+ case NDR_ECRUNREGISTERPUSHNOTIFICATION:
+ retval = dcesrv_EcRUnregisterPushNotification(dce_call, mem_ctx, (struct EcRUnregisterPushNotification *)r);
+ break;
+ case NDR_ECDUMMYRPC:
+ dcesrv_EcDummyRpc(dce_call, mem_ctx, (struct EcDummyRpc *)r);
+ break;
+ case NDR_ECRGETDCNAME:
+ dcesrv_EcRGetDCName(dce_call, mem_ctx, (struct EcRGetDCName *)r);
+ break;
+ case NDR_ECRNETGETDCNAME:
+ dcesrv_EcRNetGetDCName(dce_call, mem_ctx, (struct EcRNetGetDCName *)r);
+ break;
+ case NDR_ECDORPCEXT:
+ dcesrv_EcDoRpcExt(dce_call, mem_ctx, (struct EcDoRpcExt *)r);
+ break;
+ case NDR_ECDOCONNECTEX:
+ retval = dcesrv_EcDoConnectEx(dce_call, mem_ctx, (struct EcDoConnectEx *)r);
+ return NT_STATUS_NET_WRITE_FAULT;
+ break;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Initialize the EMSMDB OpenChange server
+
+ \param dce_ctx pointer to the server context
+
+ \return NT_STATUS_OK on success
+ */
+static NTSTATUS dcesrv_exchange_emsmdb_init(struct dcesrv_context *dce_ctx)
+{
+ /* Initialize exchange_emsmdb session */
+ emsmdb_session = talloc_zero(dce_ctx, struct exchange_emsmdb_session);
+ if (!emsmdb_session) return NT_STATUS_NO_MEMORY;
+ emsmdb_session->session = NULL;
+
+ /* Open read/write context on OpenChange dispatcher database */
+ openchange_ldb_ctx = emsmdbp_openchange_ldb_init(dce_ctx->lp_ctx);
+ if (!openchange_ldb_ctx) {
+ smb_panic("unable to initialize 'openchange.ldb' context");
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Terminate the EMSMDB connection and release the associated
+ session and context if still available. This case occurs when the
+ client doesn't call EcDoDisconnect but quit unexpectedly.
+
+ \param server_id reference to the server identifier structure
+ \param context_id the connection context identifier
+
+ \return NT_STATUS_OK on success
+ */
+static NTSTATUS dcesrv_exchange_emsmdb_unbind(struct server_id server_id, uint32_t context_id)
+{
+ struct exchange_emsmdb_session *session;
+
+ for (session = emsmdb_session; session; session = session->next) {
+ if ((mpm_session_cmp_sub(session->session, server_id, context_id) == true)) {
+ mpm_session_release(session->session);
+ DLIST_REMOVE(emsmdb_session, session);
+ DEBUG(6, ("[%s:%d]: Session found and released\n", __FUNCTION__, __LINE__));
+ return NT_STATUS_OK;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Entry point for the default OpenChange EMSMDB server
+
+ \return NT_STATUS_OK on success, otherwise NTSTATUS error
+ */
+NTSTATUS samba_init_module(void)
+{
+ struct mapiproxy_module server;
+ NTSTATUS ret;
+
+ /* Fill in our name */
+ server.name = "exchange_emsmdb";
+ server.status = MAPIPROXY_DEFAULT;
+ server.description = "OpenChange EMSMDB server";
+ server.endpoint = "exchange_emsmdb";
+
+ /* Fill in all the operations */
+ server.init = dcesrv_exchange_emsmdb_init;
+ server.unbind = dcesrv_exchange_emsmdb_unbind;
+ server.dispatch = dcesrv_exchange_emsmdb_dispatch;
+ server.push = NULL;
+ server.pull = NULL;
+ server.ndr_pull = NULL;
+
+ /* Register ourselves with the MAPIPROXY server subsystem */
+ ret = mapiproxy_server_register(&server);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("Failed to register the 'exchange_emsmdb' default mapiproxy server!\n"));
+ return ret;
+ }
+
+ return ret;
+}
Added: trunk/openchange/mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.h
===================================================================
--- trunk/openchange/mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.h (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,148 @@
+/*
+ MAPI Proxy - Exchange EMSMDB Server
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 __DCESRV_EXCHANGE_EMSMDB_H
+#define __DCESRV_EXCHANGE_EMSMDB_H
+
+#include <libmapi/libmapi.h>
+#include <libmapi/proto_private.h>
+#include <mapiproxy/libmapiproxy/libmapiproxy.h>
+#include <mapiproxy/libmapistore/mapistore.h>
+#include <ldb.h>
+#include <ldb_errors.h>
+#include <util/debug.h>
+#include <time.h>
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+struct emsmdbp_context {
+ char *szUserDN;
+ char *szDisplayName;
+ struct loadparm_context *lp_ctx;
+ void *oc_ctx;
+ void *conf_ctx;
+ void *users_ctx;
+ struct mapistore_context *mstore_ctx;
+ struct mapi_handles_context *handles_ctx;
+};
+
+
+struct exchange_emsmdb_session {
+ uint32_t pullTimeStamp;
+ struct mpm_session *session;
+ struct exchange_emsmdb_session *prev;
+ struct exchange_emsmdb_session *next;
+};
+
+enum emsmdbp_object_type {
+ EMSMDBP_OBJECT_UNDEF = 0x0,
+ EMSMDBP_OBJECT_MAILBOX = 0x1,
+ EMSMDBP_OBJECT_FOLDER = 0x2,
+ EMSMDBP_OBJECT_MESSAGE = 0x3,
+ EMSMDBP_OBJECT_TABLE = 0x4
+};
+
+struct emsmdbp_object_mailbox {
+ char *owner_Name;
+ char *owner_EssDN;
+ char *szUserDN;
+};
+
+
+struct emsmdbp_object_folder {
+ uint64_t folderID;
+ bool IsSystemFolder;
+ int systemfolder;
+ uint32_t contextID;
+};
+
+union emsmdbp_objects {
+ struct emsmdbp_object_mailbox *mailbox;
+ struct emsmdbp_object_folder *folder;
+};
+
+struct emsmdbp_object {
+ enum emsmdbp_object_type type;
+ union emsmdbp_objects object;
+ struct mapistore_context *mstore_ctx;
+ void *private_data;
+};
+
+
+#define EMSMDB_PCMSPOLLMAX 60000
+#define EMSMDB_PCRETRY 6
+#define EMSMDB_PCRETRYDELAY 10000
+
+#define EMSMDBP_MAILBOX_ROOT 0x1
+#define EMSMDBP_DEFERRED_ACTIONS 0x2
+#define EMSMDBP_SPOOLER_QUEUE 0x3
+#define EMSMDBP_TOP_INFORMATION_STORE 0x4
+#define EMSMDBP_INBOX 0x5
+#define EMSMDBP_OUTBOX 0x6
+#define EMSMDBP_SENT_ITEMS 0x7
+#define EMSMDBP_DELETED_ITEMS 0x8
+#define EMSMDBP_COMMON_VIEWS 0x9
+#define EMSMDBP_SCHEDULE 0xA
+#define EMSMDBP_SEARCH 0xB
+#define EMSMDBP_VIEWS 0xC
+#define EMSMDBP_SHORTCUTS 0xD
+
+__BEGIN_DECLS
+
+NTSTATUS samba_init_module(void);
+
+/* definitions from emsmdbp.c */
+struct emsmdbp_context *emsmdbp_init(struct loadparm_context *, void *);
+void *emsmdbp_openchange_ldb_init(struct loadparm_context *);
+bool emsmdbp_destructor(void *);
+bool emsmdbp_verify_user(struct dcesrv_call_state *, struct emsmdbp_context *);
+bool emsmdbp_verify_userdn(struct dcesrv_call_state *, struct emsmdbp_context *, const char *, struct ldb_message **);
+
+/* definitions from emsmdbp_object.c */
+struct emsmdbp_object *emsmdbp_object_init(TALLOC_CTX *, struct emsmdbp_context *);
+struct emsmdbp_object *emsmdbp_object_mailbox_init(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *);
+struct emsmdbp_object *emsmdbp_object_folder_init(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, struct mapi_handles *);
+
+/* definitions from oxcfold.c */
+enum MAPISTATUS EcDoRpc_RopOpenFolder(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *, uint32_t *, uint16_t *);
+
+/* definitions from oxcnotif.c */
+enum MAPISTATUS EcDoRpc_RopRegisterNotification(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *, uint32_t *, uint16_t *);
+
+/* definitions from oxcprpt.c */
+enum MAPISTATUS EcDoRpc_RopGetPropertiesSpecific(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *, uint32_t *, uint16_t *);
+
+/* definitions from oxcstor.c */
+enum MAPISTATUS EcDoRpc_RopLogon(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *, uint32_t *, uint16_t *);
+enum MAPISTATUS EcDoRpc_RopRelease(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, uint32_t *, uint16_t *);
+enum MAPISTATUS EcDoRpc_RopGetReceiveFolder(TALLOC_CTX *, struct emsmdbp_context *, struct EcDoRpc_MAPI_REQ *, struct EcDoRpc_MAPI_REPL *, uint32_t *, uint16_t *);
+
+__END_DECLS
+
+#endif /* __DCESRV_EXCHANGE_EMSMDB_H */
Added: trunk/openchange/mapiproxy/servers/default/emsmdb/emsmdbp.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/emsmdb/emsmdbp.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/emsmdb/emsmdbp.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,293 @@
+/*
+ OpenChange Server implementation
+
+ EMSMDBP: EMSMDB Provider implementation
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file emsmdbp.c
+
+ \brief EMSMDB Provider implementation
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "dcesrv_exchange_emsmdb.h"
+
+/**
+ \details Release the MAPISTORE context used by EMSMDB provider
+ context
+
+ \param data pointer on data to destroy
+
+ \return 0 on success, otherwise -1
+ */
+static int emsmdbp_mapi_store_destructor(void *data)
+{
+ struct mapistore_context *mstore_ctx = (struct mapistore_context *) data;
+
+ mapistore_release(mstore_ctx);
+ DEBUG(6, ("[%s:%d]: MAPISTORE context released\n", __FUNCTION__, __LINE__));
+ return true;
+}
+
+/**
+ \details Release the MAPI handles context used by EMSMDB provider
+ context
+
+ \param data pointer on data to destroy
+
+ \return 0 on success, otherwise -1
+ */
+static int emsmdbp_mapi_handles_destructor(void *data)
+{
+ enum MAPISTATUS retval;
+ struct mapi_handles_context *handles_ctx = (struct mapi_handles_context *) data;
+
+ retval = mapi_handles_release(handles_ctx);
+ DEBUG(6, ("[%s:%d]: MAPI handles context released (%s)\n", __FUNCTION__, __LINE__,
+ mapi_get_errstr(retval)));
+
+ return (retval == MAPI_E_SUCCESS) ? 0 : -1;
+}
+
+/**
+ \details Initialize the EMSMDBP context and open connections to
+ Samba databases.
+
+ \param lp_ctx pointer to the loadparm_context
+ \param ldb_ctx pointer to the openchange dispatcher ldb database
+
+ \return Allocated emsmdbp_context pointer on success, otherwise
+ NULL
+ */
+_PUBLIC_ struct emsmdbp_context *emsmdbp_init(struct loadparm_context *lp_ctx,
+ void *ldb_ctx)
+{
+ struct emsmdbp_context *emsmdbp_ctx;
+ struct tevent_context *ev;
+ char *configuration = NULL;
+ char *users = NULL;
+ int ret;
+
+ /* Sanity Checks */
+ if (!lp_ctx) return NULL;
+
+ emsmdbp_ctx = talloc_zero(lp_ctx, struct emsmdbp_context);
+ if (!emsmdbp_ctx) {
+ return NULL;
+ }
+
+ ev = tevent_context_init(talloc_autofree_context());
+ if (!ev) {
+ talloc_free(emsmdbp_ctx);
+ return NULL;
+ }
+
+ /* Save a pointer to the loadparm context */
+ emsmdbp_ctx->lp_ctx = lp_ctx;
+
+ /* Return an opaque context pointer on the configuration database */
+ configuration = private_path(emsmdbp_ctx, lp_ctx, "configuration.ldb");
+ emsmdbp_ctx->conf_ctx = ldb_init(emsmdbp_ctx, ev);
+ if (!emsmdbp_ctx->conf_ctx) {
+ talloc_free(configuration);
+ talloc_free(emsmdbp_ctx);
+ return NULL;
+ }
+
+ ret = ldb_connect(emsmdbp_ctx->conf_ctx, configuration, LDB_FLG_RDONLY, NULL);
+ talloc_free(configuration);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("[%s:%d]: Connection to \"configuration.ldb\" failed\n", __FUNCTION__, __LINE__));
+ talloc_free(emsmdbp_ctx);
+ return NULL;
+ }
+
+ /* Return an opaque pointer on the users database */
+ users = private_path(emsmdbp_ctx, lp_ctx, "users.ldb");
+ emsmdbp_ctx->users_ctx = ldb_init(emsmdbp_ctx, ev);
+ if (!emsmdbp_ctx->users_ctx) {
+ talloc_free(users);
+ talloc_free(emsmdbp_ctx);
+ return NULL;
+ }
+
+ ret = ldb_connect(emsmdbp_ctx->users_ctx, users, LDB_FLG_RDONLY, NULL);
+ talloc_free(users);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("[%s:%d]: Connection to \"users.ldb\" failed\n", __FUNCTION__, __LINE__));
+ talloc_free(emsmdbp_ctx);
+ return NULL;
+ }
+
+ /* Reference global OpenChange dispatcher database pointer within current context */
+ emsmdbp_ctx->oc_ctx = ldb_ctx;
+
+ /* Initialize the mapistore context */
+ emsmdbp_ctx->mstore_ctx = mapistore_init(emsmdbp_ctx, NULL);
+ if (!emsmdbp_ctx->mstore_ctx) {
+ DEBUG(0, ("[%s:%d]: MAPISTORE initialization failed\n", __FUNCTION__, __LINE__));
+
+ talloc_free(emsmdbp_ctx);
+ return NULL;
+ }
+ talloc_set_destructor((void *)emsmdbp_ctx->mstore_ctx, (int (*)(void *))emsmdbp_mapi_store_destructor);
+
+ /* Initialize MAPI handles context */
+ emsmdbp_ctx->handles_ctx = mapi_handles_init(emsmdbp_ctx);
+ if (!emsmdbp_ctx->handles_ctx) {
+ DEBUG(0, ("[%s:%d]: MAPI handles context initialization failed\n", __FUNCTION__, __LINE__));
+ talloc_free(emsmdbp_ctx);
+ return NULL;
+ }
+ talloc_set_destructor((void *)emsmdbp_ctx->handles_ctx, (int (*)(void *))emsmdbp_mapi_handles_destructor);
+
+ return emsmdbp_ctx;
+}
+
+
+/**
+ \details Open openchange.ldb database
+
+ \param lp_ctx pointer on the loadparm_context
+
+ \note This function is just a wrapper over
+ mapiproxy_server_openchange_ldb_init
+
+ \return Allocated LDB context on success, otherwise NULL
+ */
+_PUBLIC_ void *emsmdbp_openchange_ldb_init(struct loadparm_context *lp_ctx)
+{
+ /* Sanity checks */
+ if (!lp_ctx) return NULL;
+
+ return mapiproxy_server_openchange_ldb_init(lp_ctx);
+}
+
+
+_PUBLIC_ bool emsmdbp_destructor(void *data)
+{
+ struct emsmdbp_context *emsmdbp_ctx = (struct emsmdbp_context *)data;
+
+ if (!emsmdbp_ctx) return false;
+
+ talloc_free(emsmdbp_ctx);
+ DEBUG(0, ("[%s:%d]: emsmdbp_ctx found and released\n", __FUNCTION__, __LINE__));
+
+ return true;
+}
+
+
+/**
+ \details Check if the authenticated user belongs to the Exchange
+ organization and is enabled
+
+ \param dce_call pointer to the session context
+ \param emsmdbp_ctx pointer to the EMSMDBP context
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool emsmdbp_verify_user(struct dcesrv_call_state *dce_call,
+ struct emsmdbp_context *emsmdbp_ctx)
+{
+ int ret;
+ const char *username = NULL;
+ int msExchUserAccountControl;
+ struct ldb_result *res = NULL;
+ char *ldb_filter;
+ const char * const recipient_attrs[] = { "msExchUserAccountControl", NULL };
+
+ username = dce_call->context->conn->auth_state.session_info->server_info->account_name;
+
+ ldb_filter = talloc_asprintf(emsmdbp_ctx, "CN=%s", username);
+ ret = ldb_search(emsmdbp_ctx->users_ctx, emsmdbp_ctx, &res,
+ ldb_get_default_basedn(emsmdbp_ctx->users_ctx),
+ LDB_SCOPE_SUBTREE, recipient_attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ /* If the search failed */
+ if (ret != LDB_SUCCESS || !res->count) {
+ return false;
+ }
+
+ /* If msExchUserAccountControl attribute is not found */
+ if (!res->msgs[0]->num_elements) {
+ return false;
+ }
+
+ /* If the attribute exists check its value */
+ msExchUserAccountControl = ldb_msg_find_attr_as_int(res->msgs[0], "msExchUserAccountControl", 2);
+ if (msExchUserAccountControl == 2) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ \details Check if the user record which legacyExchangeDN points to
+ belongs to the Exchange organization and is enabled
+
+ \param dce_call pointer to the session context
+ \param emsmdbp_ctx pointer to the EMSMDBP context
+ \param legacyExchangeDN pointer to the userDN to lookup
+ \param msg pointer on pointer to the LDB message matching the record
+
+ \note Users can set msg to NULL if they do not intend to retrieve
+ the message
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool emsmdbp_verify_userdn(struct dcesrv_call_state *dce_call,
+ struct emsmdbp_context *emsmdbp_ctx,
+ const char *legacyExchangeDN,
+ struct ldb_message **msg)
+{
+ int ret;
+ int msExchUserAccountControl;
+ struct ldb_result *res = NULL;
+ char *ldb_filter;
+ const char * const recipient_attrs[] = { "*", NULL };
+
+ /* Sanity Checks */
+ if (!legacyExchangeDN) return false;
+
+ ldb_filter = talloc_asprintf(emsmdbp_ctx, "(legacyExchangeDN=%s)", legacyExchangeDN);
+ ret = ldb_search(emsmdbp_ctx->users_ctx, emsmdbp_ctx, &res,
+ ldb_get_default_basedn(emsmdbp_ctx->users_ctx),
+ LDB_SCOPE_SUBTREE, recipient_attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ /* If the search failed */
+ if (ret != LDB_SUCCESS || !res->count) {
+ return false;
+ }
+
+ /* Checks msExchUserAccountControl value */
+ msExchUserAccountControl = ldb_msg_find_attr_as_int(res->msgs[0], "msExchUserAccountControl", 2);
+ if (msExchUserAccountControl == 2) {
+ return false;
+ }
+
+ if (msg) {
+ *msg = res->msgs[0];
+ }
+
+ return true;
+}
Added: trunk/openchange/mapiproxy/servers/default/emsmdb/emsmdbp_object.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/emsmdb/emsmdbp_object.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/emsmdb/emsmdbp_object.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,236 @@
+/*
+ OpenChange Server implementation
+
+ EMSMDBP: EMSMDB Provider implementation
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file emsmdbp_object.c
+
+ \brief Server-side specific objects init/release routines
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/libmapiproxy/libmapiproxy.h"
+#include "dcesrv_exchange_emsmdb.h"
+
+static const char *emsmdbp_getstr_type(struct emsmdbp_object *object)
+{
+ switch (object->type) {
+ case EMSMDBP_OBJECT_UNDEF:
+ return "undefined";
+ case EMSMDBP_OBJECT_MAILBOX:
+ return "mailbox";
+ case EMSMDBP_OBJECT_FOLDER:
+ return "folder";
+ case EMSMDBP_OBJECT_MESSAGE:
+ return "message";
+ case EMSMDBP_OBJECT_TABLE:
+ return "table";
+ default:
+ return "unknown";
+ }
+
+ return "unknown";
+}
+
+
+/**
+ \details talloc destructor fo emsmdbp_objects
+
+ \param data generic pointer on data
+
+ \return 0 on success, otherwise -1
+ */
+static int emsmdbp_object_destructor(void *data)
+{
+ struct emsmdbp_object *object = (struct emsmdbp_object *) data;
+ int ret;
+
+ if (!data) return -1;
+
+ DEBUG(4, ("[%s:%d]: emsmdbp %s object released\n", __FUNCTION__, __LINE__,
+ emsmdbp_getstr_type(object)));
+
+ switch (object->type) {
+ case EMSMDBP_OBJECT_FOLDER:
+ ret = mapistore_del_context(object->mstore_ctx, object->object.folder->contextID);
+ DEBUG(4, ("[%s:%d] mapistore folder context retval = %d\n", __FUNCTION__, __LINE__, ret));
+ break;
+ default:
+ break;
+ }
+
+ talloc_free(object);
+
+ return 0;
+}
+
+/**
+ \details Initialize an emsmdbp_object
+
+ \param mem_ctx pointer to the memory context
+
+ \return Allocated emsmdbp object on success, otherwise NULL
+ */
+_PUBLIC_ struct emsmdbp_object *emsmdbp_object_init(TALLOC_CTX *mem_ctx, struct emsmdbp_context *emsmdbp_ctx)
+{
+ struct emsmdbp_object *object = NULL;
+
+ object = talloc_zero(mem_ctx, struct emsmdbp_object);
+ if (!object) return NULL;
+
+ talloc_set_destructor((void *)object, (int (*)(void *))emsmdbp_object_destructor);
+
+ object->type = EMSMDBP_OBJECT_UNDEF;
+ object->mstore_ctx = emsmdbp_ctx->mstore_ctx;
+ object->object.mailbox = NULL;
+ object->object.folder = NULL;
+ object->private_data = NULL;
+
+ return object;
+}
+
+
+/**
+ \details Initialize a mailbox object
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param request pointer to the Logon MAPI request
+
+ \return Allocated emsmdbp object on success, otherwise NULL
+ */
+_PUBLIC_ struct emsmdbp_object *emsmdbp_object_mailbox_init(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct EcDoRpc_MAPI_REQ *request)
+{
+ struct emsmdbp_object *object;
+ const char *displayName;
+ char *ldb_filter;
+ const char * const recipient_attrs[] = { "*", NULL };
+ int ret;
+ struct ldb_result *res = NULL;
+
+ /* Sanity checks */
+ if (!emsmdbp_ctx) return NULL;
+ if (!request) return NULL;
+
+ object = emsmdbp_object_init(mem_ctx, emsmdbp_ctx);
+ if (!object) return NULL;
+
+ /* Initialize the mailbox object */
+ object->object.mailbox = talloc_zero(object, struct emsmdbp_object_mailbox);
+ if (!object->object.mailbox) {
+ talloc_free(object);
+ return NULL;
+ }
+
+ object->type = EMSMDBP_OBJECT_MAILBOX;
+ object->object.mailbox->owner_Name = NULL;
+ object->object.mailbox->owner_EssDN = NULL;
+ object->object.mailbox->szUserDN = NULL;
+
+ object->object.mailbox->owner_EssDN = talloc_strdup(object->object.mailbox, request->u.mapi_Logon.EssDN);
+ object->object.mailbox->szUserDN = talloc_strdup(object->object.mailbox, emsmdbp_ctx->szUserDN);
+
+ ldb_filter = talloc_asprintf(mem_ctx, "(legacyExchangeDN=%s)", object->object.mailbox->owner_EssDN);
+ ret = ldb_search(emsmdbp_ctx->users_ctx, mem_ctx, &res,
+ ldb_get_default_basedn(emsmdbp_ctx->users_ctx),
+ LDB_SCOPE_SUBTREE, recipient_attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ if (res->count == 1) {
+ displayName = ldb_msg_find_attr_as_string(res->msgs[0], "displayName", NULL);
+ if (displayName) {
+ object->object.mailbox->owner_Name = talloc_strdup(object->object.mailbox, displayName);
+ }
+ }
+
+ talloc_free(res);
+
+ return object;
+}
+
+
+/**
+ \details Initialize a folder object
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param request pointer to the OpenFolder MAPI request
+ \param parent pointer to the parent MAPI handle
+
+ \return Allocated emsmdbp object on success, otherwise NULL
+ */
+_PUBLIC_ struct emsmdbp_object *emsmdbp_object_folder_init(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct EcDoRpc_MAPI_REQ *request,
+ struct mapi_handles *parent)
+{
+ enum MAPISTATUS retval;
+ struct emsmdbp_object *object;
+ int mailboxfolder;
+ char *mapistore_uri = NULL;
+ uint32_t context_id;
+ int ret;
+
+ /* Sanity checks */
+ if (!emsmdbp_ctx) return NULL;
+ if (!request) return NULL;
+
+ object = emsmdbp_object_init(mem_ctx, emsmdbp_ctx);
+ if (!object) return NULL;
+
+ object->object.folder = talloc_zero(object, struct emsmdbp_object_folder);
+ if (!object->object.folder) {
+ talloc_free(object);
+ return NULL;
+ }
+
+ object->type = EMSMDBP_OBJECT_FOLDER;
+ object->object.folder->contextID = -1;
+ object->object.folder->folderID = request->u.mapi_OpenFolder.folder_id;
+
+ retval = mapi_handles_get_systemfolder(parent, &mailboxfolder);
+ object->object.folder->IsSystemFolder = (!mailboxfolder) ? true : false;
+
+ if (object->object.folder->IsSystemFolder == false) {
+ /* Retrieve the systemfolder value */
+ object->object.folder->systemfolder = -1;
+ /* assign mapistore context from parent */
+ } else {
+ object->object.folder->systemfolder = 1;
+ /* mapistore backend initialization goes here */
+ retval = openchangedb_get_mapistoreURI(mem_ctx, emsmdbp_ctx->oc_ctx,
+ object->object.folder->folderID, &mapistore_uri);
+ if (retval == MAPI_E_SUCCESS) {
+ ret = mapistore_add_context(emsmdbp_ctx->mstore_ctx, mapistore_uri, &context_id);
+ if (ret != MAPISTORE_SUCCESS) {
+ talloc_free(object);
+ return NULL;
+ }
+ object->object.folder->contextID = context_id;
+ } else {
+ talloc_free(object);
+ return NULL;
+ }
+ }
+
+ return object;
+}
Added: trunk/openchange/mapiproxy/servers/default/emsmdb/oxcfold.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/emsmdb/oxcfold.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/emsmdb/oxcfold.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,136 @@
+/*
+ OpenChange Server implementation
+
+ EMSMDBP: EMSMDB Provider implementation
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file oxcfold.c
+
+ \brief Folder object routines and Rops
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/libmapiproxy/libmapiproxy.h"
+#include "mapiproxy/libmapiserver/libmapiserver.h"
+#include "dcesrv_exchange_emsmdb.h"
+
+
+/**
+ \details Open a System or Special folder object.
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param request OpenFolder request
+ \param response pointer to the OpenFolder response
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+static enum MAPISTATUS RopOpenFolder_SystemSpecialFolder(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct OpenFolder_req request,
+ struct OpenFolder_repl *response)
+{
+ /* Find parent record */
+ /* Set parent record as basedn */
+ /* Look for systemfolder given its FolderID */
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details EcDoRpc OpenFolder (0x02) Rop. This operation opens an
+ existing folder.
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param mapi_req pointer to the OpenFolder EcDoRpc_MAPI_REQ
+ structure
+ \param mapi_repl pointer to the OpenFolder EcDoRpc_MAPI_REPL
+ structure
+ \param handles pointer to the MAPI handles array
+ \param size pointer to the mapi_response size to update
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS EcDoRpc_RopOpenFolder(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct EcDoRpc_MAPI_REQ *mapi_req,
+ struct EcDoRpc_MAPI_REPL *mapi_repl,
+ uint32_t *handles, uint16_t *size)
+{
+ enum MAPISTATUS retval;
+ struct OpenFolder_req request;
+ struct OpenFolder_repl response;
+ struct mapi_handles *parent = NULL;
+ struct mapi_handles *rec = NULL;
+ struct emsmdbp_object *object;
+ uint32_t handle;
+ int parentfolder = -1;
+
+ DEBUG(4, ("exchange_emsmdb: [OXCFOLD] OpenFolder (0x02)\n"));
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
+
+ request = mapi_req->u.mapi_OpenFolder;
+ response = mapi_repl->u.mapi_OpenFolder;
+
+ mapi_repl->u.mapi_OpenFolder.HasRules = 0;
+ mapi_repl->u.mapi_OpenFolder.IsGhosted = 0;
+
+ /* Step 1. Retrieve parent handle in the hierarchy */
+ handle = handles[mapi_req->handle_idx];
+ retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &parent);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ retval = mapi_handles_get_systemfolder(parent, &parentfolder);
+
+ switch (parentfolder) {
+ case 0x0:
+ /* system/special folder */
+ retval = RopOpenFolder_SystemSpecialFolder(mem_ctx, emsmdbp_ctx, request, &response);
+ mapi_repl->error_code = retval;
+ break;
+ default:
+ /* handled by mapistore */
+ break;
+ }
+
+ *size += libmapiserver_RopOpenFolder_size(mapi_repl);
+
+ /* Fill EcDoRpc_MAPI_REPL reply */
+ if (!mapi_repl->error_code) {
+ retval = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
+
+ object = emsmdbp_object_folder_init((TALLOC_CTX *)rec, emsmdbp_ctx, mapi_req, parent);
+ retval = mapi_handles_set_systemfolder(rec, object->object.folder->systemfolder);
+ retval = mapi_handles_set_private_data(rec, object);
+
+ mapi_repl->opnum = mapi_req->opnum;
+ mapi_repl->handle_idx = mapi_req->u.mapi_OpenFolder.handle_idx;
+
+ handles[mapi_repl->handle_idx] = rec->handle;
+ }
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/mapiproxy/servers/default/emsmdb/oxcnotif.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/emsmdb/oxcnotif.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/emsmdb/oxcnotif.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,81 @@
+/*
+ OpenChange Server implementation
+
+ EMSMDBP: EMSMDB Provider implementation
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file oxcnotif.c
+
+ \brief Core Notifications routines and Rops
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/libmapiproxy/libmapiproxy.h"
+#include "mapiproxy/libmapiserver/libmapiserver.h"
+#include "dcesrv_exchange_emsmdb.h"
+
+
+/**
+ \details EcDoRpc RegisterNotification (0x29) Rop. This operation
+ subscribes for specified notifications on the server and returns a
+ handle of the subscription to the client.
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param mapi_req pointer to the RegisterNotification
+ EcDoRpc_MAPI_REQ structure
+ \param mapi_repl pointer to the RegisterNotification
+ EcDoRpc_MAPI_REPL structure
+ \param handles pointer to the MAPI handles array
+ \param size pointer to the mapi_response size to update
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS EcDoRpc_RopRegisterNotification(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct EcDoRpc_MAPI_REQ *mapi_req,
+ struct EcDoRpc_MAPI_REPL *mapi_repl,
+ uint32_t *handles, uint16_t *size)
+{
+ enum MAPISTATUS retval;
+ struct mapi_handles *rec = NULL;
+ uint32_t handle;
+
+ DEBUG(4, ("exchange_emsmdb: [OXCNOTIF] RegisterNotification (0x29)\n"));
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* FIXME: Handle this call properly */
+ mapi_repl->opnum = mapi_req->opnum;
+ mapi_repl->handle_idx = mapi_req->u.mapi_RegisterNotification.handle_idx;
+ mapi_repl->error_code = MAPI_E_SUCCESS;
+
+ handle = handles[mapi_req->handle_idx];
+ retval = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
+ handles[mapi_repl->handle_idx] = rec->handle;
+
+ *size += libmapiserver_RopRegisterNotification_size();
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/mapiproxy/servers/default/emsmdb/oxcprpt.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/emsmdb/oxcprpt.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/emsmdb/oxcprpt.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,257 @@
+/*
+ OpenChange Server implementation
+
+ EMSMDBP: EMSMDB Provider implementation
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file oxcprpt.c
+
+ \brief Property and Stream Object routines and Rops
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/libmapiproxy/libmapiproxy.h"
+#include "mapiproxy/libmapiserver/libmapiserver.h"
+#include "dcesrv_exchange_emsmdb.h"
+
+
+/**
+ \details Retrieve properties on a mailbox object.
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param request GetProps request
+ \param response pointer to the GetProps reply
+ \param private_data pointer to the private data stored for this
+ object
+
+ \note Mailbox objects have a limited set of supported properties.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+static enum MAPISTATUS RopGetPropertiesSpecific_Mailbox(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct GetProps_req request,
+ struct GetProps_repl *response,
+ void *private_data)
+{
+ enum MAPISTATUS retval;
+ struct emsmdbp_object *object;
+ struct SBinary_short bin;
+ uint32_t i;
+ uint32_t error = 0;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!private_data, MAPI_E_INVALID_PARAMETER, NULL);
+
+ object = (struct emsmdbp_object *) private_data;
+
+ /* Step 1. Check if we need a layout */
+ response->layout = 0;
+ for (i = 0; i < request.prop_count; i++) {
+ switch (request.properties[i]) {
+ case PR_MAPPING_SIGNATURE:
+ case PR_IPM_PUBLIC_FOLDERS_ENTRYID:
+ response->layout = 0x1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Step 2. Fill the GetProps blob */
+ for (i = 0; i < request.prop_count; i++) {
+ switch (request.properties[i]) {
+ case PR_MAPPING_SIGNATURE:
+ case PR_IPM_PUBLIC_FOLDERS_ENTRYID:
+ error = MAPI_E_NO_ACCESS;
+ request.properties[i] = (request.properties[i] & 0xFFFF0000) + PT_ERROR;
+ libmapiserver_push_property(mem_ctx, lp_iconv_convenience(emsmdbp_ctx->lp_ctx),
+ request.properties[i], (const void *)&error,
+ &response->prop_data, response->layout);
+ break;
+ case PR_USER_ENTRYID:
+ retval = entryid_set_AB_EntryID(mem_ctx, object->object.mailbox->szUserDN, &bin);
+ libmapiserver_push_property(mem_ctx, lp_iconv_convenience(emsmdbp_ctx->lp_ctx),
+ request.properties[i], (const void *)&bin,
+ &response->prop_data, response->layout);
+ talloc_free(bin.lpb);
+ break;
+ case PR_MAILBOX_OWNER_ENTRYID:
+ retval = entryid_set_AB_EntryID(mem_ctx, object->object.mailbox->owner_EssDN, &bin);
+ libmapiserver_push_property(mem_ctx, lp_iconv_convenience(emsmdbp_ctx->lp_ctx),
+ request.properties[i], (const void *)&bin,
+ &response->prop_data, response->layout);
+ talloc_free(bin.lpb);
+ break;
+ case PR_MAILBOX_OWNER_NAME:
+ case PR_MAILBOX_OWNER_NAME_UNICODE:
+ libmapiserver_push_property(mem_ctx, lp_iconv_convenience(emsmdbp_ctx->lp_ctx),
+ request.properties[i], (const void *)object->object.mailbox->owner_Name,
+ &response->prop_data, response->layout);
+ break;
+ default:
+ error = MAPI_E_NOT_FOUND;
+ request.properties[i] = (request.properties[i] & 0xFFFF0000) + PT_ERROR;
+ libmapiserver_push_property(mem_ctx, lp_iconv_convenience(emsmdbp_ctx->lp_ctx),
+ request.properties[i], (const void *)&error,
+ &response->prop_data, response->layout);
+ break;
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve properties on a systemfolder object.
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param request GetProps request
+ \param response pointer to the private data stored for this
+ object
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+static enum MAPISTATUS RopGetPropertiesSpecific_SystemSpecialFolder(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct GetProps_req request,
+ struct GetProps_repl *response,
+ void *private_data)
+{
+ enum MAPISTATUS retval;
+ struct emsmdbp_object *object;
+ struct emsmdbp_object_folder *folder;
+ void *data;
+ int i;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!private_data, MAPI_E_INVALID_PARAMETER, NULL);
+
+ object = (struct emsmdbp_object *) private_data;
+ folder = (struct emsmdbp_object_folder *) object->object.folder;
+
+ /* Step 1. Lookup properties and set layout */
+ response->layout = 0x0;
+ for (i = 0; i < request.prop_count; i++) {
+ if (openchangedb_lookup_folder_property(emsmdbp_ctx->oc_ctx, request.properties[i],
+ folder->folderID)) {
+ response->layout = 0x1;
+ break;
+ }
+ }
+
+ /* Step 2. Fetch properties values */
+ for (i = 0; i < request.prop_count; i++) {
+ retval = openchangedb_get_folder_property(mem_ctx, emsmdbp_ctx->oc_ctx,
+ emsmdbp_ctx->szDisplayName, request.properties[i],
+ folder->folderID, (void **)&data);
+ if (retval) {
+ request.properties[i] = (request.properties[i] & 0xFFFF0000) + PT_ERROR;
+ data = (void *)&retval;
+ }
+ libmapiserver_push_property(mem_ctx, lp_iconv_convenience(emsmdbp_ctx->lp_ctx),
+ request.properties[i], (const void *)data,
+ &response->prop_data, response->layout);
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details EcDoRpc GetPropertiesSpecific (0x07) Rop. This operation
+ retrieves from properties data from specified object.
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param mapi_req pointer to the GetPropertiesSpecific
+ EcDoRpc_MAPI_REQ structure
+ \param mapi_repl pointer to the GetPropertiesSpecific
+ EcDoRpc_MAPI_REPL structure
+ \param handles pointer to the MAPI handles array
+ \param size pointer to the mapi_response size to update
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS EcDoRpc_RopGetPropertiesSpecific(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct EcDoRpc_MAPI_REQ *mapi_req,
+ struct EcDoRpc_MAPI_REPL *mapi_repl,
+ uint32_t *handles, uint16_t *size)
+{
+ enum MAPISTATUS retval;
+ struct GetProps_req request;
+ struct GetProps_repl response;
+ uint32_t handle;
+ struct mapi_handles *rec = NULL;
+ int systemfolder = -1;
+ void *private_data = NULL;
+
+ DEBUG(4, ("exchange_emsmdb: [OXCPRPT] GetPropertiesSpecific (0x07)\n"));
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
+
+ request = mapi_req->u.mapi_GetProps;
+ response = mapi_repl->u.mapi_GetProps;
+
+ /* Initialize GetProps response blob */
+ response.prop_data.length = 0;
+ response.prop_data.data = NULL;
+
+ handle = handles[mapi_req->handle_idx];
+ retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &rec);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ retval = mapi_handles_get_systemfolder(rec, &systemfolder);
+ retval = mapi_handles_get_private_data(rec, &private_data);
+
+ DEBUG(0, ("GetProps: SystemFolder = %d\n", systemfolder));
+
+ switch (systemfolder) {
+ case -1:
+ /* handled by mapistore */
+ break;
+ case 0x0:
+ /* private mailbox */
+ retval = RopGetPropertiesSpecific_Mailbox(mem_ctx, emsmdbp_ctx, request, &response, private_data);
+ break;
+ case 0x1:
+ /* system or special folder */
+ retval = RopGetPropertiesSpecific_SystemSpecialFolder(mem_ctx, emsmdbp_ctx, request, &response, private_data);
+ break;
+ }
+
+ /* Fill EcDoRpc_MAPI_REPL reply */
+ mapi_repl->opnum = mapi_req->opnum;
+ mapi_repl->handle_idx = mapi_req->handle_idx;
+ mapi_repl->error_code = MAPI_E_SUCCESS;
+ mapi_repl->u.mapi_GetProps = response;
+
+ *size += libmapiserver_RopGetPropertiesSpecific_size(mapi_req, mapi_repl);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/mapiproxy/servers/default/emsmdb/oxcstor.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/emsmdb/oxcstor.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/emsmdb/oxcstor.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,333 @@
+/*
+ OpenChange Server implementation
+
+ EMSMDBP: EMSMDB Provider implementation
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file ocxstor.c
+
+ \brief Server-side store objects routines and Rops
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/libmapiproxy/libmapiproxy.h"
+#include "mapiproxy/libmapiserver/libmapiserver.h"
+#include "dcesrv_exchange_emsmdb.h"
+
+#include <string.h>
+
+
+/**
+ \details Logs on a private mailbox
+
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param mapi_req pointer to the RopLogon EcDoRpc_MAPI_REQ structure
+ \param mapi_repl pointer to the RopLogon EcDoRpc_MAPI_REPL
+ structure the function returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+static enum MAPISTATUS RopLogon_Mailbox(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct EcDoRpc_MAPI_REQ *mapi_req,
+ struct EcDoRpc_MAPI_REPL *mapi_repl)
+{
+ enum MAPISTATUS retval;
+ char *recipient;
+ struct Logon_req request;
+ struct Logon_repl response;
+ struct tm *LogonTime;
+ time_t t;
+ NTTIME nttime;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!mapi_req->u.mapi_Logon.EssDN, MAPI_E_INVALID_PARAMETER, NULL);
+
+ request = mapi_req->u.mapi_Logon;
+ response = mapi_repl->u.mapi_Logon;
+
+ OPENCHANGE_RETVAL_IF(strcmp(request.EssDN, emsmdbp_ctx->szUserDN), MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Step 0. Retrieve recipient name */
+ recipient = x500_get_dn_element(mem_ctx, request.EssDN, "/cn=Recipients/cn=");
+ OPENCHANGE_RETVAL_IF(!recipient, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Step 1. Check if mailbox pointed by recipient belongs to the Exchange organisation */
+
+ /* Step 2. Set LogonFlags */
+ response.LogonFlags = request.LogonFlags & LogonPrivate;
+
+ /* Step 3. Build FolderIds list */
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_MAILBOX_ROOT, &response.LogonType.store_mailbox.FolderIds[0]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_DEFERRED_ACTIONS, &response.LogonType.store_mailbox.FolderIds[1]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_SPOOLER_QUEUE, &response.LogonType.store_mailbox.FolderIds[2]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_TOP_INFORMATION_STORE, &response.LogonType.store_mailbox.FolderIds[3]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_INBOX, &response.LogonType.store_mailbox.FolderIds[4]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_OUTBOX, &response.LogonType.store_mailbox.FolderIds[5]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_SENT_ITEMS, &response.LogonType.store_mailbox.FolderIds[6]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_DELETED_ITEMS, &response.LogonType.store_mailbox.FolderIds[7]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_COMMON_VIEWS, &response.LogonType.store_mailbox.FolderIds[8]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_SCHEDULE, &response.LogonType.store_mailbox.FolderIds[9]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_SEARCH, &response.LogonType.store_mailbox.FolderIds[10]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_VIEWS, &response.LogonType.store_mailbox.FolderIds[11]);
+ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, recipient, EMSMDBP_SHORTCUTS, &response.LogonType.store_mailbox.FolderIds[12]);
+
+ /* Step 4. Set ResponseFlags */
+ response.LogonType.store_mailbox.ResponseFlags = ResponseFlags_Reserved | ResponseFlags_OwnerRight | ResponseFlags_SendAsRight;
+
+ /* Step 5. Retrieve MailboxGuid */
+ retval = openchangedb_get_MailboxGuid(emsmdbp_ctx->oc_ctx, recipient, &response.LogonType.store_mailbox.MailboxGuid);
+
+ /* Step 6. Retrieve mailbox replication information */
+ retval = openchangedb_get_MailboxReplica(emsmdbp_ctx->oc_ctx, recipient,
+ &response.LogonType.store_mailbox.ReplId,
+ &response.LogonType.store_mailbox.ReplGUID);
+
+ /* Step 7. Set LogonTime both in openchange dispatcher database and reply */
+ t = time(NULL);
+ LogonTime = localtime(&t);
+ response.LogonType.store_mailbox.LogonTime.Seconds = LogonTime->tm_sec;
+ response.LogonType.store_mailbox.LogonTime.Minutes = LogonTime->tm_min;
+ response.LogonType.store_mailbox.LogonTime.Hour = LogonTime->tm_hour;
+ response.LogonType.store_mailbox.LogonTime.DayOfWeek = LogonTime->tm_wday;
+ response.LogonType.store_mailbox.LogonTime.Day = LogonTime->tm_mday;
+ response.LogonType.store_mailbox.LogonTime.Month = LogonTime->tm_mon + 1;
+ response.LogonType.store_mailbox.LogonTime.Year = LogonTime->tm_year + 1900;
+
+ /* Step 8. Retrieve GwartTime */
+ unix_to_nt_time(&nttime, t);
+ response.LogonType.store_mailbox.GwartTime = nttime - 1000000;
+
+ /* Step 9. Set StoreState */
+ response.LogonType.store_mailbox.StoreState = 0x0;
+
+ mapi_repl->u.mapi_Logon = response;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details EcDoRpc Logon (0xFE) Rop. This operation logs on to a
+ private mailbox or public folder.
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param request pointer to the Logon EcDoRpc_MAPI_REQ structure
+ \param response pointer to the Logon EcDoRpc_MAPI_REPL structure
+ the function returns
+ \param handles pointer to the MAPI handles array
+ \param size pointer to the mapi_response size to update
+
+ \note Users are only allowed to open their own mailbox at the
+ moment. This limitation will be removed when significant progress
+ have been made.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS EcDoRpc_RopLogon(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct EcDoRpc_MAPI_REQ *request,
+ struct EcDoRpc_MAPI_REPL *response,
+ uint32_t *handles, uint16_t *size)
+{
+ enum MAPISTATUS retval;
+ struct mapi_handles *rec = NULL;
+ struct emsmdbp_object *object;
+
+ DEBUG(4, ("exchange_emsmdb: [OXCSTOR] Logon (0xFE)\n"));
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!request, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!response, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Fill EcDoRpc_MAPI_REPL reply */
+ response->opnum = request->opnum;
+ response->handle_idx = request->handle_idx;
+
+ switch (request->u.mapi_Logon.LogonFlags) {
+ case LogonPrivate:
+ retval = RopLogon_Mailbox(mem_ctx, emsmdbp_ctx, request, response);
+ response->error_code = retval;
+ *size = libmapiserver_RopLogon_size(request, response);
+ break;
+ default:
+ DEBUG(4, ("exchange_emsmdb: [OXCSTOR] Logon on Public Folders not implemented\n"));
+ retval = MAPI_E_NO_SUPPORT;
+ response->error_code = retval;
+ *size = libmapiserver_RopLogon_size(request, NULL);
+ break;
+ }
+
+ if (!response->error_code) {
+ retval = mapi_handles_add(emsmdbp_ctx->handles_ctx, 0, &rec);
+ retval = mapi_handles_set_systemfolder(rec, 0);
+
+ object = emsmdbp_object_mailbox_init((TALLOC_CTX *)rec, emsmdbp_ctx, request);
+ retval = mapi_handles_set_private_data(rec, object);
+
+ handles[response->handle_idx] = rec->handle;
+ }
+
+ return retval;
+}
+
+
+/**
+ \details EcDoRpc Release (0x01) Rop. This operation releases an
+ existing MAPI handle.
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param request pointer to the Release EcDoRpc_MAPI_REQ
+ \param handles pointer to the MAPI handles array
+ \param size pointer to the mapi_response size to update
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS EcDoRpc_RopRelease(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct EcDoRpc_MAPI_REQ *request,
+ uint32_t *handles,
+ uint16_t *size)
+{
+ enum MAPISTATUS retval;
+ uint32_t handle;
+
+ *size = libmapiserver_RopRelease_size();
+
+ handle = handles[request->handle_idx];
+ retval = mapi_handles_delete(emsmdbp_ctx->handles_ctx, handle);
+ OPENCHANGE_RETVAL_IF(retval && retval != MAPI_E_NOT_FOUND, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details EcDoRpc GetReceiveFolder (0x27) Rop Internals. This
+ routine performs the GetReceiveFolder internals.
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param mapi_req pointer to the GetReceiveFolder EcDoRpc_MAPI_REQ
+ \param mapi_repl pointer to the GetReceiveFolder EcDoRpc_MAPI_REPL
+ \param handles pointer to the MAPI handles array
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+static enum MAPISTATUS RopGetReceiveFolder(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct EcDoRpc_MAPI_REQ *mapi_req,
+ struct EcDoRpc_MAPI_REPL *mapi_repl,
+ uint32_t *handles)
+{
+ enum MAPISTATUS retval;
+ struct mapi_handles *rec = NULL;
+ struct emsmdbp_object *object = NULL;
+ const char *MessageClass = NULL;
+ void *private_data = NULL;
+ uint32_t handle;
+ int i;
+
+ /* Step 1. Ensure the referring MAPI handle is mailbox one */
+ handle = handles[mapi_req->handle_idx];
+ retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &rec);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+ retval = mapi_handles_get_private_data(rec, (void **)&private_data);
+ object = (struct emsmdbp_object *) private_data;
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+ OPENCHANGE_RETVAL_IF(object->type != EMSMDBP_OBJECT_MAILBOX, MAPI_E_NO_SUPPORT, NULL);
+
+ /* Step 2. Test Message class string according to [MS-OXCSTOR] section 2.2.1.2.1.1 */
+ MessageClass = mapi_req->u.mapi_GetReceiveFolder.MessageClass;
+ if (!MessageClass || !strcmp(MessageClass, "")) {
+ MessageClass="All";
+ }
+
+ OPENCHANGE_RETVAL_IF(strlen(MessageClass) + 1 > 255, MAPI_E_INVALID_PARAMETER, NULL);
+ for (i = 0; MessageClass[i]; i++) {
+ OPENCHANGE_RETVAL_IF((MessageClass[i] < 32) || (MessageClass[i] > 126),
+ MAPI_E_INVALID_PARAMETER, NULL);
+
+ OPENCHANGE_RETVAL_IF(MessageClass[i] == '.' && MessageClass[i + 1] && MessageClass[i + 1] == '.',
+ MAPI_E_INVALID_PARAMETER, NULL);
+ }
+ OPENCHANGE_RETVAL_IF(MessageClass[0] && MessageClass[0] == '.', MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(MessageClass[0] && MessageClass[strlen(MessageClass)] == '.', MAPI_E_INVALID_PARAMETER, NULL);
+
+
+ /* Step 3. Search for the specified MessageClass substring within user mailbox */
+ retval = openchangedb_get_ReceiveFolder(mem_ctx, emsmdbp_ctx->oc_ctx, object->object.mailbox->owner_Name,
+ MessageClass, &mapi_repl->u.mapi_GetReceiveFolder.folder_id,
+ &mapi_repl->u.mapi_GetReceiveFolder.MessageClass);
+ OPENCHANGE_RETVAL_IF(retval, ecNoReceiveFolder, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details EcDoRpc GetReceiveFolder (0x27) Rop. This operation gets
+ the receive folder for incoming messages of a particular message
+ class
+
+ \param mem_ctx pointer to the memory context
+ \param emsmdbp_ctx pointer to the emsmdb provider context
+ \param mapi_req pointer to the GetReceiveFolder EcDoRpc_MAPI_REQ
+ \param mapi_repl pointer to the GetReceiveFolder EcDoRpc_MAPI_REPL
+ \param handles pointer to the MAPI handles array
+ \param size pointer to the mapi_response size to update
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS EcDoRpc_RopGetReceiveFolder(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct EcDoRpc_MAPI_REQ *mapi_req,
+ struct EcDoRpc_MAPI_REPL *mapi_repl,
+ uint32_t *handles, uint16_t *size)
+{
+ enum MAPISTATUS retval;
+
+ DEBUG(4, ("exchange_emsmdb: [OXCSTOR] GetReceiveFolder (0x27)\n"));
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Call effective code */
+ retval = RopGetReceiveFolder(mem_ctx, emsmdbp_ctx, mapi_req, mapi_repl, handles);
+
+ mapi_repl->opnum = mapi_req->opnum;
+ mapi_repl->handle_idx = mapi_req->handle_idx;
+ mapi_repl->error_code = retval;
+
+ *size = libmapiserver_RopGetReceiveFolder_size(mapi_repl);
+
+ handles[mapi_repl->handle_idx] = handles[mapi_req->handle_idx];
+
+ return retval;
+}
Added: trunk/openchange/mapiproxy/servers/default/nspi/dcesrv_exchange_nsp.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/nspi/dcesrv_exchange_nsp.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/nspi/dcesrv_exchange_nsp.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,959 @@
+/*
+ MAPI Proxy - Exchange NSPI Server
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file dcesrv_exchange_nsp.c
+
+ \brief OpenChange NSPI Server implementation
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "dcesrv_exchange_nsp.h"
+
+struct exchange_nsp_session *nsp_session = NULL;
+TDB_CONTEXT *emsabp_tdb_ctx = NULL;
+
+/**
+ \details exchange_nsp NspiBind (0x0) function, Initiates a NSPI
+ session with the client.
+
+ This function checks if the user is an Exchange user and input
+ parameters like codepage are valid. If it passes the tests, the
+ function initializes an emsabp context and returns to the client a
+ valid policy_handle and expected reply parameters.
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiBind call structure
+
+ \return MAPI_E_SUCCESS on success, otherwise a MAPI error
+ */
+static enum MAPISTATUS dcesrv_NspiBind(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiBind *r)
+{
+ struct GUID *guid = (struct GUID *) NULL;
+ struct emsabp_context *emsabp_ctx;
+ struct dcesrv_handle *handle;
+ struct policy_handle wire_handle;
+ struct exchange_nsp_session *session;
+
+ DEBUG(5, ("exchange_nsp: NspiBind (0x0)\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"));
+
+ wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
+ wire_handle.uuid = GUID_zero();
+ *r->out.handle = wire_handle;
+
+ r->out.mapiuid = r->in.mapiuid;
+ r->out.result = MAPI_E_LOGON_FAILED;
+ return MAPI_E_LOGON_FAILED;
+ }
+
+ /* Step 1. Initialize the emsabp context */
+ emsabp_ctx = emsabp_init(dce_call->conn->dce_ctx->lp_ctx, emsabp_tdb_ctx);
+ if (!emsabp_ctx) {
+ smb_panic("unable to initialize emsabp context");
+ OPENCHANGE_RETVAL_IF(!emsabp_ctx, MAPI_E_FAILONEPROVIDER, NULL);
+ }
+
+ /* Step 2. Check if incoming user belongs to the Exchange organization */
+ if (emsabp_verify_user(dce_call, emsabp_ctx) == false) {
+ talloc_free(emsabp_ctx);
+
+ wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
+ wire_handle.uuid = GUID_zero();
+ *r->out.handle = wire_handle;
+
+ r->out.mapiuid = r->in.mapiuid;
+ r->out.result = MAPI_E_LOGON_FAILED;
+ return MAPI_E_LOGON_FAILED;
+ }
+
+ /* Step 3. Check if valid cpID has been supplied */
+ if (emsabp_verify_codepage(emsabp_ctx, r->in.pStat->CodePage) == false) {
+ talloc_free(emsabp_ctx);
+
+ wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
+ wire_handle.uuid = GUID_zero();
+ *r->out.handle = wire_handle;
+
+ r->out.mapiuid = r->in.mapiuid;
+ r->out.result = MAPI_E_UNKNOWN_CPID;
+ return MAPI_E_UNKNOWN_CPID;
+ }
+
+ /* Step 4. Retrieve OpenChange server GUID */
+ guid = emsabp_get_server_GUID(emsabp_ctx);
+ OPENCHANGE_RETVAL_IF(!guid, MAPI_E_FAILONEPROVIDER, emsabp_ctx);
+
+ /* Step 5. Fill NspiBind reply */
+ handle = dcesrv_handle_new(dce_call->context, EXCHANGE_HANDLE_NSP);
+ OPENCHANGE_RETVAL_IF(!handle, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
+
+ handle->data = (void *) emsabp_ctx;
+ *r->out.handle = handle->wire_handle;
+ r->out.mapiuid = guid;
+ r->out.result = MAPI_E_SUCCESS;
+
+ /* Step 6. Associate this emsabp context to the session */
+ session = talloc((TALLOC_CTX *)nsp_session, struct exchange_nsp_session);
+ OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
+
+ session->session = mpm_session_init((TALLOC_CTX *)nsp_session, dce_call);
+ OPENCHANGE_RETVAL_IF(!session->session, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
+
+ mpm_session_set_private_data(session->session, (void *) emsabp_ctx);
+ mpm_session_set_destructor(session->session, emsabp_destructor);
+
+ DLIST_ADD_END(nsp_session, session, struct exchange_nsp_session *);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details exchange_nsp NspiUnbind (0x1) function, Terminates a NSPI
+ session with the client
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiUnbind call structure
+ */
+static enum MAPISTATUS dcesrv_NspiUnbind(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiUnbind *r)
+{
+ struct dcesrv_handle *h;
+ struct exchange_nsp_session *session;
+
+ DEBUG(5, ("exchange_nsp: NspiUnbind (0x1)\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;
+ }
+
+ /* Step 1. Retrieve handle and free if emsabp context and session are available */
+ h = dcesrv_handle_fetch(dce_call->context, r->in.handle, DCESRV_HANDLE_ANY);
+ if (h) {
+ for (session = nsp_session; session; session = session->next) {
+ if ((mpm_session_cmp(session->session, dce_call) == true)) {
+ mpm_session_release(session->session);
+ DLIST_REMOVE(nsp_session, session);
+ DEBUG(6, ("[%s:%d]: Session found and released\n", __FUNCTION__, __LINE__));
+ }
+ }
+ }
+
+ r->out.result = 1;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details exchange_nsp NspiUpdateStat (0x2) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiUpdateStat request data
+
+ \return MAPI_E_SUCCESS on success
+*/
+static enum MAPISTATUS dcesrv_NspiUpdateStat(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiUpdateStat *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiUpdateStat (0x2) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiQueryRows (0x3) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiQueryRows request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_NspiQueryRows(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiQueryRows *r)
+{
+ enum MAPISTATUS retval = MAPI_E_SUCCESS;
+ struct dcesrv_handle *h;
+ struct emsabp_context *emsabp_ctx;
+ struct SPropTagArray *pPropTags;
+ uint32_t i;
+
+ DEBUG(3, ("exchange_nsp: NspiQueryRows (0x3)\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;
+ }
+
+ h = dcesrv_handle_fetch(dce_call->context, r->in.handle, DCESRV_HANDLE_ANY);
+ emsabp_ctx = (struct emsabp_context *) h->data;
+
+ /* Step 1. Sanity Checks (MS-NSPI Server Processing Rules) */
+ if (r->in.pStat->ContainerID && (emsabp_tdb_lookup_MId(emsabp_ctx->tdb_ctx, r->in.pStat->ContainerID) == false)) {
+ retval = MAPI_E_INVALID_BOOKMARK;
+ goto failure;
+ }
+
+ if (r->in.pPropTags == NULL) {
+ pPropTags = set_SPropTagArray(mem_ctx, 0x7,
+ PR_EMS_AB_CONTAINERID,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_DISPLAY_NAME,
+ PR_OFFICE_TELEPHONE_NUMBER,
+ PR_COMPANY_NAME,
+ PR_OFFICE_LOCATION);
+ } else {
+ pPropTags = r->in.pPropTags;
+ }
+
+ if (r->in.lpETable == NULL) {
+ /* FIXME */
+ return MAPI_E_INVALID_BOOKMARK;
+ }
+
+ if (retval != MAPI_E_SUCCESS) {
+ failure:
+ r->out.pStat = r->in.pStat;
+ r->out.ppRows = talloc(mem_ctx, struct SRowSet *);
+ r->out.ppRows[0] = NULL;
+ r->out.result = retval;
+
+ return retval;
+ }
+
+ /* Step 2. Fill ppRows */
+ r->out.ppRows = talloc(mem_ctx, struct SRowSet *);
+ r->out.ppRows[0] = talloc(mem_ctx, struct SRowSet);
+ r->out.ppRows[0]->cRows = r->in.Count;
+ r->out.ppRows[0]->aRow = talloc_array(mem_ctx, struct SRow, r->in.Count);
+ for (i = 0; i < r->in.Count; i++) {
+ retval = emsabp_fetch_attrs(mem_ctx, emsabp_ctx, &(r->out.ppRows[0]->aRow[i]), r->in.lpETable[i], pPropTags);
+ if (retval != MAPI_E_SUCCESS) {
+ goto failure;
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details exchange_nsp NspiSeekEntries (0x4) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiSeekEntries request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_NspiSeekEntries(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiSeekEntries *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiSeekEntries (0x4) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiGetMatches (0x5) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiGetMatches request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_NspiGetMatches(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiGetMatches *r)
+{
+ enum MAPISTATUS retval;
+ struct dcesrv_handle *h;
+ struct emsabp_context *emsabp_ctx;
+ struct SPropTagArray *ppOutMIds = NULL;
+ uint32_t i;
+
+
+ DEBUG(3, ("exchange_nsp: NspiGetMatches (0x5)\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;
+ }
+
+ h = dcesrv_handle_fetch(dce_call->context, r->in.handle, DCESRV_HANDLE_ANY);
+ emsabp_ctx = (struct emsabp_context *) h->data;
+
+ /* Step 1. Retrieve MIds array given search criterias */
+ ppOutMIds = talloc_zero(mem_ctx, struct SPropTagArray);
+ retval = emsabp_search(mem_ctx, emsabp_ctx, ppOutMIds, r->in.Filter, r->in.pStat, r->in.ulRequested);
+ if (retval != MAPI_E_SUCCESS) {
+ failure:
+ r->out.pStat = r->in.pStat;
+ ppOutMIds = NULL;
+ r->out.ppOutMIds = &ppOutMIds;
+ r->out.ppRows = talloc(mem_ctx, struct SRowSet *);
+ r->out.ppRows[0] = NULL;
+ r->out.result = retval;
+
+ return retval;
+ }
+
+ *r->out.ppOutMIds = ppOutMIds;
+
+ /* Step 2. Retrieve requested properties for these MIds */
+ r->out.ppRows = talloc_zero(mem_ctx, struct SRowSet *);
+ r->out.ppRows[0] = talloc_zero(mem_ctx, struct SRowSet);
+ r->out.ppRows[0]->cRows = ppOutMIds->cValues;
+ r->out.ppRows[0]->aRow = talloc_array(mem_ctx, struct SRow, ppOutMIds->cValues);
+
+
+ for (i = 0; i < ppOutMIds->cValues; i++) {
+ retval = emsabp_fetch_attrs(mem_ctx, emsabp_ctx, &(r->out.ppRows[0]->aRow[i]),
+ ppOutMIds->aulPropTag[i], r->in.pPropTags);
+ if (retval) goto failure;
+ }
+
+ r->out.result = MAPI_E_SUCCESS;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details exchange_nsp NspiResortRestriction (0x6) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiResortRestriction request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_NspiResortRestriction(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiResortRestriction *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiResortRestriction (0x6) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiDNToMId (0x7) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiDNToMId request data
+
+ \note Only searches within configuration.ldb are supported at the
+ moment.
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_NspiDNToMId(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiDNToMId *r)
+{
+ enum MAPISTATUS retval;
+ struct dcesrv_handle *h;
+ struct emsabp_context *emsabp_ctx;
+ struct ldb_message *msg;
+ uint32_t i;
+ uint32_t MId;
+ const char *dn;
+
+ DEBUG(3, ("exchange_nsp: NspiDNToMId (0x7)\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;
+ }
+
+ h = dcesrv_handle_fetch(dce_call->context, r->in.handle, DCESRV_HANDLE_ANY);
+ emsabp_ctx = (struct emsabp_context *) h->data;
+
+ r->out.ppMIds = talloc_array(mem_ctx, struct SPropTagArray *, 2);
+ r->out.ppMIds[0] = talloc_zero(mem_ctx, struct SPropTagArray);
+ r->out.ppMIds[0]->cValues = r->in.pNames->Count;
+ r->out.ppMIds[0]->aulPropTag = talloc_array(mem_ctx, uint32_t, r->in.pNames->Count);
+
+ for (i = 0; i < r->in.pNames->Count; i++) {
+ /* Step 1. Check if the input legacyDN exists */
+ retval = emsabp_search_legacyExchangeDN(emsabp_ctx, r->in.pNames->Strings[i], &msg);
+ if (retval != MAPI_E_SUCCESS) {
+ r->out.ppMIds[0]->aulPropTag[i] = 0;
+ } else {
+ dn = ldb_msg_find_attr_as_string(msg, "distinguishedName", NULL);
+ retval = emsabp_tdb_fetch_MId(emsabp_ctx->tdb_ctx, dn, &MId);
+ if (retval) {
+ retval = emsabp_tdb_insert(emsabp_ctx->tdb_ctx, dn);
+ retval = emsabp_tdb_fetch_MId(emsabp_ctx->tdb_ctx, dn, &MId);
+ }
+ r->out.ppMIds[0]->aulPropTag[i] = MId;
+ }
+ }
+
+ r->out.result = MAPI_E_SUCCESS;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details exchange_nsp NspiGetPropList (0x8) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiGetPropList request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_NspiGetPropList(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiGetPropList *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiGetPropList (0x8) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiGetProps (0x9) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiGetProps request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_NspiGetProps(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiGetProps *r)
+{
+ enum MAPISTATUS retval;
+ struct dcesrv_handle *h;
+ struct emsabp_context *emsabp_ctx;
+ uint32_t MId;
+ char *dn;
+
+ DEBUG(3, ("exchange_nsp: NspiGetProps (0x9)\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;
+ }
+
+ h = dcesrv_handle_fetch(dce_call->context, r->in.handle, DCESRV_HANDLE_ANY);
+ emsabp_ctx = (struct emsabp_context *) h->data;
+
+ MId = r->in.pStat->CurrentRec;
+
+ /* Step 1. Sanity Checks (MS-NSPI Server Processing Rules) */
+ if (r->in.pStat->ContainerID && (emsabp_tdb_lookup_MId(emsabp_ctx->tdb_ctx, r->in.pStat->ContainerID) == false)) {
+ retval = MAPI_E_INVALID_BOOKMARK;
+ goto failure;
+ }
+
+ retval = emsabp_tdb_fetch_dn_from_MId(mem_ctx, emsabp_ctx->tdb_ctx, MId, &dn);
+ if (retval != MAPI_E_SUCCESS) {
+ failure:
+ r->out.ppRows = talloc_array(mem_ctx, struct SRow *, 2);
+ r->out.ppRows[0] = NULL;
+ r->out.result = MAPI_E_INVALID_BOOKMARK;
+ return r->out.result;
+ }
+
+ /* Step 2. Fetch properties */
+ r->out.ppRows = talloc_array(mem_ctx, struct SRow *, 2);
+ r->out.ppRows[0] = talloc_zero(mem_ctx, struct SRow);
+ r->out.ppRows[0]->ulAdrEntryPad = 0;
+ r->out.ppRows[0]->cValues = r->in.pPropTags->cValues;
+ r->out.ppRows[0]->lpProps = talloc_array(mem_ctx, struct SPropValue, r->in.pPropTags->cValues);
+
+ retval = emsabp_fetch_attrs(mem_ctx, emsabp_ctx, r->out.ppRows[0], MId, r->in.pPropTags);
+ if (retval != MAPI_E_SUCCESS) {
+ talloc_free(r->out.ppRows[0]->lpProps);
+ talloc_free(r->out.ppRows[0]);
+ talloc_free(r->out.ppRows[0]);
+ r->out.result = MAPI_W_ERRORS_RETURNED;
+ goto failure;
+ }
+
+ r->out.result = MAPI_E_SUCCESS;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details exchange_nsp NspiCompareMIds (0xA) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiCompareMIds request data
+
+ \return MAPI_E_SUCCESS on success
+*/
+static enum MAPISTATUS dcesrv_NspiCompareMIds(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiCompareMIds *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiCompareMIds (0xA) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiModProps (0xB) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiModProps request data
+
+ \return MAPI_E_SUCCESS on success
+
+ */
+static enum MAPISTATUS dcesrv_NspiModProps(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiModProps *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiModProps (0xB) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiGetSpecialTable (0xC) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiGetSpecialTable request data
+
+ \note MS-NSPI specifies lpVersion "holds the value of the version
+ number of the hierarchy table that the client has." We will ignore
+ this for the moment.
+
+ \return MAPI_E_SUCCESS on success
+
+ */
+static enum MAPISTATUS dcesrv_NspiGetSpecialTable(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiGetSpecialTable *r)
+{
+ struct dcesrv_handle *h;
+ struct emsabp_context *emsabp_ctx;
+
+ DEBUG(3, ("exchange_nsp: NspiGetSpecialTable (0xC)\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;
+ }
+
+ h = dcesrv_handle_fetch(dce_call->context, r->in.handle, DCESRV_HANDLE_ANY);
+ emsabp_ctx = (struct emsabp_context *) h->data;
+
+ /* Step 1. (FIXME) We arbitrary set lpVersion to 0x1 */
+ r->out.lpVersion = talloc_zero(mem_ctx, uint32_t);
+ *r->out.lpVersion = 0x1;
+
+ /* Step 2. Allocate output SRowSet and call associated emsabp function */
+ r->out.ppRows = talloc_zero(mem_ctx, struct SRowSet *);
+ OPENCHANGE_RETVAL_IF(!r->out.ppRows, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+ r->out.ppRows[0] = talloc_zero(mem_ctx, struct SRowSet);
+ OPENCHANGE_RETVAL_IF(!r->out.ppRows[0], MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+
+ switch (r->in.dwFlags) {
+ case NspiAddressCreationTemplates:
+ case NspiAddressCreationTemplates|NspiUnicodeStrings:
+ DEBUG(0, ("CreationTemplates Table requested\n"));
+ r->out.result = emsabp_get_CreationTemplatesTable(mem_ctx, emsabp_ctx, r->in.dwFlags, r->out.ppRows);
+ break;
+ case NspiUnicodeStrings:
+ case 0x0:
+ DEBUG(0, ("Hierarchy Table requested\n"));
+ r->out.result = emsabp_get_HierarchyTable(mem_ctx, emsabp_ctx, r->in.dwFlags, r->out.ppRows);
+ break;
+ default:
+ talloc_free(r->out.ppRows);
+ talloc_free(r->out.ppRows[0]);
+ return MAPI_E_NO_SUPPORT;
+ }
+
+ return r->out.result;
+}
+
+
+/**
+ \details exchange_nsp NspiGetTemplateInfo (0xD) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiGetTemplateInfo request data
+
+ \return MAPI_E_SUCCESS on success
+
+ */
+static enum MAPISTATUS dcesrv_NspiGetTemplateInfo(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiGetTemplateInfo *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiGetTemplateInfo (0xD) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiModLinkAtt (0xE) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiModLinkAtt request data
+
+ \return MAPI_E_SUCCESS on success
+
+ */
+static enum MAPISTATUS dcesrv_NspiModLinkAtt(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiModLinkAtt *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiModLinkAtt (0xE) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiDeleteEntries (0xF) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiDeleteEntries request data
+
+ \return MAPI_E_SUCCESS on success
+
+ */
+static enum MAPISTATUS dcesrv_NspiDeleteEntries(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiDeleteEntries *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiDeleteEntries (0xF) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiQueryColumns (0x10) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiQueryColumns request data
+
+ \return MAPI_E_SUCCESS on success
+
+ */
+static enum MAPISTATUS dcesrv_NspiQueryColumns(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiQueryColumns *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiQueryColumns (0x10) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiGetNamesFromIDs (0x11) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiGetNamesFromIDs request data
+
+ \return MAPI_E_SUCCESS on success
+
+ */
+static enum MAPISTATUS dcesrv_NspiGetNamesFromIDs(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiGetNamesFromIDs *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiGetNamesFromIDs (0x11) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiGetIDsFromNames (0x12) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiGetIDsFromNames request data
+
+ \return MAPI_E_SUCCESS on success
+
+ */
+static enum MAPISTATUS dcesrv_NspiGetIDsFromNames(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiGetIDsFromNames *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiGetIDsFromNames (0x12) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiResolveNames (0x13) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiResolveNames request data
+
+ \return MAPI_E_SUCCESS on success
+
+ */
+static enum MAPISTATUS dcesrv_NspiResolveNames(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiResolveNames *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiResolveNames (0x13) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_nsp NspiResolveNamesW (0x14) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the NspiResolveNamesW request data
+
+ \return MAPI_E_SUCCESS on success
+
+ */
+static enum MAPISTATUS dcesrv_NspiResolveNamesW(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct NspiResolveNamesW *r)
+{
+ DEBUG(3, ("exchange_nsp: NspiResolveNamesW (0x14) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details Dispatch incoming NSPI call to the correct OpenChange
+ server function.
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r generic pointer on NSPI data
+ \param mapiproxy pointer to the mapiproxy structure controlling
+ mapiproxy behavior
+
+ \return NT_STATUS_OK
+ */
+static NTSTATUS dcesrv_exchange_nsp_dispatch(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ void *r, struct mapiproxy *mapiproxy)
+{
+ enum MAPISTATUS retval;
+ const struct ndr_interface_table *table;
+ uint16_t opnum;
+
+ table = (const struct ndr_interface_table *) dce_call->context->iface->private;
+ opnum = dce_call->pkt.u.request.opnum;
+
+ /* Sanity checks */
+ if (!table) return NT_STATUS_UNSUCCESSFUL;
+ if (table->name && strcmp(table->name, NDR_EXCHANGE_NSP_NAME)) return NT_STATUS_UNSUCCESSFUL;
+
+ switch (opnum) {
+ case NDR_NSPIBIND:
+ retval = dcesrv_NspiBind(dce_call, mem_ctx, (struct NspiBind *)r);
+ break;
+ case NDR_NSPIUNBIND:
+ retval = dcesrv_NspiUnbind(dce_call, mem_ctx, (struct NspiUnbind *)r);
+ break;
+ case NDR_NSPIUPDATESTAT:
+ retval = dcesrv_NspiUpdateStat(dce_call, mem_ctx, (struct NspiUpdateStat *)r);
+ break;
+ case NDR_NSPIQUERYROWS:
+ retval = dcesrv_NspiQueryRows(dce_call, mem_ctx, (struct NspiQueryRows *)r);
+ break;
+ case NDR_NSPISEEKENTRIES:
+ retval = dcesrv_NspiSeekEntries(dce_call, mem_ctx, (struct NspiSeekEntries *)r);
+ break;
+ case NDR_NSPIGETMATCHES:
+ retval = dcesrv_NspiGetMatches(dce_call, mem_ctx, (struct NspiGetMatches *)r);
+ break;
+ case NDR_NSPIRESORTRESTRICTION:
+ retval = dcesrv_NspiResortRestriction(dce_call, mem_ctx, (struct NspiResortRestriction *)r);
+ break;
+ case NDR_NSPIDNTOMID:
+ retval = dcesrv_NspiDNToMId(dce_call, mem_ctx, (struct NspiDNToMId *)r);
+ break;
+ case NDR_NSPIGETPROPLIST:
+ retval = dcesrv_NspiGetPropList(dce_call, mem_ctx, (struct NspiGetPropList *)r);
+ break;
+ case NDR_NSPIGETPROPS:
+ retval = dcesrv_NspiGetProps(dce_call, mem_ctx, (struct NspiGetProps *)r);
+ break;
+ case NDR_NSPICOMPAREMIDS:
+ retval = dcesrv_NspiCompareMIds(dce_call, mem_ctx, (struct NspiCompareMIds *)r);
+ break;
+ case NDR_NSPIMODPROPS:
+ retval = dcesrv_NspiModProps(dce_call, mem_ctx, (struct NspiModProps *)r);
+ break;
+ case NDR_NSPIGETSPECIALTABLE:
+ retval = dcesrv_NspiGetSpecialTable(dce_call, mem_ctx, (struct NspiGetSpecialTable *)r);
+ break;
+ case NDR_NSPIGETTEMPLATEINFO:
+ retval = dcesrv_NspiGetTemplateInfo(dce_call, mem_ctx, (struct NspiGetTemplateInfo *)r);
+ break;
+ case NDR_NSPIMODLINKATT:
+ retval = dcesrv_NspiModLinkAtt(dce_call, mem_ctx, (struct NspiModLinkAtt *)r);
+ break;
+ case NDR_NSPIDELETEENTRIES:
+ retval = dcesrv_NspiDeleteEntries(dce_call, mem_ctx, (struct NspiDeleteEntries *)r);
+ break;
+ case NDR_NSPIQUERYCOLUMNS:
+ retval = dcesrv_NspiQueryColumns(dce_call, mem_ctx, (struct NspiQueryColumns *)r);
+ break;
+ case NDR_NSPIGETNAMESFROMIDS:
+ retval = dcesrv_NspiGetNamesFromIDs(dce_call, mem_ctx, (struct NspiGetNamesFromIDs *)r);
+ break;
+ case NDR_NSPIGETIDSFROMNAMES:
+ retval = dcesrv_NspiGetIDsFromNames(dce_call, mem_ctx, (struct NspiGetIDsFromNames *)r);
+ break;
+ case NDR_NSPIRESOLVENAMES:
+ retval = dcesrv_NspiResolveNames(dce_call, mem_ctx, (struct NspiResolveNames *)r);
+ break;
+ case NDR_NSPIRESOLVENAMESW:
+ retval = dcesrv_NspiResolveNamesW(dce_call, mem_ctx, (struct NspiResolveNamesW *)r);
+ break;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Initialize the NSPI OpenChange server
+
+ \param dce_ctx pointer to the server context
+
+ \return NT_STATUS_OK on success, otherwise NT_STATUS_NO_MEMORY
+ */
+static NTSTATUS dcesrv_exchange_nsp_init(struct dcesrv_context *dce_ctx)
+{
+ /* Initialize exchange_nsp session */
+ nsp_session = talloc_zero(dce_ctx, struct exchange_nsp_session);
+ if (!nsp_session) return NT_STATUS_NO_MEMORY;
+ nsp_session->session = NULL;
+
+ /* Open a read-write pointer on the EMSABP TDB database */
+ emsabp_tdb_ctx = emsabp_tdb_init((TALLOC_CTX *)dce_ctx, dce_ctx->lp_ctx);
+ if (!emsabp_tdb_ctx) {
+ smb_panic("unable to initialize EMSABP context");
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Terminates the NSPI connection and release the associated
+ session and context if still available. This case occurs when the
+ client doesn't call NspiUnbind but quit unexpectedly.
+
+ \param server_id reference to the server identifier structure
+ \param context_id the connection context identifier
+
+ \return NT_STATUS_OK on success
+ */
+static NTSTATUS dcesrv_exchange_nsp_unbind(struct server_id server_id, uint32_t context_id)
+{
+ struct exchange_nsp_session *session;
+
+ for (session = nsp_session; session; session = session->next) {
+ if ((mpm_session_cmp_sub(session->session, server_id, context_id) == true)) {
+ mpm_session_release(session->session);
+ DLIST_REMOVE(nsp_session, session);
+ DEBUG(6, ("[%s:%d]: Session found and released\n", __FUNCTION__, __LINE__));
+ return NT_STATUS_OK;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Entry point for the default OpenChange NSPI server
+
+ \return NT_STATUS_OK on success, otherwise NTSTATUS error
+ */
+NTSTATUS samba_init_module(void)
+{
+ struct mapiproxy_module server;
+ NTSTATUS ret;
+
+ /* Fill in our name */
+ server.name = "exchange_nsp";
+ server.status = MAPIPROXY_DEFAULT;
+ server.description = "OpenChange NSPI server";
+ server.endpoint = "exchange_nsp";
+
+ /* Fill in all the operations */
+ server.init = dcesrv_exchange_nsp_init;
+ server.unbind = dcesrv_exchange_nsp_unbind;
+ server.dispatch = dcesrv_exchange_nsp_dispatch;
+ server.push = NULL;
+ server.pull = NULL;
+ server.ndr_pull = NULL;
+
+ /* Register ourselves with the MAPIPROXY server subsystem */
+ ret = mapiproxy_server_register(&server);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("Failed to register the 'exchange_nsp' default mapiproxy server!\n"));
+ return ret;
+ }
+
+ return ret;
+}
Added: trunk/openchange/mapiproxy/servers/default/nspi/dcesrv_exchange_nsp.h
===================================================================
--- trunk/openchange/mapiproxy/servers/default/nspi/dcesrv_exchange_nsp.h (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/nspi/dcesrv_exchange_nsp.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,153 @@
+/*
+ MAPI Proxy - Exchange NSPI Server
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 __DCESRV_EXCHANGE_NSP_H
+#define __DCESRV_EXCHANGE_NSP_H
+
+#include <libmapi/libmapi.h>
+#include <libmapi/proto_private.h>
+#include <mapiproxy/libmapiproxy/libmapiproxy.h>
+#include <ldb.h>
+#include <ldb_errors.h>
+#include <fcntl.h>
+#include <util/debug.h>
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+struct emsabp_context {
+ struct loadparm_context *lp_ctx;
+ void *conf_ctx;
+ void *users_ctx;
+ void *ldb_ctx;
+ TDB_CONTEXT *tdb_ctx;
+ TDB_CONTEXT *ttdb_ctx;
+ TALLOC_CTX *mem_ctx;
+};
+
+
+struct exchange_nsp_session {
+ struct mpm_session *session;
+ struct exchange_nsp_session *prev;
+ struct exchange_nsp_session *next;
+};
+
+
+struct emsabp_MId {
+ uint32_t MId;
+ char *dn;
+};
+
+/**
+ PermanentEntryID structure
+ */
+struct PermanentEntryID {
+ uint8_t ID_type; /* constant: 0x0 */
+ uint8_t R1; /* reserved: 0x0 */
+ uint8_t R2; /* reserved: 0x0 */
+ uint8_t R3; /* reserved: 0x0 */
+ struct FlatUID_r ProviderUID; /* constant: GUID_NSPI */
+ uint32_t R4; /* constant: 0x1 */
+ uint32_t DisplayType; /* must match one of the existing Display Type value */
+ char *dn; /* DN string representing the object GUID */
+};
+
+
+/**
+ EphemeralEntryID structure
+ */
+struct EphemeralEntryID {
+ uint8_t ID_type; /* constant: 0x87 */
+ uint8_t R1; /* reserved: 0x0 */
+ uint8_t R2; /* reserved: 0x0 */
+ uint8_t R3; /* reserved: 0x0 */
+ struct FlatUID_r ProviderUID; /* NSPI server GUID */
+ uint32_t R4; /* constant: 0x1 */
+ uint32_t DisplayType; /* must match one of the existing Display Type value */
+ uint32_t MId; /* MId of this object */
+};
+
+#define EMSABP_DN "/guid=%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X"
+#define EMSABP_ADDRTYPE "EX"
+
+/**
+ NSPI PR_CONTAINER_FLAGS values
+ */
+#define AB_RECIPIENTS 0x1
+#define AB_SUBCONTAINERS 0x2
+#define AB_UNMODIFIABLE 0x8
+
+#define EMSABP_TDB_MID_START 0x1b28
+#define EMSABP_TDB_TMP_MID_START 0x5000
+#define EMSABP_TDB_DATA_REC "MId_index"
+
+__BEGIN_DECLS
+
+NTSTATUS samba_init_module(void);
+
+/* definitions from emsabp.c */
+struct emsabp_context *emsabp_init(struct loadparm_context *, TDB_CONTEXT *);
+bool emsabp_destructor(void *);
+bool emsabp_verify_user(struct dcesrv_call_state *, struct emsabp_context *);
+bool emsabp_verify_codepage(struct emsabp_context *, uint32_t);
+bool emsabp_verify_lcid(struct emsabp_context *, uint32_t);
+struct GUID *emsabp_get_server_GUID(struct emsabp_context *);
+enum MAPISTATUS emsabp_set_EphemeralEntryID(struct emsabp_context *, uint32_t, uint32_t, struct EphemeralEntryID *);
+enum MAPISTATUS emsabp_set_PermanentEntryID(struct emsabp_context *, uint32_t, struct ldb_message *, struct PermanentEntryID *);
+enum MAPISTATUS emsabp_EphemeralEntryID_to_Binary_r(TALLOC_CTX *, struct EphemeralEntryID *, struct Binary_r *);
+enum MAPISTATUS emsabp_PermanentEntryID_to_Binary_r(TALLOC_CTX *, struct PermanentEntryID *, struct Binary_r *);
+enum MAPISTATUS emsabp_get_HierarchyTable(TALLOC_CTX *, struct emsabp_context *, uint32_t, struct SRowSet **);
+enum MAPISTATUS emsabp_get_CreationTemplatesTable(TALLOC_CTX *, struct emsabp_context *, uint32_t, struct SRowSet **);
+void *emsabp_query(TALLOC_CTX *, struct emsabp_context *, struct ldb_message *, uint32_t, uint32_t);
+enum MAPISTATUS emsabp_fetch_attrs(TALLOC_CTX *, struct emsabp_context *, struct SRow *, uint32_t, struct SPropTagArray *);
+enum MAPISTATUS emsabp_table_fetch_attrs(TALLOC_CTX *, struct emsabp_context *, struct SRow *, uint32_t, struct PermanentEntryID *,
+ struct PermanentEntryID *, struct ldb_message *, bool);
+enum MAPISTATUS emsabp_search(TALLOC_CTX *, struct emsabp_context *, struct SPropTagArray *, struct Restriction_r *, struct STAT *, uint32_t);
+enum MAPISTATUS emsabp_search_dn(struct emsabp_context *, const char *, struct ldb_message **);
+enum MAPISTATUS emsabp_search_legacyExchangeDN(struct emsabp_context *, const char *, struct ldb_message **);
+
+/* definitions from emsabp_tdb.c */
+TDB_CONTEXT *emsabp_tdb_init(TALLOC_CTX *, struct loadparm_context *);
+enum MAPISTATUS emsabp_tdb_close(TDB_CONTEXT *);
+enum MAPISTATUS emsabp_tdb_fetch(TDB_CONTEXT *, const char *, TDB_DATA *);
+enum MAPISTATUS emsabp_tdb_insert(TDB_CONTEXT *, const char *);
+enum MAPISTATUS emsabp_tdb_fetch_MId(TDB_CONTEXT *, const char *, uint32_t *);
+bool emsabp_tdb_lookup_MId(TDB_CONTEXT *, uint32_t);
+enum MAPISTATUS emsabp_tdb_fetch_dn_from_MId(TALLOC_CTX *, TDB_CONTEXT *, uint32_t, char **);
+
+TDB_CONTEXT *emsabp_tdb_init_tmp(TALLOC_CTX *);
+
+/* definitions from emsabp_property.c */
+const char *emsabp_property_get_attribute(uint32_t);
+uint32_t emsabp_property_get_ulPropTag(const char *);
+int emsabp_property_is_ref(uint32_t);
+const char *emsabp_property_get_ref_attr(uint32_t);
+
+__END_DECLS
+
+#endif /* __DCESRV_EXCHANGE_NSP_H */
Added: trunk/openchange/mapiproxy/servers/default/nspi/emsabp.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/nspi/emsabp.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/nspi/emsabp.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1124 @@
+/*
+ OpenChange Server implementation.
+
+ EMSABP: Address Book Provider implementation
+
+ Copyright (C) Julien Kerihuel 2006-2009.
+ Copyright (C) Pauline Khun 2006.
+
+ 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/>.
+ */
+
+/**
+ \file emsabp.c
+
+ \brief Address Book Provider implementation
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "dcesrv_exchange_nsp.h"
+
+/**
+ \details Initialize the EMSABP context and open connections to
+ Samba databases.
+
+ \param lp_ctx pointer to the loadparm context
+ \param tdb_ctx pointer to the EMSABP TDB context
+
+ \return Allocated emsabp_context on success, otherwise NULL
+ */
+_PUBLIC_ struct emsabp_context *emsabp_init(struct loadparm_context *lp_ctx,
+ TDB_CONTEXT *tdb_ctx)
+{
+ TALLOC_CTX *mem_ctx;
+ struct emsabp_context *emsabp_ctx;
+ struct tevent_context *ev;
+ char *configuration = NULL;
+ char *users = NULL;
+ int ret;
+
+ /* Sanity checks */
+ if (!lp_ctx) return NULL;
+
+ mem_ctx = talloc_named(NULL, 0, "emsabp_init");
+
+ emsabp_ctx = talloc_zero(mem_ctx, struct emsabp_context);
+ if (!emsabp_ctx) {
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ emsabp_ctx->mem_ctx = mem_ctx;
+
+ ev = tevent_context_init(mem_ctx);
+ if (!ev) {
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ /* Save a pointer to the loadparm context */
+ emsabp_ctx->lp_ctx = lp_ctx;
+
+ /* Return an opaque context pointer on the configuration database */
+ configuration = private_path(mem_ctx, lp_ctx, "configuration.ldb");
+ emsabp_ctx->conf_ctx = ldb_init(mem_ctx, ev);
+ if (!emsabp_ctx->conf_ctx) {
+ talloc_free(configuration);
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ ret = ldb_connect(emsabp_ctx->conf_ctx, configuration, LDB_FLG_RDONLY, NULL);
+ talloc_free(configuration);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("[%s:%d]: Connection to \"configuration.ldb\" failed\n", __FUNCTION__, __LINE__));
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ /* Return an opaque context pointer to the users database */
+ users = private_path(mem_ctx, lp_ctx, "users.ldb");
+ emsabp_ctx->users_ctx = ldb_init(mem_ctx, ev);
+ if (!emsabp_ctx->users_ctx) {
+ talloc_free(users);
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ ret = ldb_connect(emsabp_ctx->users_ctx, users, LDB_FLG_RDONLY, NULL);
+ talloc_free(users);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("[%s:%d]: Connection to \"users.ldb\" failed\n", __FUNCTION__, __LINE__));
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ /* Reference the global TDB context to the current emsabp context */
+ emsabp_ctx->tdb_ctx = tdb_ctx;
+
+ /* Initialize a temporary (on-memory) TDB database to store
+ * temporary MId used within EMSABP */
+ emsabp_ctx->ttdb_ctx = emsabp_tdb_init_tmp(emsabp_ctx->mem_ctx);
+ if (!emsabp_ctx->ttdb_ctx) {
+ smb_panic("unable to create on-memory TDB database");
+ }
+
+ return emsabp_ctx;
+}
+
+
+_PUBLIC_ bool emsabp_destructor(void *data)
+{
+ struct emsabp_context *emsabp_ctx = (struct emsabp_context *)data;
+
+ if (emsabp_ctx) {
+ if (emsabp_ctx->ttdb_ctx) {
+ tdb_close(emsabp_ctx->ttdb_ctx);
+ }
+
+ talloc_free(emsabp_ctx->mem_ctx);
+ return true;
+ }
+
+ return false;
+}
+
+
+/**
+ \details Check if the authenticated user belongs to the Exchange
+ organization
+
+ \param dce_call pointer to the session context
+ \param emsabp_ctx pointer to the EMSABP context
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool emsabp_verify_user(struct dcesrv_call_state *dce_call,
+ struct emsabp_context *emsabp_ctx)
+{
+ int ret;
+ const char *username = NULL;
+ int msExchUserAccountControl;
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_result *res = NULL;
+ char *ldb_filter;
+ const char * const recipient_attrs[] = { "msExchUserAccountControl", NULL };
+
+ username = dce_call->context->conn->auth_state.session_info->server_info->account_name;
+
+ ldb_filter = talloc_asprintf(emsabp_ctx->mem_ctx, "CN=%s", username);
+ ret = ldb_search(emsabp_ctx->users_ctx, emsabp_ctx->mem_ctx, &res,
+ ldb_get_default_basedn(emsabp_ctx->users_ctx),
+ scope, recipient_attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ /* If the search failed */
+ if (ret != LDB_SUCCESS || !res->count) {
+ return false;
+ }
+
+ /* If msExchUserAccountControl attribute is not found */
+ if (!res->msgs[0]->num_elements) {
+ return false;
+ }
+
+ /* If the attribute exists check its value */
+ msExchUserAccountControl = ldb_msg_find_attr_as_int(res->msgs[0], "msExchUserAccountControl", 2);
+ if (msExchUserAccountControl == 2) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ \details Check if the provided codepage is correct
+
+ \param emsabp_ctx pointer to the EMSABP context
+ \param CodePage the codepage identifier
+
+ \note The prototype is currently incorrect, but we are looking for
+ a better way to check codepage, maybe within AD. At the moment this
+ function is just a wrapper over libmapi valid_codepage function.
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool emsabp_verify_codepage(struct emsabp_context *emsabp_ctx,
+ uint32_t CodePage)
+{
+ return valid_codepage(CodePage);
+}
+
+
+/**
+ \details Retrieve the NSPI server GUID from the server object in
+ the configuration LDB database
+
+ \param emsabp_ctx pointer to the EMSABP context
+
+ \return An allocated GUID structure on success, otherwise NULL
+ */
+_PUBLIC_ struct GUID *emsabp_get_server_GUID(struct emsabp_context *emsabp_ctx)
+{
+ int ret;
+ struct loadparm_context *lp_ctx;
+ struct GUID *guid = (struct GUID *) NULL;
+ const char *netbiosname = NULL;
+ const char *guid_str = NULL;
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_result *res = NULL;
+ char *ldb_filter;
+ char *dn = NULL;
+ struct ldb_dn *ldb_dn = NULL;
+ const char * const recipient_attrs[] = { "*", NULL };
+ const char *firstorgdn = NULL;
+
+ lp_ctx = emsabp_ctx->lp_ctx;
+
+ netbiosname = lp_netbios_name(lp_ctx);
+ if (!netbiosname) return NULL;
+
+ /* Step 1. Find the Exchange Organization */
+ ldb_filter = talloc_strdup(emsabp_ctx->mem_ctx, "(objectClass=msExchOrganizationContainer)");
+ ret = ldb_search(emsabp_ctx->conf_ctx, emsabp_ctx->mem_ctx, &res,
+ ldb_get_default_basedn(emsabp_ctx->conf_ctx),
+ scope, recipient_attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ if (ret != LDB_SUCCESS || !res->count) {
+ return NULL;
+ }
+
+ firstorgdn = ldb_msg_find_attr_as_string(res->msgs[0], "distinguishedName", NULL);
+ if (!firstorgdn) {
+ return NULL;
+ }
+
+ /* Step 2. Find the OpenChange Server object */
+ dn = talloc_asprintf(emsabp_ctx->mem_ctx, "CN=Servers,CN=First Administrative Group,CN=Administrative Groups,%s",
+ firstorgdn);
+ ldb_dn = ldb_dn_new(emsabp_ctx->mem_ctx, emsabp_ctx->conf_ctx, dn);
+ talloc_free(dn);
+ if (!ldb_dn_validate(ldb_dn)) {
+ return NULL;
+ }
+
+ ret = ldb_search(emsabp_ctx->conf_ctx, emsabp_ctx->mem_ctx, &res, ldb_dn,
+ scope, recipient_attrs, "(cn=%s)", netbiosname);
+ if (ret != LDB_SUCCESS || !res->count) {
+ return NULL;
+ }
+
+ /* Step 3. Retrieve the objectGUID GUID */
+ guid_str = ldb_msg_find_attr_as_string(res->msgs[0], "objectGUID", NULL);
+ if (!guid_str) return NULL;
+
+ guid = talloc_zero(emsabp_ctx->mem_ctx, struct GUID);
+ GUID_from_string(guid_str, guid);
+
+ return guid;
+}
+
+
+/**
+ \details Build an EphemeralEntryID structure
+
+ \param emsabp_ctx pointer to the EMSABP context
+ \param DisplayType the AB object display type
+ \param MId the MId value
+ \param ephEntryID pointer to the EphemeralEntryID returned by the
+ function
+
+ \return MAPI_E_SUCCESS on success, otherwise
+ MAPI_E_NOT_ENOUGH_RESOURCES or MAPI_E_CORRUPT_STORE
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_set_EphemeralEntryID(struct emsabp_context *emsabp_ctx,
+ uint32_t DisplayType, uint32_t MId,
+ struct EphemeralEntryID *ephEntryID)
+{
+ struct GUID *guid = (struct GUID *) NULL;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!ephEntryID, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+
+ guid = emsabp_get_server_GUID(emsabp_ctx);
+ OPENCHANGE_RETVAL_IF(!guid, MAPI_E_CORRUPT_STORE, NULL);
+
+ ephEntryID->ID_type = 0x87;
+ ephEntryID->R1 = 0x0;
+ ephEntryID->R2 = 0x0;
+ ephEntryID->R3 = 0x0;
+ ephEntryID->ProviderUID.ab[0] = (guid->time_low & 0xFF);
+ ephEntryID->ProviderUID.ab[1] = ((guid->time_low >> 8) & 0xFF);
+ ephEntryID->ProviderUID.ab[2] = ((guid->time_low >> 16) & 0xFF);
+ ephEntryID->ProviderUID.ab[3] = ((guid->time_low >> 24) & 0xFF);
+ ephEntryID->ProviderUID.ab[4] = (guid->time_mid & 0xFF);
+ ephEntryID->ProviderUID.ab[5] = ((guid->time_mid >> 8) & 0xFF);
+ ephEntryID->ProviderUID.ab[6] = (guid->time_hi_and_version & 0xFF);
+ ephEntryID->ProviderUID.ab[7] = ((guid->time_hi_and_version >> 8) & 0xFF);
+ memcpy(ephEntryID->ProviderUID.ab + 8, guid->clock_seq, sizeof (uint8_t) * 2);
+ memcpy(ephEntryID->ProviderUID.ab + 10, guid->node, sizeof (uint8_t) * 6);
+ ephEntryID->R4 = 0x1;
+ ephEntryID->DisplayType = DisplayType;
+ ephEntryID->MId = MId;
+
+ talloc_free(guid);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Map an EphemeralEntryID structure into a Binary_r structure
+
+ \param mem_ctx pointer to the memory context
+ \param ephEntryID pointer to the Ephemeral EntryID structure
+ \param bin pointer to the Binary_r structure the server will return
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_INVALID_PARAMETER
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_EphemeralEntryID_to_Binary_r(TALLOC_CTX *mem_ctx,
+ struct EphemeralEntryID *ephEntryID,
+ struct Binary_r *bin)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!ephEntryID, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!bin, MAPI_E_INVALID_PARAMETER, NULL);
+
+ bin->cb = sizeof (*ephEntryID);
+ bin->lpb = talloc_array(mem_ctx, uint8_t, bin->cb);
+
+ /* Copy EphemeralEntryID into bin->lpb */
+ memset(bin->lpb, 0, bin->cb);
+ bin->lpb[0] = ephEntryID->ID_type;
+ bin->lpb[1] = ephEntryID->R1;
+ bin->lpb[2] = ephEntryID->R2;
+ bin->lpb[3] = ephEntryID->R3;
+ memcpy(bin->lpb + 4, ephEntryID->ProviderUID.ab, 16);
+ bin->lpb[20] = (ephEntryID->R4 & 0xFF);
+ bin->lpb[21] = ((ephEntryID->R4 >> 8) & 0xFF);
+ bin->lpb[22] = ((ephEntryID->R4 >> 16) & 0xFF);
+ bin->lpb[23] = ((ephEntryID->R4 >> 24) & 0xFF);
+ bin->lpb[24] = (ephEntryID->DisplayType & 0xFF);
+ bin->lpb[25] = ((ephEntryID->DisplayType >> 8) & 0xFF);
+ bin->lpb[26] = ((ephEntryID->DisplayType >> 16) & 0xFF);
+ bin->lpb[27] = ((ephEntryID->DisplayType >> 24) & 0xFF);
+ bin->lpb[28] = (ephEntryID->MId & 0xFF);
+ bin->lpb[29] = ((ephEntryID->MId >> 8) & 0xFF);
+ bin->lpb[30] = ((ephEntryID->MId >> 16) & 0xFF);
+ bin->lpb[31] = ((ephEntryID->MId >> 24) & 0xFF);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Build a PermanentEntryID structure
+
+ \param emsabp_ctx pointer to the EMSABP context
+ \param DisplayType the AB object display type
+ \param ldb_recipient pointer on the LDB message
+ \param permEntryID pointer to the PermanentEntryID returned by the
+ function
+
+ \return MAPI_E_SUCCESS on success, otherwise
+ MAPI_E_NOT_ENOUGH_RESOURCES or MAPI_E_CORRUPT_STORE
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_set_PermanentEntryID(struct emsabp_context *emsabp_ctx,
+ uint32_t DisplayType, struct ldb_message *msg,
+ struct PermanentEntryID *permEntryID)
+{
+ struct GUID *guid = (struct GUID *) NULL;
+ const char *guid_str;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!permEntryID, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+
+
+ permEntryID->ID_type = 0x0;
+ permEntryID->R1 = 0x0;
+ permEntryID->R2 = 0x0;
+ permEntryID->R3 = 0x0;
+ memcpy(permEntryID->ProviderUID.ab, GUID_NSPI, 16);
+ permEntryID->R4 = 0x1;
+ permEntryID->DisplayType = DisplayType;
+
+ if (!msg) {
+ permEntryID->dn = talloc_strdup(emsabp_ctx->mem_ctx, "/");
+ } else {
+ guid_str = ldb_msg_find_attr_as_string(msg, "objectGUID", NULL);
+ OPENCHANGE_RETVAL_IF(!guid_str, MAPI_E_CORRUPT_STORE, NULL);
+ guid = talloc_zero(emsabp_ctx->mem_ctx, struct GUID);
+ GUID_from_string(guid_str, guid);
+ permEntryID->dn = talloc_asprintf(emsabp_ctx->mem_ctx, EMSABP_DN,
+ guid->time_low, guid->time_mid,
+ guid->time_hi_and_version,
+ guid->clock_seq[0],
+ guid->clock_seq[1],
+ guid->node[0], guid->node[1],
+ guid->node[2], guid->node[3],
+ guid->node[4], guid->node[5]);
+ talloc_free(guid);
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Map a PermanentEntryID structure into a Binary_r
+ structure (for PR_ENTRYID and PR_EMS_AB_PARENT_ENTRYID properties)
+
+ \param mem_ctx pointer to the memory context
+ \param permEntryID pointer to the Permanent EntryID structure
+ \param bin pointer to the Binary_r structure the server will return
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_INVALID_PARAMETER
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_PermanentEntryID_to_Binary_r(TALLOC_CTX *mem_ctx,
+ struct PermanentEntryID *permEntryID,
+ struct Binary_r *bin)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!permEntryID, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!bin, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* Remove const char * size and replace it with effective dn string length */
+ bin->cb = sizeof (*permEntryID) - 4 + strlen(permEntryID->dn) + 1;
+ bin->lpb = talloc_array(mem_ctx, uint8_t, bin->cb);
+
+ /* Copy PermanantEntryID intro bin->lpb */
+ memset(bin->lpb, 0, bin->cb);
+ bin->lpb[0] = permEntryID->ID_type;
+ bin->lpb[1] = permEntryID->R1;
+ bin->lpb[2] = permEntryID->R2;
+ bin->lpb[3] = permEntryID->R3;
+ memcpy(bin->lpb + 4, permEntryID->ProviderUID.ab, 16);
+ bin->lpb[20] = (permEntryID->R4 & 0xFF);
+ bin->lpb[21] = ((permEntryID->R4 >> 8) & 0xFF);
+ bin->lpb[22] = ((permEntryID->R4 >> 16) & 0xFF);
+ bin->lpb[23] = ((permEntryID->R4 >> 24) & 0xFF);
+ bin->lpb[24] = (permEntryID->DisplayType & 0xFF);
+ bin->lpb[25] = ((permEntryID->DisplayType >> 8) & 0xFF);
+ bin->lpb[26] = ((permEntryID->DisplayType >> 16) & 0xFF);
+ bin->lpb[27] = ((permEntryID->DisplayType >> 24) & 0xFF);
+ memcpy(bin->lpb + 28, permEntryID->dn, strlen(permEntryID->dn) + 1);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Find the attribute matching the specified property tag and
+ return the associated data.
+
+ \param mem_ctx pointer to the memory context
+ \param emsabp_ctx pointer to the EMSABP context
+ \param msg pointer to the LDB message
+ \param ulPropTag the property tag to lookup
+ \param MId Minimal Entry ID associated to the current message
+
+ \note This implementation is at the moment limited to MAILUSER,
+ which means we arbitrary set PR_OBJECT_TYPE and PR_DISPLAY_TYPE
+ while we should have a generic method to fill these properties.
+
+ \return Valid generic pointer on success, otherwise NULL
+ */
+_PUBLIC_ void *emsabp_query(TALLOC_CTX *mem_ctx, struct emsabp_context *emsabp_ctx,
+ struct ldb_message *msg, uint32_t ulPropTag, uint32_t MId)
+{
+ enum MAPISTATUS retval;
+ void *data = (void *) NULL;
+ const char *attribute;
+ const char *ref_attribute;
+ const char *ldb_string = NULL;
+ struct Binary_r *bin;
+ struct StringArray_r *mvszA;
+ struct EphemeralEntryID ephEntryID;
+ struct ldb_message *msg2 = NULL;
+ struct ldb_message_element *ldb_element;
+ int ret;
+ const char *dn = NULL;
+ uint32_t i;
+
+ /* Step 1. Fill attributes not in AD but created using EMSABP databases */
+ switch (ulPropTag) {
+ case PR_ADDRTYPE:
+ data = (void *) talloc_strdup(mem_ctx, EMSABP_ADDRTYPE);
+ return data;
+ case PR_OBJECT_TYPE:
+ data = talloc_zero(mem_ctx, uint32_t);
+ *((uint32_t *)data) = MAPI_MAILUSER;
+ return data;
+ case PR_DISPLAY_TYPE:
+ data = talloc_zero(mem_ctx, uint32_t);
+ *((uint32_t *)data) = DT_MAILUSER;
+ return data;
+ case PR_ENTRYID:
+ bin = talloc(mem_ctx, struct Binary_r);
+ retval = emsabp_set_EphemeralEntryID(emsabp_ctx, DT_MAILUSER, MId, &ephEntryID);
+ retval = emsabp_EphemeralEntryID_to_Binary_r(mem_ctx, &ephEntryID, bin);
+ return bin;
+ case PR_INSTANCE_KEY:
+ bin = talloc_zero(mem_ctx, struct Binary_r);
+ bin->cb = 4;
+ bin->lpb = talloc_array(mem_ctx, uint8_t, bin->cb);
+ memset(bin->lpb, 0, bin->cb);
+ bin->lpb[0] = MId & 0xFF;
+ bin->lpb[1] = (MId >> 8) & 0xFF;
+ bin->lpb[2] = (MId >> 16) & 0xFF;
+ bin->lpb[3] = (MId >> 24) & 0xFF;
+ return bin;
+ default:
+ break;
+ }
+
+ /* Step 2. Retrieve the attribute name associated to ulPropTag and handle the ref case */
+ attribute = emsabp_property_get_attribute(ulPropTag);
+ if (!attribute) return NULL;
+
+ ret = emsabp_property_is_ref(ulPropTag);
+ if (ret == 1) {
+ ref_attribute = emsabp_property_get_ref_attr(ulPropTag);
+ if (ref_attribute) {
+ dn = ldb_msg_find_attr_as_string(msg, attribute, NULL);
+ retval = emsabp_search_dn(emsabp_ctx, dn, &msg2);
+ if (retval != MAPI_E_SUCCESS) {
+ return NULL;
+ }
+ attribute = ref_attribute;
+ }
+ } else {
+ msg2 = msg;
+ }
+
+ /* Step 3. Retrieve data associated to the attribute/tag */
+ switch (ulPropTag & 0xFFFF) {
+ case PT_STRING8:
+ case PT_UNICODE:
+ ldb_string = ldb_msg_find_attr_as_string(msg2, attribute, NULL);
+ if (!ldb_string) return NULL;
+ data = talloc_strdup(mem_ctx, ldb_string);
+ break;
+ case PT_MV_STRING8:
+ ldb_element = ldb_msg_find_element(msg2, attribute);
+ if (!ldb_element) return NULL;
+
+ mvszA = talloc(mem_ctx, struct StringArray_r);
+ mvszA->cValues = ldb_element[0].num_values & 0xFFFFFFFF;
+ mvszA->lppszA = talloc_array(mem_ctx, const char *, mvszA->cValues);
+ for (i = 0; i < mvszA->cValues; i++) {
+ mvszA->lppszA[i] = talloc_strdup(mem_ctx, (char *)ldb_element->values[i].data);
+ }
+ data = (void *) mvszA;
+ break;
+ default:
+ DEBUG(3, ("[%s:%d]: Unsupported property type: 0x%x\n", __FUNCTION__, __LINE__,
+ (ulPropTag & 0xFFFF)));
+ break;
+ }
+
+ return data;
+}
+
+
+/**
+ \details Builds the SRow array entry for the specified MId.
+
+ The function retrieves the DN associated to the specified MId
+ within its on-memory TDB database. It next fetches the LDB record
+ matching the DN and finally retrieve the requested properties for
+ this record.
+
+ \param mem_ctx pointer to the memory context
+ \param emsabp_ctx pointer to the EMSABP context
+ \param aRow pointer to the SRow structure where results will be
+ stored
+ \param MId MId to fetch properties for
+ \param pPropTags pointer to the property tags array
+
+ \note We currently assume records are users.ldb
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_fetch_attrs(TALLOC_CTX *mem_ctx, struct emsabp_context *emsabp_ctx,
+ struct SRow *aRow, uint32_t MId,
+ struct SPropTagArray *pPropTags)
+{
+ enum MAPISTATUS retval;
+ void *ldb_ctx;
+ char *dn;
+ const char * const recipient_attrs[] = { "*", NULL };
+ struct ldb_result *res = NULL;
+ struct ldb_dn *ldb_dn = NULL;
+ int ret;
+ uint32_t ulPropTag;
+ void *data;
+ int i;
+
+ /* Step 0. Try to Retrieve the dn associated to the MId first from temp TDB (users) */
+ ldb_ctx = emsabp_ctx->users_ctx;
+ retval = emsabp_tdb_fetch_dn_from_MId(mem_ctx, emsabp_ctx->ttdb_ctx, MId, &dn);
+ if (retval) {
+ /* If it fails try to retrieve it from the on-disk TDB database (conf) */
+ retval = emsabp_tdb_fetch_dn_from_MId(mem_ctx, emsabp_ctx->tdb_ctx, MId, &dn);
+ ldb_ctx = emsabp_ctx->conf_ctx;
+ }
+ OPENCHANGE_RETVAL_IF(retval, MAPI_E_CORRUPT_STORE, NULL);
+
+ /* Step 1. Fetch the LDB record */
+ ldb_dn = ldb_dn_new(mem_ctx, ldb_ctx, dn);
+ OPENCHANGE_RETVAL_IF(!ldb_dn_validate(ldb_dn), MAPI_E_CORRUPT_STORE, NULL);
+
+ ret = ldb_search(ldb_ctx, emsabp_ctx->mem_ctx, &res, ldb_dn, LDB_SCOPE_BASE,
+ recipient_attrs, NULL);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count || res->count != 1, MAPI_E_CORRUPT_STORE, NULL);
+
+ /* Step 2. Retrieve property values and build aRow */
+ aRow->ulAdrEntryPad = 0x0;
+ aRow->cValues = pPropTags->cValues;
+ aRow->lpProps = talloc_array(mem_ctx, struct SPropValue, aRow->cValues);
+
+ for (i = 0; i < aRow->cValues; i++) {
+ ulPropTag = pPropTags->aulPropTag[i];
+ data = emsabp_query(mem_ctx, emsabp_ctx, res->msgs[0], ulPropTag, MId);
+ if (!data) {
+ ulPropTag &= 0xFFFF0000;
+ ulPropTag += PT_ERROR;
+ }
+
+ aRow->lpProps[i].ulPropTag = ulPropTag;
+ aRow->lpProps[i].dwAlignPad = 0x0;
+ set_SPropValue(&(aRow->lpProps[i]), data);
+ }
+
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Builds the SRow array entry for the specified table
+ record.
+
+ \param mem_ctx pointer to the memory context
+ \param emsabp_ctx pointer to the EMSABP context
+ \param aRow pointer to the SRow structure where results will be
+ stored
+ \param dwFlags flags controlling whether strings should be unicode
+ encoded or not
+ \param permEntryID pointer to the current record Permanent
+ EntryID
+ \param parentPermEntryID pointer to the parent record Permanent
+ EntryID
+ \param msg pointer to the LDB message for current record
+ \param child boolean value specifying whether current record is
+ root or child within containers hierarchy
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_table_fetch_attrs(TALLOC_CTX *mem_ctx, struct emsabp_context *emsabp_ctx,
+ struct SRow *aRow, uint32_t dwFlags,
+ struct PermanentEntryID *permEntryID,
+ struct PermanentEntryID *parentPermEntryID,
+ struct ldb_message *msg, bool child)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue lpProps;
+ uint32_t i;
+ uint32_t containerID = 0;
+ const char *dn = NULL;
+
+ /* Step 1. Build the array of properties to fetch and map */
+ if (child == false) {
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
+ PR_ENTRYID,
+ PR_CONTAINER_FLAGS,
+ PR_DEPTH,
+ PR_EMS_AB_CONTAINERID,
+ ((dwFlags & NspiUnicodeStrings) ? PR_DISPLAY_NAME_UNICODE : PR_DISPLAY_NAME),
+ PR_EMS_AB_IS_MASTER);
+ } else {
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x7,
+ PR_ENTRYID,
+ PR_CONTAINER_FLAGS,
+ PR_DEPTH,
+ PR_EMS_AB_CONTAINERID,
+ ((dwFlags & NspiUnicodeStrings) ? PR_DISPLAY_NAME_UNICODE : PR_DISPLAY_NAME),
+ PR_EMS_AB_IS_MASTER,
+ PR_EMS_AB_PARENT_ENTRYID);
+ }
+
+ /* Step 2. Allocate SPropValue array and update SRow cValues field */
+ aRow->ulAdrEntryPad = 0x0;
+ aRow->cValues = 0x0;
+ aRow->lpProps = talloc_zero(mem_ctx, struct SPropValue);
+
+ /* Step 3. Global Address List or real container */
+ if (!msg) {
+ /* Global Address List record is constant */
+ for (i = 0; i < SPropTagArray->cValues; i++) {
+ lpProps.ulPropTag = SPropTagArray->aulPropTag[i];
+ lpProps.dwAlignPad = 0x0;
+
+ switch (SPropTagArray->aulPropTag[i]) {
+ case PR_ENTRYID:
+ emsabp_PermanentEntryID_to_Binary_r(mem_ctx, permEntryID, &(lpProps.value.bin));
+ break;
+ case PR_CONTAINER_FLAGS:
+ lpProps.value.l = AB_RECIPIENTS | AB_UNMODIFIABLE;
+ break;
+ case PR_DEPTH:
+ lpProps.value.l = 0x0;
+ break;
+ case PR_EMS_AB_CONTAINERID:
+ lpProps.value.l = 0x0;
+ break;
+ case PR_DISPLAY_NAME:
+ lpProps.value.lpszA = NULL;
+ break;
+ case PR_DISPLAY_NAME_UNICODE:
+ lpProps.value.lpszW = NULL;
+ break;
+ case PR_EMS_AB_IS_MASTER:
+ lpProps.value.b = false;
+ break;
+ default:
+ break;
+ }
+ SRow_addprop(aRow, lpProps);
+ /* SRow_addprop internals overwrite with MAPI_E_NOT_FOUND when data is NULL */
+ if (SPropTagArray->aulPropTag[i] == PR_DISPLAY_NAME ||
+ SPropTagArray->aulPropTag[i] == PR_DISPLAY_NAME_UNICODE) {
+ aRow->lpProps[aRow->cValues - 1].value.lpszA = NULL;
+ aRow->lpProps[aRow->cValues - 1].value.lpszW = NULL;
+ }
+ }
+ } else {
+ for (i = 0; i < SPropTagArray->cValues; i++) {
+ lpProps.ulPropTag = SPropTagArray->aulPropTag[i];
+ lpProps.dwAlignPad = 0x0;
+
+ switch (SPropTagArray->aulPropTag[i]) {
+ case PR_ENTRYID:
+ emsabp_PermanentEntryID_to_Binary_r(mem_ctx, permEntryID, &(lpProps.value.bin));
+ break;
+ case PR_CONTAINER_FLAGS:
+ switch (child) {
+ case true:
+ lpProps.value.l = AB_RECIPIENTS | AB_SUBCONTAINERS | AB_UNMODIFIABLE;
+ break;
+ case false:
+ lpProps.value.l = AB_RECIPIENTS | AB_UNMODIFIABLE;
+ }
+ break;
+ case PR_DEPTH:
+ switch (child) {
+ case true:
+ lpProps.value.l = 0x1;
+ break;
+ case false:
+ lpProps.value.l = 0x0;
+ break;
+ }
+ break;
+ case PR_EMS_AB_CONTAINERID:
+ dn = ldb_msg_find_attr_as_string(msg, "distinguishedName", NULL);
+ retval = emsabp_tdb_fetch_MId(emsabp_ctx->tdb_ctx, dn, &containerID);
+ if (retval) {
+ retval = emsabp_tdb_insert(emsabp_ctx->tdb_ctx, dn);
+ OPENCHANGE_RETVAL_IF(retval, MAPI_E_CORRUPT_STORE, NULL);
+ retval = emsabp_tdb_fetch_MId(emsabp_ctx->tdb_ctx, dn, &containerID);
+ OPENCHANGE_RETVAL_IF(retval, MAPI_E_CORRUPT_STORE, NULL);
+ }
+ lpProps.value.l = containerID;
+ break;
+ case PR_DISPLAY_NAME:
+ lpProps.value.lpszA = talloc_strdup(mem_ctx, ldb_msg_find_attr_as_string(msg, "displayName", NULL));
+ if (!lpProps.value.lpszA) {
+ lpProps.ulPropTag &= 0xFFFF0000;
+ lpProps.ulPropTag += PT_ERROR;
+ }
+ break;
+ case PR_DISPLAY_NAME_UNICODE:
+ lpProps.value.lpszW = talloc_strdup(mem_ctx, ldb_msg_find_attr_as_string(msg, "displayName", NULL));
+ if (!lpProps.value.lpszW) {
+ lpProps.ulPropTag &= 0xFFFF0000;
+ lpProps.ulPropTag += PT_ERROR;
+ }
+ break;
+ case PR_EMS_AB_IS_MASTER:
+ /* FIXME: harcoded value - no load balancing */
+ lpProps.value.l = 0x0;
+ break;
+ case PR_EMS_AB_PARENT_ENTRYID:
+ emsabp_PermanentEntryID_to_Binary_r(mem_ctx, parentPermEntryID, &lpProps.value.bin);
+ break;
+ default:
+ break;
+ }
+ SRow_addprop(aRow, lpProps);
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve and build the HierarchyTable requested by
+ GetSpecialTable NSPI call
+
+ \param mem_ctx pointer to the memory context
+ \param emsabp_ctx pointer to the EMSABP context
+ \param dwFlags flags controlling whether strings should be UNICODE
+ or not
+ \param SRowSet pointer on pointer to the output SRowSet array
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_CORRUPT_STORE
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_get_HierarchyTable(TALLOC_CTX *mem_ctx, struct emsabp_context *emsabp_ctx,
+ uint32_t dwFlags, struct SRowSet **SRowSet)
+{
+ enum MAPISTATUS retval;
+ struct SRow *aRow;
+ struct PermanentEntryID gal;
+ struct PermanentEntryID parentPermEntryID;
+ struct PermanentEntryID permEntryID;
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_request *req;
+ struct ldb_result *res = NULL;
+ char *ldb_filter;
+ struct ldb_dn *ldb_dn = NULL;
+ struct ldb_control **controls;
+ const char * const recipient_attrs[] = { "*", NULL };
+ const char *control_strings[2] = { "server_sort:0:0:displayName", NULL };
+ const char *addressBookRoots;
+ int ret;
+ uint32_t aRow_idx;
+ uint32_t i;
+
+ /* Step 1. Build the 'Global Address List' object using PermanentEntryID */
+ aRow = talloc_zero(mem_ctx, struct SRow);
+ OPENCHANGE_RETVAL_IF(!aRow, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+ aRow_idx = 0;
+
+ retval = emsabp_set_PermanentEntryID(emsabp_ctx, DT_CONTAINER, NULL, &gal);
+ OPENCHANGE_RETVAL_IF(retval, retval, aRow);
+
+ retval = emsabp_table_fetch_attrs(mem_ctx, emsabp_ctx, &aRow[aRow_idx], dwFlags, &gal, NULL, NULL, false);
+ aRow_idx++;
+
+ /* Step 2. Retrieve the object pointed by addressBookRoots attribute: 'All Address Lists' */
+ ldb_filter = talloc_strdup(emsabp_ctx->mem_ctx, "(addressBookRoots=*)");
+ ret = ldb_search(emsabp_ctx->conf_ctx, emsabp_ctx->mem_ctx, &res,
+ ldb_get_default_basedn(emsabp_ctx->conf_ctx),
+ scope, recipient_attrs, ldb_filter);
+ talloc_free(ldb_filter);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_CORRUPT_STORE, aRow);
+
+ addressBookRoots = ldb_msg_find_attr_as_string(res->msgs[0], "addressBookRoots", NULL);
+ OPENCHANGE_RETVAL_IF(!addressBookRoots, MAPI_E_CORRUPT_STORE, aRow);
+ talloc_free(res);
+
+ ldb_dn = ldb_dn_new(emsabp_ctx->mem_ctx, emsabp_ctx->conf_ctx, addressBookRoots);
+ OPENCHANGE_RETVAL_IF(!ldb_dn_validate(ldb_dn), MAPI_E_CORRUPT_STORE, aRow);
+
+ scope = LDB_SCOPE_BASE;
+ ret = ldb_search(emsabp_ctx->conf_ctx, emsabp_ctx->mem_ctx, &res, ldb_dn,
+ scope, recipient_attrs, NULL);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count || res->count != 1, MAPI_E_CORRUPT_STORE, aRow);
+
+ aRow = talloc_realloc(mem_ctx, aRow, struct SRow, aRow_idx + 1);
+ retval = emsabp_set_PermanentEntryID(emsabp_ctx, DT_CONTAINER, res->msgs[0], &parentPermEntryID);
+ emsabp_table_fetch_attrs(mem_ctx, emsabp_ctx, &aRow[aRow_idx], dwFlags, &parentPermEntryID, NULL, res->msgs[0], false);
+ aRow_idx++;
+ talloc_free(res);
+
+ /* Step 3. Retrieve 'All Address Lists' subcontainers */
+ res = talloc_zero(mem_ctx, struct ldb_result);
+ OPENCHANGE_RETVAL_IF(!res, MAPI_E_NOT_ENOUGH_RESOURCES, aRow);
+
+ controls = ldb_parse_control_strings(emsabp_ctx->conf_ctx, emsabp_ctx->mem_ctx, control_strings);
+ ret = ldb_build_search_req(&req, emsabp_ctx->conf_ctx, emsabp_ctx->mem_ctx,
+ ldb_dn, LDB_SCOPE_SUBTREE, "(purportedSearch=*)",
+ recipient_attrs, controls, res, ldb_search_default_callback, NULL);
+
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_CORRUPT_STORE, aRow);
+ }
+
+ ret = ldb_request(emsabp_ctx->conf_ctx, req);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+ }
+ talloc_free(req);
+
+ if (ret != LDB_SUCCESS || !res->count) {
+ talloc_free(res);
+ OPENCHANGE_RETVAL_IF(1, MAPI_E_CORRUPT_STORE, aRow);
+ }
+
+ aRow = talloc_realloc(mem_ctx, aRow, struct SRow, aRow_idx + res->count + 1);
+
+ for (i = 0; res->msgs[i]; i++) {
+ retval = emsabp_set_PermanentEntryID(emsabp_ctx, DT_CONTAINER, res->msgs[i], &permEntryID);
+ emsabp_table_fetch_attrs(mem_ctx, emsabp_ctx, &aRow[aRow_idx], dwFlags, &permEntryID, &parentPermEntryID, res->msgs[i], true);
+ talloc_free(permEntryID.dn);
+ memset(&permEntryID, 0, sizeof (permEntryID));
+ aRow_idx++;
+ }
+ talloc_free(res);
+ talloc_free(parentPermEntryID.dn);
+
+ /* Step 4. Build output SRowSet */
+ SRowSet[0]->cRows = aRow_idx;
+ SRowSet[0]->aRow = aRow;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve and build the CreationTemplates Table requested
+ by GetSpecialTable NSPI call
+
+ \param mem_ctx pointer to the memory context
+ \param emsabp_ctx pointer to the EMSABP context
+ \param dwFlags flags controlling whether strings should be UNICODE
+ or not
+ \param SRowSet pointer on pointer to the output SRowSet array
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_CORRUPT_STORE
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_get_CreationTemplatesTable(TALLOC_CTX *mem_ctx, struct emsabp_context *emsabp_ctx,
+ uint32_t dwFlags, struct SRowSet **SRowSet)
+{
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Search Active Directory given input search criterias. The
+ function associates for each records returned by the search a
+ unique session Minimal Entry ID and a LDB message.
+
+ \param mem_ctx pointer to the memory context
+ \param emsabp_ctx pointer to the EMSABP context
+ \param MIds pointer to the list of MIds the function returns
+ \param Restriction pointer to restriction rules to apply to the
+ search
+ \param pStat pointer the STAT structure associated to the search
+ param limit the limit number of results the function can return
+
+ \note SortTypePhoneticDisplayName sort type is currently not supported.
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_search(TALLOC_CTX *mem_ctx, struct emsabp_context *emsabp_ctx,
+ struct SPropTagArray *MIds, struct Restriction_r *restriction,
+ struct STAT *pStat, uint32_t limit)
+{
+ enum MAPISTATUS retval;
+ struct ldb_result *res = NULL;
+ struct PropertyRestriction_r *res_prop = NULL;
+ const char *recipient = NULL;
+ const char * const recipient_attrs[] = { "*", NULL };
+ char *ldb_filter;
+ int ret;
+ uint32_t i;
+ const char *dn;
+
+ /* Step 0. Sanity Checks (MS-NSPI Server Processing Rules) */
+ if (pStat->SortType == SortTypePhoneticDisplayName) {
+ return MAPI_E_CALL_FAILED;
+ }
+
+ if (((pStat->SortType == SortTypeDisplayName) || (pStat->SortType == SortTypePhoneticDisplayName)) &&
+ (pStat->ContainerID && (emsabp_tdb_lookup_MId(emsabp_ctx->tdb_ctx, pStat->ContainerID) == false))) {
+ return MAPI_E_INVALID_BOOKMARK;
+ }
+
+ if (restriction && (pStat->SortType != SortTypeDisplayName) &&
+ (pStat->SortType != SortTypePhoneticDisplayName)) {
+ return MAPI_E_CALL_FAILED;
+ }
+
+ /* Step 1. Apply restriction and retrieve results from AD */
+ if (restriction) {
+ /* FIXME: We only support RES_PROPERTY restriction */
+ if ((uint32_t)restriction->rt != RES_PROPERTY) {
+ return MAPI_E_TOO_COMPLEX;
+ }
+
+ /* FIXME: We only support PR_ANR */
+ res_prop = (struct PropertyRestriction_r *)&(restriction->res.resProperty);
+ if ((res_prop->ulPropTag != PR_ANR) && (res_prop->ulPropTag != PR_ANR_UNICODE)) {
+ return MAPI_E_NO_SUPPORT;
+ }
+
+ recipient = (res_prop->ulPropTag == PR_ANR) ?
+ res_prop->lpProp->value.lpszA :
+ res_prop->lpProp->value.lpszW;
+
+ ldb_filter = talloc_asprintf(emsabp_ctx->mem_ctx, "(&(objectClass=user)(sAMAccountName=*%s*)(!(objectClass=computer)))", recipient);
+ ret = ldb_search(emsabp_ctx->users_ctx, emsabp_ctx->mem_ctx, &res,
+ ldb_get_default_basedn(emsabp_ctx->users_ctx),
+ LDB_SCOPE_SUBTREE, recipient_attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ if (ret != LDB_SUCCESS || !res->count) {
+ return MAPI_E_NOT_FOUND;
+ }
+ } else {
+ /* FIXME Check restriction == NULL */
+ }
+
+ if (limit && res->count > limit) {
+ return MAPI_E_TABLE_TOO_BIG;
+ }
+
+ MIds->aulPropTag = talloc_array(emsabp_ctx->mem_ctx, uint32_t, res->count);
+ MIds->cValues = res->count;
+
+ /* Step 2. Create session MId for all fetched records */
+ for (i = 0; i < res->count; i++) {
+ dn = ldb_msg_find_attr_as_string(res->msgs[i], "distinguishedName", NULL);
+ retval = emsabp_tdb_fetch_MId(emsabp_ctx->ttdb_ctx, dn, &MIds->aulPropTag[i]);
+ if (retval) {
+ retval = emsabp_tdb_insert(emsabp_ctx->ttdb_ctx, dn);
+ OPENCHANGE_RETVAL_IF(retval, MAPI_E_CORRUPT_STORE, NULL);
+ retval = emsabp_tdb_fetch_MId(emsabp_ctx->ttdb_ctx, dn, &(MIds->aulPropTag[i]));
+ OPENCHANGE_RETVAL_IF(retval, MAPI_E_CORRUPT_STORE, NULL);
+ }
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Search for a given DN within AD and return the associated
+ LDB message.
+
+ \param emsabp_ctx pointer to the EMSABP context
+ \param dn pointer to the DN string to search for
+ \param ldb_res pointer on pointer to the LDB message returned by
+ the function
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_search_dn(struct emsabp_context *emsabp_ctx, const char *dn,
+ struct ldb_message **ldb_res)
+{
+ struct ldb_dn *ldb_dn = NULL;
+ struct ldb_result *res = NULL;
+ const char * const recipient_attrs[] = { "*", NULL };
+ int ret;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!dn, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ldb_res, MAPI_E_INVALID_PARAMETER, NULL);
+
+ ldb_dn = ldb_dn_new(emsabp_ctx->mem_ctx, emsabp_ctx->conf_ctx, dn);
+ OPENCHANGE_RETVAL_IF(!ldb_dn_validate(ldb_dn), MAPI_E_CORRUPT_STORE, NULL);
+
+ ret = ldb_search(emsabp_ctx->conf_ctx, emsabp_ctx->mem_ctx, &res, ldb_dn,
+ LDB_SCOPE_BASE, recipient_attrs, NULL);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count || res->count != 1, MAPI_E_CORRUPT_STORE, NULL);
+
+ *ldb_res = res->msgs[0];
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Search for a given AD record given its legacyDN parameter
+ and return the associated LDB message.
+
+ \param emsabp_ctx pointer to the EMSABP context
+ \param legacyDN pointer to the legacyDN attribute value to lookup
+ \param ldb_res pointer on pointer to the LDB message returned by
+ the function
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_search_legacyExchangeDN(struct emsabp_context *emsabp_ctx, const char *legacyDN,
+ struct ldb_message **ldb_res)
+{
+ char *ldb_filter;
+ const char * const recipient_attrs[] = { "*", NULL };
+ int ret;
+ struct ldb_result *res = NULL;
+
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!legacyDN, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!ldb_res, MAPI_E_INVALID_PARAMETER, NULL);
+
+ ldb_filter = talloc_asprintf(emsabp_ctx->mem_ctx, "(legacyExchangeDN=%s)", legacyDN);
+ ret = ldb_search(emsabp_ctx->conf_ctx, emsabp_ctx->mem_ctx, &res,
+ ldb_get_default_basedn(emsabp_ctx->conf_ctx),
+ LDB_SCOPE_SUBTREE, recipient_attrs, ldb_filter);
+ talloc_free(ldb_filter);
+
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, NULL);
+
+ *ldb_res = res->msgs[0];
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/mapiproxy/servers/default/nspi/emsabp_property.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/nspi/emsabp_property.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/nspi/emsabp_property.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,147 @@
+/*
+ OpenChange Server implementation.
+
+ EMSABP: Address Book Provider implementation
+
+ Copyright (C) Julien Kerihuel 2009.
+
+ 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/>.
+ */
+
+/**
+ \file emsabp_property.c
+
+ \brief Property Tag to AD attributes mapping
+ */
+
+#include "dcesrv_exchange_nsp.h"
+
+struct emsabp_property {
+ uint32_t ulPropTag;
+ const char *attribute;
+ bool ref;
+ const char *ref_attr;
+};
+
+static const struct emsabp_property emsabp_property[] = {
+ { PR_ACCOUNT, "sAMAccountName", false, NULL },
+ { PR_COMPANY_NAME, "company", false, NULL },
+ { PR_DISPLAY_NAME, "displayName", false, NULL },
+ { PR_EMAIL_ADDRESS, "legacyExchangeDN", false, NULL },
+ { PR_EMS_AB_HOME_MDB, "homeMDB", true, "legacyExchangeDN" },
+ { PR_EMS_AB_PROXY_ADDRESSES, "proxyAddresses", false, NULL },
+ { PR_EMS_AB_NETWORK_ADDRESS, "networkAddress", false, NULL },
+ { PR_TITLE, "personalTitle", false, NULL },
+ { 0, NULL, false, NULL }
+};
+
+
+/**
+ \details Return the AD attribute name associated to a property tag
+
+ \param ulPropTag the property tag to lookup
+
+ \return valid pointer to the attribute name on success, otherwise
+ NULL
+ */
+_PUBLIC_ const char *emsabp_property_get_attribute(uint32_t ulPropTag)
+{
+ int i;
+
+ /* if ulPropTag type is PT_UNICODE, turn it to PT_STRING8 */
+ if ((ulPropTag & 0xFFFF) == PT_UNICODE) {
+ ulPropTag &= 0xFFFF0000;
+ ulPropTag += PT_STRING8;
+ }
+
+ for (i = 0; emsabp_property[i].attribute; i++) {
+ if (ulPropTag == emsabp_property[i].ulPropTag) {
+ return emsabp_property[i].attribute;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ \details Return the property tag associated to AD attribute name
+
+ \param attribute the AD attribute name to lookup
+
+ \return property tag value on success, otherwise PT_ERROR
+ */
+_PUBLIC_ uint32_t emsabp_property_get_ulPropTag(const char *attribute)
+{
+ int i;
+
+ if (!attribute) return PT_ERROR;
+
+ for (i = 0; emsabp_property[i].attribute; i++) {
+ if (!strcmp(attribute, emsabp_property[i].attribute)) {
+ return emsabp_property[i].ulPropTag;
+ }
+ }
+
+ return PT_ERROR;
+}
+
+
+/**
+ \details Returns whether the given attribute's value references
+ another AD record
+
+ \param ulPropTag the property tag to lookup
+
+ \return 1 if the attribute is a reference, 0 if not and -1 if an
+ error occurred.
+ */
+_PUBLIC_ int emsabp_property_is_ref(uint32_t ulPropTag)
+{
+ int i;
+
+ if (!ulPropTag) return -1;
+
+ for (i = 0; emsabp_property[i].attribute; i++) {
+ if (ulPropTag == emsabp_property[i].ulPropTag) {
+ return (emsabp_property[i].ref == true) ? 1 : 0;
+ }
+ }
+
+ return -1;
+}
+
+
+/**
+ \details Returns the reference attr for a given attribute
+
+ \param ulPropTag property tag to lookup
+
+ \return pointer to a valid reference attribute on success,
+ otherwise NULL
+ */
+_PUBLIC_ const char *emsabp_property_get_ref_attr(uint32_t ulPropTag)
+{
+ int i;
+
+ if (!ulPropTag) return NULL;
+
+ for (i = 0; emsabp_property[i].attribute; i++) {
+ if (ulPropTag == emsabp_property[i].ulPropTag) {
+ return emsabp_property[i].ref_attr;
+ }
+ }
+
+ return NULL;
+}
Added: trunk/openchange/mapiproxy/servers/default/nspi/emsabp_tdb.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/nspi/emsabp_tdb.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/nspi/emsabp_tdb.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,367 @@
+/*
+ OpenChange Server implementation.
+
+ EMSABP: Address Book Provider implementation
+
+ Copyright (C) Julien Kerihuel 2006-2009.
+
+ 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/>.
+*/
+
+/**
+ \file emsabp_tdb.c
+
+ \brief EMSABP TDB database API
+*/
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "dcesrv_exchange_nsp.h"
+#include <util/debug.h>
+
+/**
+ \details Open EMSABP TDB database
+
+ \param mem_ctx pointer to the memory context
+ \param lp_ctx pointer to the loadparm context
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ TDB_CONTEXT *emsabp_tdb_init(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx)
+{
+ enum MAPISTATUS retval;
+ TDB_CONTEXT *tdb_ctx;
+ TDB_DATA key;
+ TDB_DATA dbuf;
+ int ret;
+
+ /* Sanity checks */
+ if (!lp_ctx) return NULL;
+
+ /* Step 0. Retrieve a TDB context pointer on the emsabp_tdb database */
+ tdb_ctx = mapiproxy_server_emsabp_tdb_init(lp_ctx);
+ if (!tdb_ctx) return NULL;
+
+ /* Step 1. If EMSABP_TDB_DATA_REC doesn't exist, create it */
+ retval = emsabp_tdb_fetch(tdb_ctx, EMSABP_TDB_DATA_REC, &dbuf);
+ if (retval == MAPI_E_NOT_FOUND) {
+ key.dptr = (unsigned char *) EMSABP_TDB_DATA_REC;
+ key.dsize = strlen(EMSABP_TDB_DATA_REC);
+
+ dbuf.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%x", EMSABP_TDB_MID_START);
+ dbuf.dsize = strlen((const char *)dbuf.dptr);
+
+ ret = tdb_store(tdb_ctx, key, dbuf, TDB_INSERT);
+ if (ret == -1) {
+ DEBUG(3, ("[%s:%d]: Unable to create %s record: %s\n", __FUNCTION__, __LINE__,
+ EMSABP_TDB_DATA_REC, tdb_errorstr(tdb_ctx)));
+ tdb_close(tdb_ctx);
+ return NULL;
+ }
+ } else {
+ free (dbuf.dptr);
+ }
+
+ return tdb_ctx;
+}
+
+
+/**
+ \details Initialize a temporary (on-memory) TDB database. This
+ database is used to store temporary MId used within a session
+ lifetime.
+
+ \param mem_ctx pointer to the memory context
+
+ \return Allocated TDB context on success, otherwise NULL
+ */
+_PUBLIC_ TDB_CONTEXT *emsabp_tdb_init_tmp(TALLOC_CTX *mem_ctx)
+{
+ TDB_CONTEXT *tdb_ctx;
+ TDB_DATA key;
+ TDB_DATA dbuf;
+ int ret;
+
+ /* Step 0. Initialize the temporary TDB database */
+ tdb_ctx = tdb_open(NULL, 0, TDB_INTERNAL, O_RDWR|O_CREAT, 0600);
+
+ /* Step 1. Create EMSABP_TMP_TDB_DATA_REC record */
+ key.dptr = (unsigned char *) EMSABP_TDB_DATA_REC;
+ key.dsize = strlen(EMSABP_TDB_DATA_REC);
+
+ dbuf.dptr = (unsigned char *) talloc_asprintf(mem_ctx, "0x%x", EMSABP_TDB_TMP_MID_START);
+ dbuf.dsize = strlen((const char *)dbuf.dptr);
+
+ ret = tdb_store(tdb_ctx, key, dbuf, TDB_INSERT);
+ if (ret == -1) {
+ DEBUG(3, ("[%s:%d]: Unable to create %s record: %s\n", __FUNCTION__, __LINE__,
+ EMSABP_TDB_DATA_REC, tdb_errorstr(tdb_ctx)));
+ tdb_close(tdb_ctx);
+ return NULL;
+ }
+
+ return tdb_ctx;
+}
+
+
+/**
+ \details Close EMSABP TDB database
+
+ \return MAPI_E_SUCCESS on success, otherwise
+ MAPI_E_INVALID_PARAMETER
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_tdb_close(TDB_CONTEXT *tdb_ctx)
+{
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!tdb_ctx, MAPI_E_INVALID_PARAMETER, NULL);
+
+ tdb_close(tdb_ctx);
+ DEBUG(0, ("TDB database closed\n"));
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Fetch an element within a TDB database given its key
+
+ \param keyname pointer to the TDB key to fetch
+ \param result pointer on TDB results
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_tdb_fetch(TDB_CONTEXT *tdb_ctx,
+ const char *keyname,
+ TDB_DATA *result)
+{
+ TDB_DATA key;
+ TDB_DATA dbuf;
+ size_t keylen;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!tdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!keyname, MAPI_E_INVALID_PARAMETER, NULL);
+
+ keylen = strlen(keyname);
+ OPENCHANGE_RETVAL_IF(!keylen, MAPI_E_INVALID_PARAMETER, NULL);
+
+ key.dptr = (unsigned char *)keyname;
+ key.dsize = keylen;
+
+ dbuf = tdb_fetch(tdb_ctx, key);
+ OPENCHANGE_RETVAL_IF(!dbuf.dptr, MAPI_E_NOT_FOUND, NULL);
+ OPENCHANGE_RETVAL_IF(!dbuf.dsize, MAPI_E_NOT_FOUND, NULL);
+
+ if (!result) {
+ free (dbuf.dptr);
+ } else {
+ *result = dbuf;
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Retrieve the Minimal EntryID associated to a given DN
+
+ \param tdb_ctx pointer to the EMSABP TDB context
+ \param keyname pointer to the TDB key to search for
+ \param MId pointer on the integer the function returns
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_tdb_fetch_MId(TDB_CONTEXT *tdb_ctx,
+ const char *keyname,
+ uint32_t *MId)
+{
+ TDB_DATA key;
+ TDB_DATA dbuf;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!tdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!keyname, MAPI_E_INVALID_PARAMETER, NULL);
+ OPENCHANGE_RETVAL_IF(!MId, MAPI_E_INVALID_PARAMETER, NULL);
+
+ key.dptr = (unsigned char *) keyname;
+ key.dsize = strlen(keyname);
+
+ dbuf = tdb_fetch(tdb_ctx, key);
+ OPENCHANGE_RETVAL_IF(!dbuf.dptr, MAPI_E_NOT_FOUND, NULL);
+ OPENCHANGE_RETVAL_IF(!dbuf.dsize, MAPI_E_NOT_FOUND, NULL);
+
+ *MId = strtol((const char *)dbuf.dptr, NULL, 16);
+ free(dbuf.dptr);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+static int emsabp_tdb_traverse_MId(TDB_CONTEXT *tdb_ctx,
+ TDB_DATA key, TDB_DATA dbuf,
+ void *state)
+{
+ TALLOC_CTX *mem_ctx;
+ uint32_t value;
+ char *value_str = NULL;
+ uint32_t *MId = (uint32_t *)state;
+
+ mem_ctx = talloc_named(NULL, 0, "emsabp_tdb_traverse_MId");
+ value_str = talloc_strndup(mem_ctx, (char *)dbuf.dptr, dbuf.dsize);
+ value = strtol((const char *)value_str, NULL, 16);
+ talloc_free(mem_ctx);
+ if (value == *MId) return 1;
+
+ return 0;
+}
+
+
+/**
+ \details Traverse the EMSABP TDB database and look for the input
+ MId
+
+ \param tdb_ctx pointer to the EMSABP TDB context
+ \param MId MID to lookup
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool emsabp_tdb_lookup_MId(TDB_CONTEXT *tdb_ctx,
+ uint32_t MId)
+{
+ int ret;
+
+ ret = tdb_traverse(tdb_ctx, emsabp_tdb_traverse_MId, (void *)&MId);
+
+ return (ret == 1) ? true : false;
+}
+
+
+static int emsabp_tdb_traverse_MId_DN(TDB_CONTEXT *tdb_ctx,
+ TDB_DATA key, TDB_DATA dbuf,
+ void *state)
+{
+ char *MId;
+ uint32_t value;
+ struct emsabp_MId *emsabp_MId = (struct emsabp_MId *) state;
+
+ if (key.dptr && strcmp((const char *)key.dptr, EMSABP_TDB_DATA_REC)) {
+ MId = talloc_strndup(emsabp_MId, (char *)dbuf.dptr, dbuf.dsize);
+ value = strtol((const char *)MId, NULL, 16);
+ talloc_free(MId);
+ if (value == emsabp_MId->MId) {
+ emsabp_MId->dn = talloc_strndup(emsabp_MId, (char *)key.dptr, key.dsize);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+/**
+ \details Traverse the EMSABP TDB and fetch the DN associated with
+ the MId
+
+ \param mem_ctx pointer to the memory context
+ \param tdb_ctx pointer to the EMSABP TDB context
+ \param MId MID to search
+ \param dn pointer on pointer to the dn to return
+
+ \return MAPI_E_SUCCESS on success, otherwise false
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_tdb_fetch_dn_from_MId(TALLOC_CTX *mem_ctx,
+ TDB_CONTEXT *tdb_ctx,
+ uint32_t MId,
+ char **dn)
+{
+ int ret;
+ struct emsabp_MId *emsabp_MId;
+
+ emsabp_MId = talloc_zero(mem_ctx, struct emsabp_MId);
+ emsabp_MId->dn = NULL;
+ emsabp_MId->MId = MId;
+
+ ret = tdb_traverse(tdb_ctx, emsabp_tdb_traverse_MId_DN, (void *)emsabp_MId);
+ if (ret > -1 && emsabp_MId->dn) {
+ *dn = talloc_strdup(mem_ctx, emsabp_MId->dn);
+ talloc_free(emsabp_MId);
+ return MAPI_E_SUCCESS;
+ }
+
+ *dn = NULL;
+ talloc_free(emsabp_MId);
+
+ return MAPI_E_NOT_FOUND;
+}
+
+
+/**
+ \details Insert an element into TDB database
+
+ \param tdb_ctx pointer to the EMSABP TDB context
+ \param keyname pointer to the TDB key name string
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS emsabp_tdb_insert(TDB_CONTEXT *tdb_ctx,
+ const char *keyname)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ TDB_DATA key;
+ TDB_DATA dbuf;
+ int index;
+ int ret;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!tdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!keyname, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "emsabp_tdb_insert");
+ OPENCHANGE_RETVAL_IF(!mem_ctx, MAPI_E_NOT_ENOUGH_RESOURCES, NULL);
+
+ /* Step 1. Check if the record already exists */
+ retval = emsabp_tdb_fetch(tdb_ctx, keyname, &dbuf);
+ OPENCHANGE_RETVAL_IF(!retval, ecExiting, mem_ctx);
+
+ /* Step 2. Retrieve the latest TDB data value inserted */
+ retval = emsabp_tdb_fetch(tdb_ctx, EMSABP_TDB_DATA_REC, &dbuf);
+ OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+
+ index = strtol((const char *)dbuf.dptr, NULL, 16);
+ index += 1;
+
+ free(dbuf.dptr);
+
+ dbuf.dptr = (unsigned char *)talloc_asprintf(mem_ctx, "0x%x", index);
+ dbuf.dsize = strlen((const char *)dbuf.dptr);
+
+ /* Step 3. Insert the new record */
+ key.dptr = (unsigned char *)keyname;
+ key.dsize = strlen(keyname);
+
+ ret = tdb_store(tdb_ctx, key, dbuf, TDB_INSERT);
+ OPENCHANGE_RETVAL_IF(ret == -1, MAPI_E_CORRUPT_STORE, mem_ctx);
+
+ /* Step 4. Update Data record */
+ key.dptr = (unsigned char *) EMSABP_TDB_DATA_REC;
+ key.dsize = strlen((const char *)key.dptr);
+
+ ret = tdb_store(tdb_ctx, key, dbuf, TDB_MODIFY);
+ OPENCHANGE_RETVAL_IF(ret == -1, MAPI_E_CORRUPT_STORE, mem_ctx);
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
Added: trunk/openchange/mapiproxy/servers/default/rfr/dcesrv_exchange_ds_rfr.c
===================================================================
--- trunk/openchange/mapiproxy/servers/default/rfr/dcesrv_exchange_ds_rfr.c (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/rfr/dcesrv_exchange_ds_rfr.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,229 @@
+/*
+ MAPI Proxy - Exchange RFR Server
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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/>.
+ */
+
+/**
+ \file dcesrv_exchange_rfr.c
+
+ \brief OpenChange RFR Server implementation
+ */
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "dcesrv_exchange_ds_rfr.h"
+
+/**
+ \details exchange_ds_rfr RfrGetNewDSA (0x0) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the RfrGetNewDSA request data
+
+ \note We incorrectly assume input pUserDN is correct and available,
+ but it is OK for now.
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_RfrGetNewDSA(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct RfrGetNewDSA *r)
+{
+ const char *netbiosname = NULL;
+ const char *realm = NULL;
+ char *fqdn = NULL;
+
+ DEBUG(5, ("exchange_ds_rfr: RfrGetNewDSA (0x0)\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"));
+
+ r->out.ppszUnused = NULL;
+ r->out.ppszServer = NULL;
+ r->out.result = MAPI_E_LOGON_FAILED;
+ return MAPI_E_LOGON_FAILED;
+ }
+
+ /* Step 1. We don't have load-balancing support yet, just return Samba FQDN name */
+ netbiosname = lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx);
+ realm = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
+ if (!netbiosname || !realm) {
+ r->out.ppszUnused = NULL;
+ r->out.ppszServer = NULL;
+ r->out.result = MAPI_E_NO_SUPPORT;
+ return MAPI_E_NO_SUPPORT;
+ }
+
+ fqdn = talloc_asprintf(mem_ctx, "%s.%s", netbiosname, realm);
+ r->out.ppszUnused = NULL;
+ r->out.ppszServer = talloc_array(mem_ctx, const char *, 2);
+ r->out.ppszServer[0] = strlower_talloc(mem_ctx, fqdn);
+ r->out.ppszServer[1] = NULL;
+ r->out.result = MAPI_E_SUCCESS;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details exchange_ds_rrf RfrGetFQDNFromLegacyDN (0x1) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the RfrGetFQDNFromLegacyDN request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_RfrGetFQDNFromLegacyDN(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct RfrGetFQDNFromLegacyDN *r)
+{
+ char *fqdn;
+ const char *netbiosname;
+ const char *realm;
+
+ DEBUG(3, ("exchange_ds_rfr: RfrGetFQDNFromLegacyDN (0x1)\n"));
+
+ if (!NTLM_AUTH_IS_OK(dce_call)) {
+ DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
+
+ failure:
+ r->out.ppszServerFQDN = talloc_array(mem_ctx, const char *, 2);
+ r->out.ppszServerFQDN[0] = NULL;
+ r->out.result = MAPI_E_LOGON_FAILED;
+ return MAPI_E_LOGON_FAILED;
+ }
+
+ netbiosname = lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx);
+ realm = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
+ if (!netbiosname || !realm) {
+ goto failure;
+ }
+
+ fqdn = talloc_asprintf(mem_ctx, "%s.%s", netbiosname, realm);
+ r->out.ppszServerFQDN = talloc_array(mem_ctx, const char *, 2);
+ r->out.ppszServerFQDN[0] = strlower_talloc(mem_ctx, fqdn);
+ talloc_free(fqdn);
+ r->out.result = MAPI_E_SUCCESS;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Dispatch incoming RFR call to the correct OpenChange server function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r generic pointer on RFR data
+ \param mapiproxy pointer to the mapiproxy structure controlling
+ mapiproxy behavior
+
+ \return NT_STATUS_OK
+ */
+static NTSTATUS dcesrv_exchange_ds_rfr_dispatch(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ void *r, struct mapiproxy *mapiproxy)
+{
+ enum MAPISTATUS retval;
+ const struct ndr_interface_table *table;
+ uint16_t opnum;
+
+ table = (const struct ndr_interface_table *) dce_call->context->iface->private;
+ opnum = dce_call->pkt.u.request.opnum;
+
+ /* Sanity checks */
+ if (!table) return NT_STATUS_UNSUCCESSFUL;
+ if (table->name && strcmp(table->name, NDR_EXCHANGE_DS_RFR_NAME)) return NT_STATUS_UNSUCCESSFUL;
+
+ switch (opnum) {
+ case NDR_RFRGETNEWDSA:
+ retval = dcesrv_RfrGetNewDSA(dce_call, mem_ctx, (struct RfrGetNewDSA *)r);
+ break;
+ case NDR_RFRGETFQDNFROMLEGACYDN:
+ retval = dcesrv_RfrGetFQDNFromLegacyDN(dce_call, mem_ctx, (struct RfrGetFQDNFromLegacyDN *)r);
+ break;
+ }
+
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Initialize the RFR OpenChange server
+
+ \param dce_ctx pointer to the server context
+
+ \return NT_STATUS_OK on success
+ */
+static NTSTATUS dcesrv_exchange_ds_rfr_init(struct dcesrv_context *dce_ctx)
+{
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Terminate the RFR connection
+
+ \param server_id reference to the server identifier structure
+ \param context_id the connection context identifier
+
+ \return NT_STATUS_OK on success
+ */
+static NTSTATUS dcesrv_exchange_ds_rfr_unbind(struct server_id server_id,
+ uint32_t context_id)
+{
+ return NT_STATUS_OK;
+}
+
+
+/**
+ \details Entry point for the default OpenChange RFR server
+
+ \return NT_STATUS_OK on success, otherwise NTSTATUS error
+ */
+NTSTATUS samba_init_module(void)
+{
+ struct mapiproxy_module server;
+ NTSTATUS ret;
+
+ /* Fill in our name */
+ server.name = "exchange_ds_rfr";
+ server.status = MAPIPROXY_DEFAULT;
+ server.description = "OpenChange RFR server";
+ server.endpoint = "exchange_ds_rfr";
+
+ /* Fill in all the operations */
+ server.init = dcesrv_exchange_ds_rfr_init;
+ server.unbind = dcesrv_exchange_ds_rfr_unbind;
+ server.dispatch = dcesrv_exchange_ds_rfr_dispatch;
+ server.push = NULL;
+ server.pull = NULL;
+ server.ndr_pull = NULL;
+
+ /* Register ourselves with the MAPIPROXY server subsystem */
+ ret = mapiproxy_server_register(&server);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("Failed to register the 'exchange_ds_rfr' default mapiproxy server!\n"));
+ return ret;
+ }
+
+ return ret;
+}
Added: trunk/openchange/mapiproxy/servers/default/rfr/dcesrv_exchange_ds_rfr.h
===================================================================
--- trunk/openchange/mapiproxy/servers/default/rfr/dcesrv_exchange_ds_rfr.h (rev 0)
+++ trunk/openchange/mapiproxy/servers/default/rfr/dcesrv_exchange_ds_rfr.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,44 @@
+/*
+ MAPI Proxy - Exchange RFR Server
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2009
+
+ 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 __DCESRV_EXCHANGE_DS_RFR_H
+#define __DCESRV_EXCHANGE_DS_RFR_H
+
+#include <mapiproxy/libmapiproxy/libmapiproxy.h>
+#include <util/debug.h>
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+__BEGIN_DECLS
+
+NTSTATUS samba_init_module(void);
+
+__END_DECLS
+
+#endif /* __DCESRV_EXCHANGE_DS_RFR_H */
Added: trunk/openchange/missing
===================================================================
--- trunk/openchange/missing (rev 0)
+++ trunk/openchange/missing 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,360 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2005-06-08.21
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
+
+# 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 2, 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case "$1" in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ # Exit code 63 means version mismatch. This often happens
+ # when the user try to use an ancient version of a tool on
+ # a file that requires a minimum version. In this case we
+ # we should proceed has if the program had been absent, or
+ # if --run hadn't been passed.
+ if test $? = 63; then
+ run=:
+ msg="probably too old"
+ fi
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Send bug reports to <bug-automake at gnu.org>."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# Now exit if we have it, but it failed. Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).
+case "$1" in
+ lex|yacc)
+ # Not GNU programs, they don't have --version.
+ ;;
+
+ tar)
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ exit 1
+ fi
+ ;;
+
+ *)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ # Could not run --version or --help. This is probably someone
+ # running `$TOOL --version' or `$TOOL --help' to check whether
+ # $TOOL exists and not knowing $TOOL uses missing.
+ exit 1
+ fi
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case "$1" in
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
+ test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+ fi
+ if [ -f "$file" ]; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit 1
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ # The file to touch is that specified with -o ...
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ # ... or it is the one specified with @setfilename ...
+ infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile`
+ # ... or it is derived from the source name (dir/f.texi becomes f.info)
+ test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+ fi
+ # If the file does not exist, the user really needs makeinfo;
+ # let's fail without touching anything.
+ test -f $file || exit 1
+ touch $file
+ ;;
+
+ tar)
+ shift
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar "$@" && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar "$@" && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case "$firstarg" in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ case "$firstarg" in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequisites for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Property changes on: trunk/openchange/missing
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/ndr_mapi.c
===================================================================
--- trunk/openchange/ndr_mapi.c (rev 0)
+++ trunk/openchange/ndr_mapi.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,657 @@
+/*
+ OpenChange implementation.
+
+ libndr mapi support
+
+ Copyright (C) Julien Kerihuel 2005-2008
+
+ 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 <ndr.h>
+#include <gen_ndr/ndr_exchange.h>
+
+
+static void obfuscate_data(uint8_t *data, uint32_t size, uint8_t salt)
+{
+ uint32_t i;
+
+ for (i=0; i<size; i++) {
+ data[i] ^= salt;
+ }
+}
+
+/*
+ print mapi_request / mapi_response structures
+ */
+
+void ndr_print_mapi_request(struct ndr_print *ndr, const char *name, const struct mapi_request *r)
+{
+ uint32_t rlength;
+
+ rlength = r->mapi_len - r->length;
+
+ ndr_print_uint32(ndr, "mapi_len", r->mapi_len);
+ if (r->length && r->length > sizeof(uint16_t)) {
+ uint32_t cntr_mapi_req_0;
+
+ ndr_print_uint16(ndr, "length", r->length);
+ ndr->depth++;
+ for (cntr_mapi_req_0=0; r->mapi_req[cntr_mapi_req_0].opnum; cntr_mapi_req_0++) {
+ char *idx_0 = NULL;
+ int ret;
+
+ ret = asprintf(&idx_0, "[%u]", cntr_mapi_req_0);
+ if (ret != -1 && idx_0) {
+ ndr_print_EcDoRpc_MAPI_REQ(ndr, "mapi_request", &r->mapi_req[cntr_mapi_req_0]);
+ free(idx_0);
+ }
+ }
+ ndr->depth--;
+ }
+
+ if (rlength) {
+ uint32_t i;
+
+ ndr->depth++;
+ ndr->print(ndr, "%-25s: (handles) number=%u", name, rlength / 4);
+ ndr->depth++;
+ for (i = 0; i < (rlength / 4); i++) {
+ ndr_print_uint32(ndr, "handle", r->handles[i]);
+ }
+ ndr->depth--;
+ }
+}
+
+void ndr_print_mapi_response(struct ndr_print *ndr, const char *name, const struct mapi_response *r)
+{
+ uint32_t rlength;
+
+ rlength = r->mapi_len - r->length;
+
+ ndr->print(ndr, "%-25s: length=%u", name, r->length);
+ if (r->length && r->length > sizeof(uint16_t)) {
+ uint32_t cntr_mapi_repl_0;
+
+ ndr->print(ndr, "%s: ARRAY(%d)", name, r->length - 2);
+ ndr->depth++;
+ for (cntr_mapi_repl_0=0; r->mapi_repl[cntr_mapi_repl_0].opnum; cntr_mapi_repl_0++) {
+ ndr_print_EcDoRpc_MAPI_REPL(ndr, "mapi_repl", &r->mapi_repl[cntr_mapi_repl_0]);
+ }
+ ndr->depth--;
+ }
+
+ ndr->print(ndr, "%-25s: (handles) number=%u", name, rlength / 4);
+
+ if (rlength) {
+ uint32_t i;
+
+ ndr->depth++;
+
+ for (i = 0; i < (rlength / 4); i++) {
+ ndr_print_uint32(ndr, "handle id", r->handles[i]);
+ }
+ ndr->depth--;
+ }
+}
+
+
+/*
+ push mapi_request / mapi_response onto the wire.
+
+ MAPI length field includes length bytes.
+ But these bytes do not belong to the mapi content in the user
+ context. We have to add them when pushing mapi content length
+ (uint16_t) and next substract when pushing the content blob
+*/
+
+enum ndr_err_code ndr_push_mapi_request(struct ndr_push *ndr, int ndr_flags, const struct mapi_request *r)
+{
+ uint32_t cntr_mapi_req_0;
+ uint32_t count;
+
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->length));
+
+ for (count = 0; ndr->offset < r->length - 2; count++) {
+ NDR_CHECK(ndr_push_EcDoRpc_MAPI_REQ(ndr, NDR_SCALARS, &r->mapi_req[count]));
+ }
+
+ count = (r->mapi_len - r->length) / sizeof(uint32_t);
+ for (cntr_mapi_req_0=0; cntr_mapi_req_0 < count; cntr_mapi_req_0++) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->handles[cntr_mapi_req_0]));
+ }
+
+ obfuscate_data(ndr->data, ndr->offset, 0xA5);
+
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_mapi_response(struct ndr_push *ndr, int ndr_flags, const struct mapi_response *r)
+{
+ uint32_t cntr_mapi_repl_0;
+ uint32_t count;
+
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->length));
+
+ if (r->length > sizeof (uint16_t)) {
+ for (count = 0; ndr->offset < r->length - 2; count++) {
+ NDR_CHECK(ndr_push_EcDoRpc_MAPI_REPL(ndr, NDR_SCALARS, &r->mapi_repl[count]));
+ }
+ }
+
+ count = (r->mapi_len - r->length) / sizeof (uint32_t);
+ for (cntr_mapi_repl_0 = 0; cntr_mapi_repl_0 <count; cntr_mapi_repl_0++) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->handles[cntr_mapi_repl_0]));
+ }
+
+ obfuscate_data(ndr->data, ndr->alloc_size, 0xA5);
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull mapi_request / mapi_response from the wire
+*/
+
+enum ndr_err_code ndr_pull_mapi_request(struct ndr_pull *ndr, int ndr_flags, struct mapi_request *r)
+{
+ uint32_t length,count;
+ uint32_t cntr_mapi_req_0;
+ TALLOC_CTX *_mem_save_mapi_req_0;
+ TALLOC_CTX *_mem_save_handles_0;
+ struct ndr_pull *_ndr_mapi_req;
+
+ obfuscate_data(ndr->data, ndr->data_size, 0xA5);
+
+ if (ndr->flags & LIBNDR_FLAG_REMAINING) {
+ length = ndr->data_size - ndr->offset;
+ } else {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
+ }
+ r->mapi_len = length;
+
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->length));
+
+ /* If length equals length field then skipping subcontext */
+ if (r->length > sizeof (uint16_t)) {
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_mapi_req, 0, r->length - 2));
+ _mem_save_mapi_req_0 = NDR_PULL_GET_MEM_CTX(_ndr_mapi_req);
+ r->mapi_req = talloc_zero(_mem_save_mapi_req_0, struct EcDoRpc_MAPI_REQ);
+ for (cntr_mapi_req_0 = 0; _ndr_mapi_req->offset < _ndr_mapi_req->data_size - 2; cntr_mapi_req_0++) {
+ NDR_CHECK(ndr_pull_EcDoRpc_MAPI_REQ(_ndr_mapi_req, NDR_SCALARS, &r->mapi_req[cntr_mapi_req_0]));
+ r->mapi_req = talloc_realloc(_mem_save_mapi_req_0, r->mapi_req, struct EcDoRpc_MAPI_REQ, cntr_mapi_req_0 + 2);
+ }
+ r->mapi_req = talloc_realloc(_mem_save_mapi_req_0, r->mapi_req, struct EcDoRpc_MAPI_REQ, cntr_mapi_req_0 + 2);
+ r->mapi_req[cntr_mapi_req_0].opnum = 0;
+
+ if (_ndr_mapi_req->offset != r->length - 2) {
+ return NDR_ERR_BUFSIZE;
+ }
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_mapi_req, 4, -1));
+
+ _mem_save_handles_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ count = (r->mapi_len - r->length) / sizeof(uint32_t);
+ r->handles = talloc_array(_mem_save_handles_0, uint32_t, count + 1);
+ for (cntr_mapi_req_0=0; cntr_mapi_req_0 < count; cntr_mapi_req_0++) {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->handles[cntr_mapi_req_0]));
+ }
+ } else {
+ r->handles = NULL;
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_mapi_response(struct ndr_pull *ndr, int ndr_flags, struct mapi_response *r)
+{
+ uint32_t length,count;
+ uint32_t cntr_mapi_repl_0;
+ TALLOC_CTX *_mem_save_mapi_repl_0;
+ TALLOC_CTX *_mem_save_handles_0;
+ struct ndr_pull *_ndr_mapi_repl;
+
+ obfuscate_data(ndr->data, ndr->data_size, 0xA5);
+
+ if (ndr->flags & LIBNDR_FLAG_REMAINING) {
+ length = ndr->data_size - ndr->offset;
+ } else {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
+ }
+ r->mapi_len = length;
+
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->length));
+
+ /* If length equals length field then skipping subcontext */
+ if (r->length > sizeof (uint16_t)) {
+ _mem_save_mapi_repl_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ r->mapi_repl = talloc_array(_mem_save_mapi_repl_0, struct EcDoRpc_MAPI_REPL, 2);
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_mapi_repl, 0, r->length - 2));
+ for (cntr_mapi_repl_0 = 0; _ndr_mapi_repl->offset < _ndr_mapi_repl->data_size - 2; cntr_mapi_repl_0++) {
+ NDR_CHECK(ndr_pull_EcDoRpc_MAPI_REPL(_ndr_mapi_repl, NDR_SCALARS, &r->mapi_repl[cntr_mapi_repl_0]));
+ r->mapi_repl = talloc_realloc(_ndr_mapi_repl, r->mapi_repl, struct EcDoRpc_MAPI_REPL, cntr_mapi_repl_0 + 2);
+ }
+ r->mapi_repl[cntr_mapi_repl_0].opnum = 0;
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_mapi_repl, 4, -1));
+ talloc_free(_ndr_mapi_repl);
+ }
+
+ _mem_save_handles_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ count = (r->mapi_len - r->length) / sizeof(uint32_t);
+ NDR_PULL_ALLOC_N(ndr, r->handles, count + 1);
+
+ for (cntr_mapi_repl_0=0; cntr_mapi_repl_0 < count; cntr_mapi_repl_0++) {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->handles[cntr_mapi_repl_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_handles_0, LIBNDR_FLAG_REF_ALLOC);
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ We stop processing the IDL if MAPISTATUS is different from MAPI_E_SUCCESS
+ */
+
+_PUBLIC_ enum ndr_err_code ndr_push_EcDoRpc_MAPI_REPL(struct ndr_push *ndr, int ndr_flags, const struct EcDoRpc_MAPI_REPL *r)
+{
+ if (r->opnum != op_MAPI_Release)
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 8));
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->opnum));
+ if ((r->opnum == op_MAPI_Notify) || (r->opnum == op_MAPI_Pending)) {
+ NDR_CHECK(ndr_push_set_switch_value(ndr, &r->u, r->opnum));
+ NDR_CHECK(ndr_push_EcDoRpc_MAPI_REPL_UNION(ndr, NDR_SCALARS, &r->u));
+ } else {
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->handle_idx));
+ NDR_CHECK(ndr_push_MAPISTATUS(ndr, NDR_SCALARS, r->error_code));
+ if (r->error_code == MAPI_E_SUCCESS) {
+ NDR_CHECK(ndr_push_set_switch_value(ndr, &r->u, r->opnum));
+ NDR_CHECK(ndr_push_EcDoRpc_MAPI_REPL_UNION(ndr, NDR_SCALARS, &r->u));
+ }
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_push_EcDoRpc_MAPI_REPL_UNION(ndr, NDR_BUFFERS, &r->u));
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_EcDoRpc_MAPI_REPL(struct ndr_pull *ndr, int ndr_flags, struct EcDoRpc_MAPI_REPL *r)
+{
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 8));
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->opnum));
+ if ((r->opnum == op_MAPI_Notify) || (r->opnum == op_MAPI_Pending)) {
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->u, r->opnum));
+ NDR_CHECK(ndr_pull_EcDoRpc_MAPI_REPL_UNION(ndr, NDR_SCALARS, &r->u));
+ } else {
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->handle_idx));
+ NDR_CHECK(ndr_pull_MAPISTATUS(ndr, NDR_SCALARS, &r->error_code));
+ if ( r->error_code == MAPI_E_SUCCESS) {
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->u, r->opnum));
+ NDR_CHECK(ndr_pull_EcDoRpc_MAPI_REPL_UNION(ndr, NDR_SCALARS, &r->u));
+ }
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ ndr->flags = _flags_save_STRUCT;
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+void ndr_print_EcDoRpc_MAPI_REPL(struct ndr_print *ndr, const char *name, const struct EcDoRpc_MAPI_REPL *r)
+{
+ ndr_print_struct(ndr, name, "EcDoRpc_MAPI_REPL");
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ ndr->depth++;
+ ndr_print_uint8(ndr, "opnum", r->opnum);
+ if ((r->opnum != op_MAPI_Notify) && (r->opnum != op_MAPI_Pending)) {
+ ndr_print_uint8(ndr, "handle_idx", r->handle_idx);
+ ndr_print_MAPISTATUS(ndr, "error_code", r->error_code);
+ if (r->error_code == MAPI_E_SUCCESS) {
+ ndr_print_set_switch_value(ndr, &r->u, r->opnum);
+ ndr_print_EcDoRpc_MAPI_REPL_UNION(ndr, "u", &r->u);
+ }
+ } else {
+ ndr_print_set_switch_value(ndr, &r->u, r->opnum);
+ ndr_print_EcDoRpc_MAPI_REPL_UNION(ndr, "u", &r->u);
+ }
+ ndr->depth--;
+ ndr->flags = _flags_save_STRUCT;
+ }
+}
+
+/*
+ We need to pull QueryRows replies on our own:
+ If we have no results, do not push/pull the DATA_BLOB
+*/
+
+enum ndr_err_code ndr_push_QueryRows_repl(struct ndr_push *ndr, int ndr_flags, const struct QueryRows_repl *r)
+{
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->Origin));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->RowCount));
+
+ if (r->RowCount) {
+ uint32_t _flags_save_DATA_BLOB = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
+ NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->RowData));
+ ndr->flags = _flags_save_DATA_BLOB;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_QueryRows_repl(struct ndr_pull *ndr, int ndr_flags, struct QueryRows_repl *r)
+{
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->Origin));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->RowCount));
+
+ if (r->RowCount)
+ {
+ uint32_t _flags_save_DATA_BLOB = ndr->flags;
+
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
+ NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->RowData));
+ ndr->flags = _flags_save_DATA_BLOB;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+
+enum ndr_err_code ndr_push_Logon_req(struct ndr_push *ndr, int ndr_flags, const struct Logon_req *r)
+{
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_LogonFlags(ndr, NDR_SCALARS, r->LogonFlags));
+ NDR_CHECK(ndr_push_OpenFlags(ndr, NDR_SCALARS, r->OpenFlags));
+ NDR_CHECK(ndr_push_StoreState(ndr, NDR_SCALARS, r->StoreState));
+ if (r->EssDN && r->EssDN[0] != '\0') {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_SIZE2);
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->EssDN));
+ ndr->flags = _flags_save_string;
+ } else {
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0));
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+
+_PUBLIC_ void ndr_print_SBinary_short(struct ndr_print *ndr, const char *name, const struct SBinary_short *r)
+{
+ ndr->print(ndr, "%-25s: SBinary_short cb=%u", name, (unsigned)r->cb);
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ ndr->depth++;
+ dump_data(0, r->lpb, r->cb);
+ ndr->depth--;
+ ndr->flags = _flags_save_STRUCT;
+ }
+}
+
+
+_PUBLIC_ void ndr_print_fuzzyLevel(struct ndr_print *ndr, const char *name, uint32_t r)
+{
+ ndr_print_uint32(ndr, name, r);
+ ndr->depth++;
+ switch ((r & 0x0000FFFF)) {
+ case FL_FULLSTRING:
+ ndr->print(ndr, "%-25s: FL_FULLSTRING", "lower 16 bits");
+ break;
+ case FL_SUBSTRING:
+ ndr->print(ndr, "%-25s: FL_SUBSTRING", "lower 16 bits");
+ break;
+ case FL_PREFIX:
+ ndr->print(ndr, "%-25s: FL_PREFIX", "lower 16 bits");
+ break;
+ }
+ ndr->print(ndr, "%-25s", "higher 16 bits");
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "FL_IGNORECASE", FL_IGNORECASE, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "FL_IGNORENONSPACE", FL_IGNORENONSPACE, r);
+ ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "FL_LOOSE", FL_LOOSE, r);
+ ndr->depth--;
+}
+
+/*
+ * Fake wrapper over mapi_SRestriction. Workaround the no-pointer deep
+ * recursion problem in pidl
+ */
+enum ndr_err_code ndr_push_mapi_SRestriction_wrap(struct ndr_push *ndr, int ndr_flags, const struct mapi_SRestriction_wrap *r)
+{
+ return ndr_push_mapi_SRestriction(ndr, NDR_SCALARS, (const struct mapi_SRestriction *)r);
+}
+
+
+enum ndr_err_code ndr_pull_mapi_SRestriction_wrap(struct ndr_pull *ndr, int ndr_flags, struct mapi_SRestriction_wrap *r)
+{
+ return ndr_pull_mapi_SRestriction(ndr, NDR_SCALARS|NDR_BUFFERS, (struct mapi_SRestriction *)r);
+}
+
+void ndr_print_mapi_SRestriction_wrap(struct ndr_print *ndr, const char *name, const struct mapi_SRestriction_wrap *r)
+{
+ ndr_print_mapi_SRestriction(ndr, name, (const struct mapi_SRestriction *)r);
+}
+
+/*
+ * Fake wrapper over mapi_SPropValue. Workaround the no-pointer deep
+ * recursion problem in pidl
+ */
+enum ndr_err_code ndr_push_mapi_SPropValue_wrap(struct ndr_push *ndr, int ndr_flags, const struct mapi_SPropValue_wrap *r)
+{
+ NDR_CHECK(ndr_push_align(ndr, 8));
+ return ndr_push_mapi_SPropValue(ndr, NDR_SCALARS, (const struct mapi_SPropValue *)r);
+}
+
+enum ndr_err_code ndr_pull_mapi_SPropValue_wrap(struct ndr_pull *ndr, int ndr_flags, struct mapi_SPropValue_wrap *r)
+{
+ return ndr_pull_mapi_SPropValue(ndr, NDR_SCALARS, (struct mapi_SPropValue *)r);
+}
+
+void ndr_print_mapi_SPropValue_wrap(struct ndr_print *ndr, const char *name, const struct mapi_SPropValue_wrap *r)
+{
+ return ndr_print_mapi_SPropValue(ndr, name, (const struct mapi_SPropValue *)r);
+}
+
+
+/*
+ * Fake wrapper over mapi_SPropValue_array. Workaround the no-pointer deep
+ * recursion problem in pidl
+ */
+enum ndr_err_code ndr_push_mapi_SPropValue_array_wrap(struct ndr_push *ndr, int ndr_flags, const struct mapi_SPropValue_array_wrap *r)
+{
+ NDR_CHECK(ndr_push_align(ndr, 8));
+ return ndr_push_mapi_SPropValue_array(ndr, NDR_SCALARS, (const struct mapi_SPropValue_array *)r);
+}
+
+enum ndr_err_code ndr_pull_mapi_SPropValue_array_wrap(struct ndr_pull *ndr, int ndr_flags, struct mapi_SPropValue_array_wrap *r)
+{
+ return ndr_pull_mapi_SPropValue_array(ndr, NDR_SCALARS, (struct mapi_SPropValue_array *)r);
+}
+
+void ndr_print_mapi_SPropValue_array_wrap(struct ndr_print *ndr, const char *name, const struct mapi_SPropValue_array_wrap *r)
+{
+ return ndr_print_mapi_SPropValue_array(ndr, name, (const struct mapi_SPropValue_array *)r);
+}
+
+enum ndr_err_code ndr_push_RestrictionVariable(struct ndr_push *ndr, int ndr_flags, const union RestrictionVariable *r)
+{
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ int level = ndr_push_get_switch_value(ndr, r);
+ switch (level) {
+ case 0x0: {
+ break; }
+
+ case 0x1: {
+ NDR_CHECK(ndr_push_mapi_SRestriction_comment(ndr, NDR_SCALARS, &r->res[0]));
+ break; }
+
+ default:
+ return ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ int level = ndr_push_get_switch_value(ndr, r);
+ switch (level) {
+ case 0x0:
+ break;
+
+ case 0x1:
+ if (r->res) {
+ NDR_CHECK(ndr_push_mapi_SRestriction_comment(ndr, NDR_BUFFERS, &r->res[0]));
+ }
+ break;
+
+ default:
+ return ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
+ }
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_RestrictionVariable(struct ndr_pull *ndr, int ndr_flags, union RestrictionVariable *r)
+{
+ int level;
+ TALLOC_CTX *_mem_save_res_0;
+ level = ndr_pull_get_switch_value(ndr, r);
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+
+ if (ndr_flags & NDR_SCALARS) {
+ switch (level) {
+ case 0x0: {
+ break; }
+
+ case 0x1: {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_PULL_ALLOC_N(ndr, r->res, 1);
+ _mem_save_res_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->res, 0);
+ NDR_CHECK(ndr_pull_mapi_SRestriction_comment(ndr, NDR_SCALARS, &r->res[0]));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_res_0, 0);
+ break; }
+
+ default:
+ return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ switch (level) {
+ case 0x0:
+ break;
+
+ case 0x1:
+ if (r->res) {
+ _mem_save_res_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->res, 0);
+ NDR_CHECK(ndr_pull_mapi_SRestriction_comment(ndr, NDR_BUFFERS, &r->res[0]));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_res_0, 0);
+ break; }
+
+ default:
+ return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
+ }
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+
+_PUBLIC_ void ndr_print_RestrictionVariable(struct ndr_print *ndr, const char *name, const union RestrictionVariable *r)
+{
+ int level;
+ level = ndr_print_get_switch_value(ndr, r);
+ ndr_print_union(ndr, name, level, "RestrictionVariable");
+ switch (level) {
+ case 0x0:
+ break;
+
+ case 0x1:
+ ndr_print_ptr(ndr, "res", r->res);
+ ndr->depth++;
+ if (r->res) {
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ ndr_print_mapi_SRestriction_comment(ndr, "res", &r->res[0]);
+ }
+ ndr->depth--;
+ break;
+ }
+}
+
+enum ndr_err_code ndr_push_Release_req(struct ndr_push *ndr, int ndr_flags, const struct Release_req *r)
+{
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_Release_req(struct ndr_pull *ndr, int ndr_flags, struct Release_req *r)
+{
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_Release_repl(struct ndr_push *ndr, int ndr_flags, const struct Release_repl *r)
+{
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_Release_repl(struct ndr_pull *ndr, int ndr_flags, struct Release_repl *r)
+{
+ return NDR_ERR_SUCCESS;
+}
Added: trunk/openchange/property.idl
===================================================================
--- trunk/openchange/property.idl (rev 0)
+++ trunk/openchange/property.idl 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,158 @@
+#include "idl_types.h"
+
+cpp_quote("#include <gen_ndr/ndr_misc.h>")
+
+import "exchange.idl";
+
+[
+ pointer_default(unique)
+]
+interface property
+{
+ typedef [enum16bit] enum {
+ RecurFrequency_Daily = 0x200A,
+ RecurFrequency_Weekly = 0x200B,
+ RecurFrequency_Monthly = 0x200C,
+ RecurFrequency_Yearly = 0x200D
+ } RecurFrequency;
+
+ typedef [enum16bit] enum {
+ PatternType_Day = 0x0,
+ PatternType_Week = 0x1,
+ PatternType_Month = 0x2,
+ PatternType_MonthNth = 0x3,
+ PatternType_MonthEnd = 0x4,
+ PatternType_HjMonth = 0xA,
+ PatternType_HjMonthNth = 0xB,
+ PatternType_HjMonthEnd = 0xC
+ } PatternType;
+
+ typedef [enum16bit] enum {
+ CAL_DEFAULT = 0x0,
+ CAL_GREGORIAN = 0x1,
+ CAL_GREGORIAN_US = 0x2,
+ CAL_JAPAN = 0x3,
+ CAL_TAIWAN = 0x4,
+ CAL_KOREA = 0x5,
+ CAL_HIJRI = 0x6,
+ CAL_THAI = 0x7,
+ CAL_HEBREW = 0x8,
+ CAL_GREGORIAN_ME_FRENCH = 0x9,
+ CAL_GREGORIAN_ARABIC = 0xA,
+ CAL_GREGORIAN_XLIT_ENGLISH = 0xB,
+ CAL_GREGORIAN_XLIT_FRENCH = 0xC,
+ CAL_LUNAR_JAPANESE = 0xE,
+ CAL_CHINESE_LUNAR = 0xF,
+ CAL_SAKA = 0x10,
+ CAL_LUNAR_KOREAN = 0x14
+ } CalendarType;
+
+ typedef [bitmap32bit] bitmap {
+ Su = 0x00000001,
+ M = 0x00000002,
+ Tu = 0x00000004,
+ W = 0x00000008,
+ Th = 0x00000010,
+ F = 0x00000020,
+ Sa = 0x00000040
+ } WeekRecurrencePattern;
+
+ typedef [v1_enum] enum {
+ RecurrenceN_First = 0x1,
+ RecurrenceN_Second = 0x2,
+ RecurrenceN_Third = 0x3,
+ RecurrenceN_Fourth = 0x4,
+ RecurrenceN_Last = 0x5
+ } RecurrenceN;
+
+ typedef [flag(NDR_NOALIGN)] struct {
+ WeekRecurrencePattern WeekRecurrencePattern;
+ RecurrenceN N;
+ } MonthRecurrencePattern;
+
+ typedef [nodiscriminant,flag(NDR_NOALIGN)] union {
+ [case(0x1)] WeekRecurrencePattern WeekRecurrencePattern;
+ [case(0x2)] uint32 Day;
+ [case(0x3)] MonthRecurrencePattern MonthRecurrencePattern;
+ [case(0x4)] uint32 Day;
+ [case(0xA)] uint32 Day;
+ [case(0xB)] MonthRecurrencePattern MonthRecurrencePattern;
+ [case(0xC)] uint32 Day;
+ [case(0x0)];
+ [default];
+ } PatternTypeSpecific;
+
+ typedef [v1_enum] enum {
+ END_AFTER_DATE = 0x00002021,
+ END_AFTER_N_OCCURRENCES = 0x00002022,
+ END_NEVER_END = 0x00002023,
+ NEVER_END = 0xFFFFFFFF
+ } EndType;
+
+ typedef [v1_enum] enum {
+ FirstDOW_Sunday = 0x0,
+ FirstDOW_Monday = 0x1,
+ FirstDOW_Tuesday = 0x2,
+ FirstDOW_Wednesday = 0x3,
+ FirstDOW_Thursday = 0x4,
+ FirstDOW_Friday = 0x5,
+ FirstDOW_Saturday = 0x6
+ } FirstDOW;
+
+ typedef [public,flag(NDR_NOALIGN)] struct {
+ uint16 ReaderVersion;
+ uint16 WriterVersion;
+ RecurFrequency RecurFrequency;
+ PatternType PatternType;
+ CalendarType CalendarType;
+ uint32 FirstDateTime;
+ uint32 Period;
+ uint32 SlidingFlag;
+ [switch_is(PatternType)] PatternTypeSpecific PatternTypeSpecific;
+ EndType EndType;
+ uint32 OccurrenceCount;
+ FirstDOW FirstDOW;
+ uint32 DeletedInstanceCount;
+ uint32 DeletedInstanceDates[DeletedInstanceCount];
+ uint32 ModifiedInstanceCount;
+ uint32 ModifiedInstanceDates[ModifiedInstanceCount];
+ uint32 StartDate;
+ uint32 EndDate;
+ } RecurrencePattern;
+
+ /* [MS-DIF].pdf Section 2.3.6 */
+ typedef [public,flag(NDR_NOALIGN)] struct {
+ uint16 wYear;
+ uint16 wMonth;
+ uint16 wDayOfWeek;
+ uint16 wDay;
+ uint16 wHour;
+ uint16 wMinute;
+ uint16 wSecond;
+ uint16 wMilliseconds;
+ } SYSTEMTIME;
+
+ /* pidLidTimeZoneStruct */
+ typedef [public,flag(NDR_NOALIGN)] struct {
+ uint32 lBias;
+ uint32 lStandardBias;
+ uint32 lDaylightBias;
+ uint16 wStandardYear;
+ SYSTEMTIME stStandardDate;
+ uint16 wDaylightYear;
+ SYSTEMTIME stDaylightDate;
+ } TimeZoneStruct;
+
+ /* pidLidGlobalObjectId */
+ typedef [public,flag(NDR_NOALIGN)] struct {
+ uint8 ByteArrayID[16];
+ uint8 YH;
+ uint8 YL;
+ uint8 Month;
+ uint8 D;
+ FILETIME CreationTime;
+ uint8 X[8];
+ uint32 Size;
+ uint8 Data[Size];
+ } GlobalObjectId;
+}
Added: trunk/openchange/pymapi/msg_store.c
===================================================================
--- trunk/openchange/pymapi/msg_store.c (rev 0)
+++ trunk/openchange/pymapi/msg_store.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,62 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2008.
+
+ 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 "pymapi/pymapi.h"
+
+static PyObject *py_is_mailbox_folder(PyMapiObjectObject *self, PyObject *args)
+{
+ uint64_t fid;
+ uint32_t olFolder;
+
+ if (!PyArg_ParseTuple(args, "L", &fid))
+ return NULL;
+
+ if (!IsMailboxFolder(self->object, fid, &olFolder))
+ return Py_None;
+
+ return PyInt_FromLong(olFolder);
+}
+
+static PyMethodDef msg_store_methods[] = {
+ { "is_mailbox_folder", (PyCFunction)py_is_mailbox_folder, METH_VARARGS, NULL },
+ { NULL },
+};
+
+static PyGetSetDef msg_store_getsetters[] = {
+ { NULL }
+};
+
+static PyObject *msg_store_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyErr_SetString(PyExc_NotImplementedError, "Message Stores can only be obtained from a MAPI Session");
+ return NULL;
+}
+
+PyTypeObject PyMapiMsgStoreType = {
+ PyObject_HEAD_INIT(NULL) 0,
+ .tp_name = "MessageStore",
+ .tp_basicsize = sizeof(PyMapiObjectObject),
+ .tp_methods = msg_store_methods,
+ .tp_getset = msg_store_getsetters,
+ .tp_doc = "MAPI Message Store",
+ .tp_new = msg_store_new,
+ .tp_base = &PyMapiObjectType,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+};
+
Added: trunk/openchange/pymapi/object.c
===================================================================
--- trunk/openchange/pymapi/object.c (rev 0)
+++ trunk/openchange/pymapi/object.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,344 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2008.
+
+ 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 "pymapi/pymapi.h"
+
+static PyObject *PyMapiObject_FromMapiObject(mapi_object_t *obj)
+{
+ return NULL; /* FIXME */
+}
+
+static PyObject *object_create(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ /* FIXME */
+ return (PyObject *)PyObject_New(PyMapiObjectObject, type);
+}
+
+static void object_dealloc(PyObject *_self)
+{
+ PyMapiObjectObject *self = (PyMapiObjectObject *)_self;
+ mapi_object_release(self->object);
+ PyObject_Del(_self);
+}
+
+mapi_object_t *PyMapiObject_GetMapiObject(PyObject *obj)
+{
+ PyMapiObjectObject *self = (PyMapiObjectObject *)obj;
+ if (!PyMapiObject_Check(obj))
+ return NULL;
+
+ return self->object;
+}
+
+static PyObject *py_folder_get_items_count(PyMapiObjectObject *self)
+{
+ enum MAPISTATUS status;
+ uint32_t unread, total;
+
+ status = GetFolderItemsCount(self->object, &unread, &total);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return Py_BuildValue("(ii)", unread, total);
+}
+
+static PyObject *py_folder_remove_user_permissions(PyMapiObjectObject *self, PyObject *args)
+{
+ char *username;
+ enum MAPISTATUS status;
+ if (!PyArg_ParseTuple(args, "s", &username))
+ return NULL;
+
+ status = RemoveUserPermission(self->object, username);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return Py_None;
+}
+
+static PyObject *py_folder_create(PyMapiObjectObject *self, PyObject *args)
+{
+ int foldertype;
+ char *name, *comment;
+ uint32_t flags;
+ enum MAPISTATUS status;
+ mapi_object_t child;
+
+ if (!PyArg_ParseTuple(args, "issI", &foldertype, &name, &comment, &flags))
+ return NULL;
+
+ status = CreateFolder(self->object, foldertype, name, comment, flags, &child);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return PyMapiObject_FromMapiObject(&child);
+}
+
+static PyObject *py_folder_delete(PyMapiObjectObject *self, PyObject *args)
+{
+ mapi_id_t folderid;
+ int flags;
+ enum MAPISTATUS status;
+ bool partial;
+ if (!PyArg_ParseTuple(args, "ii", &folderid, &flags))
+ return NULL;
+
+ status = DeleteFolder(self->object, folderid, flags, &partial);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return PyBool_FromLong(partial);
+}
+
+static PyObject *py_folder_empty(PyMapiObjectObject *self)
+{
+ enum MAPISTATUS status = EmptyFolder(self->object);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+ return Py_None;
+}
+
+static PyObject *py_folder_create_message(PyMapiObjectObject *self)
+{
+ mapi_object_t msg;
+ enum MAPISTATUS status = CreateMessage(self->object, &msg);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+ return PyMapiObject_FromMapiObject(&msg);
+}
+
+static PyObject *py_folder_delete_messages(PyMapiObjectObject *self, PyObject *args)
+{
+ PyObject *py_ids;
+ uint32_t cn_messages;
+ mapi_id_t *ids;
+ enum MAPISTATUS status;
+ int i;
+
+ if (!PyArg_ParseTuple(args, "O", &py_ids))
+ return NULL;
+
+ if (!PySequence_Check(py_ids)) {
+ PyErr_SetString(PyExc_TypeError, "ids should be a list of ids");
+ return NULL;
+ }
+
+ cn_messages = PySequence_Size(py_ids);
+ ids = talloc_array(NULL, mapi_id_t, cn_messages);
+ if (ids == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ for (i = 0; i < cn_messages; i++) {
+ PyObject *item;
+ item = PySequence_GetItem(py_ids, i);
+ ids[i] = PyInt_AsLong(item);
+ }
+
+ status = DeleteMessage(self->object, ids, cn_messages);
+ talloc_free(ids);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return Py_None;
+}
+
+static PyObject *py_folder_set_read_flags(PyMapiObjectObject *self, PyObject *args)
+{
+ int flags;
+ PyObject *py_ids;
+ enum MAPISTATUS status;
+ uint16_t cn_ids;
+ uint64_t *ids;
+ int i;
+ if (!PyArg_ParseTuple(args, "iO", &flags, &py_ids))
+ return NULL;
+
+ if (!PySequence_Check(py_ids)) {
+ PyErr_SetString(PyExc_TypeError, "ids should be a list of ids");
+ return NULL;
+ }
+
+ cn_ids = PySequence_Size(py_ids);
+ ids = talloc_array(NULL, uint64_t, cn_ids);
+ if (ids == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ for (i = 0; i < cn_ids; i++) {
+ PyObject *item;
+ item = PySequence_GetItem(py_ids, i);
+ ids[i] = PyInt_AsLong(item);
+ }
+
+ status = SetReadFlags(self->object, flags, cn_ids, ids);
+ talloc_free(ids);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return Py_None;
+}
+
+static PyObject *py_folder_get_message_status(PyMapiObjectObject *self, PyObject *args)
+{
+ mapi_id_t msgid;
+ uint32_t lstatus;
+ enum MAPISTATUS status;
+ if (!PyArg_ParseTuple(args, "i", &msgid))
+ return NULL;
+
+ status = GetMessageStatus(self->object, msgid, &lstatus);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return PyInt_FromLong(lstatus);
+}
+
+static PyObject *py_message_get_best_body(PyMapiObjectObject *self)
+{
+ enum MAPISTATUS status;
+ uint8_t format;
+
+ status = GetBestBody(self->object, &format);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return PyInt_FromLong(status);
+}
+
+static PyObject *py_get_default_folder(PyMapiObjectObject *self, PyObject *args)
+{
+ enum MAPISTATUS status;
+ uint32_t type;
+ uint64_t folder;
+
+ if (!PyArg_ParseTuple(args, "i", &type))
+ return NULL;
+
+ status = GetDefaultFolder(self->object, &folder, type);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return PyLong_FromLong(folder);
+}
+
+static PyObject *py_get_default_public_folder(PyMapiObjectObject *self, PyObject *args)
+{
+ enum MAPISTATUS status;
+ uint32_t type;
+ uint64_t folder;
+
+ if (!PyArg_ParseTuple(args, "i", &type))
+ return NULL;
+
+ status = GetDefaultPublicFolder(self->object, &folder, type);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return PyLong_FromLong(folder);
+}
+
+static PyObject *py_folder_add_user_permission(PyMapiObjectObject *self, PyObject *args)
+{
+ char *name;
+ int rights;
+ enum MAPISTATUS status;
+ if (!PyArg_ParseTuple(args, "si", &name, &rights))
+ return NULL;
+
+ status = AddUserPermission(self->object, name, rights);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return Py_None;
+}
+
+static PyObject *py_folder_modify_user_permission(PyMapiObjectObject *self, PyObject *args)
+{
+ char *name;
+ int rights;
+ enum MAPISTATUS status;
+ if (!PyArg_ParseTuple(args, "si", &name, &rights))
+ return NULL;
+
+ status = ModifyUserPermission(self->object, name, rights);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return Py_None;
+}
+
+static PyMethodDef object_methods[] = {
+ { "get_folder_items_count", (PyCFunction)py_folder_get_items_count, METH_NOARGS,
+ "S.get_folder_items_count() -> (unread, total)" },
+ { "remove_user_permission", (PyCFunction)py_folder_remove_user_permissions, METH_VARARGS,
+ "S.remove_user_permissions(user) -> None" },
+ { "add_user_permission", (PyCFunction)py_folder_add_user_permission, METH_VARARGS,
+ "S.add_user_permission(user, perm) -> None" },
+ { "modify_user_permission", (PyCFunction)py_folder_modify_user_permission, METH_VARARGS,
+ "S.modify_user_permission(user, perm) -> None" },
+ { "create_folder", (PyCFunction)py_folder_create, METH_VARARGS,
+ "S.create_folder(type, name, comment, flags) -> None" },
+ { "empty_folder", (PyCFunction)py_folder_empty, METH_NOARGS,
+ "S.empty_folder() -> None" },
+ { "delete_folder", (PyCFunction)py_folder_delete, METH_VARARGS,
+ "S.delete_folder(folderid, flags) -> None" },
+ { "create_message", (PyCFunction)py_folder_create_message, METH_NOARGS,
+ "S.create_message() -> message" },
+ { "delete_messages", (PyCFunction)py_folder_delete_messages, METH_VARARGS,
+ "S.delete_messages([ids]) -> None" },
+ { "get_message_status", (PyCFunction)py_folder_get_message_status, METH_VARARGS,
+ "S.get_message_status(id) -> status" },
+ { "set_read_flags", (PyCFunction)py_folder_set_read_flags, METH_VARARGS,
+ "S.set_read_flags(flags, [ids]) -> None" },
+ { "get_best_body", (PyCFunction)py_message_get_best_body, METH_NOARGS,
+ "S.get_best_body() -> format" },
+ { "get_default_folder", (PyCFunction)py_get_default_folder, METH_VARARGS,
+ "S.get_default_folder(type) -> id" },
+ { "get_default_public_folder", (PyCFunction)py_get_default_public_folder, METH_VARARGS,
+ "S.get_default_public_folder(type) -> id" },
+ { NULL },
+};
+
+static PyObject *object_get_session(PyObject *_self, void *closure)
+{
+ PyMapiObjectObject *self = (PyMapiObjectObject *)_self;
+ struct mapi_session *session;
+
+ session = mapi_object_get_session(self->object);
+
+ return PyMapiSession_FromMapiSession(session);
+}
+
+static PyObject *object_get_id(PyObject *_self, void *closure)
+{
+ PyMapiObjectObject *self = (PyMapiObjectObject *)_self;
+ mapi_id_t id;
+
+ id = mapi_object_get_id(self->object);
+
+ return PyLong_FromLong(id);
+}
+
+static PyGetSetDef object_getsetters[] = {
+ { "session", object_get_session, NULL, "The MAPI session" },
+ { "id", object_get_id, NULL, "MAPI ID" },
+ { NULL }
+};
+
+PyTypeObject PyMapiObjectType = {
+ PyObject_HEAD_INIT(NULL) 0,
+ .tp_name = "Object",
+ .tp_basicsize = sizeof(PyMapiObjectObject),
+ .tp_methods = object_methods,
+ .tp_getset = object_getsetters,
+ .tp_doc = "MAPI Object",
+ .tp_new = object_create,
+ .tp_dealloc = object_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+};
+
Added: trunk/openchange/pymapi/pymapi.c
===================================================================
--- trunk/openchange/pymapi/pymapi.c (rev 0)
+++ trunk/openchange/pymapi/pymapi.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,105 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2008.
+
+ 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 "pymapi/pymapi.h"
+
+void initmapi(void);
+
+static PyObject *py_get_proptag_value(PyObject *mod, PyObject *args)
+{
+ char *propname;
+ if (!PyArg_ParseTuple(args, "s", &propname))
+ return NULL;
+
+ return PyInt_FromLong(get_proptag_value(propname));
+}
+
+static PyObject *py_get_proptag_name(PyObject *mod, PyObject *args)
+{
+ uint32_t proptag;
+ const char *name;
+ if (!PyArg_ParseTuple(args, "i", &proptag))
+ return NULL;
+
+ name = get_proptag_name(proptag);
+ if (name == NULL)
+ return Py_None;
+ return PyString_FromString(name);
+}
+
+static PyObject *py_get_importance(PyObject *mod, PyObject *args)
+{
+ uint32_t importance;
+ const char *name;
+ if (!PyArg_ParseTuple(args, "i", &importance))
+ return NULL;
+
+ name = get_importance(importance);
+ if (name == NULL)
+ return Py_None;
+ return PyString_FromString(name);
+}
+
+static PyObject *py_get_task_status(PyObject *mod, PyObject *args)
+{
+ uint32_t task_status;
+ const char *name;
+ if (!PyArg_ParseTuple(args, "i", &task_status))
+ return NULL;
+
+ name = get_task_status(task_status);
+ if (name == NULL)
+ return Py_None;
+ return PyString_FromString(name);
+}
+
+static PyMethodDef mapi_methods[] = {
+ { "get_proptag_value", (PyCFunction)py_get_proptag_value, METH_VARARGS, NULL },
+ { "get_proptag_name", (PyCFunction)py_get_proptag_name, METH_VARARGS, NULL },
+ { "get_importance", (PyCFunction)py_get_importance, METH_VARARGS, NULL },
+ { "get_task_status", (PyCFunction)py_get_task_status, METH_VARARGS, NULL },
+ { NULL }
+};
+
+void initmapi(void)
+{
+ PyObject *m;
+
+ if (PyType_Ready(&PyMapiSessionType) < 0)
+ return;
+
+ if (PyType_Ready(&PyMapiObjectType) < 0)
+ return;
+
+ if (PyType_Ready(&PyMapiMsgStoreType) < 0)
+ return;
+
+ m = Py_InitModule3("mapi", mapi_methods, "MAPI/RPC Python bindings");
+ if (m == NULL)
+ return;
+
+ Py_INCREF((PyObject *)&PyMapiSessionType);
+ PyModule_AddObject(m, "Session", (PyObject *)&PyMapiSessionType);
+
+ Py_INCREF((PyObject *)&PyMapiObjectType);
+ PyModule_AddObject(m, "Object", (PyObject *)&PyMapiObjectType);
+
+ Py_INCREF((PyObject *)&PyMapiMsgStoreType);
+ PyModule_AddObject(m, "MessageStore", (PyObject *)&PyMapiMsgStoreType);
+}
Added: trunk/openchange/pymapi/pymapi.h
===================================================================
--- trunk/openchange/pymapi/pymapi.h (rev 0)
+++ trunk/openchange/pymapi/pymapi.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,52 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2008.
+
+ 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 _PYMAPI_H_
+#define _PYMAPI_H_
+
+#include <libmapi/libmapi.h>
+#include <Python.h>
+
+/* mapi.Session */
+PyAPI_DATA(PyTypeObject) PyMapiSessionType;
+PyObject *PyMapiSession_FromMapiSession(struct mapi_session *session);
+
+/* mapi.Object */
+typedef struct {
+ PyObject_HEAD
+ mapi_object_t *object;
+} PyMapiObjectObject;
+
+PyAPI_DATA(PyTypeObject) PyMapiObjectType;
+mapi_object_t *PyMapiObject_GetMapiObject(PyObject *);
+#define PyMapiObject_Check(op) PyObject_TypeCheck(op, &PyMapiObjectType)
+
+/* mapi.MessageStore */
+PyAPI_DATA(PyTypeObject) PyMapiMsgStoreType;
+
+/* Set a MAPISTATUS error as a Python exception */
+#define PyErr_FromMAPISTATUS(err) Py_BuildValue("(i,z)", err, NULL)
+#define PyErr_SetMAPISTATUS(err) PyErr_SetObject(PyExc_RuntimeError, PyErr_FromMAPISTATUS(err))
+#define PyErr_MAPISTATUS_IS_ERR_RAISE(err) \
+ if (err != MAPI_E_SUCCESS) { \
+ PyErr_SetMAPISTATUS(err); \
+ return NULL; \
+ }
+
+#endif
Added: trunk/openchange/pymapi/session.c
===================================================================
--- trunk/openchange/pymapi/session.c (rev 0)
+++ trunk/openchange/pymapi/session.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,190 @@
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2008.
+
+ 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 "pymapi/pymapi.h"
+
+typedef struct {
+ PyObject_HEAD
+ struct mapi_session *session;
+} PyMapiSessionObject;
+
+static PyObject *py_session_create(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ enum MAPISTATUS retval;
+ char *kwnames[] = { "profname", "password", "provider" };
+ char *profname, *password;
+ uint32_t provider = 0;
+ struct mapi_session *session;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|i", kwnames,
+ &profname, &password, &provider))
+ return NULL;
+
+ retval = MapiLogonProvider(&session, profname, password, provider);
+ if (!retval) {
+ PyErr_SetMAPISTATUS(retval);
+ return NULL;
+ }
+ return PyMapiSession_FromMapiSession(session);
+}
+
+PyObject *PyMapiSession_FromMapiSession(struct mapi_session *session)
+{
+ PyMapiSessionObject *ret;
+ ret = PyObject_New(PyMapiSessionObject, &PyMapiSessionType);
+ ret->session = session;
+ return (PyObject *)ret;
+}
+
+static PyObject *py_session_login(PyObject *args, PyObject *kwargs)
+{
+ /* FIXME */
+ return NULL;
+}
+
+static PyObject *py_open_msg_store(PyObject *self, PyObject *args)
+{
+ PyObject *py_mapi_object;
+ PyMapiSessionObject *self_session = (PyMapiSessionObject *)self;
+ mapi_object_t *obj;
+ enum MAPISTATUS retval;
+
+ if (!PyArg_ParseTuple(args, "O", &py_mapi_object))
+ return NULL;
+
+ obj = PyMapiObject_GetMapiObject(py_mapi_object);
+ if (obj == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Expected MAPI Object");
+ return NULL;
+ }
+
+ retval = OpenMsgStore(self_session->session, obj);
+ if (!retval) {
+ PyErr_SetMAPISTATUS(retval);
+ return NULL;
+ }
+
+ return Py_None;
+}
+
+static PyObject *py_open_user_mailbox(PyObject *self, PyObject *args)
+{
+ PyObject *py_mapi_object;
+ PyMapiSessionObject *self_session = (PyMapiSessionObject *)self;
+ mapi_object_t *obj;
+ enum MAPISTATUS retval;
+ char *username;
+
+ if (!PyArg_ParseTuple(args, "sO", &username, &py_mapi_object))
+ return NULL;
+
+ obj = PyMapiObject_GetMapiObject(py_mapi_object);
+ if (obj == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Expected MAPI Object");
+ return NULL;
+ }
+
+ retval = OpenUserMailbox(self_session->session, username, obj);
+ if (!retval) {
+ PyErr_SetMAPISTATUS(retval);
+ return NULL;
+ }
+
+ return Py_None;
+}
+
+static PyObject *py_open_public_folder(PyObject *self, PyObject *args)
+{
+ PyObject *py_mapi_object;
+ PyMapiSessionObject *self_session = (PyMapiSessionObject *)self;
+ mapi_object_t *obj;
+ enum MAPISTATUS retval;
+
+ if (!PyArg_ParseTuple(args, "O", &py_mapi_object))
+ return NULL;
+
+ obj = PyMapiObject_GetMapiObject(py_mapi_object);
+ if (obj == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Expected MAPI Object");
+ return NULL;
+ }
+
+ retval = OpenPublicFolder(self_session->session, obj);
+ if (!retval) {
+ PyErr_SetMAPISTATUS(retval);
+ return NULL;
+ }
+
+ return Py_None;
+}
+
+static PyObject *py_unsubscribe(PyMapiSessionObject *self, PyObject *args)
+{
+ uint32_t ulConnection;
+ enum MAPISTATUS status;
+
+ if (!PyArg_ParseTuple(args, "i", &ulConnection))
+ return NULL;
+
+ status = Unsubscribe(self->session, ulConnection);
+ PyErr_MAPISTATUS_IS_ERR_RAISE(status);
+
+ return Py_None;
+}
+
+static PyMethodDef session_methods[] = {
+ { "login", (PyCFunction) py_session_login, METH_VARARGS|METH_KEYWORDS },
+ { "open_msg_store", (PyCFunction) py_open_msg_store, METH_VARARGS,
+ "S.open_msg_store(object)\n\n"
+ "This function opens the main message store. This allows access to "
+ "the normal user folders."
+ },
+ { "open_user_mailbox", (PyCFunction) py_open_user_mailbox, METH_VARARGS,
+ "S.open_user_mailbox(username, object)\n\n"
+ "Open another users mailbox."
+ },
+ { "open_public_folder", (PyCFunction) py_open_public_folder, METH_VARARGS,
+ "S.open_public_folder(object)\n\n"
+ "This function opens the public folder store. This allows access to "
+ "the public folders."
+ },
+ { "unsubscribe", (PyCFunction) py_unsubscribe, METH_VARARGS,
+ "S.Unsubscribe(int) -> None"
+ },
+ { NULL },
+};
+
+static PyGetSetDef session_getsetters[] = {
+ { "default_profile_path", NULL, NULL },
+ { "profile_name", NULL, NULL },
+ { "message_store", NULL, NULL },
+ { NULL }
+};
+
+PyTypeObject PyMapiSessionType = {
+ PyObject_HEAD_INIT(NULL) 0,
+ .tp_name = "Session",
+ .tp_basicsize = sizeof(PyMapiSessionObject),
+ .tp_methods = session_methods,
+ .tp_getset = session_getsetters,
+ .tp_doc = "MAPI Session",
+ .tp_new = py_session_create,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+};
+
Added: trunk/openchange/python/openchange/__init__.py
===================================================================
--- trunk/openchange/python/openchange/__init__.py (rev 0)
+++ trunk/openchange/python/openchange/__init__.py 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+# OpenChange Python bindings
+# Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2008
+#
+# 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/>.
+#
+
+__docformat__ = 'restructuredText'
+
+import os, sys
+
+def find_samba_python_path():
+ """Find the python path for the Samba python modules
+
+ :return: Python path to Samba python modules, or None if
+ it was already in the path
+ """
+ try:
+ import samba
+ return None # No extra path necessary
+ except ImportError:
+ SAMBA_PREFIXES = ["/usr/local/samba", "/opt/samba"]
+ PYTHON_NAMES = ["python2.3", "python2.4", "python2.5"]
+ for samba_prefix in SAMBA_PREFIXES:
+ for python_name in PYTHON_NAMES:
+ path = os.path.join(samba_prefix, "lib", python_name,
+ "site-packages")
+ if os.path.isdir(os.path.join(path, "samba")):
+ return path
+ raise ImportError("Unable to find the Samba python path")
Added: trunk/openchange/python/openchange/mailbox.py
===================================================================
--- trunk/openchange/python/openchange/mailbox.py (rev 0)
+++ trunk/openchange/python/openchange/mailbox.py 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,307 @@
+#!/usr/bin/python
+
+# OpenChange provisioning
+# Copyright (C) Julien Kerihuel <j.kerihuel at openchange.org> 2009
+# Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2009
+#
+# 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/>.
+#
+
+import os
+import samba
+from samba import Ldb
+import ldb
+import uuid
+
+__docformat__ = 'restructuredText'
+
+
+class NoSuchServer(Exception):
+ """Raised when a server could not be found."""
+
+
+class OpenChangeDB(object):
+ """The OpenChange database.
+ """
+
+ def __init__(self, url):
+ self.url = url
+ self.ldb = Ldb(self.url)
+
+ def reopen(self):
+ self.ldb = Ldb(self.url)
+
+ def setup(self):
+ self.ldb.add_ldif("""
+dn: @OPTIONS
+checkBaseOnSearch: TRUE
+
+dn: @INDEXLIST
+ at IDXATTR: cn
+
+dn: @ATTRIBUTES
+cn: CASE_INSENSITIVE
+dn: CASE_INSENSITIVE
+
+""")
+ self.reopen()
+
+ def add_server(self, ocserverdn, netbiosname, firstorg, firstou):
+ self.ldb.add({"dn": ocserverdn,
+ "objectClass": ["top", "server"],
+ "cn": netbiosname,
+ "GlobalCount": "0x1",
+ "ReplicaID": "0x1"})
+ self.ldb.add({"dn": "CN=%s,%s" % (firstorg, ocserverdn),
+ "objectClass": ["top", "org"],
+ "cn": firstorg})
+ self.ldb.add({"dn": "CN=%s,CN=%s,%s" % (firstou, firstorg, ocserverdn),
+ "objectClass": ["top", "ou"],
+ "cn": firstou})
+
+ def lookup_server(self, cn, attributes=[]):
+ # Step 1. Search Server object
+ filter = "(&(objectClass=server)(cn=%s))" % cn
+ res = self.ldb.search("", scope=ldb.SCOPE_SUBTREE,
+ expression=filter, attrs=attributes)
+ if len(res) != 1:
+ raise NoSuchServer(cn)
+ return res[0]
+
+ def lookup_mailbox_user(self, server, username):
+ """Check if a user already exists in openchange database.
+
+ :param server: Server object name
+ :param username: Username object
+ :return: LDB Object of the user
+ """
+ server_dn = self.lookup_server(server, []).dn
+
+ # Step 2. Search User object
+ filter = "(&(objectClass=mailbox)(cn=%s))" % (username)
+ return self.ldb.search(server_dn, scope=ldb.SCOPE_SUBTREE,
+ expression=filter, attrs=[])
+
+ def user_exists(self, server, username):
+ """Check whether a user exists.
+
+ :param username: Username of the user
+ :param server: Server object name
+ """
+ return len(self.lookup_mailbox_user(server, username)) == 1
+
+ def get_message_attribute(self, server, attribute):
+ """Retrieve attribute value from given message database (server).
+
+ :param server: Server object name
+ """
+ return int(self.lookup_server(server, [attribute])[attribute][0], 16)
+
+ def get_message_ReplicaID(self, server):
+ """Retrieve current mailbox Replica ID for given message database (server).
+
+ :param server: Server object name
+ """
+ return self.get_message_attribute(server, "ReplicaID")
+
+ def get_message_GlobalCount(self, server):
+ """Retrieve current mailbox Global Count for given message database (server).
+
+ :param server: Server object name
+ """
+ return self.get_message_attribute(server, "GlobalCount")
+
+
+ def set_message_GlobalCount(self, server, GlobalCount):
+ """Update current mailbox GlobalCount for given message database (server).
+
+ :param server: Server object name
+ :param index: Mailbox new GlobalCount value
+ """
+ server_dn = self.lookup_server(server, []).dn
+
+ newGlobalCount = """
+dn: %s
+changetype: modify
+replace: GlobalCount
+GlobalCount: 0x%x
+""" % (server_dn, GlobalCount)
+
+ self.ldb.transaction_start()
+ try:
+ self.ldb.modify_ldif(newGlobalCount)
+ finally:
+ self.ldb.transaction_commit()
+
+ def add_mailbox_user(self, basedn, username):
+ """Add a user record in openchange database.
+
+ :param username: Username
+ :return: DN of the created object
+ """
+
+ mailboxGUID = str(uuid.uuid4())
+ replicaID = str(1)
+ replicaGUID = str(uuid.uuid4())
+
+ retdn = "CN=%s,%s" % (username, basedn)
+ self.ldb.add({"dn": retdn,
+ "objectClass": ["mailbox", "container"],
+ "cn": username,
+ "MailboxGUID": mailboxGUID,
+ "ReplicaID": replicaID,
+ "ReplicaGUID": replicaGUID})
+ return retdn
+
+ def add_storage_dir(self, mapistoreURL, username):
+ """Add mapistore storage space for the user
+
+ :param username: Username object
+ :param mapistore: mapistore object
+ """
+
+ mapistore_dir = os.path.join(mapistoreURL, username)
+ if not os.path.isdir(mapistore_dir):
+ os.makedirs(mapistore_dir, mode=0700)
+
+ def add_folder_property(self, folderID, attribute, value):
+ """Add a attribute/value to the record folderID refers to
+
+ :param folderID: the folder identifier where to add attribute/value
+ :param attribute: the ldb attribute
+ :param value: the attribute value
+ """
+
+ # Step 1. Find the folder record
+ res = self.ldb.search("", ldb.SCOPE_SUBTREE, "(PidTagFolderId=%s)" % folderID, ["*"])
+ if len(res) != 1:
+ raise Exception("Invalid search (PidTagFolderId=%s)" % folderID)
+
+ # Step 2. Add attribute/value pair
+ m = ldb.Message()
+ m.dn = ldb.Dn(self.ldb, "%s" % res[0].dn)
+ m[attribute] = ldb.MessageElement([value], ldb.CHANGETYPE_ADD, attribute);
+ self.ldb.modify(m)
+
+ def add_mailbox_root_folder(self, ocfirstorgdn, username,
+ foldername, parentfolder,
+ GlobalCount, ReplicaID,
+ SystemIdx, mapistoreURL):
+ """Add a root folder to the user mailbox
+
+ :param username: Username object
+ :param foldername: Folder name
+ :param GlobalCount: current global counter for message database
+ :param ReplicaID: replica identifier for message database
+ :param SystemIdx: System Index for root folders
+ """
+
+ ocuserdn = "CN=%s,%s" % (username, ocfirstorgdn)
+ FID = gen_mailbox_folder_fid(GlobalCount, ReplicaID)
+
+ # Step 1. If we are handling Mailbox Root
+ if parentfolder == 0:
+ m = ldb.Message()
+ m.dn = ldb.Dn(self.ldb, ocuserdn)
+ m["PidTagFolderId"] = ldb.MessageElement([FID], ldb.CHANGETYPE_ADD, "PidTagFolderId")
+ m["SystemIdx"] = ldb.MessageElement([str(SystemIdx)], ldb.CHANGETYPE_ADD, "SystemIdx")
+ m["mapistore_uri"] = ldb.MessageElement(["sqlite://%s/%s/%s.db" % (mapistoreURL, username, FID)], ldb.CHANGETYPE_ADD, "mapistore_uri")
+ self.ldb.modify(m)
+ return FID
+
+ # Step 2. Lookup parent DN
+ res = self.ldb.search("", ldb.SCOPE_SUBTREE, "(PidTagFolderId=%s)" % parentfolder, ["*"])
+ if len(res) != 1:
+ raise Exception("Invalid search (PidTagFolderId=%s)" % parentfolder)
+
+ # Step 3. Add root folder to correct container
+ self.ldb.add({"dn": "CN=%s,%s" % (FID, res[0].dn),
+ "objectClass": ["systemfolder"],
+ "cn": FID,
+ "PidTagParentFolderId": parentfolder,
+ "PidTagFolderId": FID,
+ "PidTagDisplayName": foldername,
+ "mapistore_uri": "sqlite://%s/%s/%s.db" % (mapistoreURL, username, FID),
+ "FolderType": str(1),
+ "SystemIdx": str(SystemIdx)})
+
+ return FID
+
+ def add_mailbox_special_folder(self, username, parentfolder, ref_fid,
+ foldername, containerclass, GlobalCount, ReplicaID,
+ mapistoreURL):
+ """Add a special folder to the user mailbox
+
+ :param username: Username object
+ :param parent_folder: Folder identifier where record should be added
+ :param ref_fid: Folder Identifier referring special folder
+ :param foldername: Folder name
+ :param containerclass: Folder container class
+ :param GlobalCount: current global counter for message database
+ :param ReplicaID: replica identifier for message database
+ :param mapistoreURL: mapistore default content repository URI
+ """
+
+ FID = gen_mailbox_folder_fid(GlobalCount, ReplicaID)
+
+ # Step 1. Lookup parent DN
+ res = self.ldb.search("", ldb.SCOPE_SUBTREE, "(PidTagFolderId=%s)" % parentfolder, ["*"])
+ if len(res) != 1:
+ raise Exception("Invalid search (PidTagFolderId=%s)" % parentfolder)
+
+ # Step 2. Add special folder to user subtree
+ self.ldb.add({"dn": "CN=%s,%s" % (FID, res[0].dn),
+ "objectClass": ["specialfolder"],
+ "cn": FID,
+ "PidTagFolderId": FID,
+ "PidTagDisplayName": foldername,
+ "PidTagContainerClass": containerclass,
+ "mapistore_uri": "sqlite://%s/%s/%s.db" % (mapistoreURL, username, FID),
+ "PidTagContentCount": str(0),
+ "PidTagContentUnreadCount": str(0),
+ "PidTagSubFolders": str(0),
+ "FolderType": str(1)})
+
+ return FID
+
+ def set_receive_folder(self, username, ocfirstorgdn, fid, messageclass):
+ """Set MessageClass for given folder
+
+ :param username: Username object
+ :param ocfirstorgdn: Base DN
+ :param fid: Folder identifier
+ :param messageclass: Explicit Message Class
+ """
+
+ # Step 1. Search fid DN
+ res = self.ldb.search("", ldb.SCOPE_SUBTREE, "(PidTagFolderId=%s)" % fid, ["*"])
+ if len(res) != 1:
+ raise "Invalid search (PidTagFolderId=%s)" % fid
+
+ m = ldb.Message()
+ m.dn = res[0].dn
+ m["PidTagMessageClass"] = ldb.MessageElement([messageclass], ldb.CHANGETYPE_ADD, "PidTagMessageClass")
+ self.ldb.modify(m)
+
+
+def gen_mailbox_folder_fid(GlobalCount, ReplicaID):
+ """Generates a Folder ID from index.
+
+ :param GlobalCount: Message database global counter
+ :param ReplicaID: Message database replica identifier
+ """
+
+ folder = "0x%.12x%.4x" % (GlobalCount, ReplicaID)
+
+ return folder
Added: trunk/openchange/python/openchange/provision.py
===================================================================
--- trunk/openchange/python/openchange/provision.py (rev 0)
+++ trunk/openchange/python/openchange/provision.py 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,469 @@
+#!/usr/bin/python
+
+# OpenChange provisioning
+# Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2008-2009
+# Copyright (C) Julien Kerihuel <j.kerihuel at openchange.org> 2009
+#
+# 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/>.
+#
+
+from base64 import b64encode
+import os
+import samba
+from openchange import mailbox
+from samba import Ldb
+from samba.samdb import SamDB
+from samba.auth import system_session
+from samba.provision import setup_add_ldif, setup_modify_ldif
+import ldb
+
+__docformat__ = 'restructuredText'
+
+DEFAULTSITE = "Default-First-Site-Name"
+FIRST_ORGANIZATION = "First Organization"
+FIRST_ORGANIZATION_UNIT = "First Organization Unit"
+
+def openchangedb_url(lp):
+ return os.path.join(lp.get("private dir"), "openchange.ldb")
+
+def openchangedb_mapistore_url(lp):
+ return os.path.join(lp.get("private dir"), "mapistore");
+
+class ProvisionNames(object):
+
+ def __init__(self):
+ self.rootdn = None
+ self.domaindn = None
+ self.configdn = None
+ self.schemadn = None
+ self.dnsdomain = None
+ self.netbiosname = None
+ self.domain = None
+ self.hostname = None
+ self.firstorg = None
+ self.firstou = None
+ self.firstorgdn = None
+ # OpenChange dispatcher database specific
+ self.ocfirstorgdn = None
+ self.ocserverdn = None
+
+def guess_names_from_smbconf(lp, firstorg=None, firstou=None):
+ """Guess configuration settings to use from smb.conf.
+
+ :param lp: Loadparm context.
+ :param firstorg: First Organization
+ :param firstou: First Organization Unit
+ """
+
+ netbiosname = lp.get("netbios name")
+ hostname = netbiosname.lower()
+
+ dnsdomain = lp.get("realm")
+ dnsdomain = dnsdomain.lower()
+
+ serverrole = lp.get("server role")
+ if serverrole == "domain controller":
+ domain = lp.get("workgroup")
+ domaindn = "DC=" + dnsdomain.replace(".", ",DC=")
+ else:
+ domain = netbiosname
+ domaindn = "CN=" + netbiosname
+
+ rootdn = domaindn
+ configdn = "CN=Configuration," + rootdn
+ schemadn = "CN=Schema," + configdn
+ sitename = DEFAULTSITE
+
+ names = ProvisionNames()
+ names.rootdn = rootdn
+ names.domaindn = domaindn
+ names.configdn = configdn
+ names.schemadn = schemadn
+ names.dnsdomain = dnsdomain
+ names.domain = domain
+ names.netbiosname = netbiosname
+ names.hostname = hostname
+ names.sitename = sitename
+
+ if firstorg is None:
+ firstorg = FIRST_ORGANIZATION
+
+ if firstou is None:
+ firstou = FIRST_ORGANIZATION_UNIT
+
+ names.firstorg = firstorg
+ names.firstou = firstou
+ names.firstorgdn = "CN=%s,CN=Microsoft Exchange,CN=Services,%s" % (firstorg, configdn)
+ names.serverdn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % (netbiosname, sitename, configdn)
+
+ # OpenChange dispatcher DB names
+ names.ocserverdn = "CN=%s,%s" % (names.netbiosname, names.domaindn)
+ names.ocfirstorg = firstorg
+ names.ocfirstorgdn = "CN=%s,CN=%s,%s" % (firstou, names.ocfirstorg, names.ocserverdn)
+
+ return names
+
+
+def install_schemas(setup_path, names, lp, creds):
+ """Install the OpenChange-specific schemas in the SAM LDAP database.
+
+ :param setup_path: Path to the setup directory.
+ :param names: provision names object.
+ :param lp: Loadparm context
+ :param creds: Credentials Context
+ """
+ session_info = system_session()
+
+ # Step 1. Extending the prefixmap attribute of the schema DN record
+ db = SamDB(url=lp.get("sam database"), session_info=session_info,
+ credentials=creds, lp=lp)
+
+ prefixmap = open(setup_path("AD/prefixMap.txt"), 'r').read()
+
+ db.transaction_start()
+
+ try:
+ print "[+] Step 1: Register Exchange OIDs"
+ setup_modify_ldif(db,
+ setup_path("AD/provision_schema_basedn_modify.ldif"), {
+ "SCHEMADN": names.schemadn,
+ "NETBIOSNAME": names.netbiosname,
+ "DEFAULTSITE": names.sitename,
+ "CONFIGDN": names.configdn,
+ "SERVERDN": names.serverdn,
+ "PREFIXMAP_B64": b64encode(prefixmap)
+ })
+ except:
+ db.transaction_cancel()
+ raise
+
+ db.transaction_commit()
+
+
+ # Step 2. Add new Exchange classes to the schema
+ db = SamDB(url=lp.get("sam database"), session_info=session_info,
+ credentials=creds, lp=lp)
+
+ db.transaction_start()
+
+ try:
+ print "[+] Step 2: Add new Exchange classes and attributes to Samba schema"
+ setup_add_ldif(db, setup_path("AD/oc_provision_schema.ldif"), {
+ "SCHEMADN": names.schemadn
+ })
+ except:
+ db.transaction_cancel()
+ raise
+
+ db.transaction_commit()
+
+ # Step 3. Add ADSC classes to the schema
+ db = SamDB(url=lp.get("sam database"), session_info=session_info,
+ credentials=creds, lp=lp)
+
+ db.transaction_start()
+
+ try:
+ print "[+] Step 3: Add missing ADSC classes to Samba schema"
+ setup_add_ldif(db, setup_path("AD/oc_provision_schema_ADSC.ldif"), {
+ "SCHEMADN": names.schemadn
+ })
+ except:
+ db.transaction_cancel()
+ raise
+
+ db.transaction_commit()
+
+
+ # Step 4. Extend existing classes and attributes
+ db = SamDB(url=lp.get("sam database"), session_info=session_info,
+ credentials=creds, lp=lp)
+
+ db.transaction_start()
+
+ try:
+ print "[+] Step 4: Extend existing Samba classes and attributes"
+ setup_modify_ldif(db, setup_path("AD/oc_provision_schema_modify.ldif"), {
+ "SCHEMADN": names.schemadn
+ })
+ except:
+ db.transaction_cancel()
+ raise
+
+ db.transaction_commit()
+
+
+ # Step 4. Add configuration objects
+ db = SamDB(url=lp.get("sam database"), session_info=system_session(),
+ credentials=creds, lp=lp)
+
+ db.transaction_start()
+
+ try:
+ print "[+] Step 5: Exchange Samba with Exchange configuration objects"
+ setup_add_ldif(db, setup_path("AD/oc_provision_configuration.ldif"), {
+ "FIRSTORG": names.firstorg,
+ "FIRSTORGDN": names.firstorgdn,
+ "CONFIGDN": names.configdn,
+ "SCHEMADN": names.schemadn,
+ "DOMAINDN": names.domaindn,
+ "DOMAIN": names.domain,
+ "DNSDOMAIN": names.dnsdomain,
+ "NETBIOSNAME": names.netbiosname,
+ "HOSTNAME": names.hostname
+ })
+ except:
+ db.transaction_cancel()
+ raise
+
+ db.transaction_commit()
+
+
+def newmailbox(lp, username, firstorg, firstou):
+ names = guess_names_from_smbconf(lp, firstorg, firstou)
+
+ db = mailbox.OpenChangeDB(openchangedb_url(lp))
+
+ # Step 1. Retrieve current FID index
+ GlobalCount = db.get_message_GlobalCount(names.netbiosname)
+ ReplicaID = db.get_message_ReplicaID(names.netbiosname)
+
+ print "[+] Mailbox for '%s'" % (username)
+ print "==================" + "=" * len(username)
+ print "* GlobalCount (0x%x) and ReplicaID (0x%x)" % (GlobalCount, ReplicaID)
+
+ # Step 2. Check if the user already exists
+ assert not db.user_exists(names.netbiosname, username)
+
+ # Step 3. Create a default mapistore content repository for this user
+ db.add_storage_dir(mapistoreURL=openchangedb_mapistore_url(lp), username=username)
+ print "* Mapistore content repository created: %s" % os.path.join(openchangedb_mapistore_url(lp), username)
+
+ # Step 4. Create the user object
+ retdn = db.add_mailbox_user(names.ocfirstorgdn, username=username)
+ print "* User object created: %s" % (retdn)
+
+ # Step 5. Create system mailbox folders for this user
+ print "* Adding System Folders"
+
+ system_folders = ({
+ "Deferred Actions": ({}, 2),
+ "Spooler Queue": ({}, 3),
+ "IPM Subtree": ({
+ "Inbox": ({}, 5),
+ "Outbox": ({}, 6),
+ "Sent Items": ({}, 7),
+ "Deleted Items": ({}, 8),
+ }, 4),
+ "Common Views": ({}, 9),
+ "Schedule": ({}, 10),
+ "Search": ({}, 11),
+ "Views": ({}, 12),
+ "Shortcuts": ({}, 13),
+ }, 1)
+
+ fids = {}
+ def add_folder(parent_fid, path, children, SystemIdx):
+ name = path[-1]
+
+ GlobalCount = db.get_message_GlobalCount(names.netbiosname)
+ ReplicaID = db.get_message_ReplicaID(names.netbiosname)
+
+ fid = db.add_mailbox_root_folder(names.ocfirstorgdn,
+ username=username, foldername=name,
+ parentfolder=parent_fid, GlobalCount=GlobalCount,
+ ReplicaID=ReplicaID, SystemIdx=SystemIdx,
+ mapistoreURL=openchangedb_mapistore_url(lp))
+
+ GlobalCount += 1
+ db.set_message_GlobalCount(names.netbiosname, GlobalCount=GlobalCount)
+
+ fids[path] = fid
+
+ print "\t* %-40s: %s" % (name, fid)
+ for name, grandchildren in children.iteritems():
+ add_folder(fid, path + (name,), grandchildren[0], grandchildren[1])
+
+ add_folder(0, ("Mailbox Root",), system_folders[0], system_folders[1])
+
+ # Step 6. Add special folders
+ print "* Adding Special Folders:"
+ special_folders = [
+ (("Mailbox Root", "IPM Subtree"), "Calendar", "IPF.Appointment", "PidTagIpmAppointmentEntryId"),
+ (("Mailbox Root", "IPM Subtree"), "Contacts", "IPF.Contact", "PidTagIpmContactEntryId"),
+ (("Mailbox Root", "IPM Subtree"), "Journal", "IPF.Journal", "PidTagIpmJournalEntryId"),
+ (("Mailbox Root", "IPM Subtree"), "Notes", "IPF.StickyNote", "PidTagIpmNoteEntryId"),
+ (("Mailbox Root", "IPM Subtree"), "Tasks", "IPF.Task", "PidTagIpmTaskEntryId"),
+ (("Mailbox Root", "IPM Subtree"), "Reminders", "Outlook.Reminder", "PidTagRemindersOnlineEntryId"),
+ (("Mailbox Root", "IPM Subtree"), "Drafts", "IPF.Notes", "PidTagIpmDraftsEntryId")
+ ]
+
+ fid_inbox = fids[("Mailbox Root", "IPM Subtree", "Inbox")]
+ fid_mailbox = fids[("Mailbox Root",)]
+ for path, foldername, containerclass, pidtag in special_folders:
+ GlobalCount = db.get_message_GlobalCount(names.netbiosname)
+ ReplicaID = db.get_message_ReplicaID(names.netbiosname)
+ fid = db.add_mailbox_special_folder(username, fids[path], fid_inbox, foldername,
+ containerclass, GlobalCount, ReplicaID,
+ openchangedb_mapistore_url(lp))
+ db.add_folder_property(fid_inbox, pidtag, fid)
+ db.add_folder_property(fid_mailbox, pidtag, fid)
+ GlobalCount += 1
+ db.set_message_GlobalCount(names.netbiosname, GlobalCount=GlobalCount)
+ print "\t* %-40s: %s (%s)" % (foldername, fid, containerclass)
+
+ # Step 7. Set default receive folders
+ print "* Adding default Receive Folders:"
+ receive_folders = [
+ (("Mailbox Root", "IPM Subtree", "Inbox"), "All"),
+ (("Mailbox Root", "IPM Subtree", "Inbox"), "IPM"),
+ (("Mailbox Root", "IPM Subtree", "Inbox"), "Report.IPM"),
+ (("Mailbox Root", "IPM Subtree",), "IPC")
+ ]
+
+ for path, messageclass in receive_folders:
+ print "\t* %-40s Message Class added to %s" % (messageclass, fids[path])
+ db.set_receive_folder(username, names.ocfirstorgdn, fids[path],
+ messageclass)
+
+ # Step 8. Set additional properties on Inbox
+ print "* Adding additional default properties to Inbox"
+ db.add_folder_property(fid_inbox, "PidTagContentCount", "0")
+ db.add_folder_property(fid_inbox, "PidTagContentUnreadCount", "0")
+ db.add_folder_property(fid_inbox, "PidTagSubFolders", "FALSE")
+ db.add_folder_property(fid_inbox, "PidTagAccess", "63")
+
+ GlobalCount = db.get_message_GlobalCount(names.netbiosname)
+ print "* GlobalCount (0x%x)" % GlobalCount
+
+
+def newuser(lp, creds, username=None):
+ """extend user record with OpenChange settings.
+
+ :param lp: Loadparm context
+ :param creds: Credentials context
+ :param username: Name of user to extend
+ """
+
+ names = guess_names_from_smbconf(lp, None, None)
+
+ db = Ldb(url="users.ldb", session_info=system_session(),
+ credentials=creds, lp=lp)
+
+ user_dn = "CN=%s,CN=Users,%s" % (username, names.domaindn)
+
+ extended_user = """
+dn: %s
+changetype: modify
+add: displayName
+add: auxiliaryClass
+add: mailNickName
+add: homeMDB
+add: legacyExchangeDN
+add: proxyAddresses
+replace: msExchUserAccountControl
+displayName: %s
+auxiliaryClass: msExchBaseClass
+mailNickname: %s
+homeMDB: CN=Mailbox Store (%s),CN=First Storage Group,CN=InformationStore,CN=%s,CN=Servers,CN=First Administrative Group,CN=Administrative Groups,CN=%s,CN=Microsoft Exchange,CN=Services,CN=Configuration,%s
+legacyExchangeDN: /o=%s/ou=First Administrative Group/cn=Recipients/cn=%s
+proxyAddresses: smtp:postmaster@%s
+proxyAddresses: X400:c=US;a= ;p=First Organizati;o=Exchange;s=%s
+proxyAddresses: SMTP:%s@%s
+msExchUserAccountControl: 0
+""" % (user_dn, username, username, names.netbiosname, names.netbiosname, names.firstorg, names.domaindn, names.firstorg, username, names.dnsdomain, username, username, names.dnsdomain)
+ db.modify_ldif(extended_user)
+
+ print "[+] User %s extended and enabled" % username
+
+
+def accountcontrol(lp, creds, username=None, value=0):
+ """enable/disable an OpenChange user account.
+
+ :param lp: Loadparm context
+ :param creds: Credentials context
+ :param username: Name of user to disable
+ :param value: the control value
+ """
+
+ names = guess_names_from_smbconf(lp, None, None)
+
+ db = Ldb(url="users.ldb", session_info=system_session(),
+ credentials=creds, lp=lp)
+
+ user_dn = "CN=%s,CN=Users,%s" % (username, names.domaindn)
+ extended_user = """
+dn: %s
+changetype: modify
+replace: msExchUserAccountControl
+msExchUserAccountControl: %d
+""" % (user_dn, value)
+ db.modify_ldif(extended_user)
+ if value == 2:
+ print "[+] Account %s disabled" % username
+ else:
+ print "[+] Account %s enabled" % username
+
+
+def provision(setup_path, lp, creds, firstorg=None, firstou=None):
+ """Extend Samba4 with OpenChange data.
+
+ :param setup_path: Path to the setup directory
+ :param lp: Loadparm context
+ :param creds: Credentials context
+ :param firstorg: First Organization
+ :param firstou: First Organization Unit
+ """
+ names = guess_names_from_smbconf(lp, firstorg, firstou)
+
+ print "NOTE: This operation can take several minutes"
+
+ # Install OpenChange-specific schemas
+ install_schemas(setup_path, names, lp, creds)
+
+
+def openchangedb_provision(lp, firstorg=None, firstou=None):
+ """Create the OpenChange database.
+
+ :param lp: Loadparm context
+ :param firstorg: First Organization
+ :param firstou: First Organization Unit
+ """
+ names = guess_names_from_smbconf(lp, firstorg, firstou)
+
+ print "Setting up openchange db"
+ openchange_ldb = mailbox.OpenChangeDB(openchangedb_url(lp))
+ openchange_ldb.setup()
+
+ # Add a server object
+ # It is responsible for holding the GlobalCount identifier (48 bytes)
+ # and the Replica identifier
+ openchange_ldb.add_server(names.ocserverdn, names.netbiosname,
+ names.firstorg, names.firstou)
+
+
+def find_setup_dir():
+ """Find the setup directory used by provision."""
+ dirname = os.path.dirname(__file__)
+ if "/site-packages/" in dirname:
+ prefix = dirname[:dirname.index("/site-packages/")]
+ for suffix in ["share/openchange/setup", "share/setup", "share/samba/setup", "setup"]:
+ ret = os.path.join(prefix, suffix)
+ if os.path.isdir(ret):
+ return ret
+ # In source tree
+ ret = os.path.join(dirname, "../../setup")
+ if os.path.isdir(ret):
+ return ret
+ raise Exception("Unable to find setup directory.")
Added: trunk/openchange/python/openchange/tests/test_mailbox.py
===================================================================
--- trunk/openchange/python/openchange/tests/test_mailbox.py (rev 0)
+++ trunk/openchange/python/openchange/tests/test_mailbox.py 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+
+# OpenChange provisioning
+# Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2009
+#
+# 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/>.
+#
+
+from openchange.mailbox import NoSuchServer, OpenChangeDB, gen_mailbox_folder_fid
+
+import os
+import unittest
+
+class OpenChangeDBTests(unittest.TestCase):
+ """Tests for OpenChangeDB."""
+
+ def setUp(self):
+ if os.path.exists("openchange.ldb"):
+ os.unlink("openchange.ldb")
+ self.db = OpenChangeDB("openchange.ldb")
+ self.db.setup()
+
+ def test_user_exists_no_server(self):
+ self.assertRaises(NoSuchServer, self.db.user_exists, "someserver", "foo")
+
+ def test_server_lookup_doesnt_exist(self):
+ self.assertRaises(NoSuchServer, self.db.lookup_server,
+ "nonexistantserver")
+
+ def test_server_lookup(self):
+ self.db.add_server("dc=blaserver", "blaserver", "firstorg", "firstou")
+ self.assertEquals("dc=blaserver", str(self.db.lookup_server("blaserver")['dn']))
+
+ def test_add_mailbox_user(self):
+ self.db.add_server("cn=myserver", "myserver", "firstorg", "firstou")
+ self.db.add_mailbox_user("cn=firstorg,cn=firstou,cn=myserver", "someuser")
+ self.assertTrue(self.db.user_exists("myserver", "someuser"))
+
+ def test_msg_globalcount_initial(self):
+ self.db.add_server("dc=myserver", "myserver", "firstorg", "firstou")
+ self.assertEquals(1, self.db.get_message_GlobalCount("myserver"))
+
+ def test_set_msg_globalcount(self):
+ self.db.add_server("dc=myserver", "myserver", "firstorg", "firstou")
+ self.db.set_message_GlobalCount("myserver", 42)
+ self.assertEquals(42, self.db.get_message_GlobalCount("myserver"))
+
+ def test_msg_replicaid_initial(self):
+ self.db.add_server("dc=myserver", "myserver", "firstorg", "firstou")
+ self.assertEquals(1, self.db.get_message_ReplicaID("myserver"))
+
+
+class MailboxFIDTests(unittest.TestCase):
+
+ def test_simple(self):
+ self.assertEquals("0x00000000109282806", gen_mailbox_folder_fid(4242, 534534))
+
Added: trunk/openchange/python/openchange/tests/test_provision.py
===================================================================
--- trunk/openchange/python/openchange/tests/test_provision.py (rev 0)
+++ trunk/openchange/python/openchange/tests/test_provision.py 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,50 @@
+#!/usr/bin/python
+
+# OpenChange provisioning
+# Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2009
+#
+# 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/>.
+#
+
+from samba import param
+from samba.credentials import Credentials
+from samba.samdb import SamDB
+from samba.tests import TestCaseInTempDir
+from samba.tests.samdb import SamDBTestCase
+from openchange.provision import install_schemas, openchangedb_provision, guess_names_from_smbconf, find_setup_dir
+
+import os
+import unittest
+
+class ExtendedSamDBTestCase(SamDBTestCase):
+
+ def test_install_schemas(self):
+ def setup_path(relpath):
+ return os.path.join(find_setup_dir(), relpath)
+
+ names = guess_names_from_smbconf(self.lp)
+ creds = Credentials()
+ creds.set_anonymous()
+ self.lp.set("sam database", os.path.join(self.tempdir, "samdb.ldb"))
+ install_schemas(setup_path, names, self.lp, creds)
+
+
+class OpenChangeDBProvisionTestCase(TestCaseInTempDir):
+
+ def test_provision(self):
+ lp = param.LoadParm()
+ lp.load_default()
+ lp.set("private dir", self.tempdir)
+ openchangedb_provision(lp)
+ os.unlink(os.path.join(self.tempdir, "openchange.ldb"))
Added: trunk/openchange/script/check_exchange
===================================================================
--- trunk/openchange/script/check_exchange (rev 0)
+++ trunk/openchange/script/check_exchange 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,191 @@
+#!/usr/bin/perl
+#
+# Nagois Plug-In to check Exchange Server
+#
+# Bill Edmunds, Academic Services, University of Exeter
+# 25th March, 2008
+#
+
+use strict;
+use lib "nagios/plugins";
+use utils qw($TIMEOUT %ERRORS &print_revision &support);
+use vars qw($PROGNAME);
+use Time::HiRes qw(gettimeofday tv_interval);
+
+# Variables
+$PROGNAME = 'check_exchange';
+my $SUCCESS = 'MAPI_E_SUCCESS';
+my $MYTIME = 10;
+my $version = "1.0";
+my $verbose = 0;
+my $pdb = '/usr/lib/nagios/plugins/check_exchange.ldb';
+my $cmd = 'openchangeclient';
+my $author = "Bill Edmunds, Academic Services, University of Exeter";
+my $email = 'W.Edmunds at exeter.ac.uk';
+my ($host, $stime, $etime, $warning, $critical);
+our($opt_h, $opt_V, $opt_v, $opt_H, $opt_d, $opt_w, $opt_c);
+my $status = 'UNKNOWN';
+
+$ENV{'BASH_ENV'}='';
+$ENV{'ENV'}='';
+$ENV{'PATH'}='/usr/local/samba/bin';
+$ENV{'LC_ALL'}='C';
+
+# Options
+use Getopt::Long;
+Getopt::Long::Configure('bundling');
+GetOptions(
+ "V" => \$opt_V, "version" => \$opt_V,
+ "h" => \$opt_h, "help" => \$opt_h,
+ "v+" => \$opt_v, "verbose+" => \$opt_v,
+ "H=s" => \$opt_H, "hostname=s" => \$opt_H,
+ "d=s" => \$opt_d, "database=s" => \$opt_d,
+ "w=f" => \$opt_w, "warning=f" => \$opt_w,
+ "c=f" => \$opt_c, "critical=f" => \$opt_c,
+);
+
+# -h means help
+if ($opt_h) {
+ print_help();
+ exit $ERRORS{'OK'};
+}
+
+# -V means version
+if ($opt_V) {
+ print_revision($PROGNAME, "\$Revision: $version \$ ");
+ exit $ERRORS{'OK'};
+}
+
+# -v means verbose
+if ($opt_v) {
+ $verbose = 1;
+ print "$PROGNAME: Check access to MS Exchange via Openchange client\n\n";
+}
+
+# -H means host/profile name
+$opt_H || plugin_error("No hostname specified");
+
+if (! utils::is_hostname($opt_H)){
+ plugin_error("$opt_H is not a valid host name");
+} else {
+ $host = $opt_H;
+}
+
+# -d means profile database name
+if (defined($opt_d) && -r $opt_d) {
+ $pdb = $opt_d;
+} else {
+ plugin_error("No profile database available") if ! -r $pdb;
+}
+
+$verbose && print "$PROGNAME: Profile database is $pdb\n\n";
+
+# -c means critical threshold
+if ($opt_c && $opt_c =~ /^\d+\.*\d*$/ && $opt_c < $TIMEOUT) {
+ $critical = $opt_c;
+} else {
+ plugin_error("Specify critical threshold 0.1 - $TIMEOUT");
+}
+
+# -w means warning threshold
+if ($opt_w =~ /^\d+\.*\d*/ && $opt_w < $critical) {
+ $warning = $opt_w;
+} else {
+ plugin_error("Specify warning threshold 0.0 - $critical");
+}
+
+# Timeout
+if (defined($TIMEOUT)) {
+ $verbose && print "$PROGNAME: Alarm set at $TIMEOUT\n\n";
+ alarm($TIMEOUT);
+} else {
+ $verbose && print "$PROGNAME: Alarm set at $MYTIME\n\n";
+ alarm($MYTIME);
+}
+
+$stime = [gettimeofday];
+$verbose && print "$PROGNAME: Running $cmd -f $pdb -p $host -F\n\n";
+open(CMD, "$cmd -f $pdb -p $host -F |") || plugin_error("Can't run openchangeclient");
+while(<CMD>) {
+ if ($verbose > 1) { print "$PROGNAME: $_"; }
+ $status = 'OK' if /$SUCCESS/io;
+ last if $status eq 'OK';
+}
+$etime = tv_interval($stime);
+
+$status = 'CRITICAL' if ($etime >= $critical || $status eq 'UNKNOWN');
+$status = 'WARNING' if ($etime >= $warning && $status ne 'CRITICAL');
+
+$verbose && print "$PROGNAME: status $status\n\n";
+
+#print "Elapsed time: $etime|time=$etime\n";
+# update to include measurement unit for Centreon graphs
+printf "Elapsed time: %s|time=%ss\n",$etime,$etime;
+
+exit $ERRORS{"$status"};
+
+# print_usage: Print usage information
+sub print_usage {
+ print <<EndOfUsage
+Usage:
+ $PROGNAME -H HOSTNAME [-d DATABASE] -w WTIME -c CTIME [-v]
+ $PROGNAME [-h | --help]
+ $PROGNAME [-V | --version]
+EndOfUsage
+}
+
+# print_help: Print help information
+sub print_help {
+ print_revision($PROGNAME, "\$Revision: $version \$ ");
+ print <<EndOfHelp;
+
+Author: $author
+$email
+License: GNU General Public License
+
+$PROGNAME: Check access to MS Exchange via Openchange client
+
+EndOfHelp
+ print_usage();
+ print <<EndOfHelp;
+
+Options:
+ -h, --help
+ Print detailed help screen.
+ -V, --version
+ Print version information.
+ -v, --verbose
+ Print verbose information.
+ -H HOSTNAME, --hostname=HOSTNAME
+ Use HOSTNAME as the MS Exchange host (Note: this is actually the
+ profile name within the Openchange profile database. The associated
+ host information is stored against the profile information).
+ -d DATABASE, --database=DATABASE
+ Use DATABASE as the profile database (Note: the profile name
+ should match the HOSTNAME above).
+ -w WTIME, --warning=WTIME
+ Exit with WARNING status if time exceeds WTIME.
+ -c CTIME, --critical=CTIME
+ Exit with CRITICAL status if time exceeds CTIME.
+
+Profile database:
+ Location currently set to:
+ $pdb
+
+Created using:
+ mapiprofile -f <DATABASE> -P <HOSTNAME> -u <USERNAME> -p <PASSWORD> -M LOCALHOST
+ -D <DOMAIN> -I <IPADDRESS> -c
+
+Note that HOSTNAME is strictly the profile name, and the host connection is really derived
+from the IPADDRESS.
+
+The author wishes to offer thanks to the OpenChange team at: openchange.org
+EndOfHelp
+}
+
+sub plugin_error {
+ my $msg = $_[0];
+ print STDERR "$PROGNAME: $msg\n";
+ print_usage();
+ exit $ERRORS{'UNKNOWN'};
+}
Property changes on: trunk/openchange/script/check_exchange
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/script/installman.sh
===================================================================
--- trunk/openchange/script/installman.sh (rev 0)
+++ trunk/openchange/script/installman.sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+MANDIR=$1
+shift 1
+MANPAGES=$*
+
+for I in $MANPAGES
+do
+ SECTION=`echo $I | grep -o '.$'`
+ DIR="$MANDIR/man$SECTION"
+ if [ ! -d "$DIR" ]
+ then
+ mkdir -p "$DIR"
+ fi
+
+ BASE=`basename $I`
+
+ echo "Installing manpage \"$BASE\" in $DIR"
+ cp $I $DIR
+done
+
+cat << EOF
+======================================================================
+The man pages have been installed. You may uninstall them using the command
+the command "make uninstallman" or make "uninstall" to uninstall binaries,
+man pages and shell scripts.
+======================================================================
+EOF
+
+exit 0
Property changes on: trunk/openchange/script/installman.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/script/installoc.sh
===================================================================
--- trunk/openchange/script/installoc.sh (rev 0)
+++ trunk/openchange/script/installoc.sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,18 @@
+#!/bin/sh
+# install OpenChange miscellaneous files
+
+SRCDIR="$1"
+JSDIR="$2"
+SETUPDIR="$3"
+
+cd $SRCDIR || exit 1
+
+echo "Installing OpenChange js libs.."
+cp libmapi/setup/scripting/libjs/*.js $JSDIR || exit 1
+echo "Done.."
+
+echo "Installing OpenChange setup templates.."
+cp libmapi/setup/*.ldif $SETUPDIR || exit 1
+echo "All Ok"
+
+exit 0
Property changes on: trunk/openchange/script/installoc.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/script/installsamba4.sh
===================================================================
--- trunk/openchange/script/installsamba4.sh (rev 0)
+++ trunk/openchange/script/installsamba4.sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,400 @@
+#!/bin/sh
+
+#
+# VARS
+#
+. `dirname $0`/samba4_ver.sh
+
+if which gmake 2>/dev/null; then
+ MAKE=gmake
+else
+ MAKE=make
+fi
+
+/usr/bin/env -i PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/samba/lib/pkgconfig
+
+RUNDIR=`dirname $0`
+HOST_OS=`$RUNDIR/../config.guess`
+
+#
+# Error check
+#
+error_check() {
+ error=$1
+ step=$2
+
+ if [ $error -ne 0 ]; then
+ echo "Error in $2 (error code $1)"
+ exit 1
+ fi
+}
+
+cleanup_talloc() {
+ # cleanup existing talloc installation
+ if test -f samba4/lib/talloc/Makefile; then
+ echo "Step0: cleaning up talloc directory"
+ OLD_PWD=$PWD
+ cd samba4/lib/talloc
+ make realdistclean
+ cd $OLD_PWD
+ fi
+}
+
+cleanup_tdb() {
+ # cleanup existing tdb installation
+ if test -f samba/lib/tdb/Makefile; then
+ echo "Step0: cleaning up tdb directory"
+ OLD_PWD=$PWD
+ cd samba4/lib/tdb
+ make realdistclean
+ cd $OLD_PWD
+ fi
+}
+
+delete_install() {
+
+ # cleanup existing existing samba4 installation
+ if test -d /usr/local/samba; then
+ echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+ echo "A previous samba4 installation has been detected"
+ echo "It is highly recommended to delete it prior compiling Samba4"
+ echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+ echo ""
+ echo -n "Proceed? [Yn]: "
+ read answer
+ case "$answer" in
+ Y|y|yes)
+ echo "Step0: Removing previous samba4 installation"
+ sudo rm -rf /usr/local/samba
+ ;;
+ N|n|no)
+ echo "Step0: Keep previous samba4 installation"
+ ;;
+ esac
+ fi
+
+ cleanup_talloc
+ cleanup_tdb
+}
+
+#
+# Checkout Samba4
+#
+checkout() {
+ OLD_PWD=$PWD
+
+ GITPATH=`whereis -b git`
+
+ if test x"$GITPATH" = x"git:"; then
+ echo "git was not found in your path!"
+ echo "Please install git"
+ exit 1
+ fi
+
+ echo "Step1: Fetching Samba4 latest GIT revision"
+ git clone git://git.samba.org/samba.git samba4
+ error_check $? "Step1"
+
+ echo "Step2: Creating openchange local copy"
+ cd samba4
+ git checkout -b openchange origin/master
+ error_check $? "Step2"
+
+ echo "Step3: Revert to commit $SAMBA4_GIT_REV"
+ git reset --hard $SAMBA4_GIT_REV
+ error_check $? "Step3"
+
+ cd $OLD_PWD
+ return $?
+}
+
+#
+# Download Samba4 release
+#
+download() {
+ OLD_PWD=$PWD
+
+ WGETPATH=`whereis -b wget`
+ TARPATH=`whereis -b tar`
+
+ if test x"$WGETPATH" = x"wget:"; then
+ echo "wget was not found in your path!"
+ echo "Please install wget"
+ exit 1
+ fi
+
+ if test x"$TARPATH" = x"tar:"; then
+ echo "tar was not found in your path!"
+ echo "Please install tar"
+ exit 1
+ fi
+
+ echo "Step0: Checking for previous samba4 directory"
+ if test -d samba4; then
+ echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+ echo "A previous samba4 directory has been detected in current folder."
+ echo "Should we delete the existing samba4 directory?"
+ echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+ echo ""
+ echo -n "Proceed? [Yn]: "
+ read answer
+ case "$answer" in
+ Y|y|yes)
+ echo "Step0: removing previous samba4 directory"
+ sudo rm -rf samba4
+ ;;
+ N|n|no)
+ echo "Step0: Keep existing directory"
+ return
+ ;;
+ esac
+ fi
+
+ echo "Step2: Fetching samba-$SAMBA4_RELEASE tarball"
+ if ! test -e samba-$SAMBA4_RELEASE.tar.gz; then
+ rm -rf samba-$SAMBA4_RELEASE.tar.gz
+ wget http://us1.samba.org/samba/ftp/samba4/samba-$SAMBA4_RELEASE.tar.gz
+ error_check $? "Step1"
+ fi
+
+ echo "Step3: Extracting $SAMBA4_RELEASE"
+ tar xzvf samba-$SAMBA4_RELEASE.tar.gz
+ error_check $? "Step2"
+ mv samba-$SAMBA4_RELEASE samba4
+
+ cd $OLD_PWD
+ return $?
+}
+
+#
+# Apply patches to samba4
+#
+patch() {
+ case "$HOST_OS" in
+ *freebsd*)
+
+ echo "[+] Patching tevent for FreeBSD"
+ OLD_PWD=$PWD
+ cd samba4/lib/tevent
+ sed 's/\$(PYTHON_CONFIG) --libs/\$(PYTHON_CONFIG) --ldflags/g' tevent.mk > tevent.mk2
+ mv tevent.mk2 tevent.mk
+ cd $OLD_PWD
+
+ echo "[+] Patching heimdal for FreeBSD"
+ OLD_PWD=$PWD
+ cd samba4/source4/heimdal/lib/roken
+ sed "s/#if defined(HAVE_OPENPTY) || defined(__linux) || defined(__osf__)/#if defined(HAVE_OPENPTY) || defined(__linux) || defined(__osf__) || defined(__FreeBSD__)/g" rkpty.c > rkpty2.c
+ mv rkpty2.c rkpty.c
+ sed -e "54i\\
+#if defined(__FreeBSD__)\\
+#include <sys/ioctl.h>\\
+#include <termios.h>\\
+#include <libutil.h>\\
+#endif" rkpty.c > rkpty2.c
+ mv rkpty2.c rkpty.c
+ cd $OLD_PWD
+ ;;
+ esac
+
+ return $?
+}
+
+#
+# Compile and Install samba4 packages:
+# talloc, tdb
+#
+packages() {
+ OLD_PWD=$PWD
+
+ delete_install
+
+ echo "Step1: Installing talloc library"
+ cd samba4/lib/talloc
+ error_check $? "Step1"
+
+ ./autogen.sh
+ error_check $? "Step1"
+
+ ./configure --prefix=/usr/local/samba
+ error_check $? "Step1"
+
+ make
+ error_check $? "Step1"
+
+ sudo make install
+ error_check $? "Step1"
+
+ make realdistclean
+ error_check $? "Step1"
+
+ cd $OLD_PWD
+
+ echo "Step2: Installing tdb library"
+
+ cd samba4/lib/tdb
+ error_check $? "Step2"
+
+ ./autogen.sh
+ error_check $? "Step2"
+
+ ./configure --prefix=/usr/local/samba
+ error_check $? "Step2"
+
+ make
+ error_check $? "Step2"
+
+ sudo make install
+ error_check $? "Step2"
+
+ make realdistclean
+ error_check $? "Step2"
+
+ cd $OLD_PWD
+
+ echo "Step3: Installing tevent library"
+
+ cd samba4/lib/tevent
+ error_check $? "Step3"
+
+ ./autogen.sh
+ error_check $? "Step3"
+
+ ./configure --prefix=/usr/local/samba
+ error_check $? "Step3"
+
+ make
+ error_check $? "Step3"
+
+ sudo make install
+ error_check $? "Step3"
+
+ make realdistclean
+ error_check $? "Step3"
+
+ cd $OLD_PWD
+}
+
+#
+# Compile Samba4
+#
+compile() {
+
+ OLD_PWD=$PWD
+
+ # Cleanup tdb and talloc directories
+ cleanup_talloc
+ cleanup_tdb
+
+ echo "Step1: Preparing Samba4 system"
+ cd samba4/source4
+ error_check $? "Step1"
+
+ ./autogen.sh
+ error_check $? "Step1"
+
+ ./configure.developer --enable-debug
+ error_check $? "Step1"
+
+ echo "Step2: Compile Samba4 (IDL)"
+ $MAKE idl_full
+
+ echo "Step3: Compile Samba4 (Source)"
+ $MAKE
+ error_check $? "Step3"
+
+ cd $OLD_PWD
+}
+
+#
+# Post install operations
+#
+post_install() {
+ case "$HOST_OS" in
+ *freebsd*)
+ OLD_PWD=$PWD
+ cd samba4/pidl
+ sudo $MAKE install
+ error_check $? "Step 1"
+ cd $OLD_PWD
+ echo "[+] Add comparison_fn_t support to ndr.h header file"
+ OLD_PWD=$PWD
+ cd /usr/local/samba/include
+ sudo sed -e "34i\\
+#if defined(__FreeBSD__)\\
+# ifndef HAVE_COMPARISON_FN_T\\
+typedef int (*comparison_fn_t)(const void *, const void *);\\
+# endif\\
+#endif" ndr.h > /tmp/ndr.h
+ sudo mv /tmp/ndr.h ndr.h
+ cd $OLD_PWD
+ ;;
+ esac
+}
+
+#
+# Install Samba4
+#
+install() {
+
+ OLD_PWD=$PWD
+
+ echo "Step1: Installing Samba"
+ echo "===> we are in $PWD"
+ cd samba4/source4
+ error_check $? "Step1"
+
+ sudo $MAKE install
+ error_check $? "Step1"
+
+ cd $OLD_PWD
+}
+
+
+#
+# main program
+#
+case $1 in
+ checkout)
+ checkout
+ ;;
+ download)
+ download
+ ;;
+ patch)
+ patch
+ ;;
+ packages)
+ packages
+ ;;
+ compile)
+ compile
+ ;;
+ install)
+ install
+ ;;
+ post_install)
+ post_install
+ ;;
+ git-all)
+ checkout
+ patch
+ packages
+ compile
+ install
+ post_install
+ ;;
+ all)
+ download
+ patch
+ packages
+ compile
+ install
+ post_install
+ ;;
+ *)
+ echo $"Usage: $0 {checkout|patch|packages|compile|install|post_install|git-all}"
+ echo $"Usage: $0 {download|patch|packages|compile|install|post_install|all}"
+ ;;
+esac
+
+exit 0
Property changes on: trunk/openchange/script/installsamba4.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/script/mapi_object_init.prop
===================================================================
--- trunk/openchange/script/mapi_object_init.prop (rev 0)
+++ trunk/openchange/script/mapi_object_init.prop 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,31 @@
+void
+uno_check(void)
+{ /* warning, named args to select() are currently not supported */
+
+ if (select("mapi_object_init", FCALL, NONE)) /* unmarked symbols of type function call */
+ { if (select("", USE, NONE)) /* unmarked symbols USEd in those stmnts */
+ { if (match(1, DEF, NONE)) /* are there matching symbols with mark 1? */
+ error("mapi_object_init follows mapi_object_init");
+ else
+ mark(1); /* mark 1 */
+ }
+ }
+
+ if (select("mapi_object_release", FCALL, NONE))
+ { if (select("", USE, NONE))
+ { if (match(1, USE, NONE))
+ unmark(); /* remove mark */
+ else
+ error("mapi_object_release without mapi_object_init");
+ } else
+ error("no argument to mapi_object_release");
+ }
+
+ if (path_ends())
+ { if (marked(1, ANY, NONE))
+ { if (known_zero())
+ no_error();
+ else
+ error("mapi_object_init without mapi_object_release");
+ } }
+}
Added: trunk/openchange/script/mkproto.pl
===================================================================
--- trunk/openchange/script/mkproto.pl (rev 0)
+++ trunk/openchange/script/mkproto.pl 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,287 @@
+#!/usr/bin/perl
+# Simple script for generating prototypes for C functions
+# Written by Jelmer Vernooij
+# based on the original mkproto.sh by Andrew Tridgell
+
+use strict;
+
+# don't use warnings module as it is not portable enough
+# use warnings;
+
+use Getopt::Long;
+
+#####################################################################
+# read a file into a string
+
+my $public_file = undef;
+my $private_file = undef;
+my $public_define = undef;
+my $private_define = undef;
+my $_public = "";
+my $_private = "";
+my $public_data = \$_public;
+my $private_data = \$_private;
+
+sub public($)
+{
+ my ($d) = @_;
+ $$public_data .= $d;
+}
+
+sub private($)
+{
+ my ($d) = @_;
+ $$private_data .= $d;
+}
+
+sub usage()
+{
+ print "Usage: mkproto.pl [options] [c files]\n";
+ print "OPTIONS:\n";
+ print " --public=FILE Write prototypes for public functions to FILE\n";
+ print " --private=FILE Write prototypes for private functions to FILE\n";
+ print " --define=DEF Use DEF to check whether header was already included\n";
+ print " --public-define=DEF Same as --define, but just for public header\n";
+ print " --private-define=DEF Same as --define, but just for private header\n";
+ print " --help Print this help message\n\n";
+ exit 0;
+}
+
+GetOptions(
+ 'public=s' => sub { my ($f,$v) = @_; $public_file = $v; },
+ 'private=s' => sub { my ($f,$v) = @_; $private_file = $v; },
+ 'define=s' => sub {
+ my ($f,$v) = @_;
+ $public_define = $v;
+ $private_define = "$v\_PRIVATE";
+ },
+ 'public-define=s' => \$public_define,
+ 'private-define=s' => \$private_define,
+ 'help' => \&usage
+) or exit(1);
+
+if (not defined($public_define) and defined($public_file)) {
+ $public_define = ".." . uc($public_file) . "__";
+ $public_define =~ tr{./}{__};
+} elsif (not defined($public_define)) {
+ $public_define = '_PROTO_H_';
+}
+
+if (not defined($private_define) and defined($private_file)) {
+ $private_define = "__" . uc($private_file) . "__";
+ $private_define =~ tr{./}{__};
+} elsif (not defined($public_define)) {
+ $public_define = '_PROTO_H_';
+}
+
+if ((defined($private_file) and defined($public_file) and ($private_file eq $public_file)) or
+ (not defined($private_file) and not defined($public_file))) {
+ $private_data = $public_data;
+}
+
+sub file_load($)
+{
+ my($filename) = shift;
+ local(*INPUTFILE);
+ open(INPUTFILE, $filename) || return undef;
+ my($saved_delim) = $/;
+ undef $/;
+ my($data) = <INPUTFILE>;
+ close(INPUTFILE);
+ $/ = $saved_delim;
+ return $data;
+}
+
+sub print_header($$)
+{
+ my ($file, $header_name) = @_;
+ $file->("#ifndef $header_name\n");
+ $file->("#define $header_name\n\n");
+ $file->("#undef _PRINTF_ATTRIBUTE\n");
+ $file->("#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2)\n\n");
+ $file->("#ifndef __BEGIN_DECLS\n");
+ $file->("#ifdef __cplusplus\n");
+ $file->("#define __BEGIN_DECLS extern \"C\" {\n");
+ $file->("#define __END_DECLS }\n");
+ $file->("#else\n");
+ $file->("#define __BEGIN_DECLS\n");
+ $file->("#define __END_DECLS\n");
+ $file->("#endif\n");
+ $file->("#endif\n");
+ $file->("\n__BEGIN_DECLS\n\n");
+ $file->("/* This file was automatically generated by mkproto.pl. DO NOT EDIT */\n\n");
+}
+
+sub print_footer($$)
+{
+ my ($file, $header_name) = @_;
+ $file->("\n__END_DECLS\n\n");
+ $file->("#undef _PRINTF_ATTRIBUTE\n");
+ $file->("#define _PRINTF_ATTRIBUTE(a1, a2)\n");
+ $file->("\n#endif /* $header_name */\n\n");
+}
+
+sub handle_loadparm($$)
+{
+ my ($file,$line) = @_;
+
+ if ($line =~ /^_PUBLIC_ FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|bool|CHAR|INTEGER|LIST)\((\w+),.*\)/o) {
+ my $scope = $1;
+ my $type = $2;
+ my $name = $3;
+
+ my %tmap = (
+ "bool" => "bool ",
+ "CONST_STRING" => "const char *",
+ "STRING" => "const char *",
+ "INTEGER" => "int ",
+ "CHAR" => "char ",
+ "LIST" => "const char **",
+ );
+
+ my %smap = (
+ "GLOBAL" => "void",
+ "LOCAL" => "int "
+ );
+
+ $file->("$tmap{$type}$name($smap{$scope});\n");
+ }
+}
+
+sub delete_arguments($)
+{
+ my ($proto) = @_;
+
+ chomp($proto);
+
+ # If function with void argument do not process it
+ return $proto if ($proto =~ /\(void\)/);
+
+ # Remove the argument name
+ $proto =~ s/([\w],[\s])*([\*]*)(\w)*([\,\)])/$1$2$4/g;
+
+ # Remove extra space between type and sep
+ $proto =~ s/([\w]+)([\s]+)([\,\)])/$1$3/g;
+
+ # Remove any spaces between , and the next char
+ $proto =~ s/([\,])(^[\w]+)([\w\)]+)/$1 $3/g;
+
+ # Remove tabulations
+ $proto =~ s/[\s]{2,}//g;
+
+ # Remove \n
+ $proto =~ s/[\n]+/ /g;
+
+ return $proto;
+}
+
+sub process_file($$$)
+{
+ my ($public_file, $private_file, $filename) = @_;
+
+ $filename =~ s/\.o$/\.c/g;
+
+ open(FH, "< $filename") || die "Failed to open $filename";
+
+ $private_file->("\n/* The following definitions come from $filename */\n\n");
+
+ while (my $line = <FH>) {
+ my $target = \&private;
+ my $is_public = 0;
+
+ # these are ordered for maximum speed
+ next if ($line =~ /^\s/);
+
+ next unless ($line =~ /\(/);
+
+ next if ($line =~ /^\/|[;]/);
+
+ if ($line =~ /^_PUBLIC_ FN_/) {
+ handle_loadparm($public_file, $line);
+ next;
+ }
+
+ if ($line =~ /^_PUBLIC_[\t ]/) {
+ $target = \&public;
+ $is_public = 1;
+ }
+
+ next unless ( $is_public || $line =~ /
+ ^void|^bool|^int|^struct|^char|^const|^\w+_[tT]\s|^uint|^unsigned|^long|
+ ^NTSTATUS|^ADS_STATUS|^enum\s.*\(|^DATA_BLOB|^WERROR|^XFILE|^FILE|^DIR|
+ ^double|^TDB_CONTEXT|^TDB_DATA|^TALLOC_CTX|^NTTIME|^FN_|^init_module|
+ ^GtkWidget|^GType|^smb_ucs2_t
+ /xo);
+
+ next if ($line =~ /^int\s*main/);
+
+ if ( $line =~ /\(.*\)\s*$/o ) {
+ chomp $line;
+ $line = delete_arguments($line);
+ $target->("$line;\n");
+ next;
+ }
+
+ $line = delete_arguments($line);
+ $target->($line);
+
+ while ($line = <FH>) {
+ if ($line =~ /\)\s*$/o) {
+ chomp $line;
+ $line = delete_arguments($line);
+ $target->("$line;\n");
+ last;
+ }
+ $target->($line);
+ }
+ }
+
+ close(FH);
+}
+
+print_header(\&public, $public_define);
+if ($public_file ne $private_file) {
+ print_header(\&private, $private_define);
+
+ private("/* this file contains prototypes for functions that " .
+ "are private \n * to this subsystem or library. These functions " .
+ "should not be \n * used outside this particular subsystem! */\n\n");
+
+ public("/* this file contains prototypes for functions that " .
+ "are part of \n * the public API of this subsystem or library. */\n\n");
+
+}
+
+public("#ifndef _PUBLIC_\n#define _PUBLIC_\n#endif\n\n");
+
+process_file(\&public, \&private, $_) foreach (@ARGV);
+print_footer(\&public, $public_define);
+if ($public_file ne $private_file) {
+ print_footer(\&private, $private_define);
+}
+
+if (not defined($public_file)) {
+ print STDOUT $$public_data;
+}
+
+if (not defined($private_file) and defined($public_file)) {
+ print STDOUT $$private_data;
+}
+
+my $old_public_data = file_load($public_file);
+my $old_private_data = file_load($private_file);
+
+if (not defined($old_public_data) or ($old_public_data ne $$public_data))
+{
+ open(PUBLIC, ">$public_file") or die("Can't open `$public_file': $!");
+ print PUBLIC "$$public_data";
+ close(PUBLIC);
+}
+
+if (($public_file ne $private_file) and (
+ not defined($old_private_data) or ($old_private_data ne $$private_data))) {
+
+ open(PRIVATE, ">$private_file") or die("Can't open `$private_file': $!");
+ print PRIVATE "$$private_data";
+ close(PRIVATE);
+}
Property changes on: trunk/openchange/script/mkproto.pl
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/script/mkrelease.sh
===================================================================
--- trunk/openchange/script/mkrelease.sh (rev 0)
+++ trunk/openchange/script/mkrelease.sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+#
+# ./script/mkrelease.sh VERSION NICKNAME FIRST_REVISION
+# ./script/mkrelease.sh 0.7 PHASER 308
+#
+
+TMPDIR=`mktemp libmapi-XXXXX`
+rm $TMPDIR || exit 1
+svn export . $TMPDIR || exit 1
+svn log -r$3:HEAD > $TMPDIR/CHANGELOG || exit 1
+
+( cd $TMPDIR/
+ ./autogen.sh || exit 1
+ ./configure || exit 1
+ make || exit 1
+ sed -i "s/^OPENCHANGE_VERSION_IS_SVN_SNAPSHOT=yes/OPENCHANGE_VERSION_IS_SVN_SNAPSHOT=no/g" VERSION || exit 1
+ ./autogen.sh || exit 1
+ ./configure || exit 1
+ make doxygen || exit 1
+ make distclean || exit 1
+ rm .bzrignore
+) || exit 1
+
+VERSION=$1-$2
+mv $TMPDIR libmapi-$VERSION || exit 1
+tar -cf libmapi-$VERSION.tar libmapi-$VERSION || exit 1
+echo "Now run: "
+echo "gpg --detach-sign --armor libmapi-$VERSION.tar"
+echo "gzip libmapi-$VERSION.tar"
+echo "And then upload "
+echo "libmapi-$VERSION.tar.gz libmapi-$VERSION.tar.asc"
Property changes on: trunk/openchange/script/mkrelease.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/script/mkversion.sh
===================================================================
--- trunk/openchange/script/mkversion.sh (rev 0)
+++ trunk/openchange/script/mkversion.sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+VERSION_FILE=$1
+OUTPUT_FILE=$2
+
+if test -z "$VERSION_FILE";then
+ $VERSION_FILE="VERSION"
+fi
+
+if test -z "$OUTPUT_FILE";then
+ $OUTPUT_FILE="libmapi/version.h"
+fi
+
+OPENCHANGE_VERSION_STRING=$3
+SOURCE_DIR=$4
+
+OPENCHANGE_MAJOR_RELEASE=`echo ${OPENCHANGE_VERSION_STRING} | cut -d. -f1`
+OPENCHANGE_MINOR_RELEASE=`echo ${OPENCHANGE_VERSION_STRING} | cut -d. -f2`
+
+OPENCHANGE_VERSION_IS_SVN_SNAPSHOT=`sed -n 's/^OPENCHANGE_VERSION_IS_SVN_SNAPSHOT=//p' $SOURCE_DIR$VERSION_FILE`
+OPENCHANGE_VERSION_RELEASE_NICKNAME=`sed -n 's/^OPENCHANGE_VERSION_RELEASE_NICKNAME=//p' $SOURCE_DIR$VERSION_FILE`
+
+
+echo "/* Autogenerated by script/mkversion.h */" >> $OUTPUT_FILE
+echo "#define OPENCHANGE_MAJOR_RELEASE ${OPENCHANGE_MAJOR_RELEASE}" >> $OUTPUT_FILE
+echo "#define OPENCHANGE_MINOR_RELEASE ${OPENCHANGE_MINOR_RELEASE}" >> $OUTPUT_FILE
+
+#
+# SVN revision number
+#
+if test x"${OPENCHANGE_VERSION_IS_SVN_SNAPSHOT}" = x"yes";then
+ _SAVE_LANG=${LANG}
+ LANG=""
+ HAVEVER="no"
+
+ if test x"${HAVEVER}" != x"yes";then
+ HAVESVN=no
+ SVN_INFO=`svn info ${SOURCE_DIR} 2>/dev/null`
+ TMP_REVISION=`echo -e "${SVN_INFO}" | grep 'Last Changed Rev.*:' |sed -e 's/Last Changed Rev.*: \([0-9]*\).*/\1/'`
+ if test -n "$TMP_REVISION"; then
+ HAVESVN=yes
+ HAVEVER=yes
+ fi
+ fi
+
+ if test x"${HAVESVN}" = x"yes";then
+ OPENCHANGE_VERSION_STRING="${OPENCHANGE_VERSION_STRING}-SVN-build-${TMP_REVISION}"
+ echo "#define OPENCHANGE_VERSION_SVN_REVISION ${TMP_REVISION}" >> $OUTPUT_FILE
+ fi
+
+ LANG=${_SAVE_LANG}
+fi
+
+echo "#define OPENCHANGE_VERSION_OFFICIAL_STRING \"${OPENCHANGE_VERSION_STRING}\"" >> $OUTPUT_FILE
+
+##
+## Add a release nickname
+##
+if test -n "${OPENCHANGE_VERSION_RELEASE_NICKNAME}";then
+ echo "#define OPENCHANGE_VERSION_RELEASE_NICKNAME ${OPENCHANGE_VERSION_RELEASE_NICKNAME}" >> $OUTPUT_FILE
+ OPENCHANGE_VERSION_STRING="${OPENCHANGE_VERSION_STRING} (${OPENCHANGE_VERSION_RELEASE_NICKNAME})"
+fi
+
+echo "#define OPENCHANGE_VERSION_STRING \"${OPENCHANGE_VERSION_STRING}\"" >> $OUTPUT_FILE
+
+##
+## Add some System related information (useful for debug and report)
+##
+echo "" >> $OUTPUT_FILE
+echo "/* System related information */" >> $OUTPUT_FILE
+
+OPENCHANGE_SYS_KERNEL_NAME=`uname -s`
+OPENCHANGE_SYS_KERNEL_RELEASE=`uname -r`
+OPENCHANGE_SYS_PROCESSOR=`uname -p`
+
+echo "#define OPENCHANGE_SYS_KERNEL_NAME \"${OPENCHANGE_SYS_KERNEL_NAME}\"" >> $OUTPUT_FILE
+echo "#define OPENCHANGE_SYS_KERNEL_RELEASE \"${OPENCHANGE_SYS_KERNEL_RELEASE}\"" >> $OUTPUT_FILE
+echo "#define OPENCHANGE_SYS_PROCESSOR \"${OPENCHANGE_SYS_PROCESSOR}\"" >> $OUTPUT_FILE
+
+echo "$0: '$OUTPUT_FILE' created for OpenChange libmapi(\"${OPENCHANGE_VERSION_STRING}\")"
+
+exit 0
Property changes on: trunk/openchange/script/mkversion.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/script/samba4_ver.sh
===================================================================
--- trunk/openchange/script/samba4_ver.sh (rev 0)
+++ trunk/openchange/script/samba4_ver.sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,4 @@
+SAMBA4_GIT_REV=57f978d
+SAMBA4_GIT_VER=4.0.0alpha6
+SAMBA4_RELEASE=4.0.0alpha6
+
Added: trunk/openchange/script/uninstallman.sh
===================================================================
--- trunk/openchange/script/uninstallman.sh (rev 0)
+++ trunk/openchange/script/uninstallman.sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,28 @@
+#!/bin/sh
+# 4 July 96 Dan.Shearer at UniSA.edu.au
+# Updated for Samba4 by Jelmer Vernooij
+
+MANDIR=$1
+shift 1
+MANPAGES=$*
+
+for I in $MANPAGES
+do
+ SECTION=`echo $I | grep -o '.$'`
+ MAN=`echo $I | grep -o '[a-zA-Z_]*\.[0-9]'`
+ FNAME=$MANDIR/man$SECTION/$MAN
+ if test -f $FNAME; then
+ echo Deleting $FNAME
+ rm -f $FNAME
+ test -f $FNAME && echo Cannot remove $FNAME... does $USER have privileges?
+ fi
+done
+
+cat << EOF
+======================================================================
+The man pages have been uninstalled. You may install them again using
+the command "make installman" or make "install" to install binaries,
+man pages and shell scripts.
+======================================================================
+EOF
+exit 0
Property changes on: trunk/openchange/script/uninstallman.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/script/uno.dfn
===================================================================
--- trunk/openchange/script/uno.dfn (rev 0)
+++ trunk/openchange/script/uno.dfn 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1 @@
+UnoType _Bool;
Added: trunk/openchange/setup/AD/oc_provision_configuration.ldif
===================================================================
--- trunk/openchange/setup/AD/oc_provision_configuration.ldif (rev 0)
+++ trunk/openchange/setup/AD/oc_provision_configuration.ldif 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,2014 @@
+################################################################
+# CN=Services,${CONFIGDN} records
+################################################################
+
+
+#
+# Exchange configuration information object
+# This object stores configuration information for the Exchange Server
+#
+dn: CN=Microsoft Exchange,CN=Services,${CONFIGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchConfigurationContainer
+cn: Microsoft Exchange
+distinguishedName: CN=Microsoft Exchange,CN=Services,${CONFIGDN}
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Microsoft Exchange
+heuristics: 6
+name: Microsoft Exchange
+objectCategory: CN=ms-Exch-Configuration-Container,${SCHEMADN}
+addressBookRoots: CN=All Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+globalAddressList: CN=Default Global Address List,CN=All Global Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+templateRoots: CN=Addressing,${FIRSTORGDN}
+#msExchPolicyRoots: CN=System Policies,${FIRSTORGDN}
+#msExchPolicyRoots: CN=Recipient Policies,${FIRSTORGDN}
+
+
+#
+# First Organization
+#
+dn: ${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchOrganizationContainer
+cn: First Organization
+distinguishedName: ${FIRSTORGDN}
+showInAdvancedViewOnly: TRUE
+adminDisplayName: {335A1087-5131-4D45-BE3E-3C6C7F76F5EC}
+name: ${FIRSTORG}
+legacyExchangeDN: /o=${FIRSTORG}
+objectCategory: CN=ms-Exch-Organization-Container,${SCHEMADN}
+msExchRoutingEnabled: FALSE
+msExchMixedMode: TRUE
+msExchAdminGroupsEnabled: FALSE
+msExchAdmins: S-1-5-21-1226241484-1028146065-4277480997-500,10
+
+
+
+#
+# Administrative Groups
+#
+dn: CN=Administrative Groups,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchAdminGroupContainer
+cn: Administrative Groups
+distinguishedName: CN=Administrative Groups,${FIRSTORGDN}
+displayName: Administrative Groups
+showInAdvancedViewOnly: TRUE
+name: Administrative Groups
+objectCategory: CN=ms-Exch-Admin-Group-Container,${SCHEMADN}
+
+
+#
+# First Administrative Group
+#
+dn: CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+objectClass: top
+objectClass: msExchAdminGroup
+cn: First Administrative Group
+distinguishedName: CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+displayName: First Administrative Group
+showInAdvancedViewOnly: TRUE
+siteFolderGUID: 4b2d197b-1cb3-486a-b8c3-42e8c5c08e27
+siteFolderServer: CN=Public Folder Store (${FIRSTORG}),CN=First Storage Group,CN=InformationStore,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+name: First Administrative Group
+legacyExchangeDN: /o=${FIRSTORG}/ou=First Administrative Group
+objectCategory: CN=ms-Exch-Admin-Group,${SCHEMADN}
+msExchAdminGroupMode: 0
+msExchDefaultAdminGroup: TRUE
+
+
+#
+# Servers
+#
+dn: CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchServersContainer
+cn: Servers
+distinguishedName: CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Servers
+containerInfo: 8
+name: Servers
+objectCategory: CN=ms-Exch-Servers-Container,${SCHEMADN}
+
+
+#
+# The OpenChange Server object
+#
+dn: CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+objectClass: top
+objectClass: server
+objectClass: msExchExchangeServer
+cn: ${NETBIOSNAME}
+serialNumber: Version 6.5 (Build 6944.4)
+distinguishedName: CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ${NETBIOSNAME}
+heuristics: 1576964
+messageTrackingEnabled: FALSE
+networkAddress: ncacn_vns_spp:${NETBIOSNAME}
+networkAddress: netbios:${NETBIOSNAME}
+networkAddress: ncacn_np:${NETBIOSNAME}
+networkAddress: ncacn_spx:${NETBIOSNAME}
+networkAddress: ncacn_ip_tcp:${HOSTNAME}.${DNSDOMAIN}
+networkAddress: ncalrpc:${NETBIOSNAME}
+name: ${NETBIOSNAME}
+versionNumber: 6944
+serverRole: 0
+legacyExchangeDN: /o=${FIRSTORG}/ou=First Administrative Group/cn=Configuration/cn=Servers/cn=${NETBIOSNAME}
+objectCategory: CN=ms-Exch-Exchange-Server,${SCHEMADN}
+#msExchHomeRoutingGroup: CN=First Routing Group,CN=Routing Groups,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+msExchMessageTrackLogFilter: -262145
+msExchTrkLogCleaningInterval: 7
+#msExchResponsibleMTAServer: CN=Microsoft MTA,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+msExchMailboxManagerActivationStyle: 0
+msExchMailboxManagerAdminMode: 2
+
+
+#
+# Information Store
+#
+dn: CN=InformationStore,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchInformationStore
+cn: InformationStore
+distinguishedName: CN=InformationStore,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+showInAdvancedViewOnly: TRUE
+adminDisplayName: InformationStore
+name: InformationStore
+objectCategory: CN=ms-Exch-Information-Store,${SCHEMADN}
+
+
+#
+# First Storage Group
+#
+dn: CN=First Storage Group,CN=InformationStore,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchStorageGroup
+cn: First Storage Group
+distinguishedName: CN=First Storage Group,CN=InformationStore,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+showInAdvancedViewOnly: TRUE
+adminDisplayName: First Storage Group
+name: First Storage Group
+systemFlags: 1610612736
+objectCategory: CN=ms-Exch-Storage-Group,${SCHEMADN}
+
+
+#
+# Public Folder Store (${NETBIOSNAME})
+#
+dn: CN=Public Folder Store (${NETBIOSNAME}),CN=First Storage Group,CN=InformationStore,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+objectClass: top
+objectClass: msExchMDB
+objectClass: msExchPublicMDB
+cn: Public Folder Store (${NETBIOSNAME})
+distinguishedName: CN=Public Folder Store (${NETBIOSNAME}),CN=First Storage Group,CN=InformationStore,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+displayName: Public Folder Store (${NETBIOSNAME})
+activationStyle: 1
+messageSizeLimit: 10240
+showInAdvancedViewOnly: TRUE
+#homeMTA: CN=Microsoft MTA,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+adminDisplayName: Public Folder Store (${NETBIOSNAME})
+proxyAddresses: SMTP:${NETBIOSNAME}-IS@${DNSDOMAIN}
+proxyAddresses: X400:c=US;a= ;p=First Organizati;o=Exchange;s=EXCH2K3-IS;
+deliveryMechanism: 1
+garbageCollPeriod: 604800
+quotaNotificationStyle: 1
+#homeMDBBL: CN=SMTP (${NETBIOSNAME}-{E95EE010-3E8A-425B-806F-15ED60887F6B}),CN=Connections,${FIRSTORGDN}
+mailNickname: ${NETBIOSNAME}-IS
+name: Public Folder Store (${NETBIOSNAME})
+systemFlags: 1610612736
+legacyExchangeDN: /o=${FIRSTORG}/ou=First Administrative Group/cn=Configuration/cn=Servers/cn=${NETBIOSNAME}/cn=Microsoft Public MDB
+objectCategory: CN=ms-Exch-Public-MDB,${SCHEMADN}
+textEncodedORAddress: c=US;a= ;p=First Organizati;o=Exchange;s=${NETBIOSNAME}-IS;
+mail: ${NETBIOSNAME}-IS@${DNSDOMAIN}
+msExchOwningServer: CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+#msExchOwningPFTree: CN=Public Folders,CN=Folder Hierarchies,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+msExchMaxCachedViews: 11
+msExchDatabaseCreated: TRUE
+msExchPoliciesIncluded: {627410A4-E1A9-4DD0-9568-FA22DEACB6B8},{26491CFC-9E50-
+ 4857-861B-0CB8DF22B5D7}
+
+
+#
+# Mailbox Store (${NETBIOSNAME})
+#
+dn: CN=Mailbox Store (${NETBIOSNAME}),CN=First Storage Group,CN=InformationStore,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+objectClass: top
+objectClass: msExchMDB
+objectClass: msExchPrivateMDB
+cn: Mailbox Store (${NETBIOSNAME})
+distinguishedName: CN=Mailbox Store (${NETBIOSNAME}),CN=First Storage Group,CN=InformationStore,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+displayName: Mailbox Store (${NETBIOSNAME})
+activationStyle: 1
+deletedItemFlags: 5
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Mailbox Store (${NETBIOSNAME})
+deliveryMechanism: 1
+garbageCollPeriod: 604800
+quotaNotificationStyle: 1
+name: Mailbox Store (${NETBIOSNAME})
+systemFlags: 1610612736
+legacyExchangeDN: /o=${FIRSTORG}/ou=First Administrative Group/cn=Configuration/cn=Servers/cn=${NETBIOSNAME}/cn=Microsoft Private MDB
+objectCategory: CN=ms-Exch-Private-MDB,${SCHEMADN}
+#msExchUseOAB: CN=Default Offline Address List,CN=Offline Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+msExchOwningServer: CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+msExchHomePublicMDB: CN=Public Folder Store (${NETBIOSNAME}),CN=First Storage Group,CN=InformationStore,CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+msExchMailboxRetentionPeriod: 2592000
+msExchMaxCachedViews: 11
+msExchDatabaseCreated: TRUE
+
+
+#
+# All Address Lists Containers
+# description: Address book root container
+#
+dn: CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchContainer
+cn: Address Lists Container
+distinguishedName: CN=Address Lists Container,${FIRSTORGDN}
+displayName: Address Lists Container
+showInAdvancedViewOnly: TRUE
+name: Address Lists Container
+objectCategory: CN=ms-Exch-Container,${SCHEMADN}
+
+
+#
+# All Global Address Lists
+#
+dn: CN=All Global Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: addressBookContainer
+cn: All Global Address Lists
+distinguishedName: CN=All Global Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+displayName: All Global Address Lists
+showInAdvancedViewOnly: TRUE
+name: All Global Address Lists
+systemFlags: 1610612736
+objectCategory: CN=Address-Book-Container,${SCHEMADN}
+
+
+#
+# Default global Address List
+#
+dn: CN=Default Global Address List,CN=All Global Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: addressBookContainer
+cn: Default Global Address List
+distinguishedName: CN=Default Global Address List,CN=All Global Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+displayName: Default Global Address List
+showInAdvancedViewOnly: TRUE
+name: Default Global Address List
+systemFlags: 1610612736
+objectCategory: CN=Address-Book-Container,${SCHEMADN}
+purportedSearch: (& (mailnickname=*) (| (&(objectCategory=person)(objectClass=user)(!(homeMDB=*))(!(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=user)(|(homeMDB=*)(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=contact))(objectCategory=group)(objectCategory=publicFolder)(objectCategory=msExchDynamicDistributionList) ))
+
+
+#
+# Offline Address Lists
+#
+dn: CN=Offline Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchContainer
+cn: Offline Address Lists
+distinguishedName: CN=Offline Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+displayName: Offline Address Lists
+showInAdvancedViewOnly: TRUE
+name: Offline Address Lists
+objectCategory: CN=ms-Exch-Container,${SCHEMADN}
+
+
+#
+# Default Offline Address List
+#
+dn: CN=Default Offline Address List,CN=Offline Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: msExchOAB
+cn: Default Offline Address List
+distinguishedName: CN=Default Offline Address List,CN=Offline Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+showInAdvancedViewOnly: TRUE
+offLineABStyle: 1
+offLineABContainers: CN=Default Global Address List,CN=All Global Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+offLineABServer: CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+siteFolderGUID: e72eae5f-ee8e-4908-becb-fb58af7c62aa
+siteFolderServer: CN=Public Folder Store (${NETBIOSNAME}),CN=First Storage Group,CN=InformationStore,CN=${NETBIOSNAME},CN=Servers,${FIRSTORGDN}
+doOABVersion: 0
+name: Default Offline Address List
+systemFlags: 1610612736
+legacyExchangeDN: /o=${FIRSTORG}/cn=addrlists/cn=oabs/cn=Default Offline Address List
+objectCategory: CN=ms-Exch-OAB,${SCHEMADN}
+msExchOABDefault: TRUE
+
+
+#
+# Recipient Update Services
+#
+dn: CN=Recipient Update Services,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchContainer
+cn: Recipient Update Services
+distinguishedName: CN=Recipient Update Services,CN=Address Lists Container,${FIRSTORGDN}
+displayName: Recipient Update Services
+showInAdvancedViewOnly: TRUE
+name: Recipient Update Services
+objectCategory: CN=ms-Exch-Container,${SCHEMADN}
+
+
+#
+# Recipient Update Service (${DOMAIN})
+#
+dn: CN=Recipient Update Service (${DOMAIN}),CN=Recipient Update Services,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: msExchAddressListService
+cn: Recipient Update Service (${DOMAIN})
+distinguishedName: CN=Recipient Update Service (${DOMAIN}),CN=Recipient Update Services,CN=Address Lists Container,${FIRSTORGDN}
+activationStyle: 2
+showInAdvancedViewOnly: TRUE
+name: Recipient Update Service (${DOMAIN})
+systemFlags: 1073741824
+objectCategory: CN=ms-Exch-Address-List-Service,${SCHEMADN}
+msExchServer1NetworkAddress: ${HOSTNAME}
+msExchServer1PageSize: 20
+msExchDoFullReplication: FALSE
+msExchReplicateNow: FALSE
+msExchPollInterval: 60
+msExchAddressListServiceLink: CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+msExchDomainLink: ${DOMAINDN}
+msExchServer1HighestUSNVector: ${NETBIOSNAME}:53500
+msExchDomainLocalGroupGuid: {D9CA41A1-5041-4FBF-8635-23B4D0BA8A48}
+msExchDomainGlobalGroupGuid: {1E2B98D3-4FAC-4FAE-B16F-A26AB09AAE34}
+msExchDomainLocalGroupSid: S-1-5-21-1226241484-1028146065-4277480997-1110
+msExchDomainGlobalGroupSid: S-1-5-21-1226241484-1028146065-4277480997-1109
+
+
+#
+# Recipient Update Service (Enterprise Configuration)
+#
+dn: CN=Recipient Update Service (Enterprise Configuration),CN=Recipient Update Services,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: msExchAddressListService
+cn: Recipient Update Service (Enterprise Configuration)
+distinguishedName: CN=Recipient Update Service (Enterprise Configuration),CN=Recipient Update Services,CN=Address Lists Container,${FIRSTORGDN}
+activationStyle: 2
+showInAdvancedViewOnly: TRUE
+name: Recipient Update Service (Enterprise Configuration)
+systemFlags: 1073741824
+objectCategory: CN=ms-Exch-Address-List-Service,CN=Schema,CN=Configuration,DC=
+ openchange2003,DC=local
+msExchServer1NetworkAddress: ${HOSTNAME}
+msExchServer1PageSize: 20
+msExchDoFullReplication: FALSE
+msExchReplicateNow: FALSE
+msExchPollInterval: 60
+msExchAddressListServiceLink: CN=${NETBIOSNAME},CN=Servers,CN=First Administrative Group,CN=Administrative Groups,${FIRSTORGDN}
+msExchDomainLink: CN=Configuration,${DOMAINDN}
+
+
+#
+# All Address Lists
+# description: Address book recipient
+#
+dn: CN=All Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: addressBookContainer
+cn: All Address Lists
+distinguishedName: CN=All Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+displayName: All Address Lists
+showInAdvancedViewOnly: TRUE
+name: All Address Lists
+systemFlags: 1610612736
+objectCategory: CN=Address-Book-Container,${SCHEMADN}
+
+#
+# All Users
+#
+dn: CN=All Users,CN=All Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: addressBookContainer
+cn: All Users
+distinguishedName: CN=All Users,CN=All Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+displayName: All Users
+showInAdvancedViewOnly: TRUE
+name: All Users
+systemFlags: 1610612736
+objectCategory: CN=Address-Book-Container,${SCHEMADN}
+purportedSearch: (& (mailnickname=*) (| (&(objectCategory=person)(objectClass=user)(!(homeMDB=*))(!(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=user)(|(homeMDB=*)(msExchHomeServerName=*))) ))
+
+
+#
+# All Groups
+#
+dn: CN=All Groups,CN=All Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: addressBookContainer
+cn: All Groups
+distinguishedName: CN=All Groups,CN=All Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+displayName: All Groups
+showInAdvancedViewOnly: TRUE
+name: All Groups
+systemFlags: 1610612736
+objectCategory: CN=Address-Book-Container,${SCHEMADN}
+purportedSearch: (& (mailnickname=*) (| (objectCategory=group) ))
+
+
+#
+# All Contacts
+# description: Address book recipient
+#
+dn: CN=All Contacts,CN=All Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: addressBookContainer
+cn: All Contacts
+distinguishedName: CN=All Contacts,CN=All Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+displayName: All Contacts
+showInAdvancedViewOnly: TRUE
+name: All Contacts
+systemFlags: 1610612736
+objectCategory: CN=Address-Book-Container,${SCHEMADN}
+purportedSearch: (& (mailnickname=*) (| (&(objectCategory=person)(objectClass=contact)) ))
+
+
+#
+# Public Folders
+# description: Address book recipient
+#
+dn: CN=Public Folders,CN=All Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+objectClass: top
+objectClass: addressBookContainer
+cn: Public Folders
+distinguishedName: CN=Public Folders,CN=All Address Lists,CN=Address Lists Container,${FIRSTORGDN}
+displayName: Public Folders
+showInAdvancedViewOnly: TRUE
+name: Public Folders
+systemFlags: 1610612736
+objectCategory: CN=Address-Book-Container,${SCHEMADN}
+purportedSearch: (& (mailnickname=*) (| (objectCategory=publicFolder) ))
+
+
+#
+# Addressing
+# description: Address container
+#
+dn: CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchContainer
+cn: Addressing
+distinguishedName: CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Addressing
+containerInfo: 16
+name: Addressing
+legacyExchangeDN: /o=${FIRSTORG}/cn=Configuration/cn=Addressing
+objectCategory: CN=ms-Exch-Container,${SCHEMADN}
+
+
+
+#
+# Address-Templates
+# description: Specifies information for a Display Template
+#
+dn: CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchContainer
+cn: Address-Templates
+distinguishedName: CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+showInAdvancedViewOnly: TRUE
+adminDisplayName: One-Off Address Templates
+containerInfo: 32
+name: Address-Templates
+legacyExchangeDN: /o=${FIRSTORG}/cn=Configuration/cn=Addressing/cn=Address-Templates
+objectCategory: CN=ms-Exch-Container,${SCHEMADN}
+msExchTemplateRDNs: 81A
+msExchTemplateRDNs: 403
+msExchTemplateRDNs: 422
+msExchTemplateRDNs: 427
+msExchTemplateRDNs: 426
+msExchTemplateRDNs: 425
+msExchTemplateRDNs: 402
+msExchTemplateRDNs: 424
+msExchTemplateRDNs: 41b
+msExchTemplateRDNs: 418
+msExchTemplateRDNs: 41a
+msExchTemplateRDNs: 42d
+msExchTemplateRDNs: 41e
+msExchTemplateRDNs: 40e
+msExchTemplateRDNs: 41f
+msExchTemplateRDNs: 419
+msExchTemplateRDNs: 414
+msExchTemplateRDNs: 406
+msExchTemplateRDNs: 405
+msExchTemplateRDNs: 41d
+msExchTemplateRDNs: 816
+msExchTemplateRDNs: 415
+msExchTemplateRDNs: 408
+msExchTemplateRDNs: 40b
+msExchTemplateRDNs: 413
+msExchTemplateRDNs: 416
+msExchTemplateRDNs: 40d
+msExchTemplateRDNs: 401
+msExchTemplateRDNs: 410
+msExchTemplateRDNs: C0A
+msExchTemplateRDNs: 404
+msExchTemplateRDNs: 804
+msExchTemplateRDNs: 412
+msExchTemplateRDNs: 40c
+msExchTemplateRDNs: 407
+msExchTemplateRDNs: 411
+msExchTemplateRDNs: 409
+
+
+#
+# Address-Types
+# description: E-Mail Address Generators
+#
+dn: CN=Address-Types,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchContainer
+cn: Address-Types
+distinguishedName: CN=Address-Types,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+showInAdvancedViewOnly: TRUE
+adminDisplayName: E-Mail Address Generators
+containerInfo: 128
+name: Address-Types
+objectCategory: CN=ms-Exch-Container,${SCHEMADN}
+
+
+#
+# Display-Templates
+#
+#
+dn: CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+objectClass: msExchContainer
+cn: Display-Templates
+distinguishedName: CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Details Templates
+containerInfo: 64
+name: Display-Templates
+legacyExchangeDN: /o=${FIRSTORG}/cn=Configuration/cn=Addressing/cn=Display-Templates
+objectCategory: CN=ms-Exch-Container,${SCHEMADN}
+
+
+#
+# Arabic Address-Templates
+#
+dn: CN=401,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 401
+distinguishedName: CN=401,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Arabic
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Arabic
+name: 401
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=401
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Bulgarian Address-Templates
+#
+dn: CN=402,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 402
+distinguishedName: CN=402,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Bulgarian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Bulgarian
+name: 402
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=402
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Catalan Address-Templates
+#
+dn: CN=403,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 403
+distinguishedName: CN=403,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Catalan
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Catalan
+name: 403
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=403
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Chinese Traditional Address-Templates
+#
+dn: CN=404,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 404
+distinguishedName: CN=404,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Chinese Traditional
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Chinese Traditional
+name: 404
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=404
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Czech Address-Templates
+#
+dn: CN=405,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 405
+distinguishedName: CN=405,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Czech
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Czech
+name: 405
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=405
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Danish Address-Templates
+#
+dn: CN=406,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 406
+distinguishedName: CN=406,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Danish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Danish
+name: 406
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=406
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# German Address-Templates
+#
+dn: CN=407,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 407
+distinguishedName: CN=407,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: German
+showInAdvancedViewOnly: TRUE
+adminDisplayName: German
+name: 407
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=407
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Greek Address-Templates
+#
+dn: CN=408,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 408
+distinguishedName: CN=408,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Greek
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Greek
+name: 408
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=408
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# English Address-Templates
+#
+dn: CN=409,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 409
+distinguishedName: CN=409,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: English
+showInAdvancedViewOnly: TRUE
+adminDisplayName: English
+name: 409
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=409
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Finish Address-Templates
+#
+dn: CN=40b,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 40b
+distinguishedName: CN=40b,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Finnish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Finnish
+name: 40b
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=40b
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# French Address-Templates (cocorico)
+#
+dn: CN=40c,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 40c
+distinguishedName: CN=40c,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: French
+showInAdvancedViewOnly: TRUE
+adminDisplayName: French
+name: 40c
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=40c
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Hebrew Address-Templates
+#
+dn: CN=40d,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 40d
+distinguishedName: CN=40d,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Hebrew
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Hebrew
+name: 40d
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=40d
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Hungarian Address-Templates
+#
+dn: CN=40e,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 40e
+distinguishedName: CN=40e,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Hungarian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Hungarian
+name: 40e
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=40e
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Italian Address-Templates
+#
+dn: CN=410,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 410
+distinguishedName: CN=410,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Italian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Italian
+name: 410
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=410
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Japanese Address-Templates
+#
+dn: CN=411,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 411
+distinguishedName: CN=411,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Japanese
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Japanese
+name: 411
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=411
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Korean Address-Templates
+#
+dn: CN=412,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 412
+distinguishedName: CN=412,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Korean
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Korean
+name: 412
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=412
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Dutch Address-Templates
+#
+dn: CN=413,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 413
+distinguishedName: CN=413,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Dutch
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Dutch
+name: 413
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=413
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Norwegian Address-Templates
+#
+dn: CN=414,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 414
+distinguishedName: CN=414,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Norwegian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Norwegian
+name: 414
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=414
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Polish Address-Templates
+#
+dn: CN=415,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 415
+distinguishedName: CN=415,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Polish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Polish
+name: 415
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=415
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Brazilian Address-Templates (Samba)
+#
+dn: CN=416,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 416
+distinguishedName: CN=416,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Brazilian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Brazilian
+name: 416
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=416
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Romanian Address-Templates
+#
+dn: CN=418,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 418
+distinguishedName: CN=418,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Romanian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Romanian
+name: 418
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=418
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Russian Address-Templates
+#
+dn: CN=419,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 419
+distinguishedName: CN=419,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Russian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Russian
+name: 419
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=419
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Croatian Address-Templates
+#
+dn: CN=41a,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 41a
+distinguishedName: CN=41a,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Croatian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Croatian
+name: 41a
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=41a
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Slovak Address-Templates
+#
+dn: CN=41b,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 41b
+distinguishedName: CN=41b,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Slovak
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Slovak
+name: 41b
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=41b
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Swedish Address-Templates
+#
+dn: CN=41d,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 41d
+distinguishedName: CN=41d,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Swedish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Swedish
+name: 41d
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=41d
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Thai Address-Templates
+#
+dn: CN=41e,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 41e
+distinguishedName: CN=41e,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Thai
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Thai
+name: 41e
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=41e
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Turkish Address-Templates
+#
+dn: CN=41f,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 41f
+distinguishedName: CN=41f,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Turkish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Turkish
+name: 41f
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=41f
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Ukrainian Address-Templates
+#
+dn: CN=422,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 422
+distinguishedName: CN=422,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Ukrainian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Ukrainian
+name: 422
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=422
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Slovenian Address-Templates
+#
+dn: CN=424,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 424
+distinguishedName: CN=424,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Slovenian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Slovenian
+name: 424
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=424
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Estonian Address-Templates
+#
+dn: CN=425,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 425
+distinguishedName: CN=425,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Estonian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Estonian
+name: 425
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=425
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Latvian Address-Templates
+#
+dn: CN=426,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 426
+distinguishedName: CN=426,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Latvian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Latvian
+name: 426
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=426
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Lithuanian Address-Templates
+#
+dn: CN=427,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 427
+distinguishedName: CN=427,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Lithuanian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Lithuanian
+name: 427
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=427
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Basque Address-Templates
+#
+dn: CN=42d,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 42d
+distinguishedName: CN=42d,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Basque
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Basque
+name: 42d
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=42d
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Chinese Simplified Address-Templates
+#
+dn: CN=804,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 804
+distinguishedName: CN=804,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Chinese Simplified
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Chinese Simplified
+name: 804
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=804
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Portuguese Address-Templates
+#
+dn: CN=816,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 816
+distinguishedName: CN=816,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Portuguese
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Portuguese
+name: 816
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=816
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Serbian Address-Templates
+#
+dn: CN=81A,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 81A
+distinguishedName: CN=81A,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Serbian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Serbian
+name: 81A
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=81A
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Spanish Address-Templates
+#
+dn: CN=C0A,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: C0A
+distinguishedName: CN=C0A,CN=Address-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Spanish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Spanish
+name: C0A
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Address-Templates/CN=C0A
+objectCategory: CN=Container,${SCHEMADN}
+msExchTemplateRDNs: CCMAIL
+msExchTemplateRDNs: MSA
+msExchTemplateRDNs: SMTP
+msExchTemplateRDNs: MS
+msExchTemplateRDNs: x400
+
+
+#
+# Arabic Display-Templates
+#
+dn: CN=401,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 401
+distinguishedName: CN=401,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Arabic
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Arabic
+name: 401
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=401
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Bulgarian Display-Templates
+#
+dn: CN=402,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 402
+distinguishedName: CN=402,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Bulgarian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Bulgarian
+name: 402
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=402
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Catalan Display-Templates
+#
+dn: CN=403,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 403
+distinguishedName: CN=403,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Catalan
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Catalan
+name: 403
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=403
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Chinese Traditional Display-Templates
+#
+dn: CN=404,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 404
+distinguishedName: CN=404,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Chinese Traditional
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Chinese Traditional
+name: 404
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=404
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Czech Display-Templates
+#
+dn: CN=405,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 405
+distinguishedName: CN=405,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Czech
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Czech
+name: 405
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=405
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Danish Display-Templates
+#
+dn: CN=406,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 406
+distinguishedName: CN=406,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Danish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Danish
+name: 406
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=406
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# German Display-Templtes
+#
+dn: CN=407,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 407
+distinguishedName: CN=407,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: German
+showInAdvancedViewOnly: TRUE
+adminDisplayName: German
+name: 407
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=407
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Greek Display-Templates
+#
+dn: CN=408,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 408
+distinguishedName: CN=408,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Greek
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Greek
+name: 408
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=408
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# English Display-Templates
+#
+dn: CN=409,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 409
+distinguishedName: CN=409,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: English
+showInAdvancedViewOnly: TRUE
+adminDisplayName: English
+name: 409
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=409
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Finish Display-Templates
+#
+dn: CN=40b,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 40b
+distinguishedName: CN=40b,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Finnish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Finnish
+name: 40b
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=40b
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# French Display-Templates (cocorico)
+#
+dn: CN=40c,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 40c
+distinguishedName: CN=40c,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: French
+showInAdvancedViewOnly: TRUE
+adminDisplayName: French
+name: 40c
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=40c
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Hebrew Display-Templates
+#
+dn: CN=40d,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 40d
+distinguishedName: CN=40d,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Hebrew
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Hebrew
+name: 40d
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=40d
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Hungarian Display-Templates
+#
+dn: CN=40e,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 40e
+distinguishedName: CN=40e,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Hungarian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Hungarian
+name: 40e
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=40e
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Italian Display-Templates
+#
+dn: CN=410,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 410
+distinguishedName: CN=410,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Italian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Italian
+name: 410
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=410
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Japanese Display-Templates
+#
+dn: CN=411,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 411
+distinguishedName: CN=411,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Japanese
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Japanese
+name: 411
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=411
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Korean Display-Templates
+#
+dn: CN=412,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 412
+distinguishedName: CN=412,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Korean
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Korean
+name: 412
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=412
+objectCategory: CN=Container,${SCHEMADN}
+
+
+
+#
+# Dutch Display-Templates
+#
+dn: CN=413,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 413
+distinguishedName: CN=413,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Dutch
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Dutch
+name: 413
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=413
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Norwegian Display-Templates
+#
+dn: CN=414,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 414
+distinguishedName: CN=414,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Norwegian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Norwegian
+name: 414
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=414
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Polish Display-Templates
+#
+dn: CN=415,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 415
+distinguishedName: CN=415,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Polish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Polish
+name: 415
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=415
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Brazilian Display-Templates (Samba)
+#
+dn: CN=416,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 416
+distinguishedName: CN=416,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Brazilian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Brazilian
+name: 416
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=416
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Romanian Display-Templates
+#
+dn: CN=418,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 418
+distinguishedName: CN=418,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Romanian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Romanian
+name: 418
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=418
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Russian Display-Templates
+#
+dn: CN=419,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 419
+distinguishedName: CN=419,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Russian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Russian
+name: 419
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=419
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Croatian Display-Templates
+#
+dn: CN=41a,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 41a
+distinguishedName: CN=41a,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Croatian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Croatian
+name: 41a
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=41a
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Slovak Display-Templates
+#
+dn: CN=41b,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 41b
+distinguishedName: CN=41b,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Slovak
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Slovak
+name: 41b
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=41b
+objectCategory: CN=Container,${SCHEMADN}
+
+
+
+#
+# Swedish Display-Templates
+#
+dn: CN=41d,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 41d
+distinguishedName: CN=41d,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Swedish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Swedish
+name: 41d
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=41d
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Thai Display-Templates
+#
+dn: CN=41e,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 41e
+distinguishedName: CN=41e,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Thai
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Thai
+name: 41e
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=41e
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Turkish Display-Templates
+#
+dn: CN=41f,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 41f
+distinguishedName: CN=41f,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Turkish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Turkish
+name: 41f
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=41f
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Ukrainian Display-Templates
+#
+dn: CN=422,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 422
+distinguishedName: CN=422,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Ukrainian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Ukrainian
+name: 422
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=422
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Slovenian Display-Templates
+#
+dn: CN=424,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 424
+distinguishedName: CN=424,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Slovenian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Slovenian
+name: 424
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=424
+objectCategory: CN=Container,${SCHEMADN}
+
+
+
+#
+# Estonian Display-Templates
+#
+dn: CN=425,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 425
+distinguishedName: CN=425,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Estonian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Estonian
+name: 425
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=425
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Latvian Display-Templates
+#
+dn: CN=426,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 426
+distinguishedName: CN=426,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Latvian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Latvian
+name: 426
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=426
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Lithuanian Display-Templates
+#
+dn: CN=427,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 427
+distinguishedName: CN=427,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Lithuanian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Lithuanian
+name: 427
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=427
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Basque Display-Templates
+#
+dn: CN=42d,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 42d
+distinguishedName: CN=42d,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Basque
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Basque
+name: 42d
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=42d
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Chinese Simplified Display-Templates
+#
+dn: CN=804,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 804
+distinguishedName: CN=804,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Chinese Simplified
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Chinese Simplified
+name: 804
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=804
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Portuguese Display-Templates
+#
+dn: CN=816,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 816
+distinguishedName: CN=816,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Portuguese
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Portuguese
+name: 816
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=816
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Serbian Display-Templates
+#
+dn: CN=81A,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: 81A
+distinguishedName: CN=81A,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Serbian
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Serbian
+name: 81A
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=81A
+objectCategory: CN=Container,${SCHEMADN}
+
+
+#
+# Spanish Display-Templates
+#
+dn: CN=C0A,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+objectClass: top
+objectClass: container
+cn: C0A
+distinguishedName: CN=C0A,CN=Display-Templates,CN=Addressing,${FIRSTORGDN}
+instanceType: 4
+displayName: Spanish
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Spanish
+name: C0A
+legacyExchangeDN: /o=${FIRSTORG}/CN=Configuration/CN=Addressing/CN=Display-Templates/CN=C0A
+objectCategory: CN=Container,${SCHEMADN}
Added: trunk/openchange/setup/AD/oc_provision_schema.ldif
===================================================================
--- trunk/openchange/setup/AD/oc_provision_schema.ldif (rev 0)
+++ trunk/openchange/setup/AD/oc_provision_schema.ldif 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,29804 @@
+##############################################################################
+# Classes added
+##############################################################################
+
+
+
+
+
+#
+# ms-Exch-Active-Directory-Connector
+# Represents the service that synchronizes information between the
+# Exchange Server 5.5 directory and Active Directory.
+#
+dn: CN=ms-Exch-Active-Directory-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Active-Directory-Connector
+distinguishedName: CN=ms-Exch-Active-Directory-Connector,${SCHEMADN}
+possSuperiors: organizationalUnit
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.4
+mayContain: versionNumberHi
+mayContain: versionNumber
+mayContain: msExchServer2SchemaMap
+mayContain: msExchServer1SchemaMap
+mayContain: msExchChildSyncAgreements
+mayContain: displayName
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Active-Directory-Connector
+adminDescription: ms-Exch-Active-Directory-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchActiveDirectoryConnector
+name: ms-Exch-Active-Directory-Connector
+schemaIDGUID: e605672c-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Active-Directory-Connector,${SCHEMADN}
+
+
+
+dn: CN=ms-Exch-Addressing-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Addressing-Policy
+distinguishedName: CN=ms-Exch-Addressing-Policy,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.50008
+mayContain: msExchPolicyLastAppliedTime
+mayContain: msExchProxyGenServer
+mayContain: msExchPolicyLockDown
+mayContain: msExchPolicyListBL
+mayContain: msExchPolicyDefault
+mayContain: gatewayProxy
+mayContain: disabledGatewayProxy
+mayContain: msExchAliasGenUniqueness
+mayContain: msExchAliasGenType
+mayContain: msExchAliasGenFormat
+rDNAttID: cn
+uSNChanged: 16956
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Addressing-Policy
+adminDescription: ms-Exch-Addressing-Policy
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchAddressingPolicy
+name: ms-Exch-Addressing-Policy
+schemaIDGUID: e7211f02-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Addressing-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Address-List-Service
+# Domain-wide configuration object for the Address List Service.
+#
+dn: CN=ms-Exch-Address-List-Service,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Address-List-Service
+distinguishedName: CN=ms-Exch-Address-List-Service,${SCHEMADN}
+possSuperiors: exchangeAdminService
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.2
+mayContain: msExchMinAdminVersion
+mayContain: msExchDomainLocalGroupSid
+mayContain: msExchDomainLocalGroupGuid
+mayContain: msExchDomainGlobalGroupSid
+mayContain: msExchDomainGlobalGroupGuid
+mayContain: msExchProcessedSids
+mayContain: gatewayProxy
+mayContain: msExchEncryptedPassword
+mayContain: msExchServer2LastUpdateTime
+mayContain: msExchServer2HighestUSNVector
+mayContain: msExchServer2HighestUSN
+mayContain: msExchServer2Flags
+mayContain: msExchServer1HighestUSNVector
+mayContain: msExchServer1AuthenticationPassword
+mayContain: msExchServer1AuthenticationCredentials
+mayContain: msExchMasterServiceBL
+mayContain: exportContainers
+mayContain: msExchServer1SearchFilter
+mayContain: msExchServer1NetworkAddress
+mayContain: msExchServer1PageSize
+mayContain: msExchServer1LastUpdateTime
+mayContain: msExchServer1HighestUSN
+mayContain: msExchServer1Flags
+mayContain: msExchReplicateNow
+mayContain: msExchPollInterval
+mayContain: msExchDomainLink
+mayContain: msExchDoFullReplication
+mayContain: msExchAddressListServiceLink
+mayContain: activationStyle
+mayContain: activationSchedule
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Address-List-Service
+adminDescription: ms-Exch-Address-List-Service
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchAddressListService
+name: ms-Exch-Address-List-Service
+schemaIDGUID: e6a2c260-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Address-List-Service,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Address-List-Service-Container
+# Container for Recipient Update Service (RUS) objects
+#
+dn: CN=ms-Exch-Address-List-Service-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Address-List-Service-Container
+distinguishedName: CN=ms-Exch-Address-List-Service-Container,${SCHEMADN}
+possSuperiors: msExchContainer
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.13
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Address-List-Service-Container
+adminDescription: ms-Exch-Address-List-Service-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchAddressListServiceContainer
+name: ms-Exch-Address-List-Service-Container
+schemaIDGUID: b1fce95a-1d44-11d3-aa5e-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Address-List-Service-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Addr-Type
+# Specifies an EMS Address type, such as SMTP, MHS, or PROFS.
+#
+dn: CN=ms-Exch-Addr-Type,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Addr-Type
+distinguishedName: CN=ms-Exch-Addr-Type,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.3.57
+mustContain: proxyGeneratorDLL
+mustContain: fileVersion
+mustContain: cn
+mayContain: msExchMinAdminVersion
+mayContain: proxyGenerationEnabled
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Addr-Type
+adminDescription: ms-Exch-Addr-Type
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: addrType
+name: ms-Exch-Addr-Type
+schemaIDGUID: a8df74ab-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Addr-Type,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Add-In
+#
+dn: CN=ms-Exch-Add-In,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Add-In
+distinguishedName: CN=ms-Exch-Add-In,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.3.36
+mustContain: computerName
+mustContain: cn
+mayContain: owner
+mayContain: activationStyle
+mayContain: activationSchedule
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Add-In
+adminDescription: ms-Exch-Add-In
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: addIn
+name: ms-Exch-Add-In
+schemaIDGUID: a8df74aa-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Add-In,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Admin-Extension
+# Specifies a remote X.400 message transfer agent (MTA).
+#
+dn: CN=ms-Exch-Admin-Extension,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Admin-Extension
+distinguishedName: CN=ms-Exch-Admin-Extension,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.3.21
+mustContain: fileVersion
+mustContain: adminExtensionDLL
+mustContain: cn
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Admin-Extension
+adminDescription: ms-Exch-Admin-Extension
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: adminExtension
+name: ms-Exch-Admin-Extension
+schemaIDGUID: a8df74ac-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Admin-Extension,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Admin-Group
+# objectCategory for cn=First Administrative Group
+# description: An administrative group.
+#
+dn: CN=ms-Exch-Admin-Group,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Admin-Group
+distinguishedName: CN=ms-Exch-Admin-Group,${SCHEMADN}
+possSuperiors: msExchAdminGroupContainer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.50011
+mayContain: msExchMinAdminVersion
+mayContain: domainDefAltRecip
+mayContain: msExchPfCreation
+mayContain: msExchEncryptedPassword
+mayContain: msExchAdmins
+mayContain: msExchPFDefaultAdminACL
+mayContain: msExchLegacyPW
+mayContain: msExchLegacyDomain
+mayContain: msExchLegacyAccount
+mayContain: siteFolderServer
+mayContain: siteFolderGUID
+mayContain: msExchDefaultAdminGroup
+mayContain: msExchAdminGroupMode
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Admin-Group
+adminDescription: ms-Exch-Admin-Group
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchAdminGroup
+name: ms-Exch-Admin-Group
+schemaIDGUID: e768a58e-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Admin-Group,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Admin-Group-Container
+# description: An administrative group container. Used for extended rights and roles.
+#
+dn: CN=ms-Exch-Admin-Group-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Admin-Group-Container
+distinguishedName: CN=ms-Exch-Admin-Group-Container,${SCHEMADN}
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.50019
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Admin-Group-Container
+adminDescription: ms-Exch-Admin-Group-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchAdminGroupContainer
+name: ms-Exch-Admin-Group-Container
+schemaIDGUID: e7a44058-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Admin-Group-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Admin-Role
+#
+dn: CN=ms-Exch-Admin-Role,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Admin-Role
+distinguishedName: CN=ms-Exch-Admin-Role,${SCHEMADN}
+possSuperiors: msExchContainer
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.50017
+mustContain: msExchRoleRights
+mayContain: msExchRoleLocalizedNames
+mayContain: msExchRoleIncludes
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Admin-Role
+adminDescription: ms-Exch-Admin-Role
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchAdminRole
+name: ms-Exch-Admin-Role
+schemaIDGUID: e7f2edf2-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Admin-Role,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Advanced-Security-Container
+# A container object to hold the Encryption Configuration and Key
+# Manager objects
+#
+dn: CN=ms-Exch-Advanced-Security-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Advanced-Security-Container
+distinguishedName: CN=ms-Exch-Advanced-Security-Container,${SCHEMADN}
+possSuperiors: msExchAdminGroup
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.13001
+mayContain: msExchMinAdminVersion
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Advanced-Security-Container
+adminDescription: ms-Exch-Advanced-Security-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchAdvancedSecurityContainer
+name: ms-Exch-Advanced-Security-Container
+schemaIDGUID: 8cc8fb0e-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;LC;;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Advanced-Security-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Base-Class
+# description: The base auxiliary class that is applied to all classes
+# that are extended by CDO for Exchange 2000 Server (CDOEX) and the base
+# Microsoft Windows classes that are used.
+#
+dn: CN=ms-Exch-Base-Class,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Base-Class
+distinguishedName: CN=ms-Exch-Base-Class,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.14
+mayContain: msExchInconsistentState
+mayContain: heuristics
+mayContain: msExchALObjectVersion
+mayContain: msExchUnmergedAttsPt
+mayContain: showInAddressBook
+mayContain: unmergedAtts
+mayContain: replicationSignature
+mayContain: replicatedObjectVersion
+mayContain: msExchHideFromAddressLists
+mayContain: msExchADCGlobalNames
+mayContain: legacyExchangeDN
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Base-Class
+adminDescription: ms-Exch-Base-Class
+objectClassCategory: 3
+lDAPDisplayName: msExchBaseClass
+schemaIDGUID: d8782c34-46ca-11d3-aa72-00c04f8eedd8
+systemOnly: FALSE
+defaultHidingValue: TRUE
+defaultObjectCategory: CN=ms-Exch-Base-Class,${SCHEMADN}
+
+
+#
+# ms-Exch-Calendar-Connector
+# The calendar connector
+#
+dn: CN=ms-Exch-Calendar-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Calendar-Connector
+distinguishedName: CN=ms-Exch-Calendar-Connector,${SCHEMADN}
+possSuperiors: container
+subClassOf: mailGateway
+governsID: 1.2.840.113556.1.5.7000.62.1007
+mayContain: msExchNotesNotesServer
+mayContain: msExchNotesNotesINI
+mayContain: msExchEncryptedPassword
+mayContain: msExchGWiseAPIGateway
+mayContain: msExchCalConTargetSiteDN
+mayContain: msExchCalConRefreshInterval
+mayContain: msExchCalConQueryWindow
+mayContain: msExchCalConProviders
+mayContain: msExchCalConClientWait
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Calendar-Connector
+adminDescription: ms-Exch-Calendar-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchCalendarConnector
+name: ms-Exch-Calendar-Connector
+schemaIDGUID: 922180da-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Calendar-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ccMail-Connector
+# The ccMail connector
+#
+dn: CN=ms-Exch-ccMail-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-ccMail-Connector
+distinguishedName: CN=ms-Exch-ccMail-Connector,${SCHEMADN}
+possSuperiors: container
+subClassOf: mailGateway
+governsID: 1.2.840.113556.1.5.7000.62.1001
+mayContain: msExchccMailPassword
+mayContain: msExchccMailConnectAsUserid
+mayContain: msExchccMailConnectAsPassword
+mayContain: objViewContainers
+mayContain: msExchccMailPOPath
+mayContain: msExchccMailPOName
+mayContain: msExchccMailKeepForwardHistory
+mayContain: msExchccMailImportExportVersion
+mayContain: msExchccMailFilterType
+mayContain: msExchccMailADEProp
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ccMail-Connector
+adminDescription: ms-Exch-ccMail-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchccMailConnector
+name: ms-Exch-ccMail-Connector
+schemaIDGUID: e85710b6-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-ccMail-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Certificate-Information
+# The auxiliary class of users and contacts that contains all
+# certificates and certificate information. Users publish their
+# certificates to attributes located on this object.
+#
+dn: CN=ms-Exch-Certificate-Information,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Certificate-Information
+distinguishedName: CN=ms-Exch-Certificate-Information,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.7
+mayContain: userCertificate
+mayContain: userSMIMECertificate
+mayContain: userCert
+mayContain: supportedAlgorithms
+mayContain: attributeCertificate
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Certificate-Information
+adminDescription: ms-Exch-Certificate-Information
+objectClassCategory: 3
+lDAPDisplayName: msExchCertificateInformation
+name: ms-Exch-Certificate-Information
+schemaIDGUID: e8977034-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Certificate-Information,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Ban
+# A Chat Service Ban Object
+#
+dn: CN=ms-Exch-Chat-Ban,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Chat-Ban
+distinguishedName: CN=ms-Exch-Chat-Ban,${SCHEMADN}
+possSuperiors: msExchChatVirtualNetwork
+possSuperiors: msExchChatNetwork
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.8004
+mayContain: msExchChatStartTime
+mayContain: msExchChatDuration
+mayContain: msExchChatBanReason
+mayContain: msExchChatBanMask
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Ban
+adminDescription: ms-Exch-Chat-Ban
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchChatBan
+name: ms-Exch-Chat-Ban
+schemaIDGUID: e8d0a8a4-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Chat-Ban,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel
+# A Chat Service channel (room) object
+#
+dn: CN=ms-Exch-Chat-Channel,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Chat-Channel
+distinguishedName: CN=ms-Exch-Chat-Channel,${SCHEMADN}
+possSuperiors: msExchChatVirtualNetwork
+possSuperiors: msExchChatNetwork
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.8003
+mayContain: msExchChatAccess
+mayContain: msExchChatChannelTopic
+mayContain: msExchChatChannelSubject
+mayContain: msExchChatChannelPICS
+mayContain: msExchChatChannelPartMessage
+mayContain: msExchChatChannelOwnerKey
+mayContain: msExchChatChannelName
+mayContain: msExchChatChannelMode
+mayContain: msExchChatChannelLimit
+mayContain: msExchChatChannelLCID
+mayContain: msExchChatChannelLanguage
+mayContain: msExchChatChannelKey
+mayContain: msExchChatChannelJoinMessage
+mayContain: msExchChatChannelHostKey
+mayContain: msExchChatChannelFlags
+mayContain: msExchChatChannelAutoCreate
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel
+adminDescription: ms-Exch-Chat-Channel
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchChatChannel
+name: ms-Exch-Chat-Channel
+schemaIDGUID: e902ba06-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Chat-Channel,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Network
+# A Chat Service community object.
+#
+dn: CN=ms-Exch-Chat-Network,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Chat-Network
+distinguishedName: CN=ms-Exch-Chat-Network,${SCHEMADN}
+possSuperiors: msExchAdminGroup
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.8001
+mayContain: msExchBasicAuthenticationDomain
+mayContain: msExchAuthenticationFlags
+mayContain: msExchChatNetworkMode
+mayContain: msExchChatAccess
+mayContain: msExchChatTitle
+mayContain: msExchChatMOTD
+mayContain: msExchChatMaxMemberships
+mayContain: msExchChatMaxConnections
+mayContain: msExchChatMaxAnonymous
+mayContain: msExchChatEnableAuthenticated
+mayContain: msExchChatEnableAnonymous
+mayContain: msExchChatDNSReverseMode
+mayContain: msExchChatClientPort
+mayContain: msExchChatChannelMode
+mayContain: msExchChatChannelLimit
+mayContain: msExchChatChannelLCID
+mayContain: msExchChatChannelLanguage
+mayContain: msExchChatAdminMessage
+mayContain: Enabled
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Network
+adminDescription: ms-Exch-Chat-Network
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchChatNetwork
+name: ms-Exch-Chat-Network
+schemaIDGUID: e934cb68-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Chat-Network,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Protocol
+# A Chat Service user class.
+#
+dn: CN=ms-Exch-Chat-Protocol,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Chat-Protocol
+distinguishedName: CN=ms-Exch-Chat-Protocol,${SCHEMADN}
+possSuperiors: protocolCfgSharedServer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.8005
+mayContain: msExchServerBindings
+mayContain: msExchChatServerPort
+mayContain: msExchChatBroadcastAddress
+mayContain: msExchChatAccess
+mayContain: msExchChatNetworkName
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Protocol
+adminDescription: ms-Exch-Chat-Protocol
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchChatProtocol
+name: ms-Exch-Chat-Protocol
+schemaIDGUID: e9621816-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Chat-Protocol,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-User-Class
+#
+dn: CN=ms-Exch-Chat-User-Class,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Chat-User-Class
+distinguishedName: CN=ms-Exch-Chat-User-Class,${SCHEMADN}
+possSuperiors: msExchChatVirtualNetwork
+possSuperiors: msExchChatProtocol
+possSuperiors: msExchChatNetwork
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.8006
+mayContain: msExchChatMaxOctetsToMask
+mayContain: msExchChatMaxConnectionsPerIP
+mayContain: msExchChatClassScopeType
+mayContain: msExchChatClassRestrictions
+mayContain: msExchChatStartTime
+mayContain: msExchChatProtectionLevel
+mayContain: msExchChatPingDelay
+mayContain: msExchChatOutputSaturation
+mayContain: msExchChatNickDelay
+mayContain: msExchChatMessageLag
+mayContain: msExchChatMaxMemberships
+mayContain: msExchChatMaxConnections
+mayContain: msExchChatInputFloodLimit
+mayContain: msExchChatEnableAuthenticated
+mayContain: msExchChatEnableAnonymous
+mayContain: msExchChatDuration
+mayContain: msExchChatClassIP
+mayContain: msExchChatClassIdentMask
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-User-Class
+adminDescription: ms-Exch-Chat-User-Class
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchChatUserClass
+name: ms-Exch-Chat-User-Class
+schemaIDGUID: e9a0153a-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Chat-User-Class,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Virtual-Network
+# An instance of a Chat community on a physical server.
+#
+dn: CN=ms-Exch-Chat-Virtual-Network,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Chat-Virtual-Network
+distinguishedName: CN=ms-Exch-Chat-Virtual-Network,${SCHEMADN}
+possSuperiors: msExchChatProtocol
+possSuperiors: msExchChatNetwork
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.8002
+mayContain: msExchChatExtensions
+mayContain: msExchServerBindings
+mayContain: msExchChatTitle
+mayContain: msExchChatMaxConnections
+mayContain: msExchChatClientPort
+mayContain: Enabled
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Virtual-Network
+adminDescription: ms-Exch-Chat-Virtual-Network
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchChatVirtualNetwork
+name: ms-Exch-Chat-Virtual-Network
+schemaIDGUID: ea5ed15a-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Chat-Virtual-Network,${SCHEMADN}
+
+
+#
+# ms-Exch-Computer-Policy
+#
+dn: CN=ms-Exch-Computer-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Computer-Policy
+distinguishedName: CN=ms-Exch-Computer-Policy,${SCHEMADN}
+possSuperiors: container
+subClassOf: computer
+governsID: 1.2.840.113556.1.5.7000.62.50007
+mayContain: msExchPolicyLastAppliedTime
+mayContain: msExchPolicyOptionList
+mayContain: msExchPolicyLockDown
+mayContain: msExchPolicyListBL
+mayContain: msExchPolicyDefault
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Computer-Policy
+adminDescription: ms-Exch-Computer-Policy
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchComputerPolicy
+name: ms-Exch-Computer-Policy
+schemaIDGUID: ed2c752c-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Computer-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Conference-Container
+# A conferencing container. Used for extended rights and
+# roles. CN=Exchange Conferencing.
+#
+dn: CN=ms-Exch-Conference-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Conference-Container
+distinguishedName: CN=ms-Exch-Conference-Container,${SCHEMADN}
+possSuperiors: msExchAdminGroup
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.9005
+mayContain: objectCount
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Conference-Container
+adminDescription: ms-Exch-Conference-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchConferenceContainer
+name: ms-Exch-Conference-Container
+schemaIDGUID: ed7fe77a-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;CI;LCLORPRC;;;WD)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Conference-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Conference-Site
+# An Exchange Conferencing-Zone Configuration Interface Class.
+#
+dn: CN=ms-Exch-Conference-Site,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Conference-Site
+distinguishedName: CN=ms-Exch-Conference-Site,${SCHEMADN}
+possSuperiors: msExchConferenceContainer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.9001
+mayContain: msExchConferenceMailbox
+mayContain: msExchConferenceZone
+mayContain: displayName
+mayContain: wWWHomePage
+mayContain: serverName
+mayContain: objectCount
+mayContain: msExchGracePeriodPrior
+mayContain: msExchGracePeriodAfter
+mayContain: msExchAvailableServers
+mayContain: msExchAuditFlags
+mayContain: msExchAllowTimeExtensions
+mayContain: msExchAllowAdditionalResources
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Conference-Site
+adminDescription: ms-Exch-Conference-Site
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchConferenceSite
+name: ms-Exch-Conference-Site
+schemaIDGUID: eddce330-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Conference-Site,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Connection-Agreement
+# Used to store synchronization information.
+#
+dn: CN=ms-Exch-Connection-Agreement,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Connection-Agreement
+distinguishedName: CN=ms-Exch-Connection-Agreement,${SCHEMADN}
+possSuperiors: organizationalUnit
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.3
+mayContain: msExchIsConfigCA
+mayContain: msExchInterOrgAddressType
+mayContain: msExchMoveToLSA
+mayContain: msExchServer2HighestUSNVector
+mayContain: msExchServer1HighestUSNVector
+mayContain: msExchExchangeSite
+mayContain: msExchADCObjectType
+mayContain: msExchServer2IsBridgehead
+mayContain: msExchServer1IsBridgehead
+mayContain: versionNumber
+mayContain: msExchSynchronizationDirection
+mayContain: msExchServer2Type
+mayContain: msExchServer2SSLPort
+mayContain: msExchServer2SearchFilter
+mayContain: msExchServer2SchemaMap
+mayContain: msExchServer2Port
+mayContain: msExchServer2PageSize
+mayContain: msExchServer2NTAccountDomain
+mayContain: msExchServer2NetworkAddress
+mayContain: msExchServer2LastUpdateTime
+mayContain: msExchServer2ImportContainer
+mayContain: msExchServer2HighestUSN
+mayContain: msExchServer2Flags
+mayContain: msExchServer2ExportContainers
+mayContain: msExchServer2DeletionOption
+mayContain: msExchServer2AuthenticationType
+mayContain: msExchServer2AuthenticationPassword
+mayContain: msExchServer2AuthenticationCredentials
+mayContain: msExchServer2AlwaysCreateAs
+mayContain: msExchServer1Type
+mayContain: msExchServer1SSLPort
+mayContain: msExchServer1SearchFilter
+mayContain: msExchServer1SchemaMap
+mayContain: msExchServer1Port
+mayContain: msExchServer1PageSize
+mayContain: msExchServer1NTAccountDomain
+mayContain: msExchServer1NetworkAddress
+mayContain: msExchServer1LastUpdateTime
+mayContain: msExchServer1ImportContainer
+mayContain: msExchServer1HighestUSN
+mayContain: msExchServer1Flags
+mayContain: msExchServer1ExportContainers
+mayContain: msExchServer1DeletionOption
+mayContain: msExchServer1AuthenticationType
+mayContain: msExchServer1AuthenticationPassword
+mayContain: msExchServer1AuthenticationCredentials
+mayContain: msExchServer1AlwaysCreateAs
+mayContain: msExchReplicateNow
+mayContain: msExchRemoteServerList
+mayContain: msExchRemotePrivateISList
+mayContain: msExchNtdsImportContainer
+mayContain: msExchNtdsExportContainers
+mayContain: msExchNTAccountOptions
+mayContain: msExchIsBridgeheadSite
+mayContain: msExchHomeSyncService
+mayContain: msExchHomeServerName
+mayContain: msExchDoFullReplication
+mayContain: msExchDereferenceAliases
+mayContain: msExchCorrelationAttribute
+mayContain: msExchCASchemaPolicy
+mayContain: msExchAdditionalDNMap
+mayContain: msExchADCOptions
+mayContain: activationStyle
+mayContain: activationSchedule
+mayContain: displayName
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Connection-Agreement
+adminDescription: ms-Exch-Connection-Agreement
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchConnectionAgreement
+name: ms-Exch-Connection-Agreement
+schemaIDGUID: ee64c93a-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Connection-Agreement,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Connector
+#
+dn: CN=ms-Exch-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Connector
+distinguishedName: CN=ms-Exch-Connector,${SCHEMADN}
+possSuperiors: msExchConnectors
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.12004
+mayContain: msExchMinAdminVersion
+mayContain: msExchInconsistentState
+mayContain: delivContLength
+mayContain: msExchNoPFConnection
+mayContain: versionNumber
+mayContain: msExchMasterAccountSid
+mayContain: msExchMailboxSecurityDescriptor
+mayContain: msExchMailboxGuid
+mayContain: msExchRoutingDisallowPriority
+mayContain: unauthOrig
+mayContain: msExchTargetBridgeheadServersDN
+mayContain: msExchSourceBridgeheadServersDN
+mayContain: msExchRoutingTriggeredStyle
+mayContain: msExchRoutingTriggeredSchedule
+mayContain: msExchRoutingOversizedStyle
+mayContain: msExchRoutingOversizedSchedule
+mayContain: routingList
+mayContain: messageSizeLimit
+mayContain: dLMemSubmitPerms
+mayContain: dLMemRejectPerms
+mayContain: dLMemDefault
+mayContain: msExchDestinationRGDN
+mayContain: msExchConnectorType
+mayContain: connectedDomains
+mayContain: authOrig
+mayContain: activationStyle
+mayContain: activationSchedule
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Connector
+adminDescription: ms-Exch-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchConnector
+name: ms-Exch-Connector
+schemaIDGUID: 89652316-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Connectors
+# Container used to hold connection objects.
+#
+dn: CN=ms-Exch-Connectors,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Connectors
+distinguishedName: CN=ms-Exch-Connectors,${SCHEMADN}
+possSuperiors: msExchRoutingGroup
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.12003
+mayContain: msExchMinAdminVersion
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Connectors
+adminDescription: ms-Exch-Connectors
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchConnectors
+name: ms-Exch-Connectors
+schemaIDGUID: eee325dc-a980-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Connectors,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Container
+# An Exchange container. Used for extended rights and roles.
+#
+dn: CN=ms-Exch-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Container
+distinguishedName: CN=ms-Exch-Container,${SCHEMADN}
+possSuperiors: msExchAdminGroup
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.50010
+mayContain: msExchMinAdminVersion
+mayContain: msExchAdminGroupMode
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Container
+adminDescription: ms-Exch-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchContainer
+name: ms-Exch-Container
+schemaIDGUID: 006c91da-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Content-Config-Container
+#
+dn: CN=ms-Exch-Content-Config-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Content-Config-Container
+distinguishedName: CN=ms-Exch-Content-Config-Container,${SCHEMADN}
+possSuperiors: container
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.50026
+mayContain: msExchMinAdminVersion
+mayContain: msExchMimeTypes
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Content-Config-Container
+adminDescription: ms-Exch-Content-Config-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchContentConfigContainer
+name: ms-Exch-Content-Config-Container
+schemaIDGUID: ab3a1acc-1df5-11d3-aa5e-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Content-Config-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CTP
+# An Exchange conference technology provider (CTP)
+# template. CN=Exchange Data Conferencing Service.
+#
+dn: CN=ms-Exch-CTP,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-CTP
+distinguishedName: CN=ms-Exch-CTP,${SCHEMADN}
+possSuperiors: msExchConferenceSite
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.9002
+mayContain: objectCount
+mayContain: msExchCTPSnapinGUID
+mayContain: msExchCTPRequireCMSAuthentication
+mayContain: msExchCTPProviderName
+mayContain: msExchCTPProviderGUID
+mayContain: msExchCTPPropertySchema
+mayContain: msExchCTPFrameHint
+mayContain: msExchCTPClassGUID
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CTP
+adminDescription: ms-Exch-CTP
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchCTP
+name: ms-Exch-CTP
+schemaIDGUID: 00aa8efe-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-CTP,${SCHEMADN}
+
+
+#
+# ms-Exch-Custom-Attributes
+# The auxiliary class for objects that require custom attributes.
+#
+dn: CN=ms-Exch-Custom-Attributes,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Custom-Attributes
+distinguishedName: CN=ms-Exch-Custom-Attributes,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.6
+mayContain: extensionAttribute9
+mayContain: extensionAttribute8
+mayContain: extensionAttribute7
+mayContain: extensionAttribute6
+mayContain: extensionAttribute5
+mayContain: extensionAttribute4
+mayContain: extensionAttribute3
+mayContain: extensionAttribute2
+mayContain: extensionAttribute15
+mayContain: extensionAttribute14
+mayContain: extensionAttribute13
+mayContain: extensionAttribute12
+mayContain: extensionAttribute11
+mayContain: extensionAttribute10
+mayContain: extensionAttribute1
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Custom-Attributes
+adminDescription: ms-Exch-Custom-Attributes
+objectClassCategory: 3
+lDAPDisplayName: msExchCustomAttributes
+name: ms-Exch-Custom-Attributes
+schemaIDGUID: 00e629c8-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Custom-Attributes,${SCHEMADN}
+
+
+#
+# ms-Exch-Domain-Content-Config
+#
+dn: CN=ms-Exch-Domain-Content-Config,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Domain-Content-Config
+distinguishedName: CN=ms-Exch-Domain-Content-Config,${SCHEMADN}
+possSuperiors: msExchContentConfigContainer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.50027
+mayContain: msExchMinAdminVersion
+mayContain: versionNumber
+mayContain: msExchRoutingAcceptMessageType
+mayContain: msExchResolveP2
+mayContain: msExchNonMIMECharacterSet
+mayContain: msExchEncodeSMTPRelay
+mayContain: sendTNEF
+mayContain: msExchRoutingDisplaySenderEnabled
+mayContain: lineWrap
+mayContain: domainName
+mayContain: contentType
+mayContain: characterSet
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Domain-Content-Config
+adminDescription: ms-Exch-Domain-Content-Config
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchDomainContentConfig
+name: ms-Exch-Domain-Content-Config
+schemaIDGUID: ab3a1ad1-1df5-11d3-aa5e-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Domain-Content-Config,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Site-Server
+# The hub for all of the directory exchange agent (DXA) server
+# connections.
+#
+dn: CN=ms-Exch-DXA-Site-Server,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-DXA-Site-Server
+distinguishedName: CN=ms-Exch-DXA-Site-Server,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.3.60
+mustContain: cn
+mayContain: versionNumber
+mayContain: assocRemoteDXA
+mayContain: responsibleLocalDXA
+mayContain: dXALocalAdmin
+mayContain: dXAAdminForward
+mayContain: dXAAdminCopy
+mayContain: activationStyle
+mayContain: activationSchedule
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Site-Server
+adminDescription: ms-Exch-DXA-Site-Server
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: dXASiteServer
+name: ms-Exch-DXA-Site-Server
+schemaIDGUID: a8df74b0-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-DXA-Site-Server,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DX-Requestor
+# The remote directory exchange agent (DXA) requestor.
+#
+dn: CN=ms-Exch-DX-Requestor,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-DX-Requestor
+distinguishedName: CN=ms-Exch-DX-Requestor,${SCHEMADN}
+possSuperiors: container
+subClassOf: remoteDXA
+governsID: 1.2.840.113556.1.3.19
+mayContain: activationStyle
+mayContain: activationSchedule
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DX-Requestor
+adminDescription: ms-Exch-DX-Requestor
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: dXRequestor
+name: ms-Exch-DX-Requestor
+schemaIDGUID: a8df74ae-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-DX-Requestor,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DX-Server-Conn
+# The remote directory exchange agent (DXA) server.
+#
+dn: CN=ms-Exch-DX-Server-Conn,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-DX-Server-Conn
+distinguishedName: CN=ms-Exch-DX-Server-Conn,${SCHEMADN}
+possSuperiors: dXASiteServer
+subClassOf: remoteDXA
+governsID: 1.2.840.113556.1.3.20
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DX-Server-Conn
+adminDescription: ms-Exch-DX-Server-Conn
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: dXServerConn
+name: ms-Exch-DX-Server-Conn
+schemaIDGUID: a8df74af-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-DX-Server-Conn,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Dynamic-Distribution-List
+#
+dn: CN=ms-Exch-Dynamic-Distribution-List,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Dynamic-Distribution-List
+distinguishedName: CN=ms-Exch-Dynamic-Distribution-List,${SCHEMADN}
+possSuperiors: organizationalUnit
+possSuperiors: domainDNS
+possSuperiors: builtinDomain
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.12006
+mayContain: msExchPurportedSearchUI
+mayContain: msExchDynamicDLFilter
+mayContain: msExchDynamicDLBaseDN
+mayContain: managedBy
+mayContain: reportToOwner
+mayContain: reportToOriginator
+mayContain: oOFReplyToOriginator
+mayContain: msExchMemberFilter
+mayContain: msExchMemberBaseDN
+mayContain: hideDLMembership
+mayContain: mail
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Dynamic-Distribution-List
+adminDescription: ms-Exch-Dynamic-Distribution-List
+auxiliaryClass: msExchCustomAttributes
+auxiliaryClass: msExchBaseClass
+auxiliaryClass: mailRecipient
+objectClassCategory: 1
+lDAPDisplayName: msExchDynamicDistributionList
+name: ms-Exch-Dynamic-Distribution-List
+schemaIDGUID: 018849b0-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;RP;;;AU)
+defaultHidingValue: FALSE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Dynamic-Distribution-List,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Encryption-Cfg
+# Contains attributes that configure security policies for each
+# Administrative group.
+#
+dn: CN=ms-Exch-Encryption-Cfg,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Encryption-Cfg
+distinguishedName: CN=ms-Exch-Encryption-Cfg,${SCHEMADN}
+possSuperiors: msExchAdvancedSecurityContainer
+subClassOf: top
+governsID: 1.2.840.113556.1.3.16
+mustContain: cn
+mayContain: msExchMinAdminVersion
+mayContain: sMIMEAlgSelectedOther
+mayContain: sMIMEAlgSelectedNA
+mayContain: sMIMEAlgListOther
+mayContain: sMIMEAlgListNA
+mayContain: kMServer
+mayContain: encryptAlgSelectedOther
+mayContain: encryptAlgSelectedNA
+mayContain: encryptAlgListOther
+mayContain: encryptAlgListNA
+mayContain: defaultMessageFormat
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Encryption-Cfg
+adminDescription: ms-Exch-Encryption-Cfg
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: encryptionCfg
+name: ms-Exch-Encryption-Cfg
+schemaIDGUID: a8df74b1-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;RP;;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Encryption-Cfg,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Exchange-Admin-Service
+# The MAD process.
+#
+dn: CN=ms-Exch-Exchange-Admin-Service,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Exchange-Admin-Service
+distinguishedName: CN=ms-Exch-Exchange-Admin-Service,${SCHEMADN}
+possSuperiors: msExchExchangeServer
+possSuperiors: container
+possSuperiors: computer
+subClassOf: top
+governsID: 1.2.840.113556.1.3.62
+mustContain: deliveryMechanism
+mayContain: msExchMinAdminVersion
+mayContain: diagnosticRegKey
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Exchange-Admin-Service
+adminDescription: ms-Exch-Exchange-Admin-Service
+auxiliaryClass: msExchBaseClass
+auxiliaryClass: msExchMailStorage
+auxiliaryClass: mailRecipient
+objectClassCategory: 1
+lDAPDisplayName: exchangeAdminService
+name: ms-Exch-Exchange-Admin-Service
+schemaIDGUID: a8df74b2-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Exchange-Admin-Service,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Exchange-Server
+# A representation of an Exchange server object.
+#
+dn: CN=ms-Exch-Exchange-Server,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Exchange-Server
+distinguishedName: CN=ms-Exch-Exchange-Server,${SCHEMADN}
+possSuperiors: msExchServersContainer
+subClassOf: server
+governsID: 1.2.840.113556.1.5.7000.62.50009
+mayContain: msExchMinAdminVersion
+mayContain: msExchFolderAffinityList
+mayContain: msExchFolderAffinityCustom
+mayContain: msExchHomeRoutingGroupDNBL
+mayContain: msExchHomeRoutingGroup
+mayContain: msExchVPIMConvertOutbound
+mayContain: msExchVPIMConvertInbound
+mayContain: msExchServerPublicKey
+mayContain: msExchMonitoringResources
+mayContain: msExchMonitoringPollingRate
+mayContain: msExchMonitoringNotificationRate
+mayContain: msExchMonitoringMode
+mayContain: msExchMailboxManagerReportRecipient
+mayContain: msExchMailboxManagerAdminMode
+mayContain: msExchMailboxManagerActivationStyle
+mayContain: msExchMailboxManagerActivationSchedule
+mayContain: msExchResponsibleMTAServer
+mayContain: msExchPolicyOptionList
+mayContain: msExchPolicyList
+mayContain: msExchMonitoringResponses
+mayContain: msExchMonitoringQueuePollingInterval
+mayContain: msExchMonitoringQueuePollingFrequency
+mayContain: msExchMonitoringMonitoredServices
+mayContain: msExchMonitoringDiskSpace
+mayContain: monitoredServices
+mayContain: msExchInstalledComponents
+mayContain: msExchDataPath
+mayContain: msExchServerRole
+mayContain: msExchMessageTrackLogFilter
+mayContain: versionNumber
+mayContain: serverRole
+mayContain: serialNumber
+mayContain: msExchTrkLogCleaningInterval
+mayContain: messageTrackingEnabled
+mayContain: msExchLocales
+mayContain: msExchInstallPath
+mayContain: heuristics
+mayContain: msExchComputerLink
+mayContain: msExchAddressListServiceBL
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Exchange-Server
+adminDescription: ms-Exch-Exchange-Server
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchExchangeServer
+name: ms-Exch-Exchange-Server
+schemaIDGUID: 01a9aa9c-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;RP;;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Exchange-Server,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Configuration-Container
+# description: This container stores configuration information for the Exchange server.
+#
+dn: CN=ms-Exch-Configuration-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Configuration-Container
+distinguishedName: CN=ms-Exch-Configuration-Container,${SCHEMADN}
+subClassOf: container
+governsID: 1.2.840.113556.1.5.176
+mayContain: msExchPolicyRoots
+mayContain: msExchMasterService
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Configuration-Container
+adminDescription: ms-Exch-Configuration-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchConfigurationContainer
+name: ms-Exch-Configuration-Container
+schemaIDGUID: d03d6858-06f4-11d2-aa53-00c04fd7d83a
+systemOnly: FALSE
+systemMayContain: templateRoots
+systemMayContain: addressBookRoots
+systemMayContain: globalAddressList
+defaultSecurityDescriptor: D:S:
+systemFlags: 16
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Configuration-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Exchange-Server-Policy
+# The Exchange server policy.
+#
+dn: CN=ms-Exch-Exchange-Server-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Exchange-Server-Policy
+distinguishedName: CN=ms-Exch-Exchange-Server-Policy,${SCHEMADN}
+possSuperiors: container
+subClassOf: msExchExchangeServer
+governsID: 1.2.840.113556.1.5.7000.62.50025
+mayContain: msExchPolicyOptionList
+mayContain: msExchPolicyLockDown
+mayContain: msExchPolicyListBL
+mayContain: msExchPolicyLastAppliedTime
+mayContain: msExchPolicyDefault
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Exchange-Server-Policy
+adminDescription: ms-Exch-Exchange-Server-Policy
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchExchangeServerPolicy
+name: ms-Exch-Exchange-Server-Policy
+schemaIDGUID: e497942f-1d42-11d3-aa5e-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Exchange-Server-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Generic-Policy
+#
+dn: CN=ms-Exch-Generic-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Generic-Policy
+distinguishedName: CN=ms-Exch-Generic-Policy,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.50022
+mayContain: purportedSearch
+mayContain: msExchPurportedSearchUI
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Generic-Policy
+adminDescription: ms-Exch-Generic-Policy
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchGenericPolicy
+name: ms-Exch-Generic-Policy
+schemaIDGUID: e32977cd-1d31-11d3-aa5e-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Generic-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Generic-Policy-Container
+#
+dn: CN=ms-Exch-Generic-Policy-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Generic-Policy-Container
+distinguishedName: CN=ms-Exch-Generic-Policy-Container,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.50021
+mayContain: msExchADCOptions
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Generic-Policy-Container
+adminDescription: ms-Exch-Generic-Policy-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchGenericPolicyContainer
+name: ms-Exch-Generic-Policy-Container
+schemaIDGUID: e32977c3-1d31-11d3-aa5e-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Generic-Policy-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-GroupWise-Connector
+# The GroupWise Connector.
+#
+dn: CN=ms-Exch-GroupWise-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-GroupWise-Connector
+distinguishedName: CN=ms-Exch-GroupWise-Connector,${SCHEMADN}
+possSuperiors: container
+subClassOf: mailGateway
+governsID: 1.2.840.113556.1.5.7000.62.1005
+mayContain: msExchGWiseUserId
+mayContain: msExchGWisePassword
+mayContain: msExchGWiseForeignDomain
+mayContain: msExchGWiseFilterType
+mayContain: msExchGWiseAPIGatewayPath
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-GroupWise-Connector
+adminDescription: ms-Exch-GroupWise-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchGroupWiseConnector
+name: ms-Exch-GroupWise-Connector
+schemaIDGUID: 91eaaac4-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-GroupWise-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-Firewall
+# The Instant Messaging representation of firewalls.
+#
+dn: CN=ms-Exch-IM-Firewall,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-IM-Firewall
+distinguishedName: CN=ms-Exch-IM-Firewall,${SCHEMADN}
+possSuperiors: msExchIMGlobalSettingsContainer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.7015
+mustContain: msExchIMFirewallType
+mayContain: portNumber
+mayContain: msExchIMProxy
+mayContain: msExchIMIPRange
+mayContain: flags
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Firewall
+adminDescription: ms-Exch-IM-Firewall
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchIMFirewall
+name: ms-Exch-IM-Firewall
+schemaIDGUID: 9f116ebe-284e-11d3-aa68-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-IM-Firewall,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-Global-Settings-Container
+# A container for global objects.
+#
+dn: CN=ms-Exch-IM-Global-Settings-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-IM-Global-Settings-Container
+distinguishedName: CN=ms-Exch-IM-Global-Settings-Container,${SCHEMADN}
+possSuperiors: container
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.7014
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Global-Settings-Container
+adminDescription: ms-Exch-IM-Global-Settings-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchIMGlobalSettingsContainer
+name: ms-Exch-IM-Global-Settings-Container
+schemaIDGUID: 9f116eb8-284e-11d3-aa68-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-IM-Global-Settings-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-Recipient
+# The auxiliary class for all objects that will be enabled for Instant
+# Messaging.
+#
+dn: CN=ms-Exch-IM-Recipient,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-IM-Recipient
+distinguishedName: CN=ms-Exch-IM-Recipient,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.7008
+mayContain: msExchIMVirtualServer
+mayContain: msExchIMAddress
+mayContain: msExchIMPhysicalURL
+mayContain: msExchIMMetaPhysicalURL
+mayContain: msExchIMACL
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Recipient
+adminDescription: ms-Exch-IM-Recipient
+objectClassCategory: 3
+lDAPDisplayName: msExchIMRecipient
+name: ms-Exch-IM-Recipient
+schemaIDGUID: 028502f4-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-IM-Recipient,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Information-Store
+# The Information Store configuration.
+#
+dn: CN=ms-Exch-Information-Store,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Information-Store
+distinguishedName: CN=ms-Exch-Information-Store,${SCHEMADN}
+possSuperiors: msExchExchangeServer
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.11001
+mustContain: cn
+mayContain: msExchMinAdminVersion
+mayContain: msExchMaxRestoreStorageGroups
+mayContain: msExchRecovery
+mayContain: msExchESEParamZeroDatabaseDuringBackup
+mayContain: msExchESEParamPageTempDBMin
+mayContain: msExchESEParamPageFragment
+mayContain: msExchESEParamLogFileSize
+mayContain: msExchESEParamLogCheckpointPeriod
+mayContain: msExchESEParamLogBuffers
+mayContain: msExchESEParamGlobalMinVerPages
+mayContain: msExchESEParamEventSource
+mayContain: msExchESEParamEnableSortedRetrieveColumns
+mayContain: msExchESEParamEnableOnlineDefrag
+mayContain: msExchESEParamEnableIndexChecking
+mayContain: msExchESEParamDbExtensionSize
+mayContain: msExchESEParamCommitDefault
+mayContain: msExchESEParamCircularLog
+mayContain: msExchESEParamCacheSizeMin
+mayContain: msExchESEParamBaseName
+mayContain: msExchESEParamAssertAction
+mayContain: msExchESEParamStopFlushThreshold
+mayContain: msExchESEParamStartFlushThreshold
+mayContain: msExchQueuingMDB
+mayContain: msExchOwningOrg
+mayContain: msExchMinimumThreads
+mayContain: msExchMaxThreads
+mayContain: msExchMaxStoresPerGroup
+mayContain: msExchMaxStorageGroups
+mayContain: msExchMaxPoolThreads
+mayContain: msExchIFSPublicName
+mayContain: msExchIFSPublicEnabled
+mayContain: msExchIFSPrivateName
+mayContain: msExchIFSPrivateEnabled
+mayContain: msExchESEParamCacheSizeMax
+mayContain: msExchESEParamCacheSize
+mayContain: msExchDatabaseSessionIncrement
+mayContain: msExchDatabaseSessionAddend
+mayContain: msExchBackgroundThreads
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Information-Store
+adminDescription: ms-Exch-Information-Store
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchInformationStore
+name: ms-Exch-Information-Store
+schemaIDGUID: 031b371a-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Information-Store,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Ip-Conf-Container
+# The Exchange Video Conferencing container.
+#
+dn: CN=ms-Exch-Ip-Conf-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Ip-Conf-Container
+distinguishedName: CN=ms-Exch-Ip-Conf-Container,${SCHEMADN}
+possSuperiors: msExchConferenceSite
+subClassOf: msExchCTP
+governsID: 1.2.840.113556.1.5.7000.62.9006
+mayContain: msExchMaxParticipants
+mayContain: msExchMaxExtensionTime
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Ip-Conf-Container
+adminDescription: ms-Exch-Ip-Conf-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchIpConfContainer
+name: ms-Exch-Ip-Conf-Container
+schemaIDGUID: 99f5866d-12e8-11d3-aa58-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Ip-Conf-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Key-Management-Server
+# Holds configuration attributes for each Key Management Service.
+#
+dn: CN=ms-Exch-Key-Management-Server,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Key-Management-Server
+distinguishedName: CN=ms-Exch-Key-Management-Server,${SCHEMADN}
+possSuperiors: msExchAdvancedSecurityContainer
+subClassOf: certificationAuthority
+governsID: 1.2.840.113556.1.5.7000.62.13002
+mayContain: sendEMailMessage
+mayContain: securityPolicy
+mayContain: kMServer
+mayContain: kCCStatus
+mayContain: expirationTime
+mayContain: enableCompatibility
+mayContain: dXAPrevTypes
+mayContain: dXAAdminForward
+mayContain: domainDefAltRecip
+mayContain: crossCertificateCRL
+mayContain: compromisedKeyList
+mayContain: certificateRevocationListV3
+mayContain: certificateRevocationListV1
+mayContain: certificateChainV3
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Key-Management-Server
+adminDescription: ms-Exch-Key-Management-Server
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchKeyManagementServer
+name: ms-Exch-Key-Management-Server
+schemaIDGUID: 8ce334ec-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;RP;;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Key-Management-Server,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Local-DXA
+# Represents the directory exchange agent (DXA) process.
+#
+dn: CN=ms-Exch-Local-DXA,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Local-DXA
+distinguishedName: CN=ms-Exch-Local-DXA,${SCHEMADN}
+possSuperiors: msExchExchangeServer
+possSuperiors: container
+possSuperiors: computer
+subClassOf: top
+governsID: 1.2.840.113556.1.3.1
+mustContain: deliveryMechanism
+mayContain: msExchServer1NetworkAddress
+mayContain: msExchServer1AlwaysCreateAs
+mayContain: delivEITs
+mayContain: dXATemplateTimeStamp
+mayContain: dXAOutTemplateMap
+mayContain: dXAInTemplateMap
+mayContain: dXAAdminUpdate
+mayContain: diagnosticRegKey
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Local-DXA
+adminDescription: ms-Exch-Local-DXA
+auxiliaryClass: msExchBaseClass
+auxiliaryClass: mailRecipient
+objectClassCategory: 1
+lDAPDisplayName: localDXA
+name: ms-Exch-Local-DXA
+schemaIDGUID: a8df74b5-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Local-DXA,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Policy
+#
+dn: CN=ms-Exch-Mailbox-Manager-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Mailbox-Manager-Policy
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Policy,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.50033
+mayContain: msExchMailboxManagerUserMessageHeader
+mayContain: msExchMailboxManagerUserMessageFooter
+mayContain: msExchMailboxManagerUserMessageBody
+mayContain: msExchMailboxManagerSizeLimitEnabled
+mayContain: msExchMailboxManagerSizeLimit
+mayContain: msExchMailboxManagerSendUserNotificationMail
+mayContain: msExchMailboxManagerMode
+mayContain: msExchMailboxManagerKeepMessageClasses
+mayContain: msExchMailboxManagerFolderSettings
+mayContain: msExchMailboxManagerCustomMessage
+mayContain: msExchMailboxManagerAgeLimit
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Policy
+adminDescription: ms-Exch-Mailbox-Manager-Policy
+objectClassCategory: 3
+lDAPDisplayName: msExchMailboxManagerPolicy
+name: ms-Exch-Mailbox-Manager-Policy
+schemaIDGUID: 36f94fcc-ebbb-4a32-b721-1cae42b2dbab
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Mailbox-Manager-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mail-Connector
+# The Microsoft Mail Connector object.
+#
+dn: CN=ms-Exch-Mail-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Mail-Connector
+distinguishedName: CN=ms-Exch-Mail-Connector,${SCHEMADN}
+possSuperiors: container
+subClassOf: mailGateway
+governsID: 1.2.840.113556.1.3.61
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mail-Connector
+adminDescription: ms-Exch-Mail-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: mailConnector
+name: ms-Exch-Mail-Connector
+schemaIDGUID: a8df74b6-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Mail-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mail-Gateway
+# The main Gateway class.
+#
+dn: CN=ms-Exch-Mail-Gateway,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Mail-Gateway
+distinguishedName: CN=ms-Exch-Mail-Gateway,${SCHEMADN}
+possSuperiors: container
+subClassOf: msExchConnector
+governsID: 1.2.840.113556.1.3.51
+mustContain: homeMTA
+mustContain: deliveryMechanism
+mustContain: cn
+mayContain: msExchBarMessageClass
+mayContain: msExchEncryptedPassword2
+mayContain: msExchEncryptedPassword
+mayContain: msExchServer1NetworkAddress
+mayContain: msExchMaintenanceStyle
+mayContain: msExchMaintenanceSchedule
+mayContain: msExchImportContainerLinked
+mayContain: msExchExportContainersLinked
+mayContain: msExchServer1AlwaysCreateAs
+mayContain: msExchDirsyncStyle
+mayContain: msExchDirsyncSchedule
+mayContain: supportedApplicationContext
+mayContain: translationTableUsed
+mayContain: transferTimeoutUrgent
+mayContain: transferTimeoutNormal
+mayContain: transferTimeoutNonUrgent
+mayContain: transferRetryInterval
+mayContain: msExchSourceBHAddress
+mayContain: replicationSensitivity
+mayContain: pRMD
+mayContain: msExchPartnerLanguage
+mayContain: msExchPartnerCP
+mayContain: mDBUnreadLimit
+mayContain: mDBStorageQuota
+mayContain: mDBMsgTimeOutPeriod
+mayContain: mDBBackoffInterval
+mayContain: lineWrap
+mayContain: importContainer
+mayContain: homeMDB
+mayContain: msExchExportDLs
+mayContain: exportCustomRecipients
+mayContain: exportContainers
+mayContain: encapsulationMethod
+mayContain: msExchDirsyncFilters
+mayContain: diagnosticRegKey
+mayContain: msExchDestinationRGDN
+mayContain: msExchDestBHAddress
+mayContain: msExchDeliveryOrder
+mayContain: delivExtContTypes
+mayContain: delivEITs
+mayContain: delivContLength
+mayContain: msExchConnectorType
+mayContain: computerName
+mayContain: canPreserveDNs
+mayContain: msExchAdminMailbox
+mayContain: aDMD
+mayContain: c
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mail-Gateway
+adminDescription: ms-Exch-Mail-Gateway
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: mailGateway
+name: ms-Exch-Mail-Gateway
+schemaIDGUID: a8df74b7-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Mail-Gateway,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mail-Storage
+# The auxiliary class for objects that require store-specific information.
+#
+dn: CN=ms-Exch-Mail-Storage,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Mail-Storage
+distinguishedName: CN=ms-Exch-Mail-Storage,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.5
+mayContain: msExchPfRootUrl
+mayContain: msExchMailboxUrl
+mayContain: msExchUseOAB
+mayContain: msExchMailboxGuid
+mayContain: mDBUseDefaults
+mayContain: mDBStorageQuota
+mayContain: mDBOverQuotaLimit
+mayContain: mDBOverHardQuotaLimit
+mayContain: msExchHomeServerName
+mayContain: homeMDB
+mayContain: deletedItemFlags
+mayContain: autoReply
+mayContain: garbageCollPeriod
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mail-Storage
+adminDescription: ms-Exch-Mail-Storage
+objectClassCategory: 3
+lDAPDisplayName: msExchMailStorage
+name: ms-Exch-Mail-Storage
+schemaIDGUID: 03652000-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Mail-Storage,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MCU
+# The Exchange Conferencing Multipoint Control Unit (MCU) Configuration
+# Interface . CN=MachineName.
+#
+dn: CN=ms-Exch-MCU,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-MCU
+distinguishedName: CN=ms-Exch-MCU,${SCHEMADN}
+possSuperiors: msExchMCUContainer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.9004
+mayContain: msExchMCUHostsSites
+mayContain: msExchVisibilityMask
+mayContain: msExchScopeMask
+mayContain: msExchProxyName
+mayContain: msExchLocalName
+mayContain: msExchInternetName
+mayContain: enabledConnection
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MCU
+adminDescription: ms-Exch-MCU
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchMCU
+name: ms-Exch-MCU
+schemaIDGUID: 038680ec-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-MCU,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MCU-Container
+# The Exchange Data Conference Service class. CN=Exchange Data
+# Conferencing Service.
+#
+dn: CN=ms-Exch-MCU-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-MCU-Container
+distinguishedName: CN=ms-Exch-MCU-Container,${SCHEMADN}
+possSuperiors: msExchConferenceSite
+subClassOf: msExchCTP
+governsID: 1.2.840.113556.1.5.7000.62.9003
+mayContain: rangeUpper
+mayContain: rangeLower
+mayContain: msExchMaxConnections
+mayContain: msExchListPublic
+mayContain: msExchCertificate
+mayContain: msExchAuditFlags
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MCU-Container
+adminDescription: ms-Exch-MCU-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchMCUContainer
+name: ms-Exch-MCU-Container
+schemaIDGUID: 03aa4432-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-MCU-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MDB
+# Used for generic database configuration.
+#
+dn: CN=ms-Exch-MDB,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-MDB
+distinguishedName: CN=ms-Exch-MDB,${SCHEMADN}
+possSuperiors: msExchStorageGroup
+possSuperiors: msExchExchangeServer
+possSuperiors: container
+possSuperiors: computer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.11002
+mustContain: deliveryMechanism
+mustContain: cn
+mayContain: msExchMinAdminVersion
+mayContain: msExchPatchMDB
+mayContain: msExchDatabaseCreated
+mayContain: msExchDatabaseBeingRestored
+mayContain: msExchAllowEnhancedSecurity
+mayContain: msExchMaxCachedViews
+mayContain: msExchCIUpdateStyle
+mayContain: msExchCIUpdateSchedule
+mayContain: msExchCIRebuildStyle
+mayContain: msExchCIRebuildSchedule
+mayContain: msExchCILocation
+mayContain: msExchCIAvailable
+mayContain: msExchAgingKeepTime
+mayContain: homeMDBBL
+mayContain: msExchTrackDuplicates
+mayContain: msExchSLVFile
+mayContain: quotaNotificationStyle
+mayContain: quotaNotificationSchedule
+mayContain: msExchPolicyOptionList
+mayContain: msExchPolicyList
+mayContain: msExchOwningServer
+mayContain: messageTrackingEnabled
+mayContain: mDBStorageQuota
+mayContain: mDBOverQuotaLimit
+mayContain: mDBOverHardQuotaLimit
+mayContain: maximumObjectID
+mayContain: msExchEDBOffline
+mayContain: msExchEDBFile
+mayContain: msExchDownGradeMultipartSigned
+mayContain: diagnosticRegKey
+mayContain: deletedItemFlags
+mayContain: msExchConvertToFixedFont
+mayContain: msExchCatalog
+mayContain: activationStyle
+mayContain: activationSchedule
+mayContain: garbageCollPeriod
+mayContain: displayName
+mayContain: description
+mayContain: adminDisplayName
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MDB
+adminDescription: ms-Exch-MDB
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchMDB
+name: ms-Exch-MDB
+schemaIDGUID: 03d069d2-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-MDB,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Message-Delivery-Config
+#
+dn: CN=ms-Exch-Message-Delivery-Config,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Message-Delivery-Config
+distinguishedName: CN=ms-Exch-Message-Delivery-Config,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.50028
+mayContain: msExchMinAdminVersion
+mayContain: msExchTurfListAction
+mayContain: submissionContLength
+mayContain: msExchRecipLimit
+mayContain: msExchLocalDomains
+mayContain: delivContLength
+mayContain: msExchAdminMailbox
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Message-Delivery-Config
+adminDescription: ms-Exch-Message-Delivery-Config
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchMessageDeliveryConfig
+name: ms-Exch-Message-Delivery-Config
+schemaIDGUID: ab3a1ad7-1df5-11d3-aa5e-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Message-Delivery-Config,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MHS-Link-Monitoring-Config
+# The EMS saved Linked Monitoring configuration.
+#
+dn: CN=ms-Exch-MHS-Link-Monitoring-Config,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-MHS-Link-Monitoring-Config
+distinguishedName: CN=ms-Exch-MHS-Link-Monitoring-Config,${SCHEMADN}
+possSuperiors: container
+subClassOf: mHSMonitoringConfig
+governsID: 1.2.840.113556.1.3.12
+mayContain: monitoringWarningUnits
+mayContain: monitoringWarningDelay
+mayContain: monitoringRecipientsNDR
+mayContain: monitoringRecipients
+mayContain: monitoringAlertUnits
+mayContain: monitoringAlertDelay
+mayContain: monitorServers
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MHS-Link-Monitoring-Config
+adminDescription: ms-Exch-MHS-Link-Monitoring-Config
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: mHSLinkMonitoringConfig
+name: ms-Exch-MHS-Link-Monitoring-Config
+schemaIDGUID: a8df74b9-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-MHS-Link-Monitoring-Config,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MHS-Monitoring-Config
+# The EMS saved Monitoring configuration.
+#
+dn: CN=ms-Exch-MHS-Monitoring-Config,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-MHS-Monitoring-Config
+distinguishedName: CN=ms-Exch-MHS-Monitoring-Config,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.3.6
+mustContain: cn
+mayContain: runsOn
+mayContain: monitoringNormalPollUnits
+mayContain: monitoringNormalPollInterval
+mayContain: monitoringHotsitePollUnits
+mayContain: monitoringHotsitePollInterval
+mayContain: monitoringEscalationProcedure
+mayContain: monitoringAvailabilityWindow
+mayContain: monitoringAvailabilityStyle
+mayContain: monitoredServers
+mayContain: logFilename
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MHS-Monitoring-Config
+adminDescription: ms-Exch-MHS-Monitoring-Config
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: mHSMonitoringConfig
+name: ms-Exch-MHS-Monitoring-Config
+schemaIDGUID: a8df74bb-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-MHS-Monitoring-Config,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MHS-Server-Monitoring-Config
+# The EMS saved Server Monitoring configuration.
+#
+dn: CN=ms-Exch-MHS-Server-Monitoring-Config,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-MHS-Server-Monitoring-Config
+distinguishedName: CN=ms-Exch-MHS-Server-Monitoring-Config,${SCHEMADN}
+possSuperiors: container
+subClassOf: mHSMonitoringConfig
+governsID: 1.2.840.113556.1.3.7
+mayContain: serviceRestartMessage
+mayContain: serviceRestartDelay
+mayContain: serviceActionSecond
+mayContain: serviceActionOther
+mayContain: serviceActionFirst
+mayContain: monitorServices
+mayContain: monitorClock
+mayContain: clockWarningRepair
+mayContain: clockWarningOffset
+mayContain: clockAlertRepair
+mayContain: clockAlertOffset
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MHS-Server-Monitoring-Config
+adminDescription: ms-Exch-MHS-Server-Monitoring-Config
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: mHSServerMonitoringConfig
+name: ms-Exch-MHS-Server-Monitoring-Config
+schemaIDGUID: a8df74bd-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-MHS-Server-Monitoring-Config,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitors-Container
+# A container used to hold monitors. Used for extended rights and roles.
+#
+dn: CN=ms-Exch-Monitors-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Monitors-Container
+distinguishedName: CN=ms-Exch-Monitors-Container,${SCHEMADN}
+possSuperiors: msExchAdminGroup
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.50012
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitors-Container
+adminDescription: ms-Exch-Monitors-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchMonitorsContainer
+name: ms-Exch-Monitors-Container
+schemaIDGUID: 03f68f72-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Monitors-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MS-Mail-Connector
+# The Microsoft Mail Connector object.
+#
+dn: CN=ms-Exch-MS-Mail-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-MS-Mail-Connector
+distinguishedName: CN=ms-Exch-MS-Mail-Connector,${SCHEMADN}
+possSuperiors: container
+subClassOf: mailGateway
+governsID: 1.2.840.113556.1.3.31
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MS-Mail-Connector
+adminDescription: ms-Exch-MS-Mail-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: mSMailConnector
+name: ms-Exch-MS-Mail-Connector
+schemaIDGUID: a8df74be-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-MS-Mail-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MTA
+# Represents the message transfer agent (MTA) process on the computer.
+#
+dn: CN=ms-Exch-MTA,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-MTA
+distinguishedName: CN=ms-Exch-MTA,${SCHEMADN}
+possSuperiors: msExchExchangeServer
+possSuperiors: container
+possSuperiors: computer
+subClassOf: top
+governsID: 1.2.840.113556.1.3.49
+mustContain: transTimeoutMins
+mustContain: transRetryMins
+mustContain: mTALocalDesig
+mustContain: cn
+mayContain: msExchMinAdminVersion
+mayContain: msExchEncryptedPassword
+mayContain: msExchResponsibleMTAServerBL
+mayContain: msExchMTADatabasePath
+mayContain: xMITTimeoutUrgent
+mayContain: xMITTimeoutNormal
+mayContain: xMITTimeoutNonUrgent
+mayContain: transportExpeditedData
+mayContain: transferTimeoutUrgent
+mayContain: transferTimeoutNormal
+mayContain: transferTimeoutNonUrgent
+mayContain: transferRetryInterval
+mayContain: tempAssocThreshold
+mayContain: sessionDisconnectTimer
+mayContain: rTSWindowSize
+mayContain: rTSRecoveryTimeout
+mayContain: rTSCheckpointSize
+mayContain: openRetryInterval
+mayContain: numOfTransferRetries
+mayContain: numOfOpenRetries
+mayContain: messageTrackingEnabled
+mayContain: domainDefAltRecip
+mayContain: associationLifetime
+mayContain: mTALocalCred
+mayContain: msExchHomeRoutingGroupDNBL
+mayContain: expandDLsLocally
+mayContain: diagnosticRegKey
+mayContain: delivExtContTypes
+mayContain: delivEITs
+mayContain: delivContLength
+mayContain: msExchBridgeheadedRemoteConnectorsDNBL
+mayContain: msExchBridgeheadedLocalConnectorsDNBL
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MTA
+adminDescription: ms-Exch-MTA
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: mTA
+name: ms-Exch-MTA
+schemaIDGUID: a8df74a7-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-MTA,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MTA-Cfg
+#
+dn: CN=ms-Exch-MTA-Cfg,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-MTA-Cfg
+distinguishedName: CN=ms-Exch-MTA-Cfg,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.3.3
+mustContain: cn
+mayContain: xMITTimeoutUrgent
+mayContain: xMITTimeoutNormal
+mayContain: xMITTimeoutNonUrgent
+mayContain: transportExpeditedData
+mayContain: transferTimeoutUrgent
+mayContain: transferTimeoutNormal
+mayContain: transferTimeoutNonUrgent
+mayContain: transferRetryInterval
+mayContain: tempAssocThreshold
+mayContain: sessionDisconnectTimer
+mayContain: rTSWindowSize
+mayContain: rTSRecoveryTimeout
+mayContain: rTSCheckpointSize
+mayContain: openRetryInterval
+mayContain: numOfTransferRetries
+mayContain: numOfOpenRetries
+mayContain: messageTrackingEnabled
+mayContain: domainDefAltRecip
+mayContain: associationLifetime
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MTA-Cfg
+adminDescription: ms-Exch-MTA-Cfg
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: mTACfg
+name: ms-Exch-MTA-Cfg
+schemaIDGUID: a8df74a8-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-MTA-Cfg,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Multi-Media-User
+# Contains attributes for voice mailbox configuration. The attributes
+# can be updated by the mailbox owner.
+#
+dn: CN=ms-Exch-Multi-Media-User,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Multi-Media-User
+distinguishedName: CN=ms-Exch-Multi-Media-User,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.17002
+mayContain: msExchVoiceMailboxID
+mayContain: msExchTUIVolume
+mayContain: msExchTUISpeed
+mayContain: msExchTUIPassword
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Multi-Media-User
+adminDescription: ms-Exch-Multi-Media-User
+objectClassCategory: 3
+lDAPDisplayName: msExchMultiMediaUser
+name: ms-Exch-Multi-Media-User
+schemaIDGUID: 1529cf7a-2fdb-11d3-aa6d-00c04f8eedd8
+systemOnly: FALSE
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Multi-Media-User,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Connector
+# The Lotus Notes Connector object.
+#
+dn: CN=ms-Exch-Notes-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Notes-Connector
+distinguishedName: CN=ms-Exch-Notes-Connector,${SCHEMADN}
+possSuperiors: container
+subClassOf: mailGateway
+governsID: 1.2.840.113556.1.5.7000.62.1002
+mayContain: msExchNotesPassword
+mayContain: msExchNotesTargetBooks
+mayContain: msExchNotesTargetBook
+mayContain: msExchNotesSourceBooks
+mayContain: msExchNotesRtrMailbox
+mayContain: msExchNotesRoutableDomains
+mayContain: msExchNotesNotesServer
+mayContain: msExchNotesNotesLinks
+mayContain: msExchNotesNotesINI
+mayContain: msExchNotesLetterhead
+mayContain: msExchNotesForeignDomain
+mayContain: msExchNotesExportGroups
+mayContain: msExchNotesExcludeGroups
+mayContain: msExchNotesConnectorMailbox
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Connector
+adminDescription: ms-Exch-Notes-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchNotesConnector
+name: ms-Exch-Notes-Connector
+schemaIDGUID: 04c85e62-a981-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Notes-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-OAB
+# The offline address book (OAB) configuration object.
+#
+dn: CN=ms-Exch-OAB,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-OAB
+distinguishedName: CN=ms-Exch-OAB,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.9
+mustContain: offLineABStyle
+mustContain: offLineABServer
+mustContain: offLineABSchedule
+mustContain: offLineABContainers
+mustContain: msExchOABFolder
+mustContain: doOABVersion
+mayContain: siteFolderServer
+mayContain: siteFolderGUID
+mayContain: msExchUseOABBL
+mayContain: msExchOABDefault
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-OAB
+adminDescription: ms-Exch-OAB
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchOAB
+name: ms-Exch-OAB
+schemaIDGUID: 3686cdd4-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-OAB,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Carrier
+# Contains wireless carrier information.
+#
+dn: CN=ms-Exch-Oma-Carrier,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Oma-Carrier
+distinguishedName: CN=ms-Exch-Oma-Carrier,${SCHEMADN}
+subClassOf: container
+governsID: 1.2.840.113556.1.6.20.2.37
+mayContain: msExchMinAdminVersion
+mayContain: msExchOmaTranslator
+mayContain: msExchOmaExtendedProperties
+mayContain: msExchOmaDeliveryProviderDN
+mayContain: msExchOmaConfiguration
+mayContain: msExchOmaCarrierUrl
+mayContain: msExchOmaCarrierType
+mayContain: msExchOmaCarrierAddress
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Carrier
+adminDescription: ms-Exch-Oma-Carrier
+objectClassCategory: 1
+lDAPDisplayName: msExchOmaCarrier
+name: ms-Exch-Oma-Carrier
+schemaIDGUID: 8712d34c-27e5-41b2-976e-482ad8c954e7
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;LCLORPRC;;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Oma-Carrier,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Configuration-Container
+# The parent container for all OMA configuration data.
+#
+dn: CN=ms-Exch-Oma-Configuration-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Oma-Configuration-Container
+distinguishedName: CN=ms-Exch-Oma-Configuration-Container,${SCHEMADN}
+subClassOf: container
+governsID: 1.2.840.113556.1.6.20.2.32
+mayContain: msExchMinAdminVersion
+mayContain: msExchOmaExtendedProperties
+mayContain: msExchOmaAdminWirelessEnable
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Configuration-Container
+adminDescription: ms-Exch-Oma-Configuration-Container
+objectClassCategory: 1
+lDAPDisplayName: msExchOmaConfigurationContainer
+name: ms-Exch-Oma-Configuration-Container
+schemaIDGUID: db0f9abb-0770-4f09-ba64-7993d91517b7
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;LCLORPRC;;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Oma-Configuration-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Connector
+#
+dn: CN=ms-Exch-Oma-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Oma-Connector
+distinguishedName: CN=ms-Exch-Oma-Connector,${SCHEMADN}
+subClassOf: msExchConnector
+governsID: 1.2.840.113556.1.6.20.2.39
+mayContain: msExchSourceBridgeheadServersDN
+mayContain: msExchOmaCarrierUrl
+mayContain: deliveryMechanism
+mayContain: legacyExchangeDN
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Connector
+adminDescription: ms-Exch-Oma-Connector
+objectClassCategory: 1
+lDAPDisplayName: msExchOmaConnector
+name: ms-Exch-Oma-Connector
+schemaIDGUID: 4dc9d0b1-594c-407e-a7d2-426e6c20dabb
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Oma-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Container
+# The parent container for OMA device types.
+#
+dn: CN=ms-Exch-Oma-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Oma-Container
+distinguishedName: CN=ms-Exch-Oma-Container,${SCHEMADN}
+subClassOf: container
+governsID: 1.2.840.113556.1.6.20.2.38
+mayContain: msExchMinAdminVersion
+mayContain: msExchOmaExtendedProperties
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Container
+adminDescription: ms-Exch-Oma-Container
+objectClassCategory: 1
+lDAPDisplayName: msExchOmaContainer
+name: ms-Exch-Oma-Container
+schemaIDGUID: 863dab20-fb40-43a4-a5e1-825b2071050f
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Oma-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Data-Source
+# Contains information about business logic that can validate a push
+# notification.
+#
+dn: CN=ms-Exch-Oma-Data-Source,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Oma-Data-Source
+distinguishedName: CN=ms-Exch-Oma-Data-Source,${SCHEMADN}
+subClassOf: container
+governsID: 1.2.840.113556.1.6.20.2.35
+mayContain: msExchOmaValidater
+mayContain: msExchOmaExtendedProperties
+mayContain: msExchOmaDeviceCapabilityDN
+mayContain: msExchOmaDeliveryProviderDN
+mayContain: msExchOmaConfiguration
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Data-Source
+adminDescription: ms-Exch-Oma-Data-Source
+objectClassCategory: 1
+lDAPDisplayName: msExchOmaDataSource
+name: ms-Exch-Oma-Data-Source
+schemaIDGUID: dda38a4d-972a-44a2-9244-0acb4b1d34d1
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;LCLORPRC;;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Oma-Data-Source,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Delivery-Provider
+# Contains delivery protocol information.
+#
+dn: CN=ms-Exch-Oma-Delivery-Provider,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Oma-Delivery-Provider
+distinguishedName: CN=ms-Exch-Oma-Delivery-Provider,${SCHEMADN}
+subClassOf: container
+governsID: 1.2.840.113556.1.6.20.2.36
+mayContain: msExchOmaExtendedProperties
+mayContain: msExchOmaDeviceCapabilityDN
+mayContain: msExchOmaDeliverer
+mayContain: msExchOmaConfiguration
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Delivery-Provider
+adminDescription: ms-Exch-Oma-Delivery-Provider
+objectClassCategory: 1
+lDAPDisplayName: msExchOmaDeliveryProvider
+name: ms-Exch-Oma-Delivery-Provider
+schemaIDGUID: cdbf130d-c7e2-4572-94b0-fc9be7eef953
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Oma-Delivery-Provider,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Device-Capability
+# Device support for an application (such as SMS Text).
+#
+dn: CN=ms-Exch-Oma-Device-Capability,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Oma-Device-Capability
+distinguishedName: CN=ms-Exch-Oma-Device-Capability,${SCHEMADN}
+subClassOf: container
+governsID: 1.2.840.113556.1.6.20.2.34
+mayContain: msExchOmaFormatter
+mayContain: msExchOmaExtendedProperties
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Device-Capability
+adminDescription: ms-Exch-Oma-Device-Capability
+objectClassCategory: 1
+lDAPDisplayName: msExchOmaDeviceCapability
+name: ms-Exch-Oma-Device-Capability
+schemaIDGUID: df7af4df-f318-4e2c-ac43-be5b4894711c
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;LCLORPRC;;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Oma-Device-Capability,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Device-Type
+# Contains the make and model of a wireless device with
+# characteristics.
+#
+dn: CN=ms-Exch-Oma-Device-Type,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Oma-Device-Type
+distinguishedName: CN=ms-Exch-Oma-Device-Type,${SCHEMADN}
+subClassOf: container
+governsID: 1.2.840.113556.1.6.20.2.33
+mayContain: msExchOmaExtendedProperties
+mayContain: msExchOmaDeviceCapabilityDN
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Device-Type
+adminDescription: ms-Exch-Oma-Device-Type
+objectClassCategory: 1
+lDAPDisplayName: msExchOmaDeviceType
+name: ms-Exch-Oma-Device-Type
+schemaIDGUID: ca7a8fb3-21d0-4ea7-af3f-d15c6df7c094
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;LCLORPRC;;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Oma-Device-Type,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-User
+# Extends the Active Directory User.
+#
+dn: CN=ms-Exch-Oma-User,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Oma-User
+distinguishedName: CN=ms-Exch-Oma-User,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.6.20.2.31
+mayContain: msExchOmaAdminWirelessEnable
+mayContain: msExchOmaAdminExtendedSettings
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-User
+adminDescription: ms-Exch-Oma-User
+objectClassCategory: 3
+lDAPDisplayName: msExchOmaUser
+name: ms-Exch-Oma-User
+schemaIDGUID: 36a0a976-dd8d-4aad-81fd-a1b5d4016ca8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Oma-User,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Organization-Container
+# An organization container. Used for extended rights and roles.
+#
+dn: CN=ms-Exch-Organization-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Organization-Container
+distinguishedName: CN=ms-Exch-Organization-Container,${SCHEMADN}
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.50020
+mayContain: msExchMinAdminVersion
+mayContain: heuristics
+mayContain: msExchDisableUDGConversion
+mayContain: msExchServerLocalGroups
+mayContain: msExchServerGroups
+mayContain: msExchServerGlobalGroups
+mayContain: msExchAdmins
+mayContain: msExchAdminGroupsEnabled
+mayContain: msExchWebAccessName
+mayContain: submissionContLength
+mayContain: msExchMixedMode
+mayContain: msExchMimeTypes
+mayContain: delivContLength
+mayContain: msExchRoutingEnabled
+mayContain: msExchRecipLimit
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Organization-Container
+adminDescription: ms-Exch-Organization-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchOrganizationContainer
+name: ms-Exch-Organization-Container
+schemaIDGUID: 366a319c-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Organization-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-OVVM-Connector
+# The OVVM Connector.
+#
+dn: CN=ms-Exch-OVVM-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-OVVM-Connector
+distinguishedName: CN=ms-Exch-OVVM-Connector,${SCHEMADN}
+possSuperiors: container
+subClassOf: mailGateway
+governsID: 1.2.840.113556.1.5.7000.62.1004
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-OVVM-Connector
+adminDescription: ms-Exch-OVVM-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchOVVMConnector
+name: ms-Exch-OVVM-Connector
+schemaIDGUID: 91ce0e8c-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-OVVM-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-PF-Tree
+#
+dn: CN=ms-Exch-PF-Tree,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-PF-Tree
+distinguishedName: CN=ms-Exch-PF-Tree,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.11003
+mayContain: msExchMinAdminVersion
+mayContain: msExchPfCreation
+mayContain: msExchAllowEnhancedSecurity
+mayContain: msExchOwningPFTreeBL
+mayContain: msExchPFDefaultAdminACL
+mayContain: msExchPFTreeType
+mayContain: msExchPFDSContainer
+mayContain: displayName
+mayContain: description
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-PF-Tree
+adminDescription: ms-Exch-PF-Tree
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchPFTree
+name: ms-Exch-PF-Tree
+schemaIDGUID: 364d9564-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-PF-Tree,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Policies-Container
+# A container used to hold policies. Used for extended rights and
+# roles.
+#
+dn: CN=ms-Exch-Policies-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Policies-Container
+distinguishedName: CN=ms-Exch-Policies-Container,${SCHEMADN}
+possSuperiors: msExchAdminGroup
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.50014
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policies-Container
+adminDescription: ms-Exch-Policies-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchPoliciesContainer
+name: ms-Exch-Policies-Container
+schemaIDGUID: 3630f92c-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Policies-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Private-MDB
+# A private database configuration.
+#
+dn: CN=ms-Exch-Private-MDB,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Private-MDB
+distinguishedName: CN=ms-Exch-Private-MDB,${SCHEMADN}
+possSuperiors: container
+possSuperiors: computer
+subClassOf: msExchMDB
+governsID: 1.2.840.113556.1.5.7000.62.11004
+mayContain: msExchRestore
+mayContain: msExchOrigMDB
+mayContain: msExchMessageJournalRecipient
+mayContain: msExchUseOAB
+mayContain: msExchMailboxRetentionPeriod
+mayContain: msExchMaximumRecurringInstancesMonths
+mayContain: msExchMaximumRecurringInstances
+mayContain: msExchHomePublicMDB
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Private-MDB
+adminDescription: ms-Exch-Private-MDB
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchPrivateMDB
+name: ms-Exch-Private-MDB
+schemaIDGUID: 36145cf4-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Private-MDB,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Private-MDB-Policy
+#
+dn: CN=ms-Exch-Private-MDB-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Private-MDB-Policy
+distinguishedName: CN=ms-Exch-Private-MDB-Policy,${SCHEMADN}
+possSuperiors: container
+subClassOf: msExchPrivateMDB
+governsID: 1.2.840.113556.1.5.7000.62.50003
+mayContain: msExchPolicyLastAppliedTime
+mayContain: msExchPolicyOptionList
+mayContain: msExchPolicyLockDown
+mayContain: msExchPolicyListBL
+mayContain: msExchPolicyDefault
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Private-MDB-Policy
+adminDescription: ms-Exch-Private-MDB-Policy
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchPrivateMDBPolicy
+name: ms-Exch-Private-MDB-Policy
+schemaIDGUID: 35db2484-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Private-MDB-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Private-MDB-Proxy
+#
+dn: CN=ms-Exch-Private-MDB-Proxy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Private-MDB-Proxy
+distinguishedName: CN=ms-Exch-Private-MDB-Proxy,${SCHEMADN}
+possSuperiors: msExchContainer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.11007
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Private-MDB-Proxy
+adminDescription: ms-Exch-Private-MDB-Proxy
+auxiliaryClass: msExchMailStorage
+auxiliaryClass: msExchBaseClass
+auxiliaryClass: mailRecipient
+objectClassCategory: 1
+lDAPDisplayName: msExchPrivateMDBProxy
+name: ms-Exch-Private-MDB-Proxy
+schemaIDGUID: b8d47e54-4b78-11d3-aa75-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Private-MDB-Proxy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg
+#
+dn: CN=ms-Exch-Protocol-Cfg,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg
+distinguishedName: CN=ms-Exch-Protocol-Cfg,${SCHEMADN}
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.3.68
+mustContain: cn
+mayContain: msExchMinAdminVersion
+mayContain: msExchDS2MBOptions
+mayContain: heuristics
+mayContain: useSiteValues
+mayContain: sendTNEF
+mayContain: requireSSL
+mayContain: preserveInternetContent
+mayContain: portNumber
+mayContain: incomingMsgSizeLimit
+mayContain: enabledProtocolCfg
+mayContain: enabledAuthorizationPackages
+mayContain: diagnosticRegKey
+mayContain: contentType
+mayContain: clientAccessEnabled
+mayContain: characterSet
+mayContain: associationLifetime
+mayContain: anonymousAccess
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg
+adminDescription: ms-Exch-Protocol-Cfg
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfg
+name: ms-Exch-Protocol-Cfg
+schemaIDGUID: a8df74c0-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-HTTP
+#
+dn: CN=ms-Exch-Protocol-Cfg-HTTP,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-HTTP
+distinguishedName: CN=ms-Exch-Protocol-Cfg-HTTP,${SCHEMADN}
+possSuperiors: protocolCfgSharedSite
+possSuperiors: protocolCfgSharedServer
+subClassOf: protocolCfg
+governsID: 1.2.840.113556.1.3.79
+mustContain: hTTPPubGAL
+mayContain: hTTPServers
+mayContain: hTTPPubPF
+mayContain: hTTPPubGALLimit
+mayContain: hTTPPubABAttributes
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-HTTP
+adminDescription: ms-Exch-Protocol-Cfg-HTTP
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgHTTP
+name: ms-Exch-Protocol-Cfg-HTTP
+schemaIDGUID: a8df74c1-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-HTTP,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-HTTP-Container
+#
+dn: CN=ms-Exch-Protocol-Cfg-HTTP-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-HTTP-Container
+distinguishedName: CN=ms-Exch-Protocol-Cfg-HTTP-Container,${SCHEMADN}
+subClassOf: msExchProtocolCfgSharedContainer
+governsID: 1.2.840.113556.1.5.7000.62.14001
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-HTTP-Container
+adminDescription: ms-Exch-Protocol-Cfg-HTTP-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgHTTPContainer
+name: ms-Exch-Protocol-Cfg-HTTP-Container
+schemaIDGUID: 9432cae6-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-HTTP-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-HTTP-Filter
+# The Exchange HTTP service filters.
+#
+dn: CN=ms-Exch-Protocol-Cfg-HTTP-Filter,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-HTTP-Filter
+distinguishedName: CN=ms-Exch-Protocol-Cfg-HTTP-Filter,${SCHEMADN}
+possSuperiors: msExchProtocolCfgHTTPFilters
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.15003
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-HTTP-Filter
+adminDescription: ms-Exch-Protocol-Cfg-HTTP-Filter
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgHTTPFilter
+name: ms-Exch-Protocol-Cfg-HTTP-Filter
+schemaIDGUID: 8c7588c0-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-HTTP-Filter,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-HTTP-Filters
+# The Exchange HTTP service filters container.
+#
+dn: CN=ms-Exch-Protocol-Cfg-HTTP-Filters,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-HTTP-Filters
+distinguishedName: CN=ms-Exch-Protocol-Cfg-HTTP-Filters,${SCHEMADN}
+possSuperiors: protocolCfgSharedServer
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.15002
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-HTTP-Filters
+adminDescription: ms-Exch-Protocol-Cfg-HTTP-Filters
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgHTTPFilters
+name: ms-Exch-Protocol-Cfg-HTTP-Filters
+schemaIDGUID: 8c58ec88-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-HTTP-Filters,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-HTTP-Server
+# The Exchange HTTP virtual server configuration.
+#
+dn: CN=ms-Exch-Protocol-Cfg-HTTP-Server,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-HTTP-Server
+distinguishedName: CN=ms-Exch-Protocol-Cfg-HTTP-Server,${SCHEMADN}
+possSuperiors: msExchProtocolCfgHTTPContainer
+subClassOf: protocolCfgHTTP
+governsID: 1.2.840.113556.1.3.80
+mayContain: msExchEncryptedAnonymousPassword
+mayContain: msExchDefaultLoadFile
+mayContain: msExchAuthorizationPersistence
+mayContain: msExchServerAutoStart
+mayContain: msExchServerRole
+mayContain: msExchDiscussionFolder
+mayContain: msExchDefaultDomain
+mayContain: msExchUNCUsername
+mayContain: msExchUNCPassword
+mayContain: msExchServerBindings
+mayContain: msExchSecureBindings
+mayContain: msExchMaxIncomingConnections
+mayContain: msExchLogonMethod
+mayContain: msExchLogType
+mayContain: msExchIncomingConnectionTimeout
+mayContain: folderPathname
+mayContain: msExchDirBrowseFlags
+mayContain: msExchDefaultLogonDomain
+mayContain: msExchBasicAuthenticationDomain
+mayContain: msExchAuthenticationFlags
+mayContain: anonymousAccount
+mayContain: msExchAccessFlags
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-HTTP-Server
+adminDescription: ms-Exch-Protocol-Cfg-HTTP-Server
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgHTTPServer
+name: ms-Exch-Protocol-Cfg-HTTP-Server
+schemaIDGUID: a8df74c2-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-HTTP-Server,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-HTTP-Site
+#
+dn: CN=ms-Exch-Protocol-Cfg-HTTP-Site,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-HTTP-Site
+distinguishedName: CN=ms-Exch-Protocol-Cfg-HTTP-Site,${SCHEMADN}
+possSuperiors: protocolCfgSharedSite
+subClassOf: protocolCfgHTTP
+governsID: 1.2.840.113556.1.3.81
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-HTTP-Site
+adminDescription: ms-Exch-Protocol-Cfg-HTTP-Site
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgHTTPSite
+name: ms-Exch-Protocol-Cfg-HTTP-Site
+schemaIDGUID: a8df74c3-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-HTTP-Site,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-HTTP-Virtual-Directory
+# The Exchange HTTP virtual directory configuration.
+#
+dn: CN=ms-Exch-Protocol-Cfg-HTTP-Virtual-Directory,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-HTTP-Virtual-Directory
+distinguishedName: CN=ms-Exch-Protocol-Cfg-HTTP-Virtual-Directory,${SCHEMADN}
+possSuperiors: protocolCfgHTTPServer
+subClassOf: protocolCfgHTTPServer
+governsID: 1.2.840.113556.1.5.7000.62.15001
+mayContain: msExchBackEndVDirURL
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-HTTP-Virtual-Directory
+adminDescription: ms-Exch-Protocol-Cfg-HTTP-Virtual-Directory
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgHTTPVirtualDirectory
+name: ms-Exch-Protocol-Cfg-HTTP-Virtual-Directory
+schemaIDGUID: 8c3c5050-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-HTTP-Virtual-Directory,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-IM
+#
+dn: CN=ms-Exch-Protocol-Cfg-IM,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-IM
+distinguishedName: CN=ms-Exch-Protocol-Cfg-IM,${SCHEMADN}
+possSuperiors: protocolCfgSharedSite
+possSuperiors: protocolCfgSharedServer
+subClassOf: protocolCfg
+governsID: 1.2.840.113556.1.5.7000.62.7012
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-IM
+adminDescription: ms-Exch-Protocol-Cfg-IM
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgIM
+name: ms-Exch-Protocol-Cfg-IM
+schemaIDGUID: 9f116ea7-284e-11d3-aa68-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-IM,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-IMAP
+#
+dn: CN=ms-Exch-Protocol-Cfg-IMAP,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-IMAP
+distinguishedName: CN=ms-Exch-Protocol-Cfg-IMAP,${SCHEMADN}
+possSuperiors: protocolCfgSharedSite
+possSuperiors: protocolCfgSharedServer
+subClassOf: protocolCfg
+governsID: 1.2.840.113556.1.3.84
+mayContain: msExchLogonACL
+mayContain: msExchServerBindings
+mayContain: msExchSecureBindings
+mayContain: returnExactMsgSize
+mayContain: msExchPolicyOptionList
+mayContain: msExchPolicyList
+mayContain: oWAServer
+mayContain: listPublicFolders
+mayContain: formData
+mayContain: folderPathname
+mayContain: delegateUser
+mayContain: anonymousAccount
+mayContain: helpData32
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-IMAP
+adminDescription: ms-Exch-Protocol-Cfg-IMAP
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgIMAP
+name: ms-Exch-Protocol-Cfg-IMAP
+schemaIDGUID: a8df74c4-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-IMAP,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-IMAP-Container
+#
+dn: CN=ms-Exch-Protocol-Cfg-IMAP-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-IMAP-Container
+distinguishedName: CN=ms-Exch-Protocol-Cfg-IMAP-Container,${SCHEMADN}
+subClassOf: msExchProtocolCfgSharedContainer
+governsID: 1.2.840.113556.1.5.7000.62.3001
+mayContain: msExchSASLMechanisms
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-IMAP-Container
+adminDescription: ms-Exch-Protocol-Cfg-IMAP-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgIMAPContainer
+name: ms-Exch-Protocol-Cfg-IMAP-Container
+schemaIDGUID: 93da93e4-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-IMAP-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-IMAP-Policy
+#
+dn: CN=ms-Exch-Protocol-Cfg-IMAP-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-IMAP-Policy
+distinguishedName: CN=ms-Exch-Protocol-Cfg-IMAP-Policy,${SCHEMADN}
+possSuperiors: container
+subClassOf: protocolCfgIMAP
+governsID: 1.2.840.113556.1.5.7000.62.50004
+mayContain: msExchPolicyLastAppliedTime
+mayContain: msExchPolicyOptionList
+mayContain: msExchPolicyLockDown
+mayContain: msExchPolicyListBL
+mayContain: msExchPolicyDefault
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-IMAP-Policy
+adminDescription: ms-Exch-Protocol-Cfg-IMAP-Policy
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgIMAPPolicy
+name: ms-Exch-Protocol-Cfg-IMAP-Policy
+schemaIDGUID: 35f7c0bc-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-IMAP-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-IMAP-Server
+#
+dn: CN=ms-Exch-Protocol-Cfg-IMAP-Server,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-IMAP-Server
+distinguishedName: CN=ms-Exch-Protocol-Cfg-IMAP-Server,${SCHEMADN}
+possSuperiors: msExchProtocolCfgIMAPContainer
+subClassOf: protocolCfgIMAP
+governsID: 1.2.840.113556.1.3.85
+mayContain: msExchOtherAuthenticationFlags
+mayContain: msExchServerRole
+mayContain: msExchDefaultLogonDomain
+mayContain: msExchServerBindings
+mayContain: msExchServerAutoStart
+mayContain: msExchSecureBindings
+mayContain: msExchNTAuthenticationProviders
+mayContain: msExchMaxIncomingConnections
+mayContain: msExchLogType
+mayContain: msExchIPSecurity
+mayContain: msExchIncomingConnectionTimeout
+mayContain: msExchDefaultDomain
+mayContain: msExchBasicAuthenticationDomain
+mayContain: msExchAuthenticationFlags
+mayContain: msExchAdminACL
+mayContain: msExchAccessSSLFlags
+mayContain: msExchAccessFlags
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-IMAP-Server
+adminDescription: ms-Exch-Protocol-Cfg-IMAP-Server
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgIMAPServer
+name: ms-Exch-Protocol-Cfg-IMAP-Server
+schemaIDGUID: a8df74c5-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-IMAP-Server,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-IMAP-Sessions
+#
+dn: CN=ms-Exch-Protocol-Cfg-IMAP-Sessions,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-IMAP-Sessions
+distinguishedName: CN=ms-Exch-Protocol-Cfg-IMAP-Sessions,${SCHEMADN}
+possSuperiors: protocolCfgIMAPServer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.3002
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-IMAP-Sessions
+adminDescription: ms-Exch-Protocol-Cfg-IMAP-Sessions
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgIMAPSessions
+name: ms-Exch-Protocol-Cfg-IMAP-Sessions
+schemaIDGUID: 99f58672-12e8-11d3-aa58-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-IMAP-Sessions,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-IMAP-Site
+#
+dn: CN=ms-Exch-Protocol-Cfg-IMAP-Site,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-IMAP-Site
+distinguishedName: CN=ms-Exch-Protocol-Cfg-IMAP-Site,${SCHEMADN}
+possSuperiors: protocolCfgSharedSite
+subClassOf: protocolCfgIMAP
+governsID: 1.2.840.113556.1.3.86
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-IMAP-Site
+adminDescription: ms-Exch-Protocol-Cfg-IMAP-Site
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgIMAPSite
+name: ms-Exch-Protocol-Cfg-IMAP-Site
+schemaIDGUID: a8df74c6-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-IMAP-Site,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-IM-Container
+#
+dn: CN=ms-Exch-Protocol-Cfg-IM-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-IM-Container
+distinguishedName: CN=ms-Exch-Protocol-Cfg-IM-Container,${SCHEMADN}
+subClassOf: msExchProtocolCfgSharedContainer
+governsID: 1.2.840.113556.1.5.7000.62.7011
+mayContain: msExchIMDBPath
+mayContain: msExchIMDBLogPath
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-IM-Container
+adminDescription: ms-Exch-Protocol-Cfg-IM-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgIMContainer
+name: ms-Exch-Protocol-Cfg-IM-Container
+schemaIDGUID: 9f116ea3-284e-11d3-aa68-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-IM-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-IM-Virtual-Server
+# Contains the attributes that represent an Instant Messaging virtual
+# server.
+#
+dn: CN=ms-Exch-Protocol-Cfg-IM-Virtual-Server,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-IM-Virtual-Server
+distinguishedName: CN=ms-Exch-Protocol-Cfg-IM-Virtual-Server,${SCHEMADN}
+possSuperiors: msExchProtocolCfgIMContainer
+subClassOf: msExchProtocolCfgIM
+governsID: 1.2.840.113556.1.5.7000.62.7013
+mustContain: msExchIMServerIISId
+mayContain: msExchIMHostName
+mayContain: flags
+mayContain: msExchIMServerName
+mayContain: msExchIMServerHostsUsers
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-IM-Virtual-Server
+adminDescription: ms-Exch-Protocol-Cfg-IM-Virtual-Server
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgIMVirtualServer
+name: ms-Exch-Protocol-Cfg-IM-Virtual-Server
+schemaIDGUID: 9f116eb4-284e-11d3-aa68-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-IM-Virtual-Server,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-LDAP
+#
+dn: CN=ms-Exch-Protocol-Cfg-LDAP,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-LDAP
+distinguishedName: CN=ms-Exch-Protocol-Cfg-LDAP,${SCHEMADN}
+possSuperiors: protocolCfgSharedSite
+possSuperiors: protocolCfgSharedServer
+subClassOf: protocolCfg
+governsID: 1.2.840.113556.1.3.75
+mayContain: outgoingMsgSizeLimit
+mayContain: lDAPSearchCfg
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-LDAP
+adminDescription: ms-Exch-Protocol-Cfg-LDAP
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgLDAP
+name: ms-Exch-Protocol-Cfg-LDAP
+schemaIDGUID: a8df74c7-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-LDAP,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-LDAP-Server
+#
+dn: CN=ms-Exch-Protocol-Cfg-LDAP-Server,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-LDAP-Server
+distinguishedName: CN=ms-Exch-Protocol-Cfg-LDAP-Server,${SCHEMADN}
+possSuperiors: msExchProtocolCfgProtocolContainer
+possSuperiors: protocolCfgSharedServer
+subClassOf: protocolCfgLDAP
+governsID: 1.2.840.113556.1.3.77
+mayContain: referralList
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-LDAP-Server
+adminDescription: ms-Exch-Protocol-Cfg-LDAP-Server
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgLDAPServer
+name: ms-Exch-Protocol-Cfg-LDAP-Server
+schemaIDGUID: a8df74c8-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-LDAP-Server,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-LDAP-Site
+#
+dn: CN=ms-Exch-Protocol-Cfg-LDAP-Site,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-LDAP-Site
+distinguishedName: CN=ms-Exch-Protocol-Cfg-LDAP-Site,${SCHEMADN}
+possSuperiors: protocolCfgSharedSite
+subClassOf: protocolCfgLDAP
+governsID: 1.2.840.113556.1.3.76
+mayContain: referralList
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-LDAP-Site
+adminDescription: ms-Exch-Protocol-Cfg-LDAP-Site
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgLDAPSite
+name: ms-Exch-Protocol-Cfg-LDAP-Site
+schemaIDGUID: a8df74c9-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-LDAP-Site,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-NNTP
+#
+dn: CN=ms-Exch-Protocol-Cfg-NNTP,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-NNTP
+distinguishedName: CN=ms-Exch-Protocol-Cfg-NNTP,${SCHEMADN}
+possSuperiors: protocolCfgSharedSite
+possSuperiors: protocolCfgSharedServer
+subClassOf: protocolCfg
+governsID: 1.2.840.113556.1.3.72
+mayContain: usenetSiteName
+mayContain: supportSMIMESignatures
+mayContain: rootNewsgroupsFolderID
+mayContain: iNSAdmin
+mayContain: controlMsgRules
+mayContain: controlMsgFolderID
+mayContain: availableDistributions
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-NNTP
+adminDescription: ms-Exch-Protocol-Cfg-NNTP
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgNNTP
+name: ms-Exch-Protocol-Cfg-NNTP
+schemaIDGUID: a8df74ca-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-NNTP,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-NNTP-Container
+#
+dn: CN=ms-Exch-Protocol-Cfg-NNTP-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-NNTP-Container
+distinguishedName: CN=ms-Exch-Protocol-Cfg-NNTP-Container,${SCHEMADN}
+subClassOf: msExchProtocolCfgSharedContainer
+governsID: 1.2.840.113556.1.5.7000.62.6001
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-NNTP-Container
+adminDescription: ms-Exch-Protocol-Cfg-NNTP-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgNNTPContainer
+name: ms-Exch-Protocol-Cfg-NNTP-Container
+schemaIDGUID: 94162eae-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-NNTP-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-NNTP-Server
+#
+dn: CN=ms-Exch-Protocol-Cfg-NNTP-Server,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-NNTP-Server
+distinguishedName: CN=ms-Exch-Protocol-Cfg-NNTP-Server,${SCHEMADN}
+possSuperiors: msExchProtocolCfgNNTPContainer
+subClassOf: protocolCfgNNTP
+governsID: 1.2.840.113556.1.3.74
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-NNTP-Server
+adminDescription: ms-Exch-Protocol-Cfg-NNTP-Server
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgNNTPServer
+name: ms-Exch-Protocol-Cfg-NNTP-Server
+schemaIDGUID: a8df74cb-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-NNTP-Server,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-NNTP-Site
+#
+dn: CN=ms-Exch-Protocol-Cfg-NNTP-Site,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-NNTP-Site
+distinguishedName: CN=ms-Exch-Protocol-Cfg-NNTP-Site,${SCHEMADN}
+possSuperiors: protocolCfgSharedSite
+subClassOf: protocolCfgNNTP
+governsID: 1.2.840.113556.1.3.73
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-NNTP-Site
+adminDescription: ms-Exch-Protocol-Cfg-NNTP-Site
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgNNTPSite
+name: ms-Exch-Protocol-Cfg-NNTP-Site
+schemaIDGUID: a8df74cc-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-NNTP-Site,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-POP
+#
+dn: CN=ms-Exch-Protocol-Cfg-POP,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-POP
+distinguishedName: CN=ms-Exch-Protocol-Cfg-POP,${SCHEMADN}
+possSuperiors: protocolCfgSharedSite
+possSuperiors: protocolCfgSharedServer
+subClassOf: protocolCfg
+governsID: 1.2.840.113556.1.3.69
+mayContain: msExchLogonACL
+mayContain: msExchServerBindings
+mayContain: msExchSecureBindings
+mayContain: oWAServer
+mayContain: formData
+mayContain: folderPathname
+mayContain: helpData32
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-POP
+adminDescription: ms-Exch-Protocol-Cfg-POP
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgPOP
+name: ms-Exch-Protocol-Cfg-POP
+schemaIDGUID: a8df74cd-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-POP,${SCHEMADN}
+
+
+#
+# ms-Exch-Protocol-Cfg-SMTP-Container
+#
+dn: CN=ms-Exch-Protocol-Cfg-SMTP-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-SMTP-Container
+distinguishedName: CN=ms-Exch-Protocol-Cfg-SMTP-Container,${SCHEMADN}
+subClassOf: msExchProtocolCfgSharedContainer
+governsID: 1.2.840.113556.1.5.7000.62.5010
+mayContain: versionNumber
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-SMTP-Container
+adminDescription: ms-Exch-Protocol-Cfg-SMTP-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgSMTPContainer
+name: ms-Exch-Protocol-Cfg-SMTP-Container
+schemaIDGUID: 93bb9552-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-SMTP-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-SMTP-Domain
+# Contains domain level settings under an SMTP virtual server.
+#
+dn: CN=ms-Exch-Protocol-Cfg-SMTP-Domain,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-SMTP-Domain
+distinguishedName: CN=ms-Exch-Protocol-Cfg-SMTP-Domain,${SCHEMADN}
+possSuperiors: protocolCfgSMTPDomainContainer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.5006
+mayContain: msExchEncryptedPassword
+mayContain: msExchSecurityPassword
+mayContain: msExchSmtpSmartHost
+mayContain: msExchSmtpOutboundSecurityUserName
+mayContain: msExchSmtpOutboundSecurityPassword
+mayContain: msExchSmtpOutboundSecurityFlag
+mayContain: msExchSmtpDropDirectory
+mayContain: msExchSmtpDomainString
+mayContain: msExchSmtpAuthorizedTRNAccounts
+mayContain: sendTNEF
+mayContain: msExchRoutingDisplaySenderEnabled
+mayContain: msExchRoutingAcceptMessageType
+mayContain: msExchDefaultDomain
+mayContain: contentType
+mayContain: characterSet
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-SMTP-Domain
+adminDescription: ms-Exch-Protocol-Cfg-SMTP-Domain
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgSMTPDomain
+name: ms-Exch-Protocol-Cfg-SMTP-Domain
+schemaIDGUID: 33d82894-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-SMTP-Domain,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-SMTP-Domain-Container
+# Contains superior domain level settings under an SMTP virtual
+# server.
+#
+dn: CN=ms-Exch-Protocol-Cfg-SMTP-Domain-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-SMTP-Domain-Container
+distinguishedName: CN=ms-Exch-Protocol-Cfg-SMTP-Domain-Container,${SCHEMADN}
+possSuperiors: protocolCfgSMTPServer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.5004
+mayContain: msExchMinAdminVersion
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-SMTP-Domain-Container
+adminDescription: ms-Exch-Protocol-Cfg-SMTP-Domain-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgSMTPDomainContainer
+name: ms-Exch-Protocol-Cfg-SMTP-Domain-Container
+schemaIDGUID: 33bb8c5c-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-SMTP-Domain-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-SMTP-IP-Address
+#
+dn: CN=ms-Exch-Protocol-Cfg-SMTP-IP-Address,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-SMTP-IP-Address
+distinguishedName: CN=ms-Exch-Protocol-Cfg-SMTP-IP-Address,${SCHEMADN}
+possSuperiors: msExchProtocolCfgSMTPIPAddressContainer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.5009
+mayContain: msExchTurfList
+mayContain: msExchIPAddress
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-SMTP-IP-Address
+adminDescription: ms-Exch-Protocol-Cfg-SMTP-IP-Address
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgSMTPIPAddress
+name: ms-Exch-Protocol-Cfg-SMTP-IP-Address
+schemaIDGUID: 8b7b31d6-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-SMTP-IP-Address,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-SMTP-IP-Address-Container
+#
+dn: CN=ms-Exch-Protocol-Cfg-SMTP-IP-Address-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-SMTP-IP-Address-Container
+distinguishedName: CN=ms-Exch-Protocol-Cfg-SMTP-IP-Address-Container,${SCHEMADN}
+possSuperiors: protocolCfgSMTPServer
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.5008
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-SMTP-IP-Address-Container
+adminDescription: ms-Exch-Protocol-Cfg-SMTP-IP-Address-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgSMTPIPAddressContainer
+name: ms-Exch-Protocol-Cfg-SMTP-IP-Address-Container
+schemaIDGUID: 8b2c843c-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-SMTP-IP-Address-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-SMTP-Policy
+#
+dn: CN=ms-Exch-Protocol-Cfg-SMTP-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-SMTP-Policy
+distinguishedName: CN=ms-Exch-Protocol-Cfg-SMTP-Policy,${SCHEMADN}
+possSuperiors: container
+subClassOf: protocolCfgSMTP
+governsID: 1.2.840.113556.1.5.7000.62.50006
+mayContain: msExchPolicyLastAppliedTime
+mayContain: msExchPolicyOptionList
+mayContain: msExchPolicyLockDown
+mayContain: msExchPolicyListBL
+mayContain: msExchPolicyDefault
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-SMTP-Policy
+adminDescription: ms-Exch-Protocol-Cfg-SMTP-Policy
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchProtocolCfgSMTPPolicy
+name: ms-Exch-Protocol-Cfg-SMTP-Policy
+schemaIDGUID: 359f89ba-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-SMTP-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-SMTP-Routing-Sources
+# Contains information about the unused sources for routing outbound
+# mail.
+#
+dn: CN=ms-Exch-Protocol-Cfg-SMTP-Routing-Sources,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-SMTP-Routing-Sources
+distinguishedName: CN=ms-Exch-Protocol-Cfg-SMTP-Routing-Sources,${SCHEMADN}
+possSuperiors: protocolCfgSMTPServer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.5005
+mayContain: msExchMinAdminVersion
+mayContain: msExchSmtpRoutingTableType
+mayContain: msExchSmtpLdapSchemaType
+mayContain: msExchSmtpLdapPassword
+mayContain: msExchSmtpLdapNamingContext
+mayContain: msExchSmtpLdapBindType
+mayContain: msExchSmtpLdapAccount
+mayContain: msExchSmtpEnableLdapRouting
+mayContain: msExchSmtpDsPort
+mayContain: msExchSmtpDsHost
+mayContain: msExchSmtpDsFlags
+mayContain: msExchSmtpDsDomain
+mayContain: msExchSmtpDsDefaultMailRoot
+mayContain: msExchSmtpDsDataDirectory
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-SMTP-Routing-Sources
+adminDescription: ms-Exch-Protocol-Cfg-SMTP-Routing-Sources
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgSMTPRoutingSources
+name: ms-Exch-Protocol-Cfg-SMTP-Routing-Sources
+schemaIDGUID: 3397c916-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-SMTP-Routing-Sources,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-SMTP-Server
+# Contains the settings for an SMTP virtual server.
+#
+dn: CN=ms-Exch-Protocol-Cfg-SMTP-Server,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-SMTP-Server
+distinguishedName: CN=ms-Exch-Protocol-Cfg-SMTP-Server,${SCHEMADN}
+possSuperiors: msExchProtocolCfgSMTPContainer
+subClassOf: protocolCfgSMTP
+governsID: 1.2.840.113556.1.5.7000.62.5002
+mayContain: msExchSubmitRelaySD
+mayContain: msExchServerBindingsFiltering
+mayContain: msExchAuthMailDisposition
+mayContain: msExchSmtpExternalDNSServers
+mayContain: msExchEncryptedPassword
+mayContain: msExchAppliesToSmtpVSBL
+mayContain: msExchSmtpEnableVRFY
+mayContain: msExchSmtpEnableEXPN
+mayContain: msExchServerBindingsTurflist
+mayContain: msExchSecurityPassword
+mayContain: msExchAlternateServer
+mayContain: msExchSmtpSmartHostType
+mayContain: msExchSmtpSmartHost
+mayContain: msExchSmtpSendNDRTo
+mayContain: msExchSmtpSendBadmailTo
+mayContain: msExchSmtpRemoteQueueRetries
+mayContain: msExchSmtpRemoteQueueExpirationTimeout
+mayContain: msExchSmtpRemoteQueueDelayNotification
+mayContain: msExchSmtpRelayIpList
+mayContain: msExchSmtpRelayForAuth
+mayContain: msExchSmtpQueueDirectory
+mayContain: msExchSmtpPickupDirectory
+mayContain: msExchSmtpPerformReverseDnsLookup
+mayContain: msExchSmtpOutgoingSecurePort
+mayContain: msExchSmtpOutgoingPort
+mayContain: msExchSmtpOutgoingConnectionTimeout
+mayContain: msExchSmtpOutboundSecurityUserName
+mayContain: msExchSmtpOutboundSecurityPassword
+mayContain: msExchSmtpOutboundSecurityFlag
+mayContain: msExchSmtpMaxSessionSize
+mayContain: msExchSmtpMaxRecipients
+mayContain: msExchSmtpMaxOutgoingConnectionsPerDomain
+mayContain: msExchSmtpMaxOutgoingConnections
+mayContain: msExchSmtpMaxOutboundMsgPerDomainFlag
+mayContain: msExchSmtpMaxOutboundMsgPerDomain
+mayContain: msExchSmtpMaxMessageSize
+mayContain: msExchSmtpMaxHopCount
+mayContain: msExchSmtpMasqueradeDomain
+mayContain: msExchSmtpLocalQueueExpirationTimeout
+mayContain: msExchSmtpLocalQueueDelayNotification
+mayContain: msExchSmtpInboundCommandSupportOptions
+mayContain: msExchSmtpFullyQualifiedDomainName
+mayContain: msExchSmtpDropDirectory
+mayContain: msExchSmtpDoMasquerade
+mayContain: msExchSmtpBadMailDirectory
+mayContain: msExchServerBindings
+mayContain: msExchServerAutoStart
+mayContain: msExchSecureBindings
+mayContain: msExchSaslLogonDomain
+mayContain: msExchNTAuthenticationProviders
+mayContain: msExchMaxIncomingConnections
+mayContain: msExchLogType
+mayContain: msExchIPSecurity
+mayContain: msExchIncomingConnectionTimeout
+mayContain: msExchHomeRoutingGroupDNBL
+mayContain: msExchDefaultDomain
+mayContain: msExchBridgeheadedRemoteConnectorsDNBL
+mayContain: msExchBridgeheadedLocalConnectorsDNBL
+mayContain: msExchAuthenticationFlags
+mayContain: msExchAdminACL
+mayContain: msExchAccessSSLFlags
+mayContain: msExchAccessFlags
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-SMTP-Server
+adminDescription: ms-Exch-Protocol-Cfg-SMTP-Server
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgSMTPServer
+name: ms-Exch-Protocol-Cfg-SMTP-Server
+schemaIDGUID: 3378ca84-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-SMTP-Server,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-SMTP-Sessions
+#
+dn: CN=ms-Exch-Protocol-Cfg-SMTP-Sessions,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-SMTP-Sessions
+distinguishedName: CN=ms-Exch-Protocol-Cfg-SMTP-Sessions,${SCHEMADN}
+possSuperiors: protocolCfgSMTPServer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.5007
+mayContain: msExchMinAdminVersion
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-SMTP-Sessions
+adminDescription: ms-Exch-Protocol-Cfg-SMTP-Sessions
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgSMTPSessions
+name: ms-Exch-Protocol-Cfg-SMTP-Sessions
+schemaIDGUID: 8ef628c6-b093-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-SMTP-Sessions,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Cfg-SMTP-Site
+# Contains settings for legacy site SMTP settings.
+#
+dn: CN=ms-Exch-Protocol-Cfg-SMTP-Site,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Protocol-Cfg-SMTP-Site
+distinguishedName: CN=ms-Exch-Protocol-Cfg-SMTP-Site,${SCHEMADN}
+possSuperiors: protocolCfgSharedSite
+subClassOf: protocolCfgSMTP
+governsID: 1.2.840.113556.1.5.7000.62.5003
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Cfg-SMTP-Site
+adminDescription: ms-Exch-Protocol-Cfg-SMTP-Site
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: protocolCfgSMTPSite
+name: ms-Exch-Protocol-Cfg-SMTP-Site
+schemaIDGUID: 32f0e47a-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Protocol-Cfg-SMTP-Site,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Pseudo-PF
+# Used internally by the store.
+#
+dn: CN=ms-Exch-Pseudo-PF,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Pseudo-PF
+distinguishedName: CN=ms-Exch-Pseudo-PF,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.50030
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Pseudo-PF
+adminDescription: ms-Exch-Pseudo-PF
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchPseudoPF
+name: ms-Exch-Pseudo-PF
+schemaIDGUID: cec4472b-22ae-11d3-aa62-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Pseudo-PF,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Pseudo-PF-Admin
+# Used internally by the store.
+#
+dn: CN=ms-Exch-Pseudo-PF-Admin,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Pseudo-PF-Admin
+distinguishedName: CN=ms-Exch-Pseudo-PF-Admin,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.50029
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Pseudo-PF-Admin
+adminDescription: ms-Exch-Pseudo-PF-Admin
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchPseudoPFAdmin
+name: ms-Exch-Pseudo-PF-Admin
+schemaIDGUID: 9ae2fa1b-22b0-11d3-aa62-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Pseudo-PF-Admin,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Public-Folder
+# A representation of a public folder.
+#
+dn: CN=ms-Exch-Public-Folder,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Public-Folder
+distinguishedName: CN=ms-Exch-Public-Folder,${SCHEMADN}
+possSuperiors: msExchSystemObjectsContainer
+possSuperiors: organizationalUnit
+possSuperiors: domainDNS
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.3.15
+mayContain: pFContacts
+mayContain: msExchPFTreeType
+mayContain: title
+mayContain: co
+mayContain: st
+mayContain: physicalDeliveryOfficeName
+mayContain: l
+mayContain: department
+mayContain: company
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Public-Folder
+adminDescription: ms-Exch-Public-Folder
+auxiliaryClass: msExchBaseClass
+auxiliaryClass: msExchMailStorage
+auxiliaryClass: msExchCustomAttributes
+auxiliaryClass: mailRecipient
+objectClassCategory: 1
+lDAPDisplayName: publicFolder
+name: ms-Exch-Public-Folder
+schemaIDGUID: f0f8ffac-1191-11d0-a060-00aa006c33ed
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(OA;;RP;59ba2f42-79a2-11d0-9020-00c04fc2d3cf;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Public-Folder,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Public-Folder-Tree-Container
+# A container used to hold public folders. Used for extended rights and
+# roles.
+#
+dn: CN=ms-Exch-Public-Folder-Tree-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Public-Folder-Tree-Container
+distinguishedName: CN=ms-Exch-Public-Folder-Tree-Container,${SCHEMADN}
+possSuperiors: msExchAdminGroup
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.50015
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Public-Folder-Tree-Container
+adminDescription: ms-Exch-Public-Folder-Tree-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchPublicFolderTreeContainer
+name: ms-Exch-Public-Folder-Tree-Container
+schemaIDGUID: 3582ed82-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Public-Folder-Tree-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Public-MDB
+# A public database configuration.
+#
+dn: CN=ms-Exch-Public-MDB,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Public-MDB
+distinguishedName: CN=ms-Exch-Public-MDB,${SCHEMADN}
+possSuperiors: container
+possSuperiors: computer
+subClassOf: msExchMDB
+governsID: 1.2.840.113556.1.5.7000.62.11005
+mayContain: msExchPreferredBackfillSource
+mayContain: messageSizeLimit
+mayContain: msExchOverallAgeLimit
+mayContain: msExchReplicationStyle
+mayContain: msExchReplicationSchedule
+mayContain: msExchReplicationMsgSize
+mayContain: msExchPollInterval
+mayContain: msExchOwningPFTree
+mayContain: msExchFirstInstance
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Public-MDB
+adminDescription: ms-Exch-Public-MDB
+auxiliaryClass: msExchBaseClass
+auxiliaryClass: mailRecipient
+objectClassCategory: 1
+lDAPDisplayName: msExchPublicMDB
+name: ms-Exch-Public-MDB
+schemaIDGUID: 3568b3a4-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Public-MDB,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Public-MDB-Policy
+#
+dn: CN=ms-Exch-Public-MDB-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Public-MDB-Policy
+distinguishedName: CN=ms-Exch-Public-MDB-Policy,${SCHEMADN}
+possSuperiors: container
+subClassOf: msExchPublicMDB
+governsID: 1.2.840.113556.1.5.7000.62.50002
+mayContain: msExchPolicyLastAppliedTime
+mayContain: msExchPolicyOptionList
+mayContain: msExchPolicyLockDown
+mayContain: msExchPolicyListBL
+mayContain: msExchPolicyDefault
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Public-MDB-Policy
+adminDescription: ms-Exch-Public-MDB-Policy
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchPublicMDBPolicy
+name: ms-Exch-Public-MDB-Policy
+schemaIDGUID: 354c176c-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Public-MDB-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-RAS-Stack
+# The Remote Access Service (RAS) Transport Stack for the MTA.
+#
+dn: CN=ms-Exch-RAS-Stack,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-RAS-Stack
+distinguishedName: CN=ms-Exch-RAS-Stack,${SCHEMADN}
+possSuperiors: mTA
+possSuperiors: container
+possSuperiors: computer
+subClassOf: transportStack
+governsID: 1.2.840.113556.1.3.26
+mayContain: rASCallbackNumber
+mayContain: encrypt
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RAS-Stack
+adminDescription: ms-Exch-RAS-Stack
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: rASStack
+name: ms-Exch-RAS-Stack
+schemaIDGUID: a8df74d3-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-RAS-Stack,${SCHEMADN}
+
+
+
+#
+# ms-Exch-RAS-X400-Link
+# Specifies a remote X.400 MTA using a RAS Transport.
+#
+dn: CN=ms-Exch-RAS-X400-Link,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-RAS-X400-Link
+distinguishedName: CN=ms-Exch-RAS-X400-Link,${SCHEMADN}
+possSuperiors: container
+subClassOf: x400Link
+governsID: 1.2.840.113556.1.3.34
+mayContain: rASRemoteSRVRName
+mayContain: rASPhonebookEntryName
+mayContain: rASPhoneNumber
+mayContain: rASCallbackNumber
+mayContain: authorizedUser
+mayContain: authorizedPassword
+mayContain: authorizedDomain
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RAS-X400-Link
+adminDescription: ms-Exch-RAS-X400-Link
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: rASX400Link
+name: ms-Exch-RAS-X400-Link
+schemaIDGUID: a8df74d4-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-RAS-X400-Link,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Recipient-Policy
+#
+dn: CN=ms-Exch-Recipient-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Recipient-Policy
+distinguishedName: CN=ms-Exch-Recipient-Policy,${SCHEMADN}
+possSuperiors: msExchRecipientPolicyContainer
+subClassOf: msExchGenericPolicy
+governsID: 1.2.840.113556.1.5.7000.62.50024
+mayContain: msExchMinAdminVersion
+mayContain: msExchAddressListOU
+mayContain: msExchNonAuthoritativeDomains
+mayContain: msExchAppliesToSmtpVS
+mayContain: msExchProxyGenOptions
+mayContain: msExchPolicyOrder
+mayContain: gatewayProxy
+mayContain: disabledGatewayProxy
+mayContain: msExchAssociatedAG
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Recipient-Policy
+adminDescription: ms-Exch-Recipient-Policy
+auxiliaryClass: msExchMailboxManagerPolicy
+auxiliaryClass: msExchBaseClass
+auxiliaryClass: msExchMailStorage
+auxiliaryClass: msExchCustomAttributes
+auxiliaryClass: mailRecipient
+objectClassCategory: 1
+lDAPDisplayName: msExchRecipientPolicy
+name: ms-Exch-Recipient-Policy
+schemaIDGUID: e32977d8-1d31-11d3-aa5e-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Recipient-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Recipient-Policy-Container
+#
+dn: CN=ms-Exch-Recipient-Policy-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Recipient-Policy-Container
+distinguishedName: CN=ms-Exch-Recipient-Policy-Container,${SCHEMADN}
+possSuperiors: msExchOrganizationContainer
+subClassOf: msExchGenericPolicyContainer
+governsID: 1.2.840.113556.1.5.7000.62.50023
+mayContain: msExchMinAdminVersion
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Recipient-Policy-Container
+adminDescription: ms-Exch-Recipient-Policy-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchRecipientPolicyContainer
+name: ms-Exch-Recipient-Policy-Container
+schemaIDGUID: e32977d2-1d31-11d3-aa5e-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Recipient-Policy-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Remote-DXA
+# The remote directory Exchange objects (requester and server).
+#
+dn: CN=ms-Exch-Remote-DXA,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Remote-DXA
+distinguishedName: CN=ms-Exch-Remote-DXA,${SCHEMADN}
+possSuperiors: dXASiteServer
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.3.2
+mustContain: exportCustomRecipients
+mustContain: dXARemoteClient
+mustContain: cn
+mayContain: versionNumber
+mayContain: msExchServer1AlwaysCreateAs
+mayContain: msExchPrevExportDLs
+mayContain: msExchImportContainerLinked
+mayContain: msExchExportDLs
+mayContain: msExchExportContainersLinked
+mayContain: assocRemoteDXA
+mayContain: deletedItemFlags
+mayContain: responsibleLocalDXA
+mayContain: reqSeq
+mayContain: replicationSensitivity
+mayContain: messageSizeLimit
+mayContain: importContainer
+mayContain: exportContainers
+mayContain: dXAUnConfContainerList
+mayContain: dXATypes
+mayContain: dXATemplateOptions
+mayContain: dXASvrSeqUSN
+mayContain: dXASvrSeqTime
+mayContain: dXASvrSeq
+mayContain: dXAReqName
+mayContain: dXAReqSeqUSN
+mayContain: dXAReqSeqTime
+mayContain: dXAReqSeq
+mayContain: dXARecipientCP
+mayContain: dXAPrevTypes
+mayContain: dXAPrevTemplateOptions
+mayContain: dXAPrevReplicationSensitivity
+mayContain: dXAPrevRemoteEntries
+mayContain: dXAPrevInExchangeSensitivity
+mayContain: dXAPrevExportNativeOnly
+mayContain: dXAPrevExchangeOptions
+mayContain: dXAPassword
+mayContain: dXANativeAddressType
+mayContain: dXALocalAdmin
+mayContain: dXAImportNow
+mayContain: dXAImpSeqUSN
+mayContain: dXAImpSeqTime
+mayContain: dXAImpSeq
+mayContain: dXAExportNow
+mayContain: dXAExchangeOptions
+mayContain: dXAConfSeqUSN
+mayContain: dXAConfSeq
+mayContain: dXAConfReqTime
+mayContain: dXAConfContainerList
+mayContain: dXAAppendReqCN
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Remote-DXA
+adminDescription: ms-Exch-Remote-DXA
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: remoteDXA
+name: ms-Exch-Remote-DXA
+schemaIDGUID: a8df74d5-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Remote-DXA,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Replication-Connector
+#
+dn: CN=ms-Exch-Replication-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Replication-Connector
+distinguishedName: CN=ms-Exch-Replication-Connector,${SCHEMADN}
+possSuperiors: msExchReplicationConnectorContainer
+subClassOf: msExchConnector
+governsID: 1.2.840.113556.1.5.7000.62.11
+mayContain: trustLevel
+mayContain: replicationStagger
+mayContain: replicationMailMsgSize
+mayContain: remoteSite
+mayContain: remoteBridgeHeadAddress
+mayContain: remoteBridgeHead
+mayContain: outboundSites
+mayContain: localBridgeHeadAddress
+mayContain: localBridgeHead
+mayContain: kCCStatus
+mayContain: inboundSites
+mayContain: activationStyle
+mayContain: activationSchedule
+mayContain: addressType
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Replication-Connector
+adminDescription: ms-Exch-Replication-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchReplicationConnector
+name: ms-Exch-Replication-Connector
+schemaIDGUID: 99f58682-12e8-11d3-aa58-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Replication-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Replication-Connector-Container
+#
+dn: CN=ms-Exch-Replication-Connector-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Replication-Connector-Container
+distinguishedName: CN=ms-Exch-Replication-Connector-Container,${SCHEMADN}
+possSuperiors: msExchAdminGroup
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.12
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Replication-Connector-Container
+adminDescription: ms-Exch-Replication-Connector-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchReplicationConnectorContainer
+name: ms-Exch-Replication-Connector-Container
+schemaIDGUID: 99f5867e-12e8-11d3-aa58-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Replication-Connector-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-RFC1006-Stack
+# The RFC 1006 (TCP/IP) Transport Stack for the MTA.
+#
+dn: CN=ms-Exch-RFC1006-Stack,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-RFC1006-Stack
+distinguishedName: CN=ms-Exch-RFC1006-Stack,${SCHEMADN}
+possSuperiors: mTA
+subClassOf: transportStack
+governsID: 1.2.840.113556.1.3.24
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RFC1006-Stack
+adminDescription: ms-Exch-RFC1006-Stack
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: rFC1006Stack
+name: ms-Exch-RFC1006-Stack
+schemaIDGUID: a8df74d7-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-RFC1006-Stack,${SCHEMADN}
+
+
+
+#
+# ms-Exch-RFC1006-X400-Link
+# Specifies a remote X.400 MTA using an RFC 1006 (TCP/IP) Transport.
+#
+dn: CN=ms-Exch-RFC1006-X400-Link,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-RFC1006-X400-Link
+distinguishedName: CN=ms-Exch-RFC1006-X400-Link,${SCHEMADN}
+subClassOf: x400Link
+governsID: 1.2.840.113556.1.3.32
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RFC1006-X400-Link
+adminDescription: ms-Exch-RFC1006-X400-Link
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: rFC1006X400Link
+name: ms-Exch-RFC1006-X400-Link
+schemaIDGUID: a8df74d8-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-RFC1006-X400-Link,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Routing-Group
+# Container used to hold routing group information.
+#
+dn: CN=ms-Exch-Routing-Group,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Routing-Group
+distinguishedName: CN=ms-Exch-Routing-Group,${SCHEMADN}
+possSuperiors: msExchRoutingGroupContainer
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.12002
+mayContain: msExchMinAdminVersion
+mayContain: msExchRoutingGroupMembersBL
+mayContain: msExchInconsistentState
+mayContain: msExchRoutingMasterDN
+mayContain: msExchRoutingGroupMembersDN
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Group
+adminDescription: ms-Exch-Routing-Group
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchRoutingGroup
+name: ms-Exch-Routing-Group
+schemaIDGUID: 35154156-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Routing-Group,${SCHEMADN}
+
+#
+# ms-Exch-Routing-Group-Connector
+#
+dn: CN=ms-Exch-Routing-Group-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Routing-Group-Connector
+distinguishedName: CN=ms-Exch-Routing-Group-Connector,${SCHEMADN}
+possSuperiors: msExchConnectors
+subClassOf: msExchConnector
+governsID: 1.2.840.113556.1.5.7000.62.12007
+mayContain: msExchEncryptedPassword
+mayContain: targetMTAs
+mayContain: homeMTA
+mayContain: domainName
+mayContain: authorizedUser
+mayContain: authorizedPassword
+mayContain: authorizedDomain
+mayContain: cost
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Group-Connector
+adminDescription: ms-Exch-Routing-Group-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchRoutingGroupConnector
+name: ms-Exch-Routing-Group-Connector
+schemaIDGUID: 899e5b86-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Routing-Group-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Routing-Group-Container
+# Container used to hold routing groups.
+#
+dn: CN=ms-Exch-Routing-Group-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Routing-Group-Container
+distinguishedName: CN=ms-Exch-Routing-Group-Container,${SCHEMADN}
+possSuperiors: msExchAdminGroup
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.12001
+mayContain: msExchMinAdminVersion
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Group-Container
+adminDescription: ms-Exch-Routing-Group-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchRoutingGroupContainer
+name: ms-Exch-Routing-Group-Container
+schemaIDGUID: 34de6b40-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Routing-Group-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Routing-SMTP-Connector
+#
+dn: CN=ms-Exch-Routing-SMTP-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Routing-SMTP-Connector
+distinguishedName: CN=ms-Exch-Routing-SMTP-Connector,${SCHEMADN}
+possSuperiors: msExchConnectors
+subClassOf: mailGateway
+governsID: 1.2.840.113556.1.5.7000.62.12008
+mayContain: msExchSmtpTRNSmartHost
+mayContain: msExchSecurityPassword
+mayContain: msExchRoutingETRNDomains
+mayContain: msExchSmtpSmartHost
+mayContain: msExchSmtpOutboundSecurityUserName
+mayContain: msExchSmtpOutboundSecurityPassword
+mayContain: msExchSmtpOutboundSecurityFlag
+mayContain: msExchSmtpAuthorizedTRNAccounts
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-SMTP-Connector
+adminDescription: ms-Exch-Routing-SMTP-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchRoutingSMTPConnector
+name: ms-Exch-Routing-SMTP-Connector
+schemaIDGUID: 89baf7be-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Routing-SMTP-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Schedule-Plus-Connector
+#
+dn: CN=ms-Exch-Schedule-Plus-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Schedule-Plus-Connector
+distinguishedName: CN=ms-Exch-Schedule-Plus-Connector,${SCHEMADN}
+possSuperiors: container
+subClassOf: exchangeAdminService
+governsID: 1.2.840.113556.1.5.7000.62.1008
+mayContain: computerName
+mayContain: transferRetryInterval
+mayContain: msExchSchedPlusSchedist
+mayContain: msExchSchedPlusFullUpdate
+mayContain: msExchSchedPlusAGOnly
+mayContain: msExchAdminMailbox
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Schedule-Plus-Connector
+adminDescription: ms-Exch-Schedule-Plus-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchSchedulePlusConnector
+name: ms-Exch-Schedule-Plus-Connector
+schemaIDGUID: b1fce946-1d44-11d3-aa5e-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Schedule-Plus-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Schema-Map-Policy
+# The policy object for connection agreements.
+#
+dn: CN=ms-Exch-Schema-Map-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Schema-Map-Policy
+distinguishedName: CN=ms-Exch-Schema-Map-Policy,${SCHEMADN}
+possSuperiors: organizationalUnit
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.1
+mayContain: msExchADCObjectType
+mayContain: versionNumber
+mayContain: msExchServer2SchemaMap
+mayContain: msExchServer2ObjectMatch
+mayContain: msExchServer2Flags
+mayContain: msExchServer1SchemaMap
+mayContain: msExchServer1ObjectMatch
+mayContain: msExchServer1Flags
+mayContain: msExchSchemaPolicyConsumers
+mayContain: msExchAccessControlMap
+mayContain: displayName
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Schema-Map-Policy
+adminDescription: ms-Exch-Schema-Map-Policy
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchSchemaMapPolicy
+name: ms-Exch-Schema-Map-Policy
+schemaIDGUID: 348af8f2-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Schema-Map-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Servers-Container
+# A container used to hold servers. Used for extended rights and roles.
+#
+dn: CN=ms-Exch-Servers-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Servers-Container
+distinguishedName: CN=ms-Exch-Servers-Container,${SCHEMADN}
+possSuperiors: msExchAdminGroup
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.50013
+mayContain: msExchMinAdminVersion
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Servers-Container
+adminDescription: ms-Exch-Servers-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchServersContainer
+name: ms-Exch-Servers-Container
+schemaIDGUID: 346e5cba-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;LC;;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Servers-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Site-Addressing
+# Represents the messaging domain.
+#
+dn: CN=ms-Exch-Site-Addressing,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Site-Addressing
+distinguishedName: CN=ms-Exch-Site-Addressing,${SCHEMADN}
+possSuperiors: msExchAdminGroup
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.3.0
+mustContain: cn
+mayContain: spaceLastComputed
+mayContain: siteProxySpace
+mayContain: routingList
+mayContain: ridServer
+mayContain: gWARTLastModified
+mayContain: gatewayRoutingTree
+mayContain: gatewayProxy
+mayContain: filterLocalAddresses
+mayContain: disabledGatewayProxy
+mayContain: activationStyle
+mayContain: activationSchedule
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Site-Addressing
+adminDescription: ms-Exch-Site-Addressing
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: siteAddressing
+name: ms-Exch-Site-Addressing
+schemaIDGUID: a8df74d9-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Site-Addressing,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Site-Connector
+# A symbolic link to another domain's message transfer agents (MTAs).
+#
+dn: CN=ms-Exch-Site-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Site-Connector
+distinguishedName: CN=ms-Exch-Site-Connector,${SCHEMADN}
+possSuperiors: container
+subClassOf: msExchConnector
+governsID: 1.2.840.113556.1.3.50
+mustContain: cn
+mayContain: targetMTAs
+mayContain: msExchTargetBridgeheadServersDN
+mayContain: msExchSourceBridgeheadServersDN
+mayContain: msExchSourceBHAddress
+mayContain: routingList
+mayContain: homeMTA
+mayContain: domainName
+mayContain: msExchDestinationRGDN
+mayContain: msExchDestBHAddress
+mayContain: msExchConnectorType
+mayContain: bridgeheadServers
+mayContain: authorizedUser
+mayContain: authorizedPassword
+mayContain: authorizedDomain
+mayContain: cost
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Site-Connector
+adminDescription: ms-Exch-Site-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: siteConnector
+name: ms-Exch-Site-Connector
+schemaIDGUID: a8df74da-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Site-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Site-Replication-Service
+#
+dn: CN=ms-Exch-Site-Replication-Service,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Site-Replication-Service
+distinguishedName: CN=ms-Exch-Site-Replication-Service,${SCHEMADN}
+possSuperiors: msExchExchangeServer
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.10
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Site-Replication-Service
+adminDescription: ms-Exch-Site-Replication-Service
+auxiliaryClass: msExchBaseClass
+auxiliaryClass: msExchMailStorage
+auxiliaryClass: mailRecipient
+objectClassCategory: 1
+lDAPDisplayName: msExchSiteReplicationService
+name: ms-Exch-Site-Replication-Service
+schemaIDGUID: 99f5867b-12e8-11d3-aa58-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Site-Replication-Service,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Connection-Turf-List
+# Contains the attributes for Accept and Deny Internet Protocol (IP)
+# lists.
+#
+dn: CN=ms-Exch-Smtp-Connection-Turf-List,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Smtp-Connection-Turf-List
+distinguishedName: CN=ms-Exch-Smtp-Connection-Turf-List,${SCHEMADN}
+possSuperiors: msExchSMTPTurfList
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.12010
+mayContain: msExchSMTPGlobalIPDenyList
+mayContain: msExchSMTPGlobalIPAcceptList
+mayContain: msExchMinAdminVersion
+mayContain: msExchSmtpConnectionWhitelist
+mayContain: msExchSmtpConnectionRulesPriority
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Connection-Turf-List
+adminDescription: ms-Exch-Smtp-Connection-Turf-List
+objectClassCategory: 1
+lDAPDisplayName: msExchSmtpConnectionTurfList
+name: ms-Exch-Smtp-Connection-Turf-List
+schemaIDGUID: 7eea7de9-319e-408a-8460-e35e2c9da389
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Smtp-Connection-Turf-List,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Connection-Turf-List-Rule
+#
+dn: CN=ms-Exch-Smtp-Connection-Turf-List-Rule,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Smtp-Connection-Turf-List-Rule
+distinguishedName: CN=ms-Exch-Smtp-Connection-Turf-List-Rule,${SCHEMADN}
+possSuperiors: msExchSmtpConnectionTurfList
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.12011
+mayContain: msExchSmtpConnectionTurfListResponse
+mayContain: msExchSmtpConnectionTurfListOptions
+mayContain: msExchSmtpConnectionTurfListMask
+mayContain: msExchSmtpConnectionTurfListDNS
+mayContain: msExchSmtpConnectionTurfListDisplay
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Connection-Turf-List-Rule
+adminDescription: ms-Exch-Smtp-Connection-Turf-List-Rule
+objectClassCategory: 1
+lDAPDisplayName: msExchSmtpConnectionTurfListRule
+name: ms-Exch-Smtp-Connection-Turf-List-Rule
+schemaIDGUID: 6abadfad-e2f6-4ddb-9820-0da9c47da32c
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Smtp-Connection-Turf-List-Rule,${SCHEMADN}
+
+
+
+#
+# ms-Exch-SMTP-Turf-List
+#
+dn: CN=ms-Exch-SMTP-Turf-List,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-SMTP-Turf-List
+distinguishedName: CN=ms-Exch-SMTP-Turf-List,${SCHEMADN}
+possSuperiors: msExchMessageDeliveryConfig
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.12009
+mayContain: msExchMinAdminVersion
+mayContain: msExchRecipTurfListOptions
+mayContain: msExchRecipTurfListNames
+mayContain: msExchTurfListOptions
+mayContain: versionNumber
+mayContain: msExchTurfListNames
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-SMTP-Turf-List
+adminDescription: ms-Exch-SMTP-Turf-List
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchSMTPTurfList
+name: ms-Exch-SMTP-Turf-List
+schemaIDGUID: 0b836da5-3b20-11d3-aa6f-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-SMTP-Turf-List,${SCHEMADN}
+
+
+
+#
+# ms-Exch-SNADS-Connector
+# The SNA Distribution System (SNADS) Connector.
+#
+dn: CN=ms-Exch-SNADS-Connector,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-SNADS-Connector
+distinguishedName: CN=ms-Exch-SNADS-Connector,${SCHEMADN}
+possSuperiors: container
+subClassOf: mailGateway
+governsID: 1.2.840.113556.1.5.7000.62.1003
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-SNADS-Connector
+adminDescription: ms-Exch-SNADS-Connector
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchSNADSConnector
+name: ms-Exch-SNADS-Connector
+schemaIDGUID: 91b17254-b09e-11d2-aa06-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-SNADS-Connector,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Storage-Group
+# The list of stores for this Microsoft Jet instance.
+#
+dn: CN=ms-Exch-Storage-Group,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Storage-Group
+distinguishedName: CN=ms-Exch-Storage-Group,${SCHEMADN}
+possSuperiors: computer
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.11006
+mustContain: cn
+mayContain: msExchMinAdminVersion
+mayContain: msExchESEParamCachedClosedTables
+mayContain: msExchRestore
+mayContain: msExchESEParamPageTempDBMin
+mayContain: msExchESEParamPageFragment
+mayContain: msExchESEParamMaxTemporaryTables
+mayContain: msExchESEParamMaxCursors
+mayContain: msExchESEParamEnableOnlineDefrag
+mayContain: msExchESEParamEnableIndexChecking
+mayContain: msExchESEParamDbExtensionSize
+mayContain: msExchESEParamCommitDefault
+mayContain: msExchESEParamCheckpointDepthMax
+mayContain: msExchESEParamBaseName
+mayContain: msExchRecovery
+mayContain: msExchESEParamZeroDatabaseDuringBackup
+mayContain: msExchESEParamWaitLogFlush
+mayContain: msExchESEParamTempPath
+mayContain: msExchESEParamSystemPath
+mayContain: msExchESEParamPreferredVerPages
+mayContain: msExchESEParamPreferredMaxOpenTables
+mayContain: msExchESEParamMaxVerPages
+mayContain: msExchESEParamMaxSessions
+mayContain: msExchESEParamMaxOpenTables
+mayContain: msExchESEParamLogWaitingUserMax
+mayContain: msExchESEParamLogFileSize
+mayContain: msExchESEParamLogFilePath
+mayContain: msExchESEParamLogCheckpointPeriod
+mayContain: msExchESEParamLogBuffers
+mayContain: msExchESEParamEventSource
+mayContain: msExchESEParamCircularLog
+mayContain: displayName
+mayContain: description
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Storage-Group
+adminDescription: ms-Exch-Storage-Group
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchStorageGroup
+name: ms-Exch-Storage-Group
+schemaIDGUID: 3435244a-a982-11d2-a9ff-00c04f8eedd8
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Storage-Group,${SCHEMADN}
+
+
+
+#
+# ms-Exch-System-Objects-Container
+# The Exchange container for system-related objects, such as public
+# folder proxies.
+#
+dn: CN=ms-Exch-System-Objects-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-System-Objects-Container
+distinguishedName: CN=ms-Exch-System-Objects-Container,${SCHEMADN}
+possSuperiors: domainDNS
+subClassOf: container
+governsID: 1.2.840.113556.1.5.7000.62.50034
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-System-Objects-Container
+adminDescription: ms-Exch-System-Objects-Container
+objectClassCategory: 1
+lDAPDisplayName: msExchSystemObjectsContainer
+name: ms-Exch-System-Objects-Container
+schemaIDGUID: 0bffa04c-7d8e-44cd-968a-b2cac11d17e1
+systemOnly: FALSE
+defaultSecurityDescriptor: D:(A;;RPLCLORC;;;AU)
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-System-Objects-Container,${SCHEMADN}
+
+
+
+#
+# ms-Exch-System-Policy
+# The internal system policy.
+#
+dn: CN=ms-Exch-System-Policy,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-System-Policy
+distinguishedName: CN=ms-Exch-System-Policy,${SCHEMADN}
+possSuperiors: msExchSystemPolicyContainer
+subClassOf: msExchGenericPolicy
+governsID: 1.2.840.113556.1.5.7000.62.16
+mayContain: msExchMinAdminVersion
+mayContain: heuristics
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-System-Policy
+adminDescription: ms-Exch-System-Policy
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchSystemPolicy
+name: ms-Exch-System-Policy
+schemaIDGUID: ba085a33-8807-4c6c-9522-2cf5a2a5e9c2
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-System-Policy,${SCHEMADN}
+
+
+
+#
+# ms-Exch-System-Policy-Container
+#
+dn: CN=ms-Exch-System-Policy-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-System-Policy-Container
+distinguishedName: CN=ms-Exch-System-Policy-Container,${SCHEMADN}
+possSuperiors: msExchOrganizationContainer
+subClassOf: msExchGenericPolicyContainer
+governsID: 1.2.840.113556.1.5.7000.62.15
+mayContain: msExchMinAdminVersion
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-System-Policy-Container
+adminDescription: ms-Exch-System-Policy-Container
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: msExchSystemPolicyContainer
+name: ms-Exch-System-Policy-Container
+schemaIDGUID: 32412a7a-22af-479c-a444-624c0137122e
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-System-Policy-Container,${SCHEMADN}
+
+
+#
+# ms-Exch-TP4-Stack
+# The TP4 Transport Stack for the MTA.
+#
+dn: CN=ms-Exch-TP4-Stack,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-TP4-Stack
+distinguishedName: CN=ms-Exch-TP4-Stack,${SCHEMADN}
+possSuperiors: mTA
+possSuperiors: container
+possSuperiors: computer
+subClassOf: transportStack
+governsID: 1.2.840.113556.1.3.25
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-TP4-Stack
+adminDescription: ms-Exch-TP4-Stack
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: tP4Stack
+name: ms-Exch-TP4-Stack
+schemaIDGUID: a8df74db-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-TP4-Stack,${SCHEMADN}
+
+
+#
+# ms-Exch-TP4-X400-Link
+# Specifies a remote X.400 MTA using a TP4 Transport.
+#
+dn: CN=ms-Exch-TP4-X400-Link,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-TP4-X400-Link
+distinguishedName: CN=ms-Exch-TP4-X400-Link,${SCHEMADN}
+possSuperiors: container
+subClassOf: x400Link
+governsID: 1.2.840.113556.1.3.33
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-TP4-X400-Link
+adminDescription: ms-Exch-TP4-X400-Link
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: tP4X400Link
+name: ms-Exch-TP4-X400-Link
+schemaIDGUID: a8df74dc-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-TP4-X400-Link,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Transport-Stack
+# Represents the X.400 Transport Stacks.
+#
+dn: CN=ms-Exch-Transport-Stack,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Transport-Stack
+distinguishedName: CN=ms-Exch-Transport-Stack,${SCHEMADN}
+possSuperiors: mTA
+possSuperiors: container
+possSuperiors: computer
+subClassOf: top
+governsID: 1.2.840.113556.1.3.18
+mustContain: cn
+mayContain: supportingStackBL
+mayContain: x400SelectorSyntax
+mayContain: tSelector
+mayContain: sSelector
+mayContain: pSelector
+mayContain: nAddressType
+mayContain: nAddress
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Transport-Stack
+adminDescription: ms-Exch-Transport-Stack
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: transportStack
+name: ms-Exch-Transport-Stack
+schemaIDGUID: a8df74dd-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Transport-Stack,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Uce
+# Reserved.
+#
+dn: CN=ms-Exch-Uce,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-Uce
+distinguishedName: CN=ms-Exch-Uce,${SCHEMADN}
+possSuperiors: msExchMessageDeliveryConfig
+subClassOf: top
+governsID: 1.2.840.113556.1.5.7000.62.50037
+mayContain: msExchUceStoreActionThreshold
+mayContain: msExchUceEnabled
+mayContain: msExchUceBlockThreshold
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Uce
+adminDescription: ms-Exch-Uce
+objectClassCategory: 1
+lDAPDisplayName: msExchUce
+name: ms-Exch-Uce
+schemaIDGUID: c5ccdce1-b399-405f-8ab7-bc6434d2e422
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-Uce,${SCHEMADN}
+
+
+
+#
+# ms-Exch-X25-Stack
+# The X.25 Transport Stack for the MTA.
+#
+dn: CN=ms-Exch-X25-Stack,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-X25-Stack
+distinguishedName: CN=ms-Exch-X25-Stack,${SCHEMADN}
+possSuperiors: mTA
+possSuperiors: container
+possSuperiors: computer
+subClassOf: transportStack
+governsID: 1.2.840.113556.1.3.27
+mustContain: x25LeasedLinePort
+mayContain: x25LeasedOrSwitched
+mayContain: x25FacilitiesDataIncoming
+mayContain: x25CallUserDataIncoming
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X25-Stack
+adminDescription: ms-Exch-X25-Stack
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: x25Stack
+name: ms-Exch-X25-Stack
+schemaIDGUID: a8df74de-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-X25-Stack,${SCHEMADN}
+
+
+
+#
+# ms-Exch-X25-X400-Link
+# Specifies a remote X.400 MTA using an X.25 Transport.
+#
+dn: CN=ms-Exch-X25-X400-Link,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-X25-X400-Link
+distinguishedName: CN=ms-Exch-X25-X400-Link,${SCHEMADN}
+possSuperiors: container
+subClassOf: x400Link
+governsID: 1.2.840.113556.1.3.35
+mayContain: x25RemoteMTAPhone
+mayContain: x25FacilitiesDataOutgoing
+mayContain: x25FacilitiesDataIncoming
+mayContain: x25CallUserDataOutgoing
+mayContain: x25CallUserDataIncoming
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X25-X400-Link
+adminDescription: ms-Exch-X25-X400-Link
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: x25X400Link
+name: ms-Exch-X25-X400-Link
+schemaIDGUID: a8df74df-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-X25-X400-Link,${SCHEMADN}
+
+
+
+#
+# ms-Exch-X400-Link
+# Specifies a remote X.400 MTA.
+#
+dn: CN=ms-Exch-X400-Link,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: ms-Exch-X400-Link
+distinguishedName: CN=ms-Exch-X400-Link,${SCHEMADN}
+possSuperiors: container
+subClassOf: mailGateway
+governsID: 1.2.840.113556.1.3.29
+mayContain: x400SelectorSyntax
+mayContain: x400AttachmentType
+mayContain: twoWayAlternateFacility
+mayContain: turnRequestThreshold
+mayContain: transportExpeditedData
+mayContain: tempAssocThreshold
+mayContain: tSelector
+mayContain: supportingStack
+mayContain: sessionDisconnectTimer
+mayContain: sSelectorInbound
+mayContain: sSelector
+mayContain: rTSWindowSize
+mayContain: rTSRecoveryTimeout
+mayContain: rTSCheckpointSize
+mayContain: pSelectorInbound
+mayContain: pSelector
+mayContain: openRetryInterval
+mayContain: numOfTransferRetries
+mayContain: numOfOpenRetries
+mayContain: nAddressType
+mayContain: nAddress
+mayContain: mTALocalDesig
+mayContain: mTALocalCred
+mayContain: localInitialTurn
+mayContain: gatewayLocalDesig
+mayContain: gatewayLocalCred
+mayContain: associationLifetime
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X400-Link
+adminDescription: ms-Exch-X400-Link
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: x400Link
+name: ms-Exch-X400-Link
+schemaIDGUID: a8df74e0-c5ea-11d1-bbcb-0080c76670c0
+systemOnly: FALSE
+defaultSecurityDescriptor: D:S:
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=ms-Exch-X400-Link,${SCHEMADN}
+
+
+
+##############################################################################
+# AttributeSchema added
+##############################################################################
+
+
+
+
+#
+# msExch-Proxy-Gen-Options
+#
+dn: CN=msExch-Proxy-Gen-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: msExch-Proxy-Gen-Options
+distinguishedName: CN=msExch-Proxy-Gen-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50044
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: msExch-Proxy-Gen-Options
+adminDescription: msExch-Proxy-Gen-Options
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchProxyGenOptions
+name: msExch-Proxy-Gen-Options
+schemaIDGUID: 974c9a02-33fc-11d3-aa6e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Access-Control-Map
+# Contains the mapping for the access controls.
+#
+dn: CN=ms-Exch-Access-Control-Map,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Access-Control-Map
+distinguishedName: CN=ms-Exch-Access-Control-Map,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.64
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Access-Control-Map
+adminDescription: ms-Exch-Access-Control-Map
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchAccessControlMap
+name: ms-Exch-Access-Control-Map
+schemaIDGUID: 8ff54464-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Access-Flags
+# The authentication method to use.
+#
+dn: CN=ms-Exch-Access-Flags,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Access-Flags
+distinguishedName: CN=ms-Exch-Access-Flags,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2016
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Access-Flags
+adminDescription: ms-Exch-Access-Flags
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchAccessFlags
+name: ms-Exch-Access-Flags
+schemaIDGUID: 901b6a04-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Access-SSL-Flags
+# The type of encrypted channel that this resource supports.
+#
+dn: CN=ms-Exch-Access-SSL-Flags,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Access-SSL-Flags
+distinguishedName: CN=ms-Exch-Access-SSL-Flags,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2006
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Access-SSL-Flags
+adminDescription: ms-Exch-Access-SSL-Flags
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchAccessSSLFlags
+name: ms-Exch-Access-SSL-Flags
+schemaIDGUID: 903f2d4a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Activation-Schedule
+# This is the schedule if "scheduled times" is selected.
+#
+dn: CN=ms-Exch-Activation-Schedule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Activation-Schedule
+distinguishedName: CN=ms-Exch-Activation-Schedule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.213
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 84
+rangeUpper: 84
+mAPIID: 32837
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Activation-Schedule
+adminDescription: ms-Exch-Activation-Schedule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: activationSchedule
+name: ms-Exch-Activation-Schedule
+schemaIDGUID: bf967916-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Activation-Style
+#
+dn: CN=ms-Exch-Activation-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Activation-Style
+distinguishedName: CN=ms-Exch-Activation-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.73
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+mAPIID: 32838
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Activation-Style
+adminDescription: ms-Exch-Activation-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: activationStyle
+name: ms-Exch-Activation-Style
+schemaIDGUID: bf967917-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ADC-Global-Names
+#
+dn: CN=ms-Exch-ADC-Global-Names,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ADC-Global-Names
+distinguishedName: CN=ms-Exch-ADC-Global-Names,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.63
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ADC-Global-Names
+adminDescription: ms-Exch-ADC-Global-Names
+oMSyntax: 64
+searchFlags: 1
+lDAPDisplayName: msExchADCGlobalNames
+name: ms-Exch-ADC-Global-Names
+schemaIDGUID: 9062f090-b093-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ADC-Object-Type
+# A bit used to distinguish the type of connection agreement.
+#
+dn: CN=ms-Exch-ADC-Object-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ADC-Object-Type
+distinguishedName: CN=ms-Exch-ADC-Object-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.84
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ADC-Object-Type
+adminDescription: ms-Exch-ADC-Object-Type
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchADCObjectType
+name: ms-Exch-ADC-Object-Type
+schemaIDGUID: 4859fb55-1924-11d3-aa59-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ADC-Options
+# The options bitstring.
+#
+dn: CN=ms-Exch-ADC-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ADC-Options
+distinguishedName: CN=ms-Exch-ADC-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.41
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ADC-Options
+adminDescription: ms-Exch-ADC-Options
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchADCOptions
+name: ms-Exch-ADC-Options
+schemaIDGUID: 90891630-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Additional-DN-Map
+# Additional source-target pairs for straight distinguished name (DN)
+# mapping.
+#
+dn: CN=ms-Exch-Additional-DN-Map,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Additional-DN-Map
+distinguishedName: CN=ms-Exch-Additional-DN-Map,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.42
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Additional-DN-Map
+adminDescription: ms-Exch-Additional-DN-Map
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchAdditionalDNMap
+name: ms-Exch-Additional-DN-Map
+schemaIDGUID: 90a814c2-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Address-List-OU
+#
+dn: CN=ms-Exch-Address-List-OU,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Address-List-OU
+distinguishedName: CN=ms-Exch-Address-List-OU,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.112
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Address-List-OU
+adminDescription: ms-Exch-Address-List-OU
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchAddressListOU
+name: ms-Exch-Address-List-OU
+schemaIDGUID: f4b93a0d-f30c-44ff-aa47-e74806dbced2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Address-List-Service-BL
+# The link from the Exchange server to the address list service
+# running on it.
+#
+dn: CN=ms-Exch-Address-List-Service-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Address-List-Service-BL
+distinguishedName: CN=ms-Exch-Address-List-Service-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.74
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1017
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Address-List-Service-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Address-List-Service-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchAddressListServiceBL
+name: ms-Exch-Address-List-Service-BL
+schemaIDGUID: 8a407b6e-b09e-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Address-List-Service-Link
+# A link from the address list service to the Exchange server it
+# should be running on.
+#
+dn: CN=ms-Exch-Address-List-Service-Link,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Address-List-Service-Link
+distinguishedName: CN=ms-Exch-Address-List-Service-Link,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.75
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1016
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Address-List-Service-Link
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Address-List-Service-Link
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchAddressListServiceLink
+name: ms-Exch-Address-List-Service-Link
+schemaIDGUID: 9b6e9584-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Add-Groups-To-Token
+#
+dn: CN=ms-Exch-Add-Groups-To-Token,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Add-Groups-To-Token
+distinguishedName: CN=ms-Exch-Add-Groups-To-Token,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.95
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Add-Groups-To-Token
+adminDescription: ms-Exch-Add-Groups-To-Token
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchAddGroupsToToken
+name: ms-Exch-Add-Groups-To-Token
+schemaIDGUID: 9c4d7592-ef4a-4c69-8f30-6f18ca1ec370
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ADMD
+# Used by the message transfer agent (MTA) to determine if Internal
+# Trace Information should be stripped.
+dn: CN=ms-Exch-ADMD,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ADMD
+distinguishedName: CN=ms-Exch-ADMD,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.232
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 16
+mAPIID: 32841
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ADMD
+adminDescription: ms-Exch-ADMD
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: aDMD
+name: ms-Exch-ADMD
+schemaIDGUID: a8df7390-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Admins
+# A link to all Exchange administrators within the organization along
+# with the appropriate permissions.
+#
+dn: CN=ms-Exch-Admins,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Admins
+distinguishedName: CN=ms-Exch-Admins,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50064
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Admins
+adminDescription: ms-Exch-Admins
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchAdmins
+name: ms-Exch-Admins
+schemaIDGUID: b644c27a-a419-40b6-a62e-180930df5610
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Admin-ACL
+# The access control list (ACL).
+#
+dn: CN=ms-Exch-Admin-ACL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Admin-ACL
+distinguishedName: CN=ms-Exch-Admin-ACL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2011
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Admin-ACL
+adminDescription: ms-Exch-Admin-ACL
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchAdminACL
+name: ms-Exch-Admin-ACL
+schemaIDGUID: 90c975ae-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Admin-Extension-DLL
+#
+dn: CN=ms-Exch-Admin-Extension-DLL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Admin-Extension-DLL
+distinguishedName: CN=ms-Exch-Admin-Extension-DLL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.95
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 255
+mAPIID: 32844
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Admin-Extension-DLL
+adminDescription: ms-Exch-Admin-Extension-DLL
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: adminExtensionDLL
+name: ms-Exch-Admin-Extension-DLL
+schemaIDGUID: a8df7391-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Admin-Groups-Enabled
+# Used by the user interface (UI) to determine whether to display
+# Administrator Groups.
+#
+dn: CN=ms-Exch-Admin-Groups-Enabled,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Admin-Groups-Enabled
+distinguishedName: CN=ms-Exch-Admin-Groups-Enabled,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50026
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Admin-Groups-Enabled
+adminDescription: ms-Exch-Admin-Groups-Enabled
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchAdminGroupsEnabled
+name: ms-Exch-Admin-Groups-Enabled
+schemaIDGUID: e32977ae-1d31-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Admin-Group-Mode
+# The type of servers that are in the Administrator Group.
+#
+dn: CN=ms-Exch-Admin-Group-Mode,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Admin-Group-Mode
+distinguishedName: CN=ms-Exch-Admin-Group-Mode,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50014
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Admin-Group-Mode
+adminDescription: ms-Exch-Admin-Group-Mode
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchAdminGroupMode
+name: ms-Exch-Admin-Group-Mode
+schemaIDGUID: 90ead69a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Admin-Mailbox
+# A link to the administrator mailbox of the cc:Mail Connector.
+#
+dn: CN=ms-Exch-Admin-Mailbox,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Admin-Mailbox
+distinguishedName: CN=ms-Exch-Admin-Mailbox,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1034
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Admin-Mailbox
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Admin-Mailbox
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchAdminMailbox
+name: ms-Exch-Admin-Mailbox
+schemaIDGUID: 94e9a76c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Aging-Keep-Time
+# The time value used to determine when to remove indexes, views, and
+# categorizations. The default is 8 days.
+#
+dn: CN=ms-Exch-Aging-Keep-Time,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Aging-Keep-Time
+distinguishedName: CN=ms-Exch-Aging-Keep-Time,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11059
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Aging-Keep-Time
+adminDescription: ms-Exch-Aging-Keep-Time
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchAgingKeepTime
+name: ms-Exch-Aging-Keep-Time
+schemaIDGUID: 5872299f-123a-11d3-aa58-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Alias-Gen-Format
+# The time/date that this policy was applied.
+#
+dn: CN=ms-Exch-Alias-Gen-Format,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Alias-Gen-Format
+distinguishedName: CN=ms-Exch-Alias-Gen-Format,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50010
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Alias-Gen-Format
+adminDescription: ms-Exch-Alias-Gen-Format
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchAliasGenFormat
+name: ms-Exch-Alias-Gen-Format
+schemaIDGUID: 912b3618-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Alias-Gen-Type
+# The time/date that this policy was applied.
+#
+dn: CN=ms-Exch-Alias-Gen-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Alias-Gen-Type
+distinguishedName: CN=ms-Exch-Alias-Gen-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50011
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Alias-Gen-Type
+adminDescription: ms-Exch-Alias-Gen-Type
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchAliasGenType
+name: ms-Exch-Alias-Gen-Type
+schemaIDGUID: 914ef95e-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Alias-Gen-Uniqueness
+# The time/date that this policy was applied.
+#
+dn: CN=ms-Exch-Alias-Gen-Uniqueness,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Alias-Gen-Uniqueness
+distinguishedName: CN=ms-Exch-Alias-Gen-Uniqueness,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50012
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Alias-Gen-Uniqueness
+adminDescription: ms-Exch-Alias-Gen-Uniqueness
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchAliasGenUniqueness
+name: ms-Exch-Alias-Gen-Uniqueness
+schemaIDGUID: 91705a4a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Allow-Additional-Resources
+# Allows conference resource extension requests.
+#
+dn: CN=ms-Exch-Allow-Additional-Resources,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Allow-Additional-Resources
+distinguishedName: CN=ms-Exch-Allow-Additional-Resources,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9006
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Allow-Additional-Resources
+adminDescription: ms-Exch-Allow-Additional-Resources
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchAllowAdditionalResources
+name: ms-Exch-Allow-Additional-Resources
+schemaIDGUID: 91941d90-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Allow-Enhanced-Security
+#
+dn: CN=ms-Exch-Allow-Enhanced-Security,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Allow-Enhanced-Security
+distinguishedName: CN=ms-Exch-Allow-Enhanced-Security,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11087
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Allow-Enhanced-Security
+adminDescription: ms-Exch-Allow-Enhanced-Security
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchAllowEnhancedSecurity
+name: ms-Exch-Allow-Enhanced-Security
+schemaIDGUID: 63b79cf2-1f4b-4766-ba5b-814b6077640f
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Allow-Time-Extensions
+# Allows conference time extension requests.
+#
+dn: CN=ms-Exch-Allow-Time-Extensions,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Allow-Time-Extensions
+distinguishedName: CN=ms-Exch-Allow-Time-Extensions,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9005
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Allow-Time-Extensions
+adminDescription: ms-Exch-Allow-Time-Extensions
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchAllowTimeExtensions
+name: ms-Exch-Allow-Time-Extensions
+schemaIDGUID: 91b7e0d6-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Alternate-Server
+# Contains the host name of an alternate server that accepts mail for
+# the default domain.
+dn: CN=ms-Exch-Alternate-Server,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Alternate-Server
+distinguishedName: CN=ms-Exch-Alternate-Server,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12532
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Alternate-Server
+adminDescription: ms-Exch-Alternate-Server
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: msExchAlternateServer
+name: ms-Exch-Alternate-Server
+schemaIDGUID: 974c99f9-33fc-11d3-aa6e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Alt-Recipient
+# Delivers to this recipient if a specified recipient cannot be
+# delivered to.
+#
+dn: CN=ms-Exch-Alt-Recipient,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Alt-Recipient
+distinguishedName: CN=ms-Exch-Alt-Recipient,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.126
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 32846
+linkID: 12
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Alt-Recipient
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Alt-Recipient
+oMSyntax: 127
+searchFlags: 16
+lDAPDisplayName: altRecipient
+name: ms-Exch-Alt-Recipient
+schemaIDGUID: bf96791e-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Alt-Recipient-BL
+# A backlink to ms-Exch-Alt-Recipient.
+#
+dn: CN=ms-Exch-Alt-Recipient-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Alt-Recipient-BL
+distinguishedName: CN=ms-Exch-Alt-Recipient-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.294
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32847
+linkID: 13
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Alt-Recipient-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Alt-Recipient-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: altRecipientBL
+name: ms-Exch-Alt-Recipient-BL
+schemaIDGUID: bf96791f-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-AL-Object-Version
+#
+dn: CN=ms-Exch-AL-Object-Version,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-AL-Object-Version
+distinguishedName: CN=ms-Exch-AL-Object-Version,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.59
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-AL-Object-Version
+adminDescription: ms-Exch-AL-Object-Version
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchALObjectVersion
+name: ms-Exch-AL-Object-Version
+schemaIDGUID: 910c3786-b093-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Anonymous-Access
+# Determines whether or not anonymous access is allowed via this
+# protocol.
+#
+dn: CN=ms-Exch-Anonymous-Access,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Anonymous-Access
+distinguishedName: CN=ms-Exch-Anonymous-Access,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.482
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 33159
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Anonymous-Access
+adminDescription: ms-Exch-Anonymous-Access
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: anonymousAccess
+name: ms-Exch-Anonymous-Access
+schemaIDGUID: a8df7392-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Anonymous-Account
+#
+dn: CN=ms-Exch-Anonymous-Account,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Anonymous-Account
+distinguishedName: CN=ms-Exch-Anonymous-Account,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.561
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 256
+mAPIID: 35878
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Anonymous-Account
+adminDescription: ms-Exch-Anonymous-Account
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: anonymousAccount
+name: ms-Exch-Anonymous-Account
+schemaIDGUID: a8df7393-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Applies-To-Smtp-VS
+#
+dn: CN=ms-Exch-Applies-To-Smtp-VS,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Applies-To-Smtp-VS
+distinguishedName: CN=ms-Exch-Applies-To-Smtp-VS,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5058
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1034
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Applies-To-Smtp-VS
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Applies-To-Smtp-VS
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchAppliesToSmtpVS
+name: ms-Exch-Applies-To-Smtp-VS
+schemaIDGUID: 2925413e-fa41-4d01-945d-a15b5d6bb965
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Applies-To-Smtp-VS-BL
+#
+dn: CN=ms-Exch-Applies-To-Smtp-VS-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Applies-To-Smtp-VS-BL
+distinguishedName: CN=ms-Exch-Applies-To-Smtp-VS-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5059
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1035
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Applies-To-Smtp-VS-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Applies-To-Smtp-VS-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchAppliesToSmtpVSBL
+name: ms-Exch-Applies-To-Smtp-VS-BL
+schemaIDGUID: f7d091b1-1ced-446a-b521-563a01eaf22c
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Assistant-Name
+#
+#dn: CN=ms-Exch-Assistant-Name,${SCHEMADN}
+#objectClass: top
+#objectClass: attributeSchema
+#cn: ms-Exch-Assistant-Name
+#distinguishedName: CN=ms-Exch-Assistant-Name,${SCHEMADN}
+#attributeID: 1.2.840.113556.1.2.444
+#attributeSyntax: 2.5.5.12
+#isSingleValued: TRUE
+#rangeLower: 1
+#rangeUpper: 256
+#mAPIID: 14896
+#adminDisplayName: ms-Exch-Assistant-Name
+#adminDescription: ms-Exch-Assistant-Name
+#oMSyntax: 64
+#searchFlags: 0
+#lDAPDisplayName: msExchAssistantName
+#name: ms-Exch-Assistant-Name
+#schemaIDGUID: a8df7394-c5ea-11d1-bbcb-0080c76670c0
+#attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+#objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Associated-AG
+#
+dn: CN=ms-Exch-Associated-AG,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Associated-AG
+distinguishedName: CN=ms-Exch-Associated-AG,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50031
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Associated-AG
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Associated-AG
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchAssociatedAG
+name: ms-Exch-Associated-AG
+schemaIDGUID: e5971321-1d3e-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Association-Lifetime
+# The length of time a connection can be idle before it is closed.
+#
+dn: CN=ms-Exch-Association-Lifetime,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Association-Lifetime
+distinguishedName: CN=ms-Exch-Association-Lifetime,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.149
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 32850
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Association-Lifetime
+adminDescription: ms-Exch-Association-Lifetime
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: associationLifetime
+name: ms-Exch-Association-Lifetime
+schemaIDGUID: a8df7396-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Assoc-Remote-DXA
+#
+dn: CN=ms-Exch-Assoc-Remote-DXA,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Assoc-Remote-DXA
+distinguishedName: CN=ms-Exch-Assoc-Remote-DXA,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.299
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32849
+linkID: 123
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Assoc-Remote-DXA
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Assoc-Remote-DXA
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: assocRemoteDXA
+name: ms-Exch-Assoc-Remote-DXA
+schemaIDGUID: 16775789-47f3-11d1-a9c3-0000f80367c1
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Attribute-Certificate
+#
+dn: CN=ms-Exch-Attribute-Certificate,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Attribute-Certificate
+distinguishedName: CN=ms-Exch-Attribute-Certificate,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.587
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 32767
+mAPIID: 35909
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Attribute-Certificate
+adminDescription: ms-Exch-Attribute-Certificate
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: attributeCertificate
+name: ms-Exch-Attribute-Certificate
+schemaIDGUID: 1677578b-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Audit-Flags
+# A bitmap indicating the events to log.
+#
+dn: CN=ms-Exch-Audit-Flags,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Audit-Flags
+distinguishedName: CN=ms-Exch-Audit-Flags,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9004
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Audit-Flags
+adminDescription: ms-Exch-Audit-Flags
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchAuditFlags
+name: ms-Exch-Audit-Flags
+schemaIDGUID: 91d47d0e-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Authentication-Flags
+# Indicates which type of authentication this resource accepts.
+#
+dn: CN=ms-Exch-Authentication-Flags,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Authentication-Flags
+distinguishedName: CN=ms-Exch-Authentication-Flags,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2003
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Authentication-Flags
+adminDescription: ms-Exch-Authentication-Flags
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchAuthenticationFlags
+name: ms-Exch-Authentication-Flags
+schemaIDGUID: 91f5ddfa-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-AuthMailDisposition
+#
+dn: CN=ms-Exch-AuthMailDisposition,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-AuthMailDisposition
+distinguishedName: CN=ms-Exch-AuthMailDisposition,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.5061
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-AuthMailDisposition
+adminDescription: ms-Exch-AuthMailDisposition
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchAuthMailDisposition
+name: ms-Exch-AuthMailDisposition
+schemaIDGUID: 57cfb6f7-1e2c-4d3e-96df-40208624baff
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Authorization-Persistence
+#
+dn: CN=ms-Exch-Authorization-Persistence,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Authorization-Persistence
+distinguishedName: CN=ms-Exch-Authorization-Persistence,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15011
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Authorization-Persistence
+adminDescription: ms-Exch-Authorization-Persistence
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchAuthorizationPersistence
+name: ms-Exch-Authorization-Persistence
+schemaIDGUID: d6ae616b-16c5-44ce-b272-8b923aebe335
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Authorized-Domain
+# The domain name of the authentication account to be used when
+# connecting to the other side of the connector.
+#
+dn: CN=ms-Exch-Authorized-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Authorized-Domain
+distinguishedName: CN=ms-Exch-Authorized-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.202
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 15
+mAPIID: 32852
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Authorized-Domain
+adminDescription: ms-Exch-Authorized-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: authorizedDomain
+name: ms-Exch-Authorized-Domain
+schemaIDGUID: a8df739a-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Authorized-Password
+# The password of the authentication account to be used when connecting
+# to the other side of the connector.
+#
+dn: CN=ms-Exch-Authorized-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Authorized-Password
+distinguishedName: CN=ms-Exch-Authorized-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.193
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 512
+mAPIID: 32853
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Authorized-Password
+adminDescription: ms-Exch-Authorized-Password
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: authorizedPassword
+name: ms-Exch-Authorized-Password
+schemaIDGUID: a8df739b-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Authorized-User
+# The user name of the authentication account to be used when connecting
+# to the other side of the connector.
+#
+dn: CN=ms-Exch-Authorized-User,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Authorized-User
+distinguishedName: CN=ms-Exch-Authorized-User,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.276
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 512
+mAPIID: 32854
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Authorized-User
+adminDescription: ms-Exch-Authorized-User
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: authorizedUser
+name: ms-Exch-Authorized-User
+schemaIDGUID: a8df739d-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Auth-Orig
+# The users who are allowed to send mail to this recipient.
+#
+dn: CN=ms-Exch-Auth-Orig,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Auth-Orig
+distinguishedName: CN=ms-Exch-Auth-Orig,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.129
+attributeSyntax: 2.5.5.7
+isSingleValued: FALSE
+linkID: 110
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Auth-Orig
+oMObjectClass:: VgYBAgULHQ==
+adminDescription: ms-Exch-Auth-Orig
+oMSyntax: 127
+searchFlags: 16
+lDAPDisplayName: authOrig
+name: ms-Exch-Auth-Orig
+schemaIDGUID: a8df7397-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Auth-Orig-BL
+# A backlink to ms-Exch-Auth-Orig.
+#
+dn: CN=ms-Exch-Auth-Orig-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Auth-Orig-BL
+distinguishedName: CN=ms-Exch-Auth-Orig-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.290
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32851
+linkID: 111
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Auth-Orig-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Auth-Orig-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: authOrigBL
+name: ms-Exch-Auth-Orig-BL
+schemaIDGUID: a8df7398-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+systemFlags: 1
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-AutoReply
+#
+dn: CN=ms-Exch-AutoReply,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-AutoReply
+distinguishedName: CN=ms-Exch-AutoReply,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.286
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32779
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-AutoReply
+adminDescription: ms-Exch-AutoReply
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: autoReply
+name: ms-Exch-AutoReply
+schemaIDGUID: bf967929-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-AutoReply-Message
+# Contains Internet Locator Service (ILS) settings in the form
+# SERVER/ACCOUNT.
+#
+dn: CN=ms-Exch-AutoReply-Message,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-AutoReply-Message
+distinguishedName: CN=ms-Exch-AutoReply-Message,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.287
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32778
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-AutoReply-Message
+adminDescription: ms-Exch-AutoReply-Message
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: autoReplyMessage
+name: ms-Exch-AutoReply-Message
+schemaIDGUID: bf96792a-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Available-Authorization-Packages
+#
+dn: CN=ms-Exch-Available-Authorization-Packages,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Available-Authorization-Packages
+distinguishedName: CN=ms-Exch-Available-Authorization-Packages,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.476
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 512
+mAPIID: 33153
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Available-Authorization-Packages
+adminDescription: ms-Exch-Available-Authorization-Packages
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: availableAuthorizationPackages
+name: ms-Exch-Available-Authorization-Packages
+schemaIDGUID: a8df739e-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Available-Distributions
+#
+dn: CN=ms-Exch-Available-Distributions,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Available-Distributions
+distinguishedName: CN=ms-Exch-Available-Distributions,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.486
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 10240
+mAPIID: 33163
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Available-Distributions
+adminDescription: ms-Exch-Available-Distributions
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: availableDistributions
+name: ms-Exch-Available-Distributions
+schemaIDGUID: a8df739f-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Available-Servers
+# The installed conferencing servers.
+#
+dn: CN=ms-Exch-Available-Servers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Available-Servers
+distinguishedName: CN=ms-Exch-Available-Servers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9020
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Available-Servers
+adminDescription: ms-Exch-Available-Servers
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchAvailableServers
+name: ms-Exch-Available-Servers
+schemaIDGUID: 923b022c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-BackEnd-VDir-URL
+#
+dn: CN=ms-Exch-BackEnd-VDir-URL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-BackEnd-VDir-URL
+distinguishedName: CN=ms-Exch-BackEnd-VDir-URL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15012
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-BackEnd-VDir-URL
+adminDescription: ms-Exch-BackEnd-VDir-URL
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchBackEndVDirURL
+name: ms-Exch-BackEnd-VDir-URL
+schemaIDGUID: b4b283b6-0c3f-4a59-9e50-be9026228231
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Background-Threads
+# The maximum number of background threads per server.
+#
+dn: CN=ms-Exch-Background-Threads,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Background-Threads
+distinguishedName: CN=ms-Exch-Background-Threads,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11038
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Background-Threads
+adminDescription: ms-Exch-Background-Threads
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchBackgroundThreads
+name: ms-Exch-Background-Threads
+schemaIDGUID: 93d051f0-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Bar-Message-Class
+#
+dn: CN=ms-Exch-Bar-Message-Class,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Bar-Message-Class
+distinguishedName: CN=ms-Exch-Bar-Message-Class,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1064
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Bar-Message-Class
+adminDescription: ms-Exch-Bar-Message-Class
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchBarMessageClass
+name: ms-Exch-Bar-Message-Class
+schemaIDGUID: cf43e549-2ae1-410f-b896-02e40b934373
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Basic-Authentication-Domain
+# The default domain name for incoming basic authentication.
+#
+dn: CN=ms-Exch-Basic-Authentication-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Basic-Authentication-Domain
+distinguishedName: CN=ms-Exch-Basic-Authentication-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2010
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Basic-Authentication-Domain
+adminDescription: ms-Exch-Basic-Authentication-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchBasicAuthenticationDomain
+name: ms-Exch-Basic-Authentication-Domain
+schemaIDGUID: 94262698-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Bridgeheaded-Local-Connectors-DN-BL
+# A list of connectors (in the VSI's routing group) that this VSI is
+# the bridgehead for.
+#
+dn: CN=ms-Exch-Bridgeheaded-Local-Connectors-DN-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Bridgeheaded-Local-Connectors-DN-BL
+distinguishedName: CN=ms-Exch-Bridgeheaded-Local-Connectors-DN-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12515
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1003
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Bridgeheaded-Local-Connectors-DN-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Bridgeheaded-Local-Connectors-DN-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchBridgeheadedLocalConnectorsDNBL
+name: ms-Exch-Bridgeheaded-Local-Connectors-DN-BL
+schemaIDGUID: 944c4c38-b093-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Bridgeheaded-Remote-Connectors-DN-BL
+# A list of connectors (in a remote routing group) that this VSI is
+# the bridgehead for.
+#
+dn: CN=ms-Exch-Bridgeheaded-Remote-Connectors-DN-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Bridgeheaded-Remote-Connectors-DN-BL
+distinguishedName: CN=ms-Exch-Bridgeheaded-Remote-Connectors-DN-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12516
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1005
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Bridgeheaded-Remote-Connectors-DN-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Bridgeheaded-Remote-Connectors-DN-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchBridgeheadedRemoteConnectorsDNBL
+name: ms-Exch-Bridgeheaded-Remote-Connectors-DN-BL
+schemaIDGUID: 946dad24-b093-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Bridgehead-Servers
+#
+dn: CN=ms-Exch-Bridgehead-Servers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Bridgehead-Servers
+distinguishedName: CN=ms-Exch-Bridgehead-Servers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.463
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 33140
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Bridgehead-Servers
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Bridgehead-Servers
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: bridgeheadServers
+name: ms-Exch-Bridgehead-Servers
+schemaIDGUID: a8df73a0-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Business-Roles
+#
+dn: CN=ms-Exch-Business-Roles,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Business-Roles
+distinguishedName: CN=ms-Exch-Business-Roles,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.105
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 4096
+mAPIID: 32803
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Business-Roles
+adminDescription: ms-Exch-Business-Roles
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: businessRoles
+name: ms-Exch-Business-Roles
+schemaIDGUID: f0f8ff87-1191-11d0-a060-00aa006c33ed
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CalCon-Client-Wait
+#
+dn: CN=ms-Exch-CalCon-Client-Wait,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CalCon-Client-Wait
+distinguishedName: CN=ms-Exch-CalCon-Client-Wait,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1043
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CalCon-Client-Wait
+adminDescription: ms-Exch-CalCon-Client-Wait
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchCalConClientWait
+name: ms-Exch-CalCon-Client-Wait
+schemaIDGUID: 75447978-3752-4256-a89f-b4dfebae9a32
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CalCon-Providers
+#
+dn: CN=ms-Exch-CalCon-Providers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CalCon-Providers
+distinguishedName: CN=ms-Exch-CalCon-Providers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1042
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CalCon-Providers
+adminDescription: ms-Exch-CalCon-Providers
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchCalConProviders
+name: ms-Exch-CalCon-Providers
+schemaIDGUID: 73b41a3e-68b0-45a1-9e30-697b6d19aee6
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CalCon-Query-Window
+#
+dn: CN=ms-Exch-CalCon-Query-Window,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CalCon-Query-Window
+distinguishedName: CN=ms-Exch-CalCon-Query-Window,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1040
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CalCon-Query-Window
+adminDescription: ms-Exch-CalCon-Query-Window
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchCalConQueryWindow
+name: ms-Exch-CalCon-Query-Window
+schemaIDGUID: 5ebb881a-19d4-4526-b6f7-cc46d9aa1869
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CalCon-Refresh-Interval
+#
+dn: CN=ms-Exch-CalCon-Refresh-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CalCon-Refresh-Interval
+distinguishedName: CN=ms-Exch-CalCon-Refresh-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1041
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CalCon-Refresh-Interval
+adminDescription: ms-Exch-CalCon-Refresh-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchCalConRefreshInterval
+name: ms-Exch-CalCon-Refresh-Interval
+schemaIDGUID: 22bf39b6-7528-412c-b277-aa268db43960
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CalCon-Target-SiteDN
+#
+dn: CN=ms-Exch-CalCon-Target-SiteDN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CalCon-Target-SiteDN
+distinguishedName: CN=ms-Exch-CalCon-Target-SiteDN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1044
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CalCon-Target-SiteDN
+adminDescription: ms-Exch-CalCon-Target-SiteDN
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchCalConTargetSiteDN
+name: ms-Exch-CalCon-Target-SiteDN
+schemaIDGUID: 33b45526-8e8b-4679-97c3-4eeff39c7fbd
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Can-Preserve-DNs
+#
+dn: CN=ms-Exch-Can-Preserve-DNs,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Can-Preserve-DNs
+distinguishedName: CN=ms-Exch-Can-Preserve-DNs,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.455
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32864
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Can-Preserve-DNs
+adminDescription: ms-Exch-Can-Preserve-DNs
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: canPreserveDNs
+name: ms-Exch-Can-Preserve-DNs
+schemaIDGUID: a8df73a9-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Catalog
+# The globally unique identifier (GUID) of the catalog for this message
+# database (MDB).
+#
+dn: CN=ms-Exch-Catalog,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Catalog
+distinguishedName: CN=ms-Exch-Catalog,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11052
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Catalog
+adminDescription: ms-Exch-Catalog
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchCatalog
+name: ms-Exch-Catalog
+schemaIDGUID: 94abaa48-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-CA-Schema-Policy
+# A link to a schema policy that this certification authority (CA)
+# uses.
+#
+dn: CN=ms-Exch-CA-Schema-Policy,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CA-Schema-Policy
+distinguishedName: CN=ms-Exch-CA-Schema-Policy,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.56
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1006
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CA-Schema-Policy
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-CA-Schema-Policy
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchCASchemaPolicy
+name: ms-Exch-CA-Schema-Policy
+schemaIDGUID: 948f0e10-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ccMail-ADE-Prop
+# Allows the Automatic Directory Exchange (ADE) to propagate
+# synchronized entries to downstream cc:Mail post offices.
+#
+dn: CN=ms-Exch-ccMail-ADE-Prop,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ccMail-ADE-Prop
+distinguishedName: CN=ms-Exch-ccMail-ADE-Prop,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1036
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ccMail-ADE-Prop
+adminDescription: ms-Exch-ccMail-ADE-Prop
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchccMailADEProp
+name: ms-Exch-ccMail-ADE-Prop
+schemaIDGUID: 94caa8da-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ccMail-Connect-As-Password
+#
+dn: CN=ms-Exch-ccMail-Connect-As-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ccMail-Connect-As-Password
+distinguishedName: CN=ms-Exch-ccMail-Connect-As-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1207
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ccMail-Connect-As-Password
+adminDescription: ms-Exch-ccMail-Connect-As-Password
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchccMailConnectAsPassword
+name: ms-Exch-ccMail-Connect-As-Password
+schemaIDGUID: b8d47e43-4b78-11d3-aa75-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ccMail-Connect-As-Userid
+#
+dn: CN=ms-Exch-ccMail-Connect-As-Userid,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ccMail-Connect-As-Userid
+distinguishedName: CN=ms-Exch-ccMail-Connect-As-Userid,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1206
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ccMail-Connect-As-Userid
+adminDescription: ms-Exch-ccMail-Connect-As-Userid
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchccMailConnectAsUserid
+name: ms-Exch-ccMail-Connect-As-Userid
+schemaIDGUID: b8d47e3c-4b78-11d3-aa75-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ccMail-Password
+# The Administrator password to the cc:Mail post office.
+#
+dn: CN=ms-Exch-ccMail-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ccMail-Password
+distinguishedName: CN=ms-Exch-ccMail-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1039
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ccMail-Password
+adminDescription: ms-Exch-ccMail-Password
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchccMailPassword
+name: ms-Exch-ccMail-Password
+schemaIDGUID: 4634194c-4a93-11d3-aa73-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ccMail-PO-Name
+# The name of the cc:Mail post office where the connector exports and
+# imports mail.
+#
+dn: CN=ms-Exch-ccMail-PO-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ccMail-PO-Name
+distinguishedName: CN=ms-Exch-ccMail-PO-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1031
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ccMail-PO-Name
+adminDescription: ms-Exch-ccMail-PO-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchccMailPOName
+name: ms-Exch-ccMail-PO-Name
+schemaIDGUID: 95633f5a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ccMail-PO-Path
+# The file path to the cc:Mail post office.
+#
+dn: CN=ms-Exch-ccMail-PO-Path,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ccMail-PO-Path
+distinguishedName: CN=ms-Exch-ccMail-PO-Path,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1033
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ccMail-PO-Path
+adminDescription: ms-Exch-ccMail-PO-Path
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchccMailPOPath
+name: ms-Exch-ccMail-PO-Path
+schemaIDGUID: 98ed3cf2-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Certificate
+# Reserved.
+#
+dn: CN=ms-Exch-Certificate,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Certificate
+distinguishedName: CN=ms-Exch-Certificate,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9012
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Certificate
+adminDescription: ms-Exch-Certificate
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchCertificate
+name: ms-Exch-Certificate
+schemaIDGUID: 98ce3e60-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Certificate-Chain-V3
+#
+dn: CN=ms-Exch-Certificate-Chain-V3,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Certificate-Chain-V3
+distinguishedName: CN=ms-Exch-Certificate-Chain-V3,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.562
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+mAPIID: 35879
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Certificate-Chain-V3
+adminDescription: ms-Exch-Certificate-Chain-V3
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: certificateChainV3
+name: ms-Exch-Certificate-Chain-V3
+schemaIDGUID: a8df73aa-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Certificate-Revocation-List-V1
+#
+dn: CN=ms-Exch-Certificate-Revocation-List-V1,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Certificate-Revocation-List-V1
+distinguishedName: CN=ms-Exch-Certificate-Revocation-List-V1,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.564
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+mAPIID: 35881
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Certificate-Revocation-List-V1
+adminDescription: ms-Exch-Certificate-Revocation-List-V1
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: certificateRevocationListV1
+name: ms-Exch-Certificate-Revocation-List-V1
+schemaIDGUID: a8df73ab-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Certificate-Revocation-List-V3
+#
+dn: CN=ms-Exch-Certificate-Revocation-List-V3,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Certificate-Revocation-List-V3
+distinguishedName: CN=ms-Exch-Certificate-Revocation-List-V3,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.563
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+mAPIID: 35880
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Certificate-Revocation-List-V3
+adminDescription: ms-Exch-Certificate-Revocation-List-V3
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: certificateRevocationListV3
+name: ms-Exch-Certificate-Revocation-List-V3
+schemaIDGUID: a8df73ac-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Character-Set
+# The Multipurpose Internet Mail Extensions (MIME) tag of the
+# character set used by the client.
+#
+dn: CN=ms-Exch-Character-Set,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Character-Set
+distinguishedName: CN=ms-Exch-Character-Set,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.480
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 33157
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Character-Set
+adminDescription: ms-Exch-Character-Set
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: characterSet
+name: ms-Exch-Character-Set
+schemaIDGUID: a8df73ad-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Character-Set-List
+#
+dn: CN=ms-Exch-Character-Set-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Character-Set-List
+distinguishedName: CN=ms-Exch-Character-Set-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.477
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 128
+mAPIID: 33154
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Character-Set-List
+adminDescription: ms-Exch-Character-Set-List
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: characterSetList
+name: ms-Exch-Character-Set-List
+schemaIDGUID: a8df73ae-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Access
+# An ACL string representing security on this object.
+#
+dn: CN=ms-Exch-Chat-Access,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Access
+distinguishedName: CN=ms-Exch-Chat-Access,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8044
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Access
+adminDescription: ms-Exch-Chat-Access
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatAccess
+name: ms-Exch-Chat-Access
+schemaIDGUID: 8cac5ed6-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Admin-Message
+# The message that will be displayed to Chat administrators.
+#
+dn: CN=ms-Exch-Chat-Admin-Message,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Admin-Message
+distinguishedName: CN=ms-Exch-Chat-Admin-Message,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8003
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Admin-Message
+adminDescription: ms-Exch-Chat-Admin-Message
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatAdminMessage
+name: ms-Exch-Chat-Admin-Message
+schemaIDGUID: 98af3fce-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Ban-Mask
+# The mask determines the scope of the ban.
+#
+dn: CN=ms-Exch-Chat-Ban-Mask,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Ban-Mask
+distinguishedName: CN=ms-Exch-Chat-Ban-Mask,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8040
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Ban-Mask
+adminDescription: ms-Exch-Chat-Ban-Mask
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatBanMask
+name: ms-Exch-Chat-Ban-Mask
+schemaIDGUID: 9890413c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Ban-Reason
+# The reason for the ban is sent to the banned user when a connection
+# is attempted.
+#
+dn: CN=ms-Exch-Chat-Ban-Reason,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Ban-Reason
+distinguishedName: CN=ms-Exch-Chat-Ban-Reason,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8043
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Ban-Reason
+adminDescription: ms-Exch-Chat-Ban-Reason
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatBanReason
+name: ms-Exch-Chat-Ban-Reason
+schemaIDGUID: 959c77ca-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Chat-Broadcast-Address
+#
+dn: CN=ms-Exch-Chat-Broadcast-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Broadcast-Address
+distinguishedName: CN=ms-Exch-Chat-Broadcast-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8009
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Broadcast-Address
+adminDescription: ms-Exch-Chat-Broadcast-Address
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatBroadcastAddress
+name: ms-Exch-Chat-Broadcast-Address
+schemaIDGUID: 95b91402-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Chat-Channel-Auto-Create
+# Determines if the registered channel will be started automatically
+# when the service loads.
+#
+dn: CN=ms-Exch-Chat-Channel-Auto-Create,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Auto-Create
+distinguishedName: CN=ms-Exch-Chat-Channel-Auto-Create,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8020
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Auto-Create
+adminDescription: ms-Exch-Chat-Channel-Auto-Create
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelAutoCreate
+name: ms-Exch-Chat-Channel-Auto-Create
+schemaIDGUID: 95d81294-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-Flags
+# Flags that determine the IRC/IRCX modes of the channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Flags,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Flags
+distinguishedName: CN=ms-Exch-Chat-Channel-Flags,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8026
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Flags
+adminDescription: ms-Exch-Chat-Channel-Flags
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelFlags
+name: ms-Exch-Chat-Channel-Flags
+schemaIDGUID: 95f4aecc-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-Host-Key
+# The keyword used by a host to access a restricted channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Host-Key,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Host-Key
+distinguishedName: CN=ms-Exch-Chat-Channel-Host-Key,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8023
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Host-Key
+adminDescription: ms-Exch-Chat-Channel-Host-Key
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelHostKey
+name: ms-Exch-Chat-Channel-Host-Key
+schemaIDGUID: 96114b04-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-Join-Message
+# The message sent to users when they join the channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Join-Message,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Join-Message
+distinguishedName: CN=ms-Exch-Chat-Channel-Join-Message,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8030
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Join-Message
+adminDescription: ms-Exch-Chat-Channel-Join-Message
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelJoinMessage
+name: ms-Exch-Chat-Channel-Join-Message
+schemaIDGUID: 962de73c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-Key
+# The keyword used by a user to access a restricted channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Key,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Key
+distinguishedName: CN=ms-Exch-Chat-Channel-Key,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8021
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Key
+adminDescription: ms-Exch-Chat-Channel-Key
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelKey
+name: ms-Exch-Chat-Channel-Key
+schemaIDGUID: 964a8374-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-Language
+# The language used in a channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Language,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Language
+distinguishedName: CN=ms-Exch-Chat-Channel-Language,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8028
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Language
+adminDescription: ms-Exch-Chat-Channel-Language
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelLanguage
+name: ms-Exch-Chat-Channel-Language
+schemaIDGUID: 96671fac-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-LCID
+#
+dn: CN=ms-Exch-Chat-Channel-LCID,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-LCID
+distinguishedName: CN=ms-Exch-Chat-Channel-LCID,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8029
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-LCID
+adminDescription: ms-Exch-Chat-Channel-LCID
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelLCID
+name: ms-Exch-Chat-Channel-LCID
+schemaIDGUID: 9683bbe4-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Chat-Channel-Limit
+# The number of users allowed to join this channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Limit
+distinguishedName: CN=ms-Exch-Chat-Channel-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8010
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Limit
+adminDescription: ms-Exch-Chat-Channel-Limit
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelLimit
+name: ms-Exch-Chat-Channel-Limit
+schemaIDGUID: 96a0581c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-Mode
+# The modes of a channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Mode,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Mode
+distinguishedName: CN=ms-Exch-Chat-Channel-Mode,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8006
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Mode
+adminDescription: ms-Exch-Chat-Channel-Mode
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelMode
+name: ms-Exch-Chat-Channel-Mode
+schemaIDGUID: 96ba91fa-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-Name
+# The IRC/IRCX style name of the channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Name
+distinguishedName: CN=ms-Exch-Chat-Channel-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8019
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Name
+adminDescription: ms-Exch-Chat-Channel-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelName
+name: ms-Exch-Chat-Channel-Name
+schemaIDGUID: 96d72e32-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Chat-Channel-Owner-Key
+# The keyword used by an owner to access a restricted channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Owner-Key,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Owner-Key
+distinguishedName: CN=ms-Exch-Chat-Channel-Owner-Key,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8022
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Owner-Key
+adminDescription: ms-Exch-Chat-Channel-Owner-Key
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelOwnerKey
+name: ms-Exch-Chat-Channel-Owner-Key
+schemaIDGUID: 96f3ca6a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-Part-Message
+# The message sent to a user when they leave the channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Part-Message,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Part-Message
+distinguishedName: CN=ms-Exch-Chat-Channel-Part-Message,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8031
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Part-Message
+adminDescription: ms-Exch-Chat-Channel-Part-Message
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelPartMessage
+name: ms-Exch-Chat-Channel-Part-Message
+schemaIDGUID: 9712c8fc-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-PICS
+# The Platform for Internet Content Selection (PICS) rating for the channel.
+#
+dn: CN=ms-Exch-Chat-Channel-PICS,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-PICS
+distinguishedName: CN=ms-Exch-Chat-Channel-PICS,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8027
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-PICS
+adminDescription: ms-Exch-Chat-Channel-PICS
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelPICS
+name: ms-Exch-Chat-Channel-PICS
+schemaIDGUID: 972d02da-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-Subject
+# The subject of the channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Subject,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Subject
+distinguishedName: CN=ms-Exch-Chat-Channel-Subject,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8025
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Subject
+adminDescription: ms-Exch-Chat-Channel-Subject
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelSubject
+name: ms-Exch-Chat-Channel-Subject
+schemaIDGUID: 97499f12-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Channel-Topic
+# The topic of the channel.
+#
+dn: CN=ms-Exch-Chat-Channel-Topic,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Channel-Topic
+distinguishedName: CN=ms-Exch-Chat-Channel-Topic,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8024
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Channel-Topic
+adminDescription: ms-Exch-Chat-Channel-Topic
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatChannelTopic
+name: ms-Exch-Chat-Channel-Topic
+schemaIDGUID: 97663b4a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Class-Ident-Mask
+# Determines the scope of the Chat
+# class. ms-Exch-Chat-Class-Scope-Type Attribute determines if this
+# property is used, or if the Internet Protocol (IP)
+# ms-Exch-Chat-Class-IP Attribute property is used to scope the class.
+#
+dn: CN=ms-Exch-Chat-Class-Ident-Mask,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Class-Ident-Mask
+distinguishedName: CN=ms-Exch-Chat-Class-Ident-Mask,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8032
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Class-Ident-Mask
+adminDescription: ms-Exch-Chat-Class-Ident-Mask
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatClassIdentMask
+name: ms-Exch-Chat-Class-Ident-Mask
+schemaIDGUID: 9782d782-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Chat-Class-IP
+# Determines the scope of the Chat class specified by an IP
+# address. ms-Exch-Chat-Class-Scope-Type Attribute determines if this
+# property is used, or if the IP ms-Exch-Chat-Class-Ident-Mask
+# Attribute property is used to scope the class.
+#
+dn: CN=ms-Exch-Chat-Class-IP,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Class-IP
+distinguishedName: CN=ms-Exch-Chat-Class-IP,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8033
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Class-IP
+adminDescription: ms-Exch-Chat-Class-IP
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatClassIP
+name: ms-Exch-Chat-Class-IP
+schemaIDGUID: 97a1d614-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Class-Restrictions
+# The Chat user class restrictions.
+#
+dn: CN=ms-Exch-Chat-Class-Restrictions,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Class-Restrictions
+distinguishedName: CN=ms-Exch-Chat-Class-Restrictions,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8046
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Class-Restrictions
+adminDescription: ms-Exch-Chat-Class-Restrictions
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatClassRestrictions
+name: ms-Exch-Chat-Class-Restrictions
+schemaIDGUID: 8090a000-1234-11d3-aa58-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Class-Scope-Type
+# The Chat user class identification scope type.
+#
+dn: CN=ms-Exch-Chat-Class-Scope-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Class-Scope-Type
+distinguishedName: CN=ms-Exch-Chat-Class-Scope-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8047
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Class-Scope-Type
+adminDescription: ms-Exch-Chat-Class-Scope-Type
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchChatClassScopeType
+name: ms-Exch-Chat-Class-Scope-Type
+schemaIDGUID: 8090a006-1234-11d3-aa58-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Client-Port
+#
+dn: CN=ms-Exch-Chat-Client-Port,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Client-Port
+distinguishedName: CN=ms-Exch-Chat-Client-Port,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8007
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Client-Port
+adminDescription: ms-Exch-Chat-Client-Port
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatClientPort
+name: ms-Exch-Chat-Client-Port
+schemaIDGUID: 97be724c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-DNS-Reverse-Mode
+# Determines whether Domain Name System (DNS) reverse lookups are
+# performed on incoming client connections.
+#
+dn: CN=ms-Exch-Chat-DNS-Reverse-Mode,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-DNS-Reverse-Mode
+distinguishedName: CN=ms-Exch-Chat-DNS-Reverse-Mode,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8013
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-DNS-Reverse-Mode
+adminDescription: ms-Exch-Chat-DNS-Reverse-Mode
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatDNSReverseMode
+name: ms-Exch-Chat-DNS-Reverse-Mode
+schemaIDGUID: 97db0e84-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Duration
+# The amount of time this item is active starting from the value of
+# ms-Exch-Chat-Start-Time Attribute.
+#
+dn: CN=ms-Exch-Chat-Duration,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Duration
+distinguishedName: CN=ms-Exch-Chat-Duration,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8042
+attributeSyntax: 2.5.5.16
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Duration
+adminDescription: ms-Exch-Chat-Duration
+oMSyntax: 65
+searchFlags: 0
+lDAPDisplayName: msExchChatDuration
+name: ms-Exch-Chat-Duration
+schemaIDGUID: 97fa0d16-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Enable-Anonymous
+# Determines whether anonymous client connections are allowed to this
+# Chat co to this Chat community.
+#
+dn: CN=ms-Exch-Chat-Enable-Anonymous,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Enable-Anonymous
+distinguishedName: CN=ms-Exch-Chat-Enable-Anonymous,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8011
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Enable-Anonymous
+adminDescription: ms-Exch-Chat-Enable-Anonymous
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchChatEnableAnonymous
+name: ms-Exch-Chat-Enable-Anonymous
+schemaIDGUID: 98190ba8-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Extensions
+# A multivalued list of the Chat service extensions for this Chat
+# community on this server.
+#
+dn: CN=ms-Exch-Chat-Extensions,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Extensions
+distinguishedName: CN=ms-Exch-Chat-Extensions,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8048
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Extensions
+adminDescription: ms-Exch-Chat-Extensions
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatExtensions
+name: ms-Exch-Chat-Extensions
+schemaIDGUID: 3b9d8de5-2d93-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Input-Flood-Limit
+# Determines the maximum acceptable message rate allowed by the Chat
+# server from clients.
+#
+dn: CN=ms-Exch-Chat-Input-Flood-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Input-Flood-Limit
+distinguishedName: CN=ms-Exch-Chat-Input-Flood-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8038
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Input-Flood-Limit
+adminDescription: ms-Exch-Chat-Input-Flood-Limit
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatInputFloodLimit
+name: ms-Exch-Chat-Input-Flood-Limit
+schemaIDGUID: 987142aa-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Max-Anonymous
+# The maximum anonymous client connections that are allowed.
+#
+dn: CN=ms-Exch-Chat-Max-Anonymous,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Max-Anonymous
+distinguishedName: CN=ms-Exch-Chat-Max-Anonymous,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8015
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Max-Anonymous
+adminDescription: ms-Exch-Chat-Max-Anonymous
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatMaxAnonymous
+name: ms-Exch-Chat-Max-Anonymous
+schemaIDGUID: 9969373a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Max-Connections
+# The maximum number of client connections allowed.
+#
+dn: CN=ms-Exch-Chat-Max-Connections,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Max-Connections
+distinguishedName: CN=ms-Exch-Chat-Max-Connections,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8014
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Max-Connections
+adminDescription: ms-Exch-Chat-Max-Connections
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatMaxConnections
+name: ms-Exch-Chat-Max-Connections
+schemaIDGUID: 9985d372-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Max-Connections-Per-IP
+#
+dn: CN=ms-Exch-Chat-Max-Connections-Per-IP,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Max-Connections-Per-IP
+distinguishedName: CN=ms-Exch-Chat-Max-Connections-Per-IP,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8049
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Max-Connections-Per-IP
+adminDescription: ms-Exch-Chat-Max-Connections-Per-IP
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatMaxConnectionsPerIP
+name: ms-Exch-Chat-Max-Connections-Per-IP
+schemaIDGUID: 2ac57e6b-f737-4e41-8386-7295ddbe05e6
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Max-Memberships
+# The maximum number of channels that a Chat client may join at one
+# time.
+#
+dn: CN=ms-Exch-Chat-Max-Memberships,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Max-Memberships
+distinguishedName: CN=ms-Exch-Chat-Max-Memberships,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8016
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Max-Memberships
+adminDescription: ms-Exch-Chat-Max-Memberships
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatMaxMemberships
+name: ms-Exch-Chat-Max-Memberships
+schemaIDGUID: 99a4d204-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Max-Octets-To-Mask
+#
+dn: CN=ms-Exch-Chat-Max-Octets-To-Mask,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Max-Octets-To-Mask
+distinguishedName: CN=ms-Exch-Chat-Max-Octets-To-Mask,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8050
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Max-Octets-To-Mask
+adminDescription: ms-Exch-Chat-Max-Octets-To-Mask
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatMaxOctetsToMask
+name: ms-Exch-Chat-Max-Octets-To-Mask
+schemaIDGUID: 3de37b23-2789-4df7-b51f-f920ce544458
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Message-Lag
+# The amount of lag imparted to all messages to prevent flooding.
+#
+dn: CN=ms-Exch-Chat-Message-Lag,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Message-Lag
+distinguishedName: CN=ms-Exch-Chat-Message-Lag,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8034
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Message-Lag
+adminDescription: ms-Exch-Chat-Message-Lag
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatMessageLag
+name: ms-Exch-Chat-Message-Lag
+schemaIDGUID: 99e2cf28-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-MOTD
+# The message sent to users when they connect to a Chat community.
+#
+dn: CN=ms-Exch-Chat-MOTD,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-MOTD
+distinguishedName: CN=ms-Exch-Chat-MOTD,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8004
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-MOTD
+adminDescription: ms-Exch-Chat-MOTD
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatMOTD
+name: ms-Exch-Chat-MOTD
+schemaIDGUID: 99ff6b60-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Network-Mode
+# The Chat network settings for channel creation and defaults.
+#
+dn: CN=ms-Exch-Chat-Network-Mode,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Network-Mode
+distinguishedName: CN=ms-Exch-Chat-Network-Mode,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8045
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Network-Mode
+adminDescription: ms-Exch-Chat-Network-Mode
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatNetworkMode
+name: ms-Exch-Chat-Network-Mode
+schemaIDGUID: 917cfe98-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Network-Name
+#
+dn: CN=ms-Exch-Chat-Network-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Network-Name
+distinguishedName: CN=ms-Exch-Chat-Network-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8001
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Network-Name
+adminDescription: ms-Exch-Chat-Network-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatNetworkName
+name: ms-Exch-Chat-Network-Name
+schemaIDGUID: 9a1e69f2-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Nick-Delay
+# The amount of delay imparted on a user between changing
+# nicknames. Used for flood control.
+#
+dn: CN=ms-Exch-Chat-Nick-Delay,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Nick-Delay
+distinguishedName: CN=ms-Exch-Chat-Nick-Delay,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8036
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Nick-Delay
+adminDescription: ms-Exch-Chat-Nick-Delay
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatNickDelay
+name: ms-Exch-Chat-Nick-Delay
+schemaIDGUID: 9a3d6884-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Output-Saturation
+# The maximum level of buffering allowed before a client connection is
+# terminated.
+#
+dn: CN=ms-Exch-Chat-Output-Saturation,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Output-Saturation
+distinguishedName: CN=ms-Exch-Chat-Output-Saturation,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8039
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Output-Saturation
+adminDescription: ms-Exch-Chat-Output-Saturation
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatOutputSaturation
+name: ms-Exch-Chat-Output-Saturation
+schemaIDGUID: 9a5c6716-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Ping-Delay
+# The frequency of keep-alive pings from the Chat server.
+#
+dn: CN=ms-Exch-Chat-Ping-Delay,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Ping-Delay
+distinguishedName: CN=ms-Exch-Chat-Ping-Delay,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8037
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Ping-Delay
+adminDescription: ms-Exch-Chat-Ping-Delay
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatPingDelay
+name: ms-Exch-Chat-Ping-Delay
+schemaIDGUID: 9a7b65a8-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Protection-Level
+# The general attack protection level used by the Chat server.
+#
+dn: CN=ms-Exch-Chat-Protection-Level,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Protection-Level
+distinguishedName: CN=ms-Exch-Chat-Protection-Level,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8035
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Protection-Level
+adminDescription: ms-Exch-Chat-Protection-Level
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatProtectionLevel
+name: ms-Exch-Chat-Protection-Level
+schemaIDGUID: 9a9a643a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Server-Port
+#
+dn: CN=ms-Exch-Chat-Server-Port,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Server-Port
+distinguishedName: CN=ms-Exch-Chat-Server-Port,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8008
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Server-Port
+adminDescription: ms-Exch-Chat-Server-Port
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchChatServerPort
+name: ms-Exch-Chat-Server-Port
+schemaIDGUID: 9ab70072-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Chat-Start-Time
+# The time at which this item becomes active. The duration for which
+# it is active is determined by the value of ms-Exch-Chat-Duration
+# Attribute.
+#
+dn: CN=ms-Exch-Chat-Start-Time,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Start-Time
+distinguishedName: CN=ms-Exch-Chat-Start-Time,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8041
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Start-Time
+adminDescription: ms-Exch-Chat-Start-Time
+oMSyntax: 23
+searchFlags: 0
+lDAPDisplayName: msExchChatStartTime
+name: ms-Exch-Chat-Start-Time
+schemaIDGUID: 9ad39caa-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Chat-Title
+# A description of the Chat community displayed to users when they
+# connect.
+#
+dn: CN=ms-Exch-Chat-Title,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Chat-Title
+distinguishedName: CN=ms-Exch-Chat-Title,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8002
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Chat-Title
+adminDescription: ms-Exch-Chat-Title
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchChatTitle
+name: ms-Exch-Chat-Title
+schemaIDGUID: 9af29b3c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Child-Sync-Agreements
+# A backlink to the connection agreements from the service.
+#
+dn: CN=ms-Exch-Child-Sync-Agreements,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Child-Sync-Agreements
+distinguishedName: CN=ms-Exch-Child-Sync-Agreements,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.37
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 147
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Child-Sync-Agreements
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Child-Sync-Agreements
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchChildSyncAgreements
+name: ms-Exch-Child-Sync-Agreements
+schemaIDGUID: 9b309860-b093-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CI-Available
+#
+dn: CN=ms-Exch-CI-Available,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CI-Available
+distinguishedName: CN=ms-Exch-CI-Available,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11066
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CI-Available
+adminDescription: ms-Exch-CI-Available
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchCIAvailable
+name: ms-Exch-CI-Available
+schemaIDGUID: 035da50e-1a9e-11d3-aa59-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CI-Location
+# Stores the location of the index.
+#
+dn: CN=ms-Exch-CI-Location,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CI-Location
+distinguishedName: CN=ms-Exch-CI-Location,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11068
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CI-Location
+adminDescription: ms-Exch-CI-Location
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchCILocation
+name: ms-Exch-CI-Location
+schemaIDGUID: cec44725-22ae-11d3-aa62-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CI-Rebuild-Schedule
+#
+dn: CN=ms-Exch-CI-Rebuild-Schedule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CI-Rebuild-Schedule
+distinguishedName: CN=ms-Exch-CI-Rebuild-Schedule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11063
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 84
+rangeUpper: 84
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CI-Rebuild-Schedule
+adminDescription: ms-Exch-CI-Rebuild-Schedule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchCIRebuildSchedule
+name: ms-Exch-CI-Rebuild-Schedule
+schemaIDGUID: 035da4fd-1a9e-11d3-aa59-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-CI-Rebuild-Style
+#
+dn: CN=ms-Exch-CI-Rebuild-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CI-Rebuild-Style
+distinguishedName: CN=ms-Exch-CI-Rebuild-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11065
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CI-Rebuild-Style
+adminDescription: ms-Exch-CI-Rebuild-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchCIRebuildStyle
+name: ms-Exch-CI-Rebuild-Style
+schemaIDGUID: 035da507-1a9e-11d3-aa59-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-CI-Update-Schedule
+#
+dn: CN=ms-Exch-CI-Update-Schedule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CI-Update-Schedule
+distinguishedName: CN=ms-Exch-CI-Update-Schedule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11062
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 84
+rangeUpper: 84
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CI-Update-Schedule
+adminDescription: ms-Exch-CI-Update-Schedule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchCIUpdateSchedule
+name: ms-Exch-CI-Update-Schedule
+schemaIDGUID: 035da4f8-1a9e-11d3-aa59-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-CI-Update-Style
+#
+dn: CN=ms-Exch-CI-Update-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CI-Update-Style
+distinguishedName: CN=ms-Exch-CI-Update-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11064
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CI-Update-Style
+adminDescription: ms-Exch-CI-Update-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchCIUpdateStyle
+name: ms-Exch-CI-Update-Style
+schemaIDGUID: 035da502-1a9e-11d3-aa59-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Client-Access-Enabled
+#
+dn: CN=ms-Exch-Client-Access-Enabled,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Client-Access-Enabled
+distinguishedName: CN=ms-Exch-Client-Access-Enabled,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.559
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 35876
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Client-Access-Enabled
+adminDescription: ms-Exch-Client-Access-Enabled
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: clientAccessEnabled
+name: ms-Exch-Client-Access-Enabled
+schemaIDGUID: a8df73af-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Clock-Alert-Offset
+#
+dn: CN=ms-Exch-Clock-Alert-Offset,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Clock-Alert-Offset
+distinguishedName: CN=ms-Exch-Clock-Alert-Offset,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.165
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32865
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Clock-Alert-Offset
+adminDescription: ms-Exch-Clock-Alert-Offset
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: clockAlertOffset
+name: ms-Exch-Clock-Alert-Offset
+schemaIDGUID: a8df73b0-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Clock-Alert-Repair
+#
+dn: CN=ms-Exch-Clock-Alert-Repair,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Clock-Alert-Repair
+distinguishedName: CN=ms-Exch-Clock-Alert-Repair,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.164
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32866
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Clock-Alert-Repair
+adminDescription: ms-Exch-Clock-Alert-Repair
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: clockAlertRepair
+name: ms-Exch-Clock-Alert-Repair
+schemaIDGUID: a8df73b1-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Clock-Warning-Offset
+#
+dn: CN=ms-Exch-Clock-Warning-Offset,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Clock-Warning-Offset
+distinguishedName: CN=ms-Exch-Clock-Warning-Offset,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.177
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32867
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Clock-Warning-Offset
+adminDescription: ms-Exch-Clock-Warning-Offset
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: clockWarningOffset
+name: ms-Exch-Clock-Warning-Offset
+schemaIDGUID: a8df73b2-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Clock-Warning-Repair
+#
+dn: CN=ms-Exch-Clock-Warning-Repair,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Clock-Warning-Repair
+distinguishedName: CN=ms-Exch-Clock-Warning-Repair,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.166
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32868
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Clock-Warning-Repair
+adminDescription: ms-Exch-Clock-Warning-Repair
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: clockWarningRepair
+name: ms-Exch-Clock-Warning-Repair
+schemaIDGUID: a8df73b3-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Compromised-Key-List
+#
+dn: CN=ms-Exch-Compromised-Key-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Compromised-Key-List
+distinguishedName: CN=ms-Exch-Compromised-Key-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.542
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+mAPIID: 33220
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Compromised-Key-List
+adminDescription: ms-Exch-Compromised-Key-List
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: compromisedKeyList
+name: ms-Exch-Compromised-Key-List
+schemaIDGUID: 167757a9-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Computer-Link
+# A link from the computer to the Exchange server.
+#
+dn: CN=ms-Exch-Computer-Link,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Computer-Link
+distinguishedName: CN=ms-Exch-Computer-Link,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.72
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1018
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Computer-Link
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Computer-Link
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchComputerLink
+name: ms-Exch-Computer-Link
+schemaIDGUID: 8a5852f2-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Computer-Name
+#
+dn: CN=ms-Exch-Computer-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Computer-Name
+distinguishedName: CN=ms-Exch-Computer-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.20
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 256
+mAPIID: 32869
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Computer-Name
+adminDescription: ms-Exch-Computer-Name
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: computerName
+name: ms-Exch-Computer-Name
+schemaIDGUID: a8df73b4-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Conference-Mailbox
+# The forward link to the Exchange Conferencing Service conference
+# calendar mailbox.
+#
+dn: CN=ms-Exch-Conference-Mailbox,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Conference-Mailbox
+distinguishedName: CN=ms-Exch-Conference-Mailbox,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9029
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1036
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Conference-Mailbox
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Conference-Mailbox
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchConferenceMailbox
+name: ms-Exch-Conference-Mailbox
+schemaIDGUID: 628f0513-88f6-4cef-9de4-b367eb7e8383
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Conference-Mailbox-BL
+# The backlink to the Exchange Conferencing Service conference
+# calendar mailbox.
+#
+dn: CN=ms-Exch-Conference-Mailbox-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Conference-Mailbox-BL
+distinguishedName: CN=ms-Exch-Conference-Mailbox-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9030
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1037
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Conference-Mailbox-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Conference-Mailbox-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchConferenceMailboxBL
+name: ms-Exch-Conference-Mailbox-BL
+schemaIDGUID: 9423ec2c-383b-44b2-8913-ab79ac609bd4
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Conference-Zone
+# The Exchange Conferencing Service site forward link.
+#
+dn: CN=ms-Exch-Conference-Zone,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Conference-Zone
+distinguishedName: CN=ms-Exch-Conference-Zone,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9015
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1020
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Conference-Zone
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Conference-Zone
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchConferenceZone
+name: ms-Exch-Conference-Zone
+schemaIDGUID: 8cfd6eca-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Conference-Zone-BL
+# The Exchange Conferencing Service site backlink.
+#
+dn: CN=ms-Exch-Conference-Zone-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Conference-Zone-BL
+distinguishedName: CN=ms-Exch-Conference-Zone-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9024
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1021
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Conference-Zone-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Conference-Zone-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchConferenceZoneBL
+name: ms-Exch-Conference-Zone-BL
+schemaIDGUID: 8d1a0b02-b09e-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Connected-Domains
+# The sites or AGs that are connected using this connector.
+#
+dn: CN=ms-Exch-Connected-Domains,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Connected-Domains
+distinguishedName: CN=ms-Exch-Connected-Domains,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.211
+attributeSyntax: 2.5.5.4
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 1243
+mAPIID: 32870
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Connected-Domains
+adminDescription: ms-Exch-Connected-Domains
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: connectedDomains
+name: ms-Exch-Connected-Domains
+schemaIDGUID: a8df73b5-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Connection-List-Filter
+#
+dn: CN=ms-Exch-Connection-List-Filter,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Connection-List-Filter
+distinguishedName: CN=ms-Exch-Connection-List-Filter,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.475
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 10240
+mAPIID: 33152
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Connection-List-Filter
+adminDescription: ms-Exch-Connection-List-Filter
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: connectionListFilter
+name: ms-Exch-Connection-List-Filter
+schemaIDGUID: a8df73b6-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Connection-List-Filter-Type
+#
+dn: CN=ms-Exch-Connection-List-Filter-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Connection-List-Filter-Type
+distinguishedName: CN=ms-Exch-Connection-List-Filter-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.526
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 33204
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Connection-List-Filter-Type
+adminDescription: ms-Exch-Connection-List-Filter-Type
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: connectionListFilterType
+name: ms-Exch-Connection-List-Filter-Type
+schemaIDGUID: a8df73b7-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Connector-Type
+# The type of Exchange connector.
+#
+dn: CN=ms-Exch-Connector-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Connector-Type
+distinguishedName: CN=ms-Exch-Connector-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12508
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 255
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Connector-Type
+adminDescription: ms-Exch-Connector-Type
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchConnectorType
+name: ms-Exch-Connector-Type
+schemaIDGUID: 9b8d9416-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Container-Info
+#
+dn: CN=ms-Exch-Container-Info,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Container-Info
+distinguishedName: CN=ms-Exch-Container-Info,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.296
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32871
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Container-Info
+adminDescription: ms-Exch-Container-Info
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: containerInfo
+name: ms-Exch-Container-Info
+schemaIDGUID: bf967942-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Content-Type
+# Contains information about MIME versus Unix-to-Unix encode
+# (UUENCODE) and Rich Text Format (RTF) for a domain content
+# configuration.
+#
+dn: CN=ms-Exch-Content-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Content-Type
+distinguishedName: CN=ms-Exch-Content-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.481
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 4
+mAPIID: 33158
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Content-Type
+adminDescription: ms-Exch-Content-Type
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: contentType
+name: ms-Exch-Content-Type
+schemaIDGUID: a8df73b9-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Controlling-Zone
+# The forward link to the Exchange Conferencing Service resource
+# mailbox.
+#
+dn: CN=ms-Exch-Controlling-Zone,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Controlling-Zone
+distinguishedName: CN=ms-Exch-Controlling-Zone,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9026
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Controlling-Zone
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Controlling-Zone
+oMSyntax: 127
+searchFlags: 16
+lDAPDisplayName: msExchControllingZone
+name: ms-Exch-Controlling-Zone
+schemaIDGUID: 91462882-b09e-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Control-Msg-Folder-ID
+#
+dn: CN=ms-Exch-Control-Msg-Folder-ID,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Control-Msg-Folder-ID
+distinguishedName: CN=ms-Exch-Control-Msg-Folder-ID,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.483
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 33160
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Control-Msg-Folder-ID
+adminDescription: ms-Exch-Control-Msg-Folder-ID
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: controlMsgFolderID
+name: ms-Exch-Control-Msg-Folder-ID
+schemaIDGUID: a8df73ba-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Control-Msg-Rules
+#
+dn: CN=ms-Exch-Control-Msg-Rules,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Control-Msg-Rules
+distinguishedName: CN=ms-Exch-Control-Msg-Rules,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.485
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32767
+mAPIID: 33162
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Control-Msg-Rules
+adminDescription: ms-Exch-Control-Msg-Rules
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: controlMsgRules
+name: ms-Exch-Control-Msg-Rules
+schemaIDGUID: a8df73bb-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Convert-To-Fixed-Font
+# If True, the store configures IMAIL to convert Internet messages to
+# fixed font for RTF clients. The default is False.
+#
+dn: CN=ms-Exch-Convert-To-Fixed-Font,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Convert-To-Fixed-Font
+distinguishedName: CN=ms-Exch-Convert-To-Fixed-Font,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11021
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Convert-To-Fixed-Font
+adminDescription: ms-Exch-Convert-To-Fixed-Font
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchConvertToFixedFont
+name: ms-Exch-Convert-To-Fixed-Font
+schemaIDGUID: 9bac92a8-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Correlation-Attribute
+# The LDAP display name of the attribute used to correlate
+# entries. This is not used for replication between Exchange and
+# Microsoft® Windows®.
+#
+dn: CN=ms-Exch-Correlation-Attribute,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Correlation-Attribute
+distinguishedName: CN=ms-Exch-Correlation-Attribute,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.43
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Correlation-Attribute
+adminDescription: ms-Exch-Correlation-Attribute
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchCorrelationAttribute
+name: ms-Exch-Correlation-Attribute
+schemaIDGUID: 9c098e5e-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Cross-Certificate-CRL
+#
+dn: CN=ms-Exch-Cross-Certificate-CRL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Cross-Certificate-CRL
+distinguishedName: CN=ms-Exch-Cross-Certificate-CRL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.565
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+mAPIID: 35888
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Cross-Certificate-CRL
+adminDescription: ms-Exch-Cross-Certificate-CRL
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: crossCertificateCRL
+name: ms-Exch-Cross-Certificate-CRL
+schemaIDGUID: a8df73bc-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CTP-Class-GUID
+# The component implementation GUID for the conference technology
+# provider (CTP).
+#
+dn: CN=ms-Exch-CTP-Class-GUID,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CTP-Class-GUID
+distinguishedName: CN=ms-Exch-CTP-Class-GUID,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9008
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CTP-Class-GUID
+adminDescription: ms-Exch-CTP-Class-GUID
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchCTPClassGUID
+name: ms-Exch-CTP-Class-GUID
+schemaIDGUID: 9c288cf0-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CTP-Frame-Hint
+# The frame hint size.
+#
+dn: CN=ms-Exch-CTP-Frame-Hint,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CTP-Frame-Hint
+distinguishedName: CN=ms-Exch-CTP-Frame-Hint,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9010
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CTP-Frame-Hint
+adminDescription: ms-Exch-CTP-Frame-Hint
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchCTPFrameHint
+name: ms-Exch-CTP-Frame-Hint
+schemaIDGUID: 9c478b82-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CTP-Property-Schema
+# The CTP property schema. This attribute is obsolete.
+#
+dn: CN=ms-Exch-CTP-Property-Schema,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CTP-Property-Schema
+distinguishedName: CN=ms-Exch-CTP-Property-Schema,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9022
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CTP-Property-Schema
+adminDescription: ms-Exch-CTP-Property-Schema
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchCTPPropertySchema
+name: ms-Exch-CTP-Property-Schema
+schemaIDGUID: 9c6427ba-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CTP-Provider-GUID
+# The CTP GUID.
+#
+dn: CN=ms-Exch-CTP-Provider-GUID,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CTP-Provider-GUID
+distinguishedName: CN=ms-Exch-CTP-Provider-GUID,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9007
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CTP-Provider-GUID
+adminDescription: ms-Exch-CTP-Provider-GUID
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchCTPProviderGUID
+name: ms-Exch-CTP-Provider-GUID
+schemaIDGUID: 9c8588a6-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CTP-Provider-Name
+# The CTP internal name.
+#
+dn: CN=ms-Exch-CTP-Provider-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CTP-Provider-Name
+distinguishedName: CN=ms-Exch-CTP-Provider-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9021
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CTP-Provider-Name
+adminDescription: ms-Exch-CTP-Provider-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchCTPProviderName
+name: ms-Exch-CTP-Provider-Name
+schemaIDGUID: 9ca48738-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CTP-Require-CMS-Authentication
+# Indicates whether authentication is required to join the selected
+# conference.
+#
+dn: CN=ms-Exch-CTP-Require-CMS-Authentication,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CTP-Require-CMS-Authentication
+distinguishedName: CN=ms-Exch-CTP-Require-CMS-Authentication,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9023
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CTP-Require-CMS-Authentication
+adminDescription: ms-Exch-CTP-Require-CMS-Authentication
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchCTPRequireCMSAuthentication
+name: ms-Exch-CTP-Require-CMS-Authentication
+schemaIDGUID: 8aa962e6-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-CTP-Snapin-GUID
+# The Microsoft Management Console (MMC) snap-in implementation GUID
+# for the CTP.
+#
+dn: CN=ms-Exch-CTP-Snapin-GUID,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-CTP-Snapin-GUID
+distinguishedName: CN=ms-Exch-CTP-Snapin-GUID,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9009
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-CTP-Snapin-GUID
+adminDescription: ms-Exch-CTP-Snapin-GUID
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchCTPSnapinGUID
+name: ms-Exch-CTP-Snapin-GUID
+schemaIDGUID: 9cc385ca-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Custom-Proxy-Addresses
+#
+dn: CN=ms-Exch-Custom-Proxy-Addresses,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Custom-Proxy-Addresses
+distinguishedName: CN=ms-Exch-Custom-Proxy-Addresses,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50049
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Custom-Proxy-Addresses
+adminDescription: ms-Exch-Custom-Proxy-Addresses
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchCustomProxyAddresses
+name: ms-Exch-Custom-Proxy-Addresses
+schemaIDGUID: e24d7a90-439d-11d3-aa72-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Database-Being-Restored
+# Prevents any mount to the database. This is set during a restore.
+#
+dn: CN=ms-Exch-Database-Being-Restored,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Database-Being-Restored
+distinguishedName: CN=ms-Exch-Database-Being-Restored,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11085
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Database-Being-Restored
+adminDescription: ms-Exch-Database-Being-Restored
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchDatabaseBeingRestored
+name: ms-Exch-Database-Being-Restored
+schemaIDGUID: 372fadff-d0b6-4552-8057-f3a0d2c706a7
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Database-Created
+# Indicates to the store whether or not the database is to be created.
+#
+dn: CN=ms-Exch-Database-Created,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Database-Created
+distinguishedName: CN=ms-Exch-Database-Created,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11084
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Database-Created
+adminDescription: ms-Exch-Database-Created
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchDatabaseCreated
+name: ms-Exch-Database-Created
+schemaIDGUID: 14f27149-ba76-4aee-bac8-fced38fdff9d
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Database-Session-Addend
+# The accumulator for sessions.
+#
+dn: CN=ms-Exch-Database-Session-Addend,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Database-Session-Addend
+distinguishedName: CN=ms-Exch-Database-Session-Addend,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11039
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Database-Session-Addend
+adminDescription: ms-Exch-Database-Session-Addend
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchDatabaseSessionAddend
+name: ms-Exch-Database-Session-Addend
+schemaIDGUID: 9ce2845c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Database-Session-Increment
+# Number of Microsoft Jet sessions to allocate when more Jet sessions
+# are needed.
+#
+dn: CN=ms-Exch-Database-Session-Increment,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Database-Session-Increment
+distinguishedName: CN=ms-Exch-Database-Session-Increment,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11040
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Database-Session-Increment
+adminDescription: ms-Exch-Database-Session-Increment
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchDatabaseSessionIncrement
+name: ms-Exch-Database-Session-Increment
+schemaIDGUID: 9d0647a2-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Data-Path
+#
+dn: CN=ms-Exch-Data-Path,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Data-Path
+distinguishedName: CN=ms-Exch-Data-Path,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50052
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Data-Path
+adminDescription: ms-Exch-Data-Path
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDataPath
+name: ms-Exch-Data-Path
+schemaIDGUID: 61c47260-454e-11d3-aa72-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Default-Admin-Group
+# A flag indicating whether this administrator group is the default.
+#
+dn: CN=ms-Exch-Default-Admin-Group,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Default-Admin-Group
+distinguishedName: CN=ms-Exch-Default-Admin-Group,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50015
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Default-Admin-Group
+adminDescription: ms-Exch-Default-Admin-Group
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchDefaultAdminGroup
+name: ms-Exch-Default-Admin-Group
+schemaIDGUID: 847584c2-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Default-Domain
+# The domain used for basic authentication.
+#
+dn: CN=ms-Exch-Default-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Default-Domain
+distinguishedName: CN=ms-Exch-Default-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2012
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Default-Domain
+adminDescription: ms-Exch-Default-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDefaultDomain
+name: ms-Exch-Default-Domain
+schemaIDGUID: 9d22e3da-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Default-Load-File
+#
+dn: CN=ms-Exch-Default-Load-File,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Default-Load-File
+distinguishedName: CN=ms-Exch-Default-Load-File,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15010
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Default-Load-File
+adminDescription: ms-Exch-Default-Load-File
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDefaultLoadFile
+name: ms-Exch-Default-Load-File
+schemaIDGUID: 6267667c-cf34-407d-ba11-7cc8cc68ca1b
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Default-Logon-Domain
+# Specifies the default domain for logon.
+dn: CN=ms-Exch-Default-Logon-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Default-Logon-Domain
+distinguishedName: CN=ms-Exch-Default-Logon-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15001
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Default-Logon-Domain
+adminDescription: ms-Exch-Default-Logon-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDefaultLogonDomain
+name: ms-Exch-Default-Logon-Domain
+schemaIDGUID: 8bb46a46-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Default-Message-Format
+#
+dn: CN=ms-Exch-Default-Message-Format,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Default-Message-Format
+distinguishedName: CN=ms-Exch-Default-Message-Format,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.572
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 35895
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Default-Message-Format
+adminDescription: ms-Exch-Default-Message-Format
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: defaultMessageFormat
+name: ms-Exch-Default-Message-Format
+schemaIDGUID: a8df73bd-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Delegate-User
+#
+dn: CN=ms-Exch-Delegate-User,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Delegate-User
+distinguishedName: CN=ms-Exch-Delegate-User,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.591
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 35913
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Delegate-User
+adminDescription: ms-Exch-Delegate-User
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: delegateUser
+name: ms-Exch-Delegate-User
+schemaIDGUID: a8df73be-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Deleted-Item-Flags
+# Controls deleted item retention settings.
+#
+dn: CN=ms-Exch-Deleted-Item-Flags,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Deleted-Item-Flags
+distinguishedName: CN=ms-Exch-Deleted-Item-Flags,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.106
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32898
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Deleted-Item-Flags
+adminDescription: ms-Exch-Deleted-Item-Flags
+oMSyntax: 2
+searchFlags: 16
+lDAPDisplayName: deletedItemFlags
+name: ms-Exch-Deleted-Item-Flags
+schemaIDGUID: 167757c7-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Delivery-Mechanism
+#
+dn: CN=ms-Exch-Delivery-Mechanism,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Delivery-Mechanism
+distinguishedName: CN=ms-Exch-Delivery-Mechanism,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.241
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+mAPIID: 32878
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Delivery-Mechanism
+adminDescription: ms-Exch-Delivery-Mechanism
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: deliveryMechanism
+name: ms-Exch-Delivery-Mechanism
+schemaIDGUID: bf96794e-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Delivery-Order
+# Determines the order of processing messages in the connector's
+# queue. Options are: FIFO, Priority (default), and Size.
+#
+dn: CN=ms-Exch-Delivery-Order,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Delivery-Order
+distinguishedName: CN=ms-Exch-Delivery-Order,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1003
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Delivery-Order
+adminDescription: ms-Exch-Delivery-Order
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDeliveryOrder
+name: ms-Exch-Delivery-Order
+schemaIDGUID: 9d41e26c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Deliver-And-Redirect
+# Used with ms-Exch-Alt-Recipient. If True, delivers to the mailbox and
+# also redirects.
+#
+dn: CN=ms-Exch-Deliver-And-Redirect,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Deliver-And-Redirect
+distinguishedName: CN=ms-Exch-Deliver-And-Redirect,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.190
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32877
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Deliver-And-Redirect
+adminDescription: ms-Exch-Deliver-And-Redirect
+oMSyntax: 1
+searchFlags: 16
+lDAPDisplayName: deliverAndRedirect
+name: ms-Exch-Deliver-And-Redirect
+schemaIDGUID: bf96794d-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Deliv-Cont-Length
+# For recipients, the maximum message size, in kilobytes (KB), that
+# they can receive. For a connector, the maximum message size, in KB,
+# that can be sent over the connector.
+#
+dn: CN=ms-Exch-Deliv-Cont-Length,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Deliv-Cont-Length
+distinguishedName: CN=ms-Exch-Deliv-Cont-Length,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.138
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32874
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Deliv-Cont-Length
+adminDescription: ms-Exch-Deliv-Cont-Length
+oMSyntax: 2
+searchFlags: 16
+lDAPDisplayName: delivContLength
+name: ms-Exch-Deliv-Cont-Length
+schemaIDGUID: bf96794a-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Deliv-EITs
+#
+dn: CN=ms-Exch-Deliv-EITs,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Deliv-EITs
+distinguishedName: CN=ms-Exch-Deliv-EITs,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.139
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 4096
+mAPIID: 32875
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Deliv-EITs
+adminDescription: ms-Exch-Deliv-EITs
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: delivEITs
+name: ms-Exch-Deliv-EITs
+schemaIDGUID: bf96794b-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Deliv-Ext-Cont-Types
+#
+dn: CN=ms-Exch-Deliv-Ext-Cont-Types,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Deliv-Ext-Cont-Types
+distinguishedName: CN=ms-Exch-Deliv-Ext-Cont-Types,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.140
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 4096
+mAPIID: 32876
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Deliv-Ext-Cont-Types
+adminDescription: ms-Exch-Deliv-Ext-Cont-Types
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: delivExtContTypes
+name: ms-Exch-Deliv-Ext-Cont-Types
+schemaIDGUID: bf96794c-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Dereference-Aliases
+# Determines if x.500 aliases should be dereferenced. This is
+# applicable when replicating with x.500/LDAP directories that support
+# aliases.
+#
+dn: CN=ms-Exch-Dereference-Aliases,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Dereference-Aliases
+distinguishedName: CN=ms-Exch-Dereference-Aliases,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Dereference-Aliases
+adminDescription: ms-Exch-Dereference-Aliases
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchDereferenceAliases
+name: ms-Exch-Dereference-Aliases
+schemaIDGUID: 9d60e0fe-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Destination-RG-DN
+# The routing group (RG) on the other side of an Exchange Connector.
+#
+dn: CN=ms-Exch-Destination-RG-DN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Destination-RG-DN
+distinguishedName: CN=ms-Exch-Destination-RG-DN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12507
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Destination-RG-DN
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Destination-RG-DN
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchDestinationRGDN
+name: ms-Exch-Destination-RG-DN
+schemaIDGUID: 9d9ede22-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Dest-BH-Address
+# This attribute is obsolete.
+#
+dn: CN=ms-Exch-Dest-BH-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Dest-BH-Address
+distinguishedName: CN=ms-Exch-Dest-BH-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12510
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 255
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Dest-BH-Address
+adminDescription: ms-Exch-Dest-BH-Address
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchDestBHAddress
+name: ms-Exch-Dest-BH-Address
+schemaIDGUID: 9d8241ea-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Diagnostic-Reg-Key
+# The location of the diagnostic registry key.
+#
+dn: CN=ms-Exch-Diagnostic-Reg-Key,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Diagnostic-Reg-Key
+distinguishedName: CN=ms-Exch-Diagnostic-Reg-Key,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.189
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 256
+mAPIID: 32881
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Diagnostic-Reg-Key
+adminDescription: ms-Exch-Diagnostic-Reg-Key
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: diagnosticRegKey
+name: ms-Exch-Diagnostic-Reg-Key
+schemaIDGUID: bf967952-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Dirsync-Filters
+# A list of relational expressions that determine which directory
+# entries are propagated from Lotus Notes to Exchange during directory
+# synchronization.
+#
+dn: CN=ms-Exch-Dirsync-Filters,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Dirsync-Filters
+distinguishedName: CN=ms-Exch-Dirsync-Filters,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1005
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Dirsync-Filters
+adminDescription: ms-Exch-Dirsync-Filters
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDirsyncFilters
+name: ms-Exch-Dirsync-Filters
+schemaIDGUID: 9dbddcb4-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Dirsync-Schedule
+#
+dn: CN=ms-Exch-Dirsync-Schedule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Dirsync-Schedule
+distinguishedName: CN=ms-Exch-Dirsync-Schedule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1008
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 84
+rangeUpper: 84
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Dirsync-Schedule
+adminDescription: ms-Exch-Dirsync-Schedule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchDirsyncSchedule
+name: ms-Exch-Dirsync-Schedule
+schemaIDGUID: 8e11ff92-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Dirsync-Style
+#
+dn: CN=ms-Exch-Dirsync-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Dirsync-Style
+distinguishedName: CN=ms-Exch-Dirsync-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1009
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Dirsync-Style
+adminDescription: ms-Exch-Dirsync-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchDirsyncStyle
+name: ms-Exch-Dirsync-Style
+schemaIDGUID: 8e2e9bca-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Dir-Browse-Flags
+# Contains the directory browsing flags.
+#
+dn: CN=ms-Exch-Dir-Browse-Flags,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Dir-Browse-Flags
+distinguishedName: CN=ms-Exch-Dir-Browse-Flags,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15005
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Dir-Browse-Flags
+adminDescription: ms-Exch-Dir-Browse-Flags
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchDirBrowseFlags
+name: ms-Exch-Dir-Browse-Flags
+schemaIDGUID: 8c221672-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Disabled-Gateway-Proxy
+#
+dn: CN=ms-Exch-Disabled-Gateway-Proxy,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Disabled-Gateway-Proxy
+distinguishedName: CN=ms-Exch-Disabled-Gateway-Proxy,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.541
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 0
+rangeUpper: 1024
+mAPIID: 33219
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Disabled-Gateway-Proxy
+adminDescription: ms-Exch-Disabled-Gateway-Proxy
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: disabledGatewayProxy
+name: ms-Exch-Disabled-Gateway-Proxy
+schemaIDGUID: a8df73c0-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Disable-UDG-Conversion
+# If set, this disables the conversion of universal distribution
+# groups to universal security groups.
+#
+dn: CN=ms-Exch-Disable-UDG-Conversion,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Disable-UDG-Conversion
+distinguishedName: CN=ms-Exch-Disable-UDG-Conversion,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11088
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Disable-UDG-Conversion
+adminDescription: ms-Exch-Disable-UDG-Conversion
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchDisableUDGConversion
+name: ms-Exch-Disable-UDG-Conversion
+schemaIDGUID: 372d6cde-38c7-47b6-a3da-be4648124ec0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Discussion-Folder
+#
+dn: CN=ms-Exch-Discussion-Folder,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Discussion-Folder
+distinguishedName: CN=ms-Exch-Discussion-Folder,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.14002
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Discussion-Folder
+adminDescription: ms-Exch-Discussion-Folder
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDiscussionFolder
+name: ms-Exch-Discussion-Folder
+schemaIDGUID: 3df30250-38a7-11d3-aa6e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DL-Member-Rule
+# This attribute is not used by Exchange.
+#
+dn: CN=ms-Exch-DL-Member-Rule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DL-Member-Rule
+distinguishedName: CN=ms-Exch-DL-Member-Rule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.330
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 4096
+mAPIID: 32884
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DL-Member-Rule
+adminDescription: ms-Exch-DL-Member-Rule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: dLMemberRule
+name: ms-Exch-DL-Member-Rule
+schemaIDGUID: a8df73c6-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DL-Mem-Default
+#
+dn: CN=ms-Exch-DL-Mem-Default,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DL-Mem-Default
+distinguishedName: CN=ms-Exch-DL-Mem-Default,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12527
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DL-Mem-Default
+adminDescription: ms-Exch-DL-Mem-Default
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: dLMemDefault
+name: ms-Exch-DL-Mem-Default
+schemaIDGUID: 89d5319c-b09e-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DL-Mem-Reject-Perms
+# A distribution list (DL) whose members may not send to this
+# recipient or send messages over this connector.
+#
+dn: CN=ms-Exch-DL-Mem-Reject-Perms,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DL-Mem-Reject-Perms
+distinguishedName: CN=ms-Exch-DL-Mem-Reject-Perms,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.47
+attributeSyntax: 2.5.5.7
+isSingleValued: FALSE
+linkID: 116
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DL-Mem-Reject-Perms
+oMObjectClass:: VgYBAgULHQ==
+adminDescription: ms-Exch-DL-Mem-Reject-Perms
+oMSyntax: 127
+searchFlags: 16
+lDAPDisplayName: dLMemRejectPerms
+name: ms-Exch-DL-Mem-Reject-Perms
+schemaIDGUID: a8df73c2-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DL-Mem-Reject-Perms-BL
+# Backlink to ms-Exch-DL-Mem-Reject-Perms.
+#
+dn: CN=ms-Exch-DL-Mem-Reject-Perms-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DL-Mem-Reject-Perms-BL
+distinguishedName: CN=ms-Exch-DL-Mem-Reject-Perms-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.293
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32882
+linkID: 117
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DL-Mem-Reject-Perms-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-DL-Mem-Reject-Perms-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: dLMemRejectPermsBL
+name: ms-Exch-DL-Mem-Reject-Perms-BL
+schemaIDGUID: a8df73c3-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+systemFlags: 1
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DL-Mem-Submit-Perms
+# A DL whose members may send to this recipient or send messages over
+# this connector.
+#
+dn: CN=ms-Exch-DL-Mem-Submit-Perms,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DL-Mem-Submit-Perms
+distinguishedName: CN=ms-Exch-DL-Mem-Submit-Perms,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.144
+attributeSyntax: 2.5.5.7
+isSingleValued: FALSE
+linkID: 112
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DL-Mem-Submit-Perms
+oMObjectClass:: VgYBAgULHQ==
+adminDescription: ms-Exch-DL-Mem-Submit-Perms
+oMSyntax: 127
+searchFlags: 16
+lDAPDisplayName: dLMemSubmitPerms
+name: ms-Exch-DL-Mem-Submit-Perms
+schemaIDGUID: a8df73c4-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DL-Mem-Submit-Perms-BL
+# Backlink to ms-Exch-DL-Mem-Submit-Perms.
+#
+dn: CN=ms-Exch-DL-Mem-Submit-Perms-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DL-Mem-Submit-Perms-BL
+distinguishedName: CN=ms-Exch-DL-Mem-Submit-Perms-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.291
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32883
+linkID: 113
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DL-Mem-Submit-Perms-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-DL-Mem-Submit-Perms-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: dLMemSubmitPermsBL
+name: ms-Exch-DL-Mem-Submit-Perms-BL
+schemaIDGUID: a8df73c5-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+systemFlags: 1
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Domain-Def-Alt-Recip
+#
+dn: CN=ms-Exch-Domain-Def-Alt-Recip,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Domain-Def-Alt-Recip
+distinguishedName: CN=ms-Exch-Domain-Def-Alt-Recip,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.145
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 32885
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Domain-Def-Alt-Recip
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Domain-Def-Alt-Recip
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: domainDefAltRecip
+name: ms-Exch-Domain-Def-Alt-Recip
+schemaIDGUID: 167757bb-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Domain-Global-Group-Guid
+# Contains the stringized GUID of the domain local group within the
+# Recipient Update Service (RUS) domain.
+#
+dn: CN=ms-Exch-Domain-Global-Group-Guid,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Domain-Global-Group-Guid
+distinguishedName: CN=ms-Exch-Domain-Global-Group-Guid,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50089
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Domain-Global-Group-Guid
+adminDescription: ms-Exch-Domain-Global-Group-Guid
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDomainGlobalGroupGuid
+name: ms-Exch-Domain-Global-Group-Guid
+schemaIDGUID: 0d5aaba3-b593-4256-88dc-a0db2d2ffeec
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Domain-Global-Group-Sid
+# Contains the stringized security identifier (SID) of the domain
+# global group within the RUS domain.
+#
+dn: CN=ms-Exch-Domain-Global-Group-Sid,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Domain-Global-Group-Sid
+distinguishedName: CN=ms-Exch-Domain-Global-Group-Sid,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50091
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Domain-Global-Group-Sid
+adminDescription: ms-Exch-Domain-Global-Group-Sid
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDomainGlobalGroupSid
+name: ms-Exch-Domain-Global-Group-Sid
+schemaIDGUID: d059b789-3e9e-4b8f-befe-db62bb580885
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Domain-Link
+# A link to the root of the domain.
+#
+dn: CN=ms-Exch-Domain-Link,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Domain-Link
+distinguishedName: CN=ms-Exch-Domain-Link,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.76
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Domain-Link
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Domain-Link
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchDomainLink
+name: ms-Exch-Domain-Link
+schemaIDGUID: 8ac39cc4-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Domain-Local-Group-Guid
+# Contains the stringized GUID of the domain local group within the RUS domain.
+#
+dn: CN=ms-Exch-Domain-Local-Group-Guid,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Domain-Local-Group-Guid
+distinguishedName: CN=ms-Exch-Domain-Local-Group-Guid,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50088
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Domain-Local-Group-Guid
+adminDescription: ms-Exch-Domain-Local-Group-Guid
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDomainLocalGroupGuid
+name: ms-Exch-Domain-Local-Group-Guid
+schemaIDGUID: 3bf8ffc0-6492-4af4-b2bf-4f9fdb423425
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Domain-Local-Group-Sid
+# Contains the stringized SID of the domain local group within the RUS
+# domain.
+dn: CN=ms-Exch-Domain-Local-Group-Sid,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Domain-Local-Group-Sid
+distinguishedName: CN=ms-Exch-Domain-Local-Group-Sid,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50090
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Domain-Local-Group-Sid
+adminDescription: ms-Exch-Domain-Local-Group-Sid
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDomainLocalGroupSid
+name: ms-Exch-Domain-Local-Group-Sid
+schemaIDGUID: d27eb1e5-a06c-4151-b789-59eabba8edca
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Domain-Name
+# Stores the domain name that a Domain Content Configuration object
+# applies to.
+#
+dn: CN=ms-Exch-Domain-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Domain-Name
+distinguishedName: CN=ms-Exch-Domain-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.147
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 362
+mAPIID: 32886
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Domain-Name
+adminDescription: ms-Exch-Domain-Name
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: domainName
+name: ms-Exch-Domain-Name
+schemaIDGUID: a8df73c8-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DownGrade-Multipart-Signed
+# If True, the store configures IMAIL to convert a multipart/signed
+# message to a normal message and discard the signature. The default
+# is False.
+#
+dn: CN=ms-Exch-DownGrade-Multipart-Signed,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DownGrade-Multipart-Signed
+distinguishedName: CN=ms-Exch-DownGrade-Multipart-Signed,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11020
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DownGrade-Multipart-Signed
+adminDescription: ms-Exch-DownGrade-Multipart-Signed
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchDownGradeMultipartSigned
+name: ms-Exch-DownGrade-Multipart-Signed
+schemaIDGUID: 9e39d6fc-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Do-Full-Replication
+# A flag used to signal the service to do a full synchronization of
+# the directories.
+#
+dn: CN=ms-Exch-Do-Full-Replication,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Do-Full-Replication
+distinguishedName: CN=ms-Exch-Do-Full-Replication,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.38
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Do-Full-Replication
+adminDescription: ms-Exch-Do-Full-Replication
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchDoFullReplication
+name: ms-Exch-Do-Full-Replication
+schemaIDGUID: 9e1ad86a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Do-OAB-Version
+#
+dn: CN=ms-Exch-Do-OAB-Version,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Do-OAB-Version
+distinguishedName: CN=ms-Exch-Do-OAB-Version,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.575
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 35898
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Do-OAB-Version
+adminDescription: ms-Exch-Do-OAB-Version
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: doOABVersion
+name: ms-Exch-Do-OAB-Version
+schemaIDGUID: a8df73c7-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DS2MB-Options
+#
+dn: CN=ms-Exch-DS2MB-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DS2MB-Options
+distinguishedName: CN=ms-Exch-DS2MB-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.14001
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DS2MB-Options
+adminDescription: ms-Exch-DS2MB-Options
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchDS2MBOptions
+name: ms-Exch-DS2MB-Options
+schemaIDGUID: 974c99da-33fc-11d3-aa6e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Admin-Copy
+#
+dn: CN=ms-Exch-DXA-Admin-Copy,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Admin-Copy
+distinguishedName: CN=ms-Exch-DXA-Admin-Copy,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.378
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32888
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Admin-Copy
+adminDescription: ms-Exch-DXA-Admin-Copy
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: dXAAdminCopy
+name: ms-Exch-DXA-Admin-Copy
+schemaIDGUID: a8df73c9-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Admin-Forward
+#
+dn: CN=ms-Exch-DXA-Admin-Forward,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Admin-Forward
+distinguishedName: CN=ms-Exch-DXA-Admin-Forward,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.379
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32889
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Admin-Forward
+adminDescription: ms-Exch-DXA-Admin-Forward
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: dXAAdminForward
+name: ms-Exch-DXA-Admin-Forward
+schemaIDGUID: 167757be-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Admin-Update
+#
+dn: CN=ms-Exch-DXA-Admin-Update,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Admin-Update
+distinguishedName: CN=ms-Exch-DXA-Admin-Update,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.381
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32890
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Admin-Update
+adminDescription: ms-Exch-DXA-Admin-Update
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: dXAAdminUpdate
+name: ms-Exch-DXA-Admin-Update
+schemaIDGUID: a8df73ca-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Append-ReqCN
+#
+dn: CN=ms-Exch-DXA-Append-ReqCN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Append-ReqCN
+distinguishedName: CN=ms-Exch-DXA-Append-ReqCN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.174
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32891
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Append-ReqCN
+adminDescription: ms-Exch-DXA-Append-ReqCN
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: dXAAppendReqCN
+name: ms-Exch-DXA-Append-ReqCN
+schemaIDGUID: a8df73cb-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Conf-Container-List
+#
+dn: CN=ms-Exch-DXA-Conf-Container-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Conf-Container-List
+distinguishedName: CN=ms-Exch-DXA-Conf-Container-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.180
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32892
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Conf-Container-List
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-DXA-Conf-Container-List
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: dXAConfContainerList
+name: ms-Exch-DXA-Conf-Container-List
+schemaIDGUID: a8df73cc-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Conf-Req-Time
+#
+dn: CN=ms-Exch-DXA-Conf-Req-Time,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Conf-Req-Time
+distinguishedName: CN=ms-Exch-DXA-Conf-Req-Time,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.122
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+mAPIID: 32893
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Conf-Req-Time
+adminDescription: ms-Exch-DXA-Conf-Req-Time
+oMSyntax: 23
+searchFlags: 0
+lDAPDisplayName: dXAConfReqTime
+name: ms-Exch-DXA-Conf-Req-Time
+schemaIDGUID: a8df73cd-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Conf-Seq
+#
+dn: CN=ms-Exch-DXA-Conf-Seq,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Conf-Seq
+distinguishedName: CN=ms-Exch-DXA-Conf-Seq,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.184
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 32894
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Conf-Seq
+adminDescription: ms-Exch-DXA-Conf-Seq
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: dXAConfSeq
+name: ms-Exch-DXA-Conf-Seq
+schemaIDGUID: a8df73ce-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Conf-Seq-USN
+#
+dn: CN=ms-Exch-DXA-Conf-Seq-USN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Conf-Seq-USN
+distinguishedName: CN=ms-Exch-DXA-Conf-Seq-USN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.45
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32895
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Conf-Seq-USN
+adminDescription: ms-Exch-DXA-Conf-Seq-USN
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: dXAConfSeqUSN
+name: ms-Exch-DXA-Conf-Seq-USN
+schemaIDGUID: a8df73cf-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Exchange-Options
+#
+dn: CN=ms-Exch-DXA-Exchange-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Exchange-Options
+distinguishedName: CN=ms-Exch-DXA-Exchange-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.359
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+mAPIID: 32896
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Exchange-Options
+adminDescription: ms-Exch-DXA-Exchange-Options
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: dXAExchangeOptions
+name: ms-Exch-DXA-Exchange-Options
+schemaIDGUID: a8df73d0-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Export-Now
+#
+dn: CN=ms-Exch-DXA-Export-Now,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Export-Now
+distinguishedName: CN=ms-Exch-DXA-Export-Now,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.377
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32897
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Export-Now
+adminDescription: ms-Exch-DXA-Export-Now
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: dXAExportNow
+name: ms-Exch-DXA-Export-Now
+schemaIDGUID: a8df73d1-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Import-Now
+#
+dn: CN=ms-Exch-DXA-Import-Now,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Import-Now
+distinguishedName: CN=ms-Exch-DXA-Import-Now,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.376
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32902
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Import-Now
+adminDescription: ms-Exch-DXA-Import-Now
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: dXAImportNow
+name: ms-Exch-DXA-Import-Now
+schemaIDGUID: a8df73d5-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Imp-Seq
+#
+dn: CN=ms-Exch-DXA-Imp-Seq,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Imp-Seq
+distinguishedName: CN=ms-Exch-DXA-Imp-Seq,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.116
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 32899
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Imp-Seq
+adminDescription: ms-Exch-DXA-Imp-Seq
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: dXAImpSeq
+name: ms-Exch-DXA-Imp-Seq
+schemaIDGUID: a8df73d2-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Imp-Seq-Time
+#
+dn: CN=ms-Exch-DXA-Imp-Seq-Time,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Imp-Seq-Time
+distinguishedName: CN=ms-Exch-DXA-Imp-Seq-Time,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.117
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+mAPIID: 32900
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Imp-Seq-Time
+adminDescription: ms-Exch-DXA-Imp-Seq-Time
+oMSyntax: 23
+searchFlags: 0
+lDAPDisplayName: dXAImpSeqTime
+name: ms-Exch-DXA-Imp-Seq-Time
+schemaIDGUID: a8df73d3-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Imp-Seq-USN
+#
+dn: CN=ms-Exch-DXA-Imp-Seq-USN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Imp-Seq-USN
+distinguishedName: CN=ms-Exch-DXA-Imp-Seq-USN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.86
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32901
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Imp-Seq-USN
+adminDescription: ms-Exch-DXA-Imp-Seq-USN
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: dXAImpSeqUSN
+name: ms-Exch-DXA-Imp-Seq-USN
+schemaIDGUID: a8df73d4-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-In-Template-Map
+#
+dn: CN=ms-Exch-DXA-In-Template-Map,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-In-Template-Map
+distinguishedName: CN=ms-Exch-DXA-In-Template-Map,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.363
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 128
+mAPIID: 32903
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-In-Template-Map
+adminDescription: ms-Exch-DXA-In-Template-Map
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: dXAInTemplateMap
+name: ms-Exch-DXA-In-Template-Map
+schemaIDGUID: a8df73d6-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Local-Admin
+#
+dn: CN=ms-Exch-DXA-Local-Admin,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Local-Admin
+distinguishedName: CN=ms-Exch-DXA-Local-Admin,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.113
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 32904
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Local-Admin
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-DXA-Local-Admin
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: dXALocalAdmin
+name: ms-Exch-DXA-Local-Admin
+schemaIDGUID: a8df73d7-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Native-Address-Type
+#
+dn: CN=ms-Exch-DXA-Native-Address-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Native-Address-Type
+distinguishedName: CN=ms-Exch-DXA-Native-Address-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.331
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 32906
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Native-Address-Type
+adminDescription: ms-Exch-DXA-Native-Address-Type
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: dXANativeAddressType
+name: ms-Exch-DXA-Native-Address-Type
+schemaIDGUID: a8df73d9-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Out-Template-Map
+#
+dn: CN=ms-Exch-DXA-Out-Template-Map,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Out-Template-Map
+distinguishedName: CN=ms-Exch-DXA-Out-Template-Map,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.364
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 128
+mAPIID: 32907
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Out-Template-Map
+adminDescription: ms-Exch-DXA-Out-Template-Map
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: dXAOutTemplateMap
+name: ms-Exch-DXA-Out-Template-Map
+schemaIDGUID: a8df73da-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Password
+#
+dn: CN=ms-Exch-DXA-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Password
+distinguishedName: CN=ms-Exch-DXA-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.305
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 12
+mAPIID: 32908
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Password
+adminDescription: ms-Exch-DXA-Password
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: dXAPassword
+name: ms-Exch-DXA-Password
+schemaIDGUID: a8df73db-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Prev-Exchange-Options
+#
+dn: CN=ms-Exch-DXA-Prev-Exchange-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Prev-Exchange-Options
+distinguishedName: CN=ms-Exch-DXA-Prev-Exchange-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.216
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+mAPIID: 32909
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Prev-Exchange-Options
+adminDescription: ms-Exch-DXA-Prev-Exchange-Options
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: dXAPrevExchangeOptions
+name: ms-Exch-DXA-Prev-Exchange-Options
+schemaIDGUID: a8df73dc-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Prev-Export-Native-Only
+#
+dn: CN=ms-Exch-DXA-Prev-Export-Native-Only,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Prev-Export-Native-Only
+distinguishedName: CN=ms-Exch-DXA-Prev-Export-Native-Only,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.203
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32910
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Prev-Export-Native-Only
+adminDescription: ms-Exch-DXA-Prev-Export-Native-Only
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: dXAPrevExportNativeOnly
+name: ms-Exch-DXA-Prev-Export-Native-Only
+schemaIDGUID: a8df73dd-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Prev-In-Exchange-Sensitivity
+#
+dn: CN=ms-Exch-DXA-Prev-In-Exchange-Sensitivity,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Prev-In-Exchange-Sensitivity
+distinguishedName: CN=ms-Exch-DXA-Prev-In-Exchange-Sensitivity,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.90
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32911
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Prev-In-Exchange-Sensitivity
+adminDescription: ms-Exch-DXA-Prev-In-Exchange-Sensitivity
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: dXAPrevInExchangeSensitivity
+name: ms-Exch-DXA-Prev-In-Exchange-Sensitivity
+schemaIDGUID: a8df73de-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Prev-Remote-Entries
+#
+dn: CN=ms-Exch-DXA-Prev-Remote-Entries,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Prev-Remote-Entries
+distinguishedName: CN=ms-Exch-DXA-Prev-Remote-Entries,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.265
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 32912
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Prev-Remote-Entries
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-DXA-Prev-Remote-Entries
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: dXAPrevRemoteEntries
+name: ms-Exch-DXA-Prev-Remote-Entries
+schemaIDGUID: a8df73df-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Prev-Replication-Sensitivity
+#
+dn: CN=ms-Exch-DXA-Prev-Replication-Sensitivity,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Prev-Replication-Sensitivity
+distinguishedName: CN=ms-Exch-DXA-Prev-Replication-Sensitivity,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.215
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32913
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Prev-Replication-Sensitivity
+adminDescription: ms-Exch-DXA-Prev-Replication-Sensitivity
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: dXAPrevReplicationSensitivity
+name: ms-Exch-DXA-Prev-Replication-Sensitivity
+schemaIDGUID: a8df73e0-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Prev-Template-Options
+#
+dn: CN=ms-Exch-DXA-Prev-Template-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Prev-Template-Options
+distinguishedName: CN=ms-Exch-DXA-Prev-Template-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.395
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+mAPIID: 32914
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Prev-Template-Options
+adminDescription: ms-Exch-DXA-Prev-Template-Options
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: dXAPrevTemplateOptions
+name: ms-Exch-DXA-Prev-Template-Options
+schemaIDGUID: a8df73e1-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Prev-Types
+#
+dn: CN=ms-Exch-DXA-Prev-Types,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Prev-Types
+distinguishedName: CN=ms-Exch-DXA-Prev-Types,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.217
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32915
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Prev-Types
+adminDescription: ms-Exch-DXA-Prev-Types
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: dXAPrevTypes
+name: ms-Exch-DXA-Prev-Types
+schemaIDGUID: 167757d8-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Recipient-CP
+#
+dn: CN=ms-Exch-DXA-Recipient-CP,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Recipient-CP
+distinguishedName: CN=ms-Exch-DXA-Recipient-CP,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.384
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 24
+mAPIID: 32916
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Recipient-CP
+adminDescription: ms-Exch-DXA-Recipient-CP
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: dXARecipientCP
+name: ms-Exch-DXA-Recipient-CP
+schemaIDGUID: a8df73e2-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Remote-Client
+#
+dn: CN=ms-Exch-DXA-Remote-Client,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Remote-Client
+distinguishedName: CN=ms-Exch-DXA-Remote-Client,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.112
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 32917
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Remote-Client
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-DXA-Remote-Client
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: dXARemoteClient
+name: ms-Exch-DXA-Remote-Client
+schemaIDGUID: a8df73e3-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-ReqName
+#
+dn: CN=ms-Exch-DXA-ReqName,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-ReqName
+distinguishedName: CN=ms-Exch-DXA-ReqName,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.446
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 32921
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-ReqName
+adminDescription: ms-Exch-DXA-ReqName
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: dXAReqName
+name: ms-Exch-DXA-ReqName
+schemaIDGUID: a8df73e7-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Req-Seq
+#
+dn: CN=ms-Exch-DXA-Req-Seq,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Req-Seq
+distinguishedName: CN=ms-Exch-DXA-Req-Seq,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.101
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 32918
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Req-Seq
+adminDescription: ms-Exch-DXA-Req-Seq
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: dXAReqSeq
+name: ms-Exch-DXA-Req-Seq
+schemaIDGUID: a8df73e4-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Req-Seq-Time
+#
+dn: CN=ms-Exch-DXA-Req-Seq-Time,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Req-Seq-Time
+distinguishedName: CN=ms-Exch-DXA-Req-Seq-Time,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.114
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+mAPIID: 32919
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Req-Seq-Time
+adminDescription: ms-Exch-DXA-Req-Seq-Time
+oMSyntax: 23
+searchFlags: 0
+lDAPDisplayName: dXAReqSeqTime
+name: ms-Exch-DXA-Req-Seq-Time
+schemaIDGUID: a8df73e5-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Req-Seq-USN
+#
+dn: CN=ms-Exch-DXA-Req-Seq-USN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Req-Seq-USN
+distinguishedName: CN=ms-Exch-DXA-Req-Seq-USN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.182
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32920
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Req-Seq-USN
+adminDescription: ms-Exch-DXA-Req-Seq-USN
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: dXAReqSeqUSN
+name: ms-Exch-DXA-Req-Seq-USN
+schemaIDGUID: a8df73e6-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Svr-Seq
+#
+dn: CN=ms-Exch-DXA-Svr-Seq,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Svr-Seq
+distinguishedName: CN=ms-Exch-DXA-Svr-Seq,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.360
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 32922
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Svr-Seq
+adminDescription: ms-Exch-DXA-Svr-Seq
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: dXASvrSeq
+name: ms-Exch-DXA-Svr-Seq
+schemaIDGUID: a8df73e8-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-Svr-Seq-Time
+#
+dn: CN=ms-Exch-DXA-Svr-Seq-Time,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Svr-Seq-Time
+distinguishedName: CN=ms-Exch-DXA-Svr-Seq-Time,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.361
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+mAPIID: 32923
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Svr-Seq-Time
+adminDescription: ms-Exch-DXA-Svr-Seq-Time
+oMSyntax: 23
+searchFlags: 0
+lDAPDisplayName: dXASvrSeqTime
+name: ms-Exch-DXA-Svr-Seq-Time
+schemaIDGUID: a8df73e9-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Svr-Seq-USN
+#
+dn: CN=ms-Exch-DXA-Svr-Seq-USN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Svr-Seq-USN
+distinguishedName: CN=ms-Exch-DXA-Svr-Seq-USN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.124
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32924
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Svr-Seq-USN
+adminDescription: ms-Exch-DXA-Svr-Seq-USN
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: dXASvrSeqUSN
+name: ms-Exch-DXA-Svr-Seq-USN
+schemaIDGUID: a8df73ea-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Template-Options
+#
+dn: CN=ms-Exch-DXA-Template-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Template-Options
+distinguishedName: CN=ms-Exch-DXA-Template-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.358
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+mAPIID: 32926
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Template-Options
+adminDescription: ms-Exch-DXA-Template-Options
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: dXATemplateOptions
+name: ms-Exch-DXA-Template-Options
+schemaIDGUID: a8df73eb-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Template-TimeStamp
+#
+dn: CN=ms-Exch-DXA-Template-TimeStamp,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Template-TimeStamp
+distinguishedName: CN=ms-Exch-DXA-Template-TimeStamp,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.365
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+mAPIID: 32927
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Template-TimeStamp
+adminDescription: ms-Exch-DXA-Template-TimeStamp
+oMSyntax: 23
+searchFlags: 0
+lDAPDisplayName: dXATemplateTimeStamp
+name: ms-Exch-DXA-Template-TimeStamp
+schemaIDGUID: a8df73ec-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-DXA-Types
+#
+dn: CN=ms-Exch-DXA-Types,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-Types
+distinguishedName: CN=ms-Exch-DXA-Types,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.119
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32928
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-Types
+adminDescription: ms-Exch-DXA-Types
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: dXATypes
+name: ms-Exch-DXA-Types
+schemaIDGUID: a8df73ed-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-DXA-UnConf-Container-List
+#
+dn: CN=ms-Exch-DXA-UnConf-Container-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-DXA-UnConf-Container-List
+distinguishedName: CN=ms-Exch-DXA-UnConf-Container-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.181
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32929
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-DXA-UnConf-Container-List
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-DXA-UnConf-Container-List
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: dXAUnConfContainerList
+name: ms-Exch-DXA-UnConf-Container-List
+schemaIDGUID: a8df73ee-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Dynamic-DL-BaseDN
+#
+dn: CN=ms-Exch-Dynamic-DL-BaseDN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Dynamic-DL-BaseDN
+distinguishedName: CN=ms-Exch-Dynamic-DL-BaseDN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12543
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Dynamic-DL-BaseDN
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Dynamic-DL-BaseDN
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchDynamicDLBaseDN
+name: ms-Exch-Dynamic-DL-BaseDN
+schemaIDGUID: 763d0ef9-bd92-41f9-ab34-7e329db76ee3
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Dynamic-DL-Filter
+#
+dn: CN=ms-Exch-Dynamic-DL-Filter,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Dynamic-DL-Filter
+distinguishedName: CN=ms-Exch-Dynamic-DL-Filter,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12544
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Dynamic-DL-Filter
+adminDescription: ms-Exch-Dynamic-DL-Filter
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchDynamicDLFilter
+name: ms-Exch-Dynamic-DL-Filter
+schemaIDGUID: e1b6d32c-6bac-48da-a313-2b58ae1c45ce
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-EDB-File
+# The database file location for this store.
+#
+dn: CN=ms-Exch-EDB-File,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-EDB-File
+distinguishedName: CN=ms-Exch-EDB-File,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11001
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-EDB-File
+adminDescription: ms-Exch-EDB-File
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchEDBFile
+name: ms-Exch-EDB-File
+schemaIDGUID: 9e58d58e-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-EDB-Offline
+# If TRUE, the MDB is offline. The default is FALSE.
+#
+dn: CN=ms-Exch-EDB-Offline,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-EDB-Offline
+distinguishedName: CN=ms-Exch-EDB-Offline,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11007
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-EDB-Offline
+adminDescription: ms-Exch-EDB-Offline
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchEDBOffline
+name: ms-Exch-EDB-Offline
+schemaIDGUID: 9e7a367a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Enabled-Authorization-Packages
+# A list of authorization packages enabled for this protocol.
+#
+dn: CN=ms-Exch-Enabled-Authorization-Packages,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Enabled-Authorization-Packages
+distinguishedName: CN=ms-Exch-Enabled-Authorization-Packages,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.479
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 128
+mAPIID: 33156
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Enabled-Authorization-Packages
+adminDescription: ms-Exch-Enabled-Authorization-Packages
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: enabledAuthorizationPackages
+name: ms-Exch-Enabled-Authorization-Packages
+schemaIDGUID: a8df73f3-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Enabled-Protocols
+#
+dn: CN=ms-Exch-Enabled-Protocols,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Enabled-Protocols
+distinguishedName: CN=ms-Exch-Enabled-Protocols,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.474
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33151
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Enabled-Protocols
+adminDescription: ms-Exch-Enabled-Protocols
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: enabledProtocols
+name: ms-Exch-Enabled-Protocols
+schemaIDGUID: f0f8ff8c-1191-11d0-a060-00aa006c33ed
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Enabled-Protocol-Cfg
+# Determines whether this protocol is enabled or not.
+dn: CN=ms-Exch-Enabled-Protocol-Cfg,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Enabled-Protocol-Cfg
+distinguishedName: CN=ms-Exch-Enabled-Protocol-Cfg,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.515
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 33192
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Enabled-Protocol-Cfg
+adminDescription: ms-Exch-Enabled-Protocol-Cfg
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: enabledProtocolCfg
+name: ms-Exch-Enabled-Protocol-Cfg
+schemaIDGUID: a8df73f4-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Enable-Compatibility
+#
+dn: CN=ms-Exch-Enable-Compatibility,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Enable-Compatibility
+distinguishedName: CN=ms-Exch-Enable-Compatibility,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.567
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 35890
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Enable-Compatibility
+adminDescription: ms-Exch-Enable-Compatibility
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: enableCompatibility
+name: ms-Exch-Enable-Compatibility
+schemaIDGUID: a8df73f1-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Enable-Internal-Evaluator
+#
+dn: CN=ms-Exch-Enable-Internal-Evaluator,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Enable-Internal-Evaluator
+distinguishedName: CN=ms-Exch-Enable-Internal-Evaluator,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.99
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Enable-Internal-Evaluator
+adminDescription: ms-Exch-Enable-Internal-Evaluator
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchEnableInternalEvaluator
+name: ms-Exch-Enable-Internal-Evaluator
+schemaIDGUID: 9a56980f-283c-4f86-8395-23011350600c
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Encapsulation-Method
+# This is present only on X.400 connectors.
+#
+dn: CN=ms-Exch-Encapsulation-Method,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Encapsulation-Method
+distinguishedName: CN=ms-Exch-Encapsulation-Method,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.448
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32930
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Encapsulation-Method
+adminDescription: ms-Exch-Encapsulation-Method
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: encapsulationMethod
+name: ms-Exch-Encapsulation-Method
+schemaIDGUID: a8df73f5-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Encode-SMTP-Relay
+# Determines whether or not messages submitted to this domain will be
+# encoded using the content configuration settings.
+#
+dn: CN=ms-Exch-Encode-SMTP-Relay,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Encode-SMTP-Relay
+distinguishedName: CN=ms-Exch-Encode-SMTP-Relay,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5053
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Encode-SMTP-Relay
+adminDescription: ms-Exch-Encode-SMTP-Relay
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchEncodeSMTPRelay
+name: ms-Exch-Encode-SMTP-Relay
+schemaIDGUID: 3a633f17-5194-11d3-aa77-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Encrypt
+#
+dn: CN=ms-Exch-Encrypt,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Encrypt
+distinguishedName: CN=ms-Exch-Encrypt,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.236
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32931
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Encrypt
+adminDescription: ms-Exch-Encrypt
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: encrypt
+name: ms-Exch-Encrypt
+schemaIDGUID: a8df73f6-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Encrypted-Anonymous-Password
+#
+dn: CN=ms-Exch-Encrypted-Anonymous-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Encrypted-Anonymous-Password
+distinguishedName: CN=ms-Exch-Encrypted-Anonymous-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15009
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Encrypted-Anonymous-Password
+adminDescription: ms-Exch-Encrypted-Anonymous-Password
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchEncryptedAnonymousPassword
+name: ms-Exch-Encrypted-Anonymous-Password
+schemaIDGUID: 5dc055fc-5c3f-4a6f-a34a-4dbcb68e2ad0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Encrypted-Password
+#
+dn: CN=ms-Exch-Encrypted-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Encrypted-Password
+distinguishedName: CN=ms-Exch-Encrypted-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50062
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Encrypted-Password
+adminDescription: ms-Exch-Encrypted-Password
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchEncryptedPassword
+name: ms-Exch-Encrypted-Password
+schemaIDGUID: 08c63250-0df6-405d-8907-0312dd1aa145
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Encrypted-Password-2
+#
+dn: CN=ms-Exch-Encrypted-Password-2,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Encrypted-Password-2
+distinguishedName: CN=ms-Exch-Encrypted-Password-2,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50065
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Encrypted-Password-2
+adminDescription: ms-Exch-Encrypted-Password-2
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchEncryptedPassword2
+name: ms-Exch-Encrypted-Password-2
+schemaIDGUID: dcbc61e9-9279-44d1-b494-25562659db75
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Encrypt-Alg-List-NA
+#
+dn: CN=ms-Exch-Encrypt-Alg-List-NA,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Encrypt-Alg-List-NA
+distinguishedName: CN=ms-Exch-Encrypt-Alg-List-NA,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.130
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 32832
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Encrypt-Alg-List-NA
+adminDescription: ms-Exch-Encrypt-Alg-List-NA
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: encryptAlgListNA
+name: ms-Exch-Encrypt-Alg-List-NA
+schemaIDGUID: a8df73f7-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Encrypt-Alg-List-Other
+#
+dn: CN=ms-Exch-Encrypt-Alg-List-Other,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Encrypt-Alg-List-Other
+distinguishedName: CN=ms-Exch-Encrypt-Alg-List-Other,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.399
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 32833
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Encrypt-Alg-List-Other
+adminDescription: ms-Exch-Encrypt-Alg-List-Other
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: encryptAlgListOther
+name: ms-Exch-Encrypt-Alg-List-Other
+schemaIDGUID: a8df73f8-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Encrypt-Alg-Selected-NA
+#
+dn: CN=ms-Exch-Encrypt-Alg-Selected-NA,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Encrypt-Alg-Selected-NA
+distinguishedName: CN=ms-Exch-Encrypt-Alg-Selected-NA,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.401
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 32835
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Encrypt-Alg-Selected-NA
+adminDescription: ms-Exch-Encrypt-Alg-Selected-NA
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: encryptAlgSelectedNA
+name: ms-Exch-Encrypt-Alg-Selected-NA
+schemaIDGUID: a8df73f9-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Encrypt-Alg-Selected-Other
+#
+dn: CN=ms-Exch-Encrypt-Alg-Selected-Other,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Encrypt-Alg-Selected-Other
+distinguishedName: CN=ms-Exch-Encrypt-Alg-Selected-Other,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.397
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 32829
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Encrypt-Alg-Selected-Other
+adminDescription: ms-Exch-Encrypt-Alg-Selected-Other
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: encryptAlgSelectedOther
+name: ms-Exch-Encrypt-Alg-Selected-Other
+schemaIDGUID: a8df73fa-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Assert-Action
+# The action on assert.
+dn: CN=ms-Exch-ESE-Param-Assert-Action,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Assert-Action
+distinguishedName: CN=ms-Exch-ESE-Param-Assert-Action,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11074
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Assert-Action
+adminDescription: ms-Exch-ESE-Param-Assert-Action
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamAssertAction
+name: ms-Exch-ESE-Param-Assert-Action
+schemaIDGUID: 2d09783d-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Base-Name
+# The base name for all Database Management System (DBMS) object names.
+#
+dn: CN=ms-Exch-ESE-Param-Base-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Base-Name
+distinguishedName: CN=ms-Exch-ESE-Param-Base-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11076
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Base-Name
+adminDescription: ms-Exch-ESE-Param-Base-Name
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchESEParamBaseName
+name: ms-Exch-ESE-Param-Base-Name
+schemaIDGUID: 2d097845-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Cached-Closed-Tables
+#
+dn: CN=ms-Exch-ESE-Param-Cached-Closed-Tables,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Cached-Closed-Tables
+distinguishedName: CN=ms-Exch-ESE-Param-Cached-Closed-Tables,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11096
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Cached-Closed-Tables
+adminDescription: ms-Exch-ESE-Param-Cached-Closed-Tables
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamCachedClosedTables
+name: ms-Exch-ESE-Param-Cached-Closed-Tables
+schemaIDGUID: d19c67f8-a0eb-432a-bedd-af10cd7da25c
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Cache-Size
+#
+dn: CN=ms-Exch-ESE-Param-Cache-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Cache-Size
+distinguishedName: CN=ms-Exch-ESE-Param-Cache-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11002
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Cache-Size
+adminDescription: ms-Exch-ESE-Param-Cache-Size
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamCacheSize
+name: ms-Exch-ESE-Param-Cache-Size
+schemaIDGUID: 9eb8339e-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Cache-Size-Max
+#
+dn: CN=ms-Exch-ESE-Param-Cache-Size-Max,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Cache-Size-Max
+distinguishedName: CN=ms-Exch-ESE-Param-Cache-Size-Max,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11003
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Cache-Size-Max
+adminDescription: ms-Exch-ESE-Param-Cache-Size-Max
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamCacheSizeMax
+name: ms-Exch-ESE-Param-Cache-Size-Max
+schemaIDGUID: 9ed73230-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Cache-Size-Min
+# The minimum cache size in pages.
+#
+dn: CN=ms-Exch-ESE-Param-Cache-Size-Min,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Cache-Size-Min
+distinguishedName: CN=ms-Exch-ESE-Param-Cache-Size-Min,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11075
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Cache-Size-Min
+adminDescription: ms-Exch-ESE-Param-Cache-Size-Min
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamCacheSizeMin
+name: ms-Exch-ESE-Param-Cache-Size-Min
+schemaIDGUID: 2d097841-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Checkpoint-Depth-Max
+# The maximum checkpoint depth in bytes.
+#
+dn: CN=ms-Exch-ESE-Param-Checkpoint-Depth-Max,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Checkpoint-Depth-Max
+distinguishedName: CN=ms-Exch-ESE-Param-Checkpoint-Depth-Max,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11081
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Checkpoint-Depth-Max
+adminDescription: ms-Exch-ESE-Param-Checkpoint-Depth-Max
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamCheckpointDepthMax
+name: ms-Exch-ESE-Param-Checkpoint-Depth-Max
+schemaIDGUID: 2d09785a-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Circular-Log
+# A Boolean flag for circular logging.
+#
+dn: CN=ms-Exch-ESE-Param-Circular-Log,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Circular-Log
+distinguishedName: CN=ms-Exch-ESE-Param-Circular-Log,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11005
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Circular-Log
+adminDescription: ms-Exch-ESE-Param-Circular-Log
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamCircularLog
+name: ms-Exch-ESE-Param-Circular-Log
+schemaIDGUID: 9ef8931c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Commit-Default
+# The default grbit for JetCommitTransaction.
+#
+dn: CN=ms-Exch-ESE-Param-Commit-Default,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Commit-Default
+distinguishedName: CN=ms-Exch-ESE-Param-Commit-Default,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11077
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Commit-Default
+adminDescription: ms-Exch-ESE-Param-Commit-Default
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamCommitDefault
+name: ms-Exch-ESE-Param-Commit-Default
+schemaIDGUID: 2d097849-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Db-Extension-Size
+# The database extension size in pages.
+#
+dn: CN=ms-Exch-ESE-Param-Db-Extension-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Db-Extension-Size
+distinguishedName: CN=ms-Exch-ESE-Param-Db-Extension-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11078
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Db-Extension-Size
+adminDescription: ms-Exch-ESE-Param-Db-Extension-Size
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamDbExtensionSize
+name: ms-Exch-ESE-Param-Db-Extension-Size
+schemaIDGUID: 2d09784d-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Enable-Index-Checking
+# Enables checking the operating system version for indexes. The
+# default is False.
+#
+dn: CN=ms-Exch-ESE-Param-Enable-Index-Checking,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Enable-Index-Checking
+distinguishedName: CN=ms-Exch-ESE-Param-Enable-Index-Checking,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11073
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Enable-Index-Checking
+adminDescription: ms-Exch-ESE-Param-Enable-Index-Checking
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchESEParamEnableIndexChecking
+name: ms-Exch-ESE-Param-Enable-Index-Checking
+schemaIDGUID: 2d097838-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Enable-Online-Defrag
+# Enables online defragmentation. The default is True.
+#
+dn: CN=ms-Exch-ESE-Param-Enable-Online-Defrag,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Enable-Online-Defrag
+distinguishedName: CN=ms-Exch-ESE-Param-Enable-Online-Defrag,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11072
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Enable-Online-Defrag
+adminDescription: ms-Exch-ESE-Param-Enable-Online-Defrag
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchESEParamEnableOnlineDefrag
+name: ms-Exch-ESE-Param-Enable-Online-Defrag
+schemaIDGUID: 2d097833-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Enable-Sorted-Retrieve-Columns
+# Internally sorts (in a dynamically allocated parallel array)
+# JET_RETRIEVECOLUMN structures passed to JetRetrieveColumns(). The
+# default is False.
+#
+dn: CN=ms-Exch-ESE-Param-Enable-Sorted-Retrieve-Columns,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Enable-Sorted-Retrieve-Columns
+distinguishedName: CN=ms-Exch-ESE-Param-Enable-Sorted-Retrieve-Columns,CN=Sche
+attributeID: 1.2.840.113556.1.4.7000.102.11069
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Enable-Sorted-Retrieve-Columns
+adminDescription: ms-Exch-ESE-Param-Enable-Sorted-Retrieve-Columns
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchESEParamEnableSortedRetrieveColumns
+name: ms-Exch-ESE-Param-Enable-Sorted-Retrieve-Columns
+schemaIDGUID: 2d097828-2b54-11d3-aa6b-00c04f8eedd8
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Event-Source
+# A language-independent process descriptor string.
+#
+dn: CN=ms-Exch-ESE-Param-Event-Source,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Event-Source
+distinguishedName: CN=ms-Exch-ESE-Param-Event-Source,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11008
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Event-Source
+adminDescription: ms-Exch-ESE-Param-Event-Source
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchESEParamEventSource
+name: ms-Exch-ESE-Param-Event-Source
+schemaIDGUID: 9f19f408-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Global-Min-Ver-Pages
+# The global minimum version page size in 16-kilobyte (KB) units.
+#
+dn: CN=ms-Exch-ESE-Param-Global-Min-Ver-Pages,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Global-Min-Ver-Pages
+distinguishedName: CN=ms-Exch-ESE-Param-Global-Min-Ver-Pages,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11082
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Global-Min-Ver-Pages
+adminDescription: ms-Exch-ESE-Param-Global-Min-Ver-Pages
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamGlobalMinVerPages
+name: ms-Exch-ESE-Param-Global-Min-Ver-Pages
+schemaIDGUID: 02e831da-2f29-11d3-aa6c-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Log-Buffers
+# Log buffers in 512 bytes.
+#
+dn: CN=ms-Exch-ESE-Param-Log-Buffers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Log-Buffers
+distinguishedName: CN=ms-Exch-ESE-Param-Log-Buffers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11009
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Log-Buffers
+adminDescription: ms-Exch-ESE-Param-Log-Buffers
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamLogBuffers
+name: ms-Exch-ESE-Param-Log-Buffers
+schemaIDGUID: 9f38f29a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Log-Checkpoint-Period
+#
+dn: CN=ms-Exch-ESE-Param-Log-Checkpoint-Period,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Log-Checkpoint-Period
+distinguishedName: CN=ms-Exch-ESE-Param-Log-Checkpoint-Period,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11010
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Log-Checkpoint-Period
+adminDescription: ms-Exch-ESE-Param-Log-Checkpoint-Period
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamLogCheckpointPeriod
+name: ms-Exch-ESE-Param-Log-Checkpoint-Period
+schemaIDGUID: 9f5a5386-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Log-File-Path
+# The path to the log file directory.
+#
+dn: CN=ms-Exch-ESE-Param-Log-File-Path,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Log-File-Path
+distinguishedName: CN=ms-Exch-ESE-Param-Log-File-Path,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11011
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Log-File-Path
+adminDescription: ms-Exch-ESE-Param-Log-File-Path
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchESEParamLogFilePath
+name: ms-Exch-ESE-Param-Log-File-Path
+schemaIDGUID: 9f795218-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Log-File-Size
+# The log file size in KB.
+dn: CN=ms-Exch-ESE-Param-Log-File-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Log-File-Size
+distinguishedName: CN=ms-Exch-ESE-Param-Log-File-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11012
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Log-File-Size
+adminDescription: ms-Exch-ESE-Param-Log-File-Size
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamLogFileSize
+name: ms-Exch-ESE-Param-Log-File-Size
+schemaIDGUID: 9f9ab304-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Log-Waiting-User-Max
+# The maximum sessions waiting on log flush.
+#
+dn: CN=ms-Exch-ESE-Param-Log-Waiting-User-Max,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Log-Waiting-User-Max
+distinguishedName: CN=ms-Exch-ESE-Param-Log-Waiting-User-Max,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11013
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Log-Waiting-User-Max
+adminDescription: ms-Exch-ESE-Param-Log-Waiting-User-Max
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamLogWaitingUserMax
+name: ms-Exch-ESE-Param-Log-Waiting-User-Max
+schemaIDGUID: 9fbe764a-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Max-Cursors
+# The maximum number of open cursors.
+#
+dn: CN=ms-Exch-ESE-Param-Max-Cursors,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Max-Cursors
+distinguishedName: CN=ms-Exch-ESE-Param-Max-Cursors,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11071
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Max-Cursors
+adminDescription: ms-Exch-ESE-Param-Max-Cursors
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamMaxCursors
+name: ms-Exch-ESE-Param-Max-Cursors
+schemaIDGUID: 2d097830-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Max-Open-Tables
+# The maximum number of open directories.
+#
+dn: CN=ms-Exch-ESE-Param-Max-Open-Tables,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Max-Open-Tables
+distinguishedName: CN=ms-Exch-ESE-Param-Max-Open-Tables,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11014
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Max-Open-Tables
+adminDescription: ms-Exch-ESE-Param-Max-Open-Tables
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamMaxOpenTables
+name: ms-Exch-ESE-Param-Max-Open-Tables
+schemaIDGUID: 9fdfd736-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Max-Sessions
+# The maximum number of sessions.
+#
+dn: CN=ms-Exch-ESE-Param-Max-Sessions,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Max-Sessions
+distinguishedName: CN=ms-Exch-ESE-Param-Max-Sessions,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11015
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Max-Sessions
+adminDescription: ms-Exch-ESE-Param-Max-Sessions
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamMaxSessions
+name: ms-Exch-ESE-Param-Max-Sessions
+schemaIDGUID: 9ffed5c8-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Max-Temporary-Tables
+# The maximum concurrent open temporary table/index creation.
+#
+dn: CN=ms-Exch-ESE-Param-Max-Temporary-Tables,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Max-Temporary-Tables
+distinguishedName: CN=ms-Exch-ESE-Param-Max-Temporary-Tables,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11070
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Max-Temporary-Tables
+adminDescription: ms-Exch-ESE-Param-Max-Temporary-Tables
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamMaxTemporaryTables
+name: ms-Exch-ESE-Param-Max-Temporary-Tables
+schemaIDGUID: 2d09782c-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Max-Ver-Pages
+# The maximum version store size in 16-KB units.
+#
+dn: CN=ms-Exch-ESE-Param-Max-Ver-Pages,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Max-Ver-Pages
+distinguishedName: CN=ms-Exch-ESE-Param-Max-Ver-Pages,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11017
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Max-Ver-Pages
+adminDescription: ms-Exch-ESE-Param-Max-Ver-Pages
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamMaxVerPages
+name: ms-Exch-ESE-Param-Max-Ver-Pages
+schemaIDGUID: a02036b4-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Page-Fragment
+# The maximum disk extent considered fragment, in pages.
+#
+dn: CN=ms-Exch-ESE-Param-Page-Fragment,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Page-Fragment
+distinguishedName: CN=ms-Exch-ESE-Param-Page-Fragment,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11080
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Page-Fragment
+adminDescription: ms-Exch-ESE-Param-Page-Fragment
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamPageFragment
+name: ms-Exch-ESE-Param-Page-Fragment
+schemaIDGUID: 2d097855-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Page-Temp-DB-Min
+# The minimum size of a temporary database, in pages.
+#
+dn: CN=ms-Exch-ESE-Param-Page-Temp-DB-Min,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Page-Temp-DB-Min
+distinguishedName: CN=ms-Exch-ESE-Param-Page-Temp-DB-Min,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11079
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Page-Temp-DB-Min
+adminDescription: ms-Exch-ESE-Param-Page-Temp-DB-Min
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamPageTempDBMin
+name: ms-Exch-ESE-Param-Page-Temp-DB-Min
+schemaIDGUID: 2d097851-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Preferred-Max-Open-Tables
+# The preferred maximum number of open directories.
+dn: CN=ms-Exch-ESE-Param-Preferred-Max-Open-Tables,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Preferred-Max-Open-Tables
+distinguishedName: CN=ms-Exch-ESE-Param-Preferred-Max-Open-Tables,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11018
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Preferred-Max-Open-Tables
+adminDescription: ms-Exch-ESE-Param-Preferred-Max-Open-Tables
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamPreferredMaxOpenTables
+name: ms-Exch-ESE-Param-Preferred-Max-Open-Tables
+schemaIDGUID: a04197a0-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Preferred-Ver-Pages
+# The preferred version store size in 16-KB units.
+#
+dn: CN=ms-Exch-ESE-Param-Preferred-Ver-Pages,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Preferred-Ver-Pages
+distinguishedName: CN=ms-Exch-ESE-Param-Preferred-Ver-Pages,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11019
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Preferred-Ver-Pages
+adminDescription: ms-Exch-ESE-Param-Preferred-Ver-Pages
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamPreferredVerPages
+name: ms-Exch-ESE-Param-Preferred-Ver-Pages
+schemaIDGUID: a062f88c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Start-Flush-Threshold
+#
+dn: CN=ms-Exch-ESE-Param-Start-Flush-Threshold,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Start-Flush-Threshold
+distinguishedName: CN=ms-Exch-ESE-Param-Start-Flush-Threshold,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11056
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Start-Flush-Threshold
+adminDescription: ms-Exch-ESE-Param-Start-Flush-Threshold
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamStartFlushThreshold
+name: ms-Exch-ESE-Param-Start-Flush-Threshold
+schemaIDGUID: 92abc93e-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Stop-Flush-Threshold
+#
+dn: CN=ms-Exch-ESE-Param-Stop-Flush-Threshold,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Stop-Flush-Threshold
+distinguishedName: CN=ms-Exch-ESE-Param-Stop-Flush-Threshold,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11057
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Stop-Flush-Threshold
+adminDescription: ms-Exch-ESE-Param-Stop-Flush-Threshold
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamStopFlushThreshold
+name: ms-Exch-ESE-Param-Stop-Flush-Threshold
+schemaIDGUID: 92c6031c-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-System-Path
+# The path to check point file.
+dn: CN=ms-Exch-ESE-Param-System-Path,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-System-Path
+distinguishedName: CN=ms-Exch-ESE-Param-System-Path,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11022
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-System-Path
+adminDescription: ms-Exch-ESE-Param-System-Path
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchESEParamSystemPath
+name: ms-Exch-ESE-Param-System-Path
+schemaIDGUID: a086bbd2-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Temp-Path
+# The path to the temporary database.
+#
+dn: CN=ms-Exch-ESE-Param-Temp-Path,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Temp-Path
+distinguishedName: CN=ms-Exch-ESE-Param-Temp-Path,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11023
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Temp-Path
+adminDescription: ms-Exch-ESE-Param-Temp-Path
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchESEParamTempPath
+name: ms-Exch-ESE-Param-Temp-Path
+schemaIDGUID: a0a5ba64-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-ESE-Param-Wait-Log-Flush
+# The wait time in milliseconds.
+#
+dn: CN=ms-Exch-ESE-Param-Wait-Log-Flush,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Wait-Log-Flush
+distinguishedName: CN=ms-Exch-ESE-Param-Wait-Log-Flush,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11016
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Wait-Log-Flush
+adminDescription: ms-Exch-ESE-Param-Wait-Log-Flush
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamWaitLogFlush
+name: ms-Exch-ESE-Param-Wait-Log-Flush
+schemaIDGUID: a0c71b50-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-ESE-Param-Zero-Database-During-Backup
+# Overwrites deleted records/long values during backup.
+#
+dn: CN=ms-Exch-ESE-Param-Zero-Database-During-Backup,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-ESE-Param-Zero-Database-During-Backup
+distinguishedName: CN=ms-Exch-ESE-Param-Zero-Database-During-Backup,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11026
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-ESE-Param-Zero-Database-During-Backup
+adminDescription: ms-Exch-ESE-Param-Zero-Database-During-Backup
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchESEParamZeroDatabaseDuringBackup
+name: ms-Exch-ESE-Param-Zero-Database-During-Backup
+schemaIDGUID: a0e619e2-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Exchange-Server-Link
+# A link to an Exchange server that this object corresponds to.
+#
+dn: CN=ms-Exch-Exchange-Server-Link,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Exchange-Server-Link
+distinguishedName: CN=ms-Exch-Exchange-Server-Link,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.71
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1019
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Exchange-Server-Link
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Exchange-Server-Link
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchExchangeServerLink
+name: ms-Exch-Exchange-Server-Link
+schemaIDGUID: a1051874-b093-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Exchange-Site
+# Contains the DN to the site that this connection agreement is for.
+#
+dn: CN=ms-Exch-Exchange-Site,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Exchange-Site
+distinguishedName: CN=ms-Exch-Exchange-Site,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.85
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Exchange-Site
+adminDescription: ms-Exch-Exchange-Site
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchExchangeSite
+name: ms-Exch-Exchange-Site
+schemaIDGUID: 24d808f5-2439-11d3-aa66-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Expand-DLs-Locally
+#
+dn: CN=ms-Exch-Expand-DLs-Locally,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Expand-DLs-Locally
+distinguishedName: CN=ms-Exch-Expand-DLs-Locally,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.201
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32932
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Expand-DLs-Locally
+adminDescription: ms-Exch-Expand-DLs-Locally
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: expandDLsLocally
+name: ms-Exch-Expand-DLs-Locally
+schemaIDGUID: a8df73fb-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Expansion-Server-Name
+#
+dn: CN=ms-Exch-Expansion-Server-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Expansion-Server-Name
+distinguishedName: CN=ms-Exch-Expansion-Server-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.49
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Expansion-Server-Name
+adminDescription: ms-Exch-Expansion-Server-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchExpansionServerName
+name: ms-Exch-Expansion-Server-Name
+schemaIDGUID: a1241706-b093-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Expiration-Time
+#
+dn: CN=ms-Exch-Expiration-Time,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Expiration-Time
+distinguishedName: CN=ms-Exch-Expiration-Time,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.394
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+mAPIID: 32808
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Expiration-Time
+adminDescription: ms-Exch-Expiration-Time
+oMSyntax: 23
+searchFlags: 1
+lDAPDisplayName: expirationTime
+name: ms-Exch-Expiration-Time
+schemaIDGUID: bf967965-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Export-Containers
+#
+dn: CN=ms-Exch-Export-Containers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Export-Containers
+distinguishedName: CN=ms-Exch-Export-Containers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.111
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32933
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Export-Containers
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Export-Containers
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: exportContainers
+name: ms-Exch-Export-Containers
+schemaIDGUID: a8df73fc-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Export-Containers-BL
+#
+dn: CN=ms-Exch-Export-Containers-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Export-Containers-BL
+distinguishedName: CN=ms-Exch-Export-Containers-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1027
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1029
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Export-Containers-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Export-Containers-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchExportContainersBL
+name: ms-Exch-Export-Containers-BL
+schemaIDGUID: 2436ac3e-1d4e-11d3-aa5e-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Export-Containers-Linked
+#
+dn: CN=ms-Exch-Export-Containers-Linked,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Export-Containers-Linked
+distinguishedName: CN=ms-Exch-Export-Containers-Linked,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1026
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1028
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Export-Containers-Linked
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Export-Containers-Linked
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchExportContainersLinked
+name: ms-Exch-Export-Containers-Linked
+schemaIDGUID: 3b7ea364-1d4d-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Export-Custom-Recipients
+#
+dn: CN=ms-Exch-Export-Custom-Recipients,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Export-Custom-Recipients
+distinguishedName: CN=ms-Exch-Export-Custom-Recipients,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.307
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32934
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Export-Custom-Recipients
+adminDescription: ms-Exch-Export-Custom-Recipients
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: exportCustomRecipients
+name: ms-Exch-Export-Custom-Recipients
+schemaIDGUID: a8df73fd-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Export-DLs
+# A flag indicating whether distribution list (DL) names are
+# propagated to foreign systems via directory synchronization.
+#
+dn: CN=ms-Exch-Export-DLs,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Export-DLs
+distinguishedName: CN=ms-Exch-Export-DLs,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1004
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Export-DLs
+adminDescription: ms-Exch-Export-DLs
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchExportDLs
+name: ms-Exch-Export-DLs
+schemaIDGUID: a14577f2-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Extension-Attribute-1
+#
+dn: CN=ms-Exch-Extension-Attribute-1,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-1
+distinguishedName: CN=ms-Exch-Extension-Attribute-1,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.423
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32813
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-1
+adminDescription: ms-Exch-Extension-Attribute-1
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute1
+name: ms-Exch-Extension-Attribute-1
+schemaIDGUID: bf967967-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-10
+#
+dn: CN=ms-Exch-Extension-Attribute-10,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-10
+distinguishedName: CN=ms-Exch-Extension-Attribute-10,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.432
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32822
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-10
+adminDescription: ms-Exch-Extension-Attribute-10
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute10
+name: ms-Exch-Extension-Attribute-10
+schemaIDGUID: bf967968-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-11
+#
+dn: CN=ms-Exch-Extension-Attribute-11,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-11
+distinguishedName: CN=ms-Exch-Extension-Attribute-11,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.599
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 2048
+mAPIID: 35927
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-11
+adminDescription: ms-Exch-Extension-Attribute-11
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute11
+name: ms-Exch-Extension-Attribute-11
+schemaIDGUID: 167757f6-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-12
+#
+dn: CN=ms-Exch-Extension-Attribute-12,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-12
+distinguishedName: CN=ms-Exch-Extension-Attribute-12,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.600
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 2048
+mAPIID: 35928
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-12
+adminDescription: ms-Exch-Extension-Attribute-12
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute12
+name: ms-Exch-Extension-Attribute-12
+schemaIDGUID: 167757f7-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-13
+#
+dn: CN=ms-Exch-Extension-Attribute-13,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-13
+distinguishedName: CN=ms-Exch-Extension-Attribute-13,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.601
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 2048
+mAPIID: 35929
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-13
+adminDescription: ms-Exch-Extension-Attribute-13
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute13
+name: ms-Exch-Extension-Attribute-13
+schemaIDGUID: 167757f8-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-14 Attribut
+#
+
+
+
+
+#
+# ms-Exch-Extension-Attribute-15
+#
+dn: CN=ms-Exch-Extension-Attribute-15,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-15
+distinguishedName: CN=ms-Exch-Extension-Attribute-15,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.603
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 2048
+mAPIID: 35937
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-15
+adminDescription: ms-Exch-Extension-Attribute-15
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute15
+name: ms-Exch-Extension-Attribute-15
+schemaIDGUID: 167757fa-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-2
+#
+dn: CN=ms-Exch-Extension-Attribute-2,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-2
+distinguishedName: CN=ms-Exch-Extension-Attribute-2,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.424
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32814
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-2
+adminDescription: ms-Exch-Extension-Attribute-2
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute2
+name: ms-Exch-Extension-Attribute-2
+schemaIDGUID: bf967969-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-3
+#
+dn: CN=ms-Exch-Extension-Attribute-3,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-3
+distinguishedName: CN=ms-Exch-Extension-Attribute-3,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.425
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32815
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-3
+adminDescription: ms-Exch-Extension-Attribute-3
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute3
+name: ms-Exch-Extension-Attribute-3
+schemaIDGUID: bf96796a-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-4
+#
+dn: CN=ms-Exch-Extension-Attribute-4,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-4
+distinguishedName: CN=ms-Exch-Extension-Attribute-4,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.426
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32816
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-4
+adminDescription: ms-Exch-Extension-Attribute-4
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute4
+name: ms-Exch-Extension-Attribute-4
+schemaIDGUID: bf96796b-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Extension-Attribute-5
+#
+dn: CN=ms-Exch-Extension-Attribute-5,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-5
+distinguishedName: CN=ms-Exch-Extension-Attribute-5,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.427
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32817
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-5
+adminDescription: ms-Exch-Extension-Attribute-5
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute5
+name: ms-Exch-Extension-Attribute-5
+schemaIDGUID: bf96796c-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-6
+#
+dn: CN=ms-Exch-Extension-Attribute-6,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-6
+distinguishedName: CN=ms-Exch-Extension-Attribute-6,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.428
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32818
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-6
+adminDescription: ms-Exch-Extension-Attribute-6
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute6
+name: ms-Exch-Extension-Attribute-6
+schemaIDGUID: bf96796d-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-7
+#
+dn: CN=ms-Exch-Extension-Attribute-7,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-7
+distinguishedName: CN=ms-Exch-Extension-Attribute-7,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.429
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32819
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-7
+adminDescription: ms-Exch-Extension-Attribute-7
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute7
+name: ms-Exch-Extension-Attribute-7
+schemaIDGUID: bf96796e-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-8
+#
+dn: CN=ms-Exch-Extension-Attribute-8,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-8
+distinguishedName: CN=ms-Exch-Extension-Attribute-8,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.430
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32820
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-8
+adminDescription: ms-Exch-Extension-Attribute-8
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute8
+name: ms-Exch-Extension-Attribute-8
+schemaIDGUID: bf96796f-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Extension-Attribute-9
+#
+dn: CN=ms-Exch-Extension-Attribute-9,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Attribute-9
+distinguishedName: CN=ms-Exch-Extension-Attribute-9,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.431
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32821
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Attribute-9
+adminDescription: ms-Exch-Extension-Attribute-9
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: extensionAttribute9
+name: ms-Exch-Extension-Attribute-9
+schemaIDGUID: bf967970-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Extension-Data
+#
+dn: CN=ms-Exch-Extension-Data,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Extension-Data
+distinguishedName: CN=ms-Exch-Extension-Data,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.228
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 32768
+mAPIID: 32936
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Extension-Data
+adminDescription: ms-Exch-Extension-Data
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: extensionData
+name: ms-Exch-Extension-Data
+schemaIDGUID: bf967971-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-FB-URL
+#
+dn: CN=ms-Exch-FB-URL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-FB-URL
+distinguishedName: CN=ms-Exch-FB-URL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.10001
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+mAPIID: 35966
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-FB-URL
+adminDescription: ms-Exch-FB-URL
+oMSyntax: 64
+searchFlags: 1
+lDAPDisplayName: msExchFBURL
+name: ms-Exch-FB-URL
+schemaIDGUID: a166d8de-b093-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-File-Version
+#
+dn: CN=ms-Exch-File-Version,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-File-Version
+distinguishedName: CN=ms-Exch-File-Version,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.178
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 8
+mAPIID: 32940
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-File-Version
+adminDescription: ms-Exch-File-Version
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: fileVersion
+name: ms-Exch-File-Version
+schemaIDGUID: 167757fb-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Filter-Local-Addresses
+#
+dn: CN=ms-Exch-Filter-Local-Addresses,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Filter-Local-Addresses
+distinguishedName: CN=ms-Exch-Filter-Local-Addresses,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.44
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32941
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Filter-Local-Addresses
+adminDescription: ms-Exch-Filter-Local-Addresses
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: filterLocalAddresses
+name: ms-Exch-Filter-Local-Addresses
+schemaIDGUID: a8df73fe-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-First-Instance
+#
+dn: CN=ms-Exch-First-Instance,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-First-Instance
+distinguishedName: CN=ms-Exch-First-Instance,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11053
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-First-Instance
+adminDescription: ms-Exch-First-Instance
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchFirstInstance
+name: ms-Exch-First-Instance
+schemaIDGUID: 8a8f2908-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Folder-Affinity-Custom
+#
+dn: CN=ms-Exch-Folder-Affinity-Custom,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Folder-Affinity-Custom
+distinguishedName: CN=ms-Exch-Folder-Affinity-Custom,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11090
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Folder-Affinity-Custom
+adminDescription: ms-Exch-Folder-Affinity-Custom
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchFolderAffinityCustom
+name: ms-Exch-Folder-Affinity-Custom
+schemaIDGUID: 5070257a-85b7-4ed4-b2e2-51f726684c58
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Folder-Affinity-List
+#
+dn: CN=ms-Exch-Folder-Affinity-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Folder-Affinity-List
+distinguishedName: CN=ms-Exch-Folder-Affinity-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11089
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Folder-Affinity-List
+adminDescription: ms-Exch-Folder-Affinity-List
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchFolderAffinityList
+name: ms-Exch-Folder-Affinity-List
+schemaIDGUID: 3592bc80-1117-4962-aa50-38c6e69bbb91
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Folder-Pathname
+#
+dn: CN=ms-Exch-Folder-Pathname,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Folder-Pathname
+distinguishedName: CN=ms-Exch-Folder-Pathname,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.337
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32772
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Folder-Pathname
+adminDescription: ms-Exch-Folder-Pathname
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: folderPathname
+name: ms-Exch-Folder-Pathname
+schemaIDGUID: f0f8ff8d-1191-11d0-a060-00aa006c33ed
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Form-Data
+#
+dn: CN=ms-Exch-Form-Data,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Form-Data
+distinguishedName: CN=ms-Exch-Form-Data,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.607
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+mAPIID: 35941
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Form-Data
+adminDescription: ms-Exch-Form-Data
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: formData
+name: ms-Exch-Form-Data
+schemaIDGUID: a8df7400-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Forwarding-Address
+# Contains an SMTP address that should be used as the mail forwarding
+# address of the object.
+#
+dn: CN=ms-Exch-Forwarding-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Forwarding-Address
+distinguishedName: CN=ms-Exch-Forwarding-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.606
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 256
+mAPIID: 35940
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Forwarding-Address
+adminDescription: ms-Exch-Forwarding-Address
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: forwardingAddress
+name: ms-Exch-Forwarding-Address
+schemaIDGUID: 167757ff-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Gateway-Local-Cred
+#
+dn: CN=ms-Exch-Gateway-Local-Cred,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Gateway-Local-Cred
+distinguishedName: CN=ms-Exch-Gateway-Local-Cred,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.37
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 32944
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Gateway-Local-Cred
+adminDescription: ms-Exch-Gateway-Local-Cred
+oMSyntax: 22
+searchFlags: 0
+lDAPDisplayName: gatewayLocalCred
+name: ms-Exch-Gateway-Local-Cred
+schemaIDGUID: a8df7401-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Gateway-Local-Desig
+#
+dn: CN=ms-Exch-Gateway-Local-Desig,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Gateway-Local-Desig
+distinguishedName: CN=ms-Exch-Gateway-Local-Desig,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.29
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 32945
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Gateway-Local-Desig
+adminDescription: ms-Exch-Gateway-Local-Desig
+oMSyntax: 22
+searchFlags: 0
+lDAPDisplayName: gatewayLocalDesig
+name: ms-Exch-Gateway-Local-Desig
+schemaIDGUID: a8df7402-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Gateway-Proxy
+#
+dn: CN=ms-Exch-Gateway-Proxy,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Gateway-Proxy
+distinguishedName: CN=ms-Exch-Gateway-Proxy,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.302
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 1123
+mAPIID: 32946
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Gateway-Proxy
+adminDescription: ms-Exch-Gateway-Proxy
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: gatewayProxy
+name: ms-Exch-Gateway-Proxy
+schemaIDGUID: 16775802-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Gateway-Routing-Tree
+# Contains the Gateway Address Resolution Table (GWART) for the site.
+#
+dn: CN=ms-Exch-Gateway-Routing-Tree,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Gateway-Routing-Tree
+distinguishedName: CN=ms-Exch-Gateway-Routing-Tree,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.167
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+mAPIID: 32947
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Gateway-Routing-Tree
+adminDescription: ms-Exch-Gateway-Routing-Tree
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: gatewayRoutingTree
+name: ms-Exch-Gateway-Routing-Tree
+schemaIDGUID: a8df7403-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Grace-Period-After
+# Defines a period, in seconds, for which the conference allows
+# attendees to continue after the scheduled termination.
+#
+dn: CN=ms-Exch-Grace-Period-After,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Grace-Period-After
+distinguishedName: CN=ms-Exch-Grace-Period-After,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9003
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Grace-Period-After
+adminDescription: ms-Exch-Grace-Period-After
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchGracePeriodAfter
+name: ms-Exch-Grace-Period-After
+schemaIDGUID: a1d6e764-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Grace-Period-Prior
+# Defines a period, in seconds, for which clients are accepted into a
+# conference prior to the scheduled start time.
+#
+dn: CN=ms-Exch-Grace-Period-Prior,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Grace-Period-Prior
+distinguishedName: CN=ms-Exch-Grace-Period-Prior,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9002
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Grace-Period-Prior
+adminDescription: ms-Exch-Grace-Period-Prior
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchGracePeriodPrior
+name: ms-Exch-Grace-Period-Prior
+schemaIDGUID: a1f84850-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-GWART-Last-Modified
+# Contains the time the Gateway Address Resolution Table (GWART) was
+# last modified.
+#
+dn: CN=ms-Exch-GWART-Last-Modified,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-GWART-Last-Modified
+distinguishedName: CN=ms-Exch-GWART-Last-Modified,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.260
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+mAPIID: 32948
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-GWART-Last-Modified
+adminDescription: ms-Exch-GWART-Last-Modified
+oMSyntax: 23
+searchFlags: 0
+lDAPDisplayName: gWARTLastModified
+name: ms-Exch-GWART-Last-Modified
+schemaIDGUID: 8fa43470-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-GWise-API-Gateway
+#
+dn: CN=ms-Exch-GWise-API-Gateway,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-GWise-API-Gateway
+distinguishedName: CN=ms-Exch-GWise-API-Gateway,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1045
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-GWise-API-Gateway
+adminDescription: ms-Exch-GWise-API-Gateway
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchGWiseAPIGateway
+name: ms-Exch-GWise-API-Gateway
+schemaIDGUID: c7e96933-bd80-44a2-a535-ec744ea5f54f
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-GWise-API-Gateway-Path
+#
+dn: CN=ms-Exch-GWise-API-Gateway-Path,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-GWise-API-Gateway-Path
+distinguishedName: CN=ms-Exch-GWise-API-Gateway-Path,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1201
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-GWise-API-Gateway-Path
+adminDescription: ms-Exch-GWise-API-Gateway-Path
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchGWiseAPIGatewayPath
+name: ms-Exch-GWise-API-Gateway-Path
+schemaIDGUID: 3b9d8dea-2d93-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-GWise-Filter-Type
+#
+dn: CN=ms-Exch-GWise-Filter-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-GWise-Filter-Type
+distinguishedName: CN=ms-Exch-GWise-Filter-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1205
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-GWise-Filter-Type
+adminDescription: ms-Exch-GWise-Filter-Type
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchGWiseFilterType
+name: ms-Exch-GWise-Filter-Type
+schemaIDGUID: 3b9d8dee-2d93-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-GWise-Foreign-Domain
+#
+dn: CN=ms-Exch-GWise-Foreign-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-GWise-Foreign-Domain
+distinguishedName: CN=ms-Exch-GWise-Foreign-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1204
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-GWise-Foreign-Domain
+adminDescription: ms-Exch-GWise-Foreign-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchGWiseForeignDomain
+name: ms-Exch-GWise-Foreign-Domain
+schemaIDGUID: 3b9d8df3-2d93-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-GWise-Password
+#
+dn: CN=ms-Exch-GWise-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-GWise-Password
+distinguishedName: CN=ms-Exch-GWise-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1203
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-GWise-Password
+adminDescription: ms-Exch-GWise-Password
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchGWisePassword
+name: ms-Exch-GWise-Password
+schemaIDGUID: 3b9d8df9-2d93-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-GWise-User-Id
+#
+dn: CN=ms-Exch-GWise-User-Id,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-GWise-User-Id
+distinguishedName: CN=ms-Exch-GWise-User-Id,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1202
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-GWise-User-Id
+adminDescription: ms-Exch-GWise-User-Id
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchGWiseUserId
+name: ms-Exch-GWise-User-Id
+schemaIDGUID: 3b9d8e00-2d93-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Heuristics
+# Contains special connector attributes, such as "allow system
+# messages".
+#
+dn: CN=ms-Exch-Heuristics,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Heuristics
+distinguishedName: CN=ms-Exch-Heuristics,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.452
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32951
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Heuristics
+adminDescription: ms-Exch-Heuristics
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: heuristics
+name: ms-Exch-Heuristics
+schemaIDGUID: bf967983-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Hide-DL-Membership
+#
+dn: CN=ms-Exch-Hide-DL-Membership,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Hide-DL-Membership
+distinguishedName: CN=ms-Exch-Hide-DL-Membership,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.297
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32952
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Hide-DL-Membership
+adminDescription: ms-Exch-Hide-DL-Membership
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: hideDLMembership
+name: ms-Exch-Hide-DL-Membership
+schemaIDGUID: a8df7405-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Hide-From-Address-Lists
+# Determines if the recipient appears in address lists.
+#
+dn: CN=ms-Exch-Hide-From-Address-Lists,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Hide-From-Address-Lists
+distinguishedName: CN=ms-Exch-Hide-From-Address-Lists,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.73
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Hide-From-Address-Lists
+adminDescription: ms-Exch-Hide-From-Address-Lists
+oMSyntax: 1
+searchFlags: 16
+lDAPDisplayName: msExchHideFromAddressLists
+name: ms-Exch-Hide-From-Address-Lists
+schemaIDGUID: a21c0b96-b093-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Home-MDB
+# The distinguished name of the MDB for this mailbox.
+#
+dn: CN=ms-Exch-Home-MDB,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Home-MDB
+distinguishedName: CN=ms-Exch-Home-MDB,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.244
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 32774
+linkID: 32
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Home-MDB
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Home-MDB
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: homeMDB
+name: ms-Exch-Home-MDB
+schemaIDGUID: bf967987-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Home-MDB-BL
+#
+dn: CN=ms-Exch-Home-MDB-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Home-MDB-BL
+distinguishedName: CN=ms-Exch-Home-MDB-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.393
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32788
+linkID: 33
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Home-MDB-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Home-MDB-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: homeMDBBL
+name: ms-Exch-Home-MDB-BL
+schemaIDGUID: bf967988-0de6-11d0-a285-00aa003049e2
+systemFlags: 1
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Home-MTA
+# Points to the MTA that services this object.
+#
+dn: CN=ms-Exch-Home-MTA,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Home-MTA
+distinguishedName: CN=ms-Exch-Home-MTA,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.171
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 32775
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Home-MTA
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Home-MTA
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: homeMTA
+name: ms-Exch-Home-MTA
+schemaIDGUID: bf967989-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Home-Public-MDB
+# The DN of the object for the home public MDB.
+#
+dn: CN=ms-Exch-Home-Public-MDB,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Home-Public-MDB
+distinguishedName: CN=ms-Exch-Home-Public-MDB,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11044
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Home-Public-MDB
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Home-Public-MDB
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchHomePublicMDB
+name: ms-Exch-Home-Public-MDB
+schemaIDGUID: a23fcedc-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Home-Routing-Group
+#
+dn: CN=ms-Exch-Home-Routing-Group,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Home-Routing-Group
+distinguishedName: CN=ms-Exch-Home-Routing-Group,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12539
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1050
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Home-Routing-Group
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Home-Routing-Group
+oMSyntax: 127
+searchFlags: 1
+lDAPDisplayName: msExchHomeRoutingGroup
+name: ms-Exch-Home-Routing-Group
+schemaIDGUID: f649deed-1c26-4ed4-b639-f333a4850bc2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Home-Routing-Group-DN-BL
+# A backlink to the routing group that this object is a member of.
+#
+dn: CN=ms-Exch-Home-Routing-Group-DN-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Home-Routing-Group-DN-BL
+distinguishedName: CN=ms-Exch-Home-Routing-Group-DN-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12513
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1001
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Home-Routing-Group-DN-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Home-Routing-Group-DN-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchHomeRoutingGroupDNBL
+name: ms-Exch-Home-Routing-Group-DN-BL
+schemaIDGUID: a2612fc8-b093-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Home-Server-Name
+#
+dn: CN=ms-Exch-Home-Server-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Home-Server-Name
+distinguishedName: CN=ms-Exch-Home-Server-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.47
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Home-Server-Name
+adminDescription: ms-Exch-Home-Server-Name
+oMSyntax: 64
+searchFlags: 25
+lDAPDisplayName: msExchHomeServerName
+name: ms-Exch-Home-Server-Name
+schemaIDGUID: a284f30e-b093-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Home-Sync-Service
+# Link to the Active Directory Connector (ADC) for this connection
+# agreement.
+#
+dn: CN=ms-Exch-Home-Sync-Service,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Home-Sync-Service
+distinguishedName: CN=ms-Exch-Home-Sync-Service,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.36
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 146
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Home-Sync-Service
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Home-Sync-Service
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchHomeSyncService
+name: ms-Exch-Home-Sync-Service
+schemaIDGUID: a2a3f1a0-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-House-Identifier
+#
+#dn: CN=ms-Exch-House-Identifier,${SCHEMADN}
+#objectClass: top
+#objectClass: attributeSchema
+#cn: ms-Exch-House-Identifier
+#distinguishedName: CN=ms-Exch-House-Identifier,${SCHEMADN}
+#attributeID: 1.2.840.113556.1.2.596
+#attributeSyntax: 2.5.5.12
+#isSingleValued: TRUE
+#rangeLower: 1
+#rangeUpper: 128
+#mAPIID: 35924
+#adminDisplayName: ms-Exch-House-Identifier
+#adminDescription: ms-Exch-House-Identifier
+#oMSyntax: 64
+#searchFlags: 0
+#lDAPDisplayName: msExchHouseIdentifier
+#name: ms-Exch-House-Identifier
+#schemaIDGUID: a8df7407-c5ea-11d1-bbcb-0080c76670c0
+#objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-HTTP-Pub-AB-Attributes
+#
+dn: CN=ms-Exch-HTTP-Pub-AB-Attributes,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-HTTP-Pub-AB-Attributes
+distinguishedName: CN=ms-Exch-HTTP-Pub-AB-Attributes,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.516
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 128
+mAPIID: 33193
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-HTTP-Pub-AB-Attributes
+adminDescription: ms-Exch-HTTP-Pub-AB-Attributes
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: hTTPPubABAttributes
+name: ms-Exch-HTTP-Pub-AB-Attributes
+schemaIDGUID: a8df7408-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-HTTP-Pub-GAL
+#
+dn: CN=ms-Exch-HTTP-Pub-GAL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-HTTP-Pub-GAL
+distinguishedName: CN=ms-Exch-HTTP-Pub-GAL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.502
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 33179
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-HTTP-Pub-GAL
+adminDescription: ms-Exch-HTTP-Pub-GAL
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: hTTPPubGAL
+name: ms-Exch-HTTP-Pub-GAL
+schemaIDGUID: a8df7409-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-HTTP-Pub-GAL-Limit
+#
+dn: CN=ms-Exch-HTTP-Pub-GAL-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-HTTP-Pub-GAL-Limit
+distinguishedName: CN=ms-Exch-HTTP-Pub-GAL-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.503
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33180
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-HTTP-Pub-GAL-Limit
+adminDescription: ms-Exch-HTTP-Pub-GAL-Limit
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: hTTPPubGALLimit
+name: ms-Exch-HTTP-Pub-GAL-Limit
+schemaIDGUID: a8df740a-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-HTTP-Pub-PF
+#
+dn: CN=ms-Exch-HTTP-Pub-PF,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-HTTP-Pub-PF
+distinguishedName: CN=ms-Exch-HTTP-Pub-PF,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.505
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 33182
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-HTTP-Pub-PF
+adminDescription: ms-Exch-HTTP-Pub-PF
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: hTTPPubPF
+name: ms-Exch-HTTP-Pub-PF
+schemaIDGUID: a8df740b-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-HTTP-Servers
+#
+dn: CN=ms-Exch-HTTP-Servers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-HTTP-Servers
+distinguishedName: CN=ms-Exch-HTTP-Servers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.517
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 256
+mAPIID: 33195
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-HTTP-Servers
+adminDescription: ms-Exch-HTTP-Servers
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: hTTPServers
+name: ms-Exch-HTTP-Servers
+schemaIDGUID: a8df740c-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IFS-Private-Enabled
+# Determines whether private mailboxes are shared.
+dn: CN=ms-Exch-IFS-Private-Enabled,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IFS-Private-Enabled
+distinguishedName: CN=ms-Exch-IFS-Private-Enabled,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11029
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IFS-Private-Enabled
+adminDescription: ms-Exch-IFS-Private-Enabled
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchIFSPrivateEnabled
+name: ms-Exch-IFS-Private-Enabled
+schemaIDGUID: a2e915d2-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-IFS-Private-Name
+# The name of the private share.
+#
+dn: CN=ms-Exch-IFS-Private-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IFS-Private-Name
+distinguishedName: CN=ms-Exch-IFS-Private-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11033
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IFS-Private-Name
+adminDescription: ms-Exch-IFS-Private-Name
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchIFSPrivateName
+name: ms-Exch-IFS-Private-Name
+schemaIDGUID: a30a76be-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IFS-Public-Enabled
+# Determines whether public folders are shared.
+#
+dn: CN=ms-Exch-IFS-Public-Enabled,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IFS-Public-Enabled
+distinguishedName: CN=ms-Exch-IFS-Public-Enabled,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11050
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IFS-Public-Enabled
+adminDescription: ms-Exch-IFS-Public-Enabled
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchIFSPublicEnabled
+name: ms-Exch-IFS-Public-Enabled
+schemaIDGUID: a32bd7aa-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-IFS-Public-Name
+# The name of the public share.
+#
+dn: CN=ms-Exch-IFS-Public-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IFS-Public-Name
+distinguishedName: CN=ms-Exch-IFS-Public-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11051
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IFS-Public-Name
+adminDescription: ms-Exch-IFS-Public-Name
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchIFSPublicName
+name: ms-Exch-IFS-Public-Name
+schemaIDGUID: a34d3896-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IMAP-OWA-URL-Prefix-Override
+#
+dn: CN=ms-Exch-IMAP-OWA-URL-Prefix-Override,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IMAP-OWA-URL-Prefix-Override
+distinguishedName: CN=ms-Exch-IMAP-OWA-URL-Prefix-Override,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50213
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IMAP-OWA-URL-Prefix-Override
+adminDescription: ms-Exch-IMAP-OWA-URL-Prefix-Override
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchIMAPOWAURLPrefixOverride
+name: ms-Exch-IMAP-OWA-URL-Prefix-Override
+schemaIDGUID: 5e26dd2a-9b0a-4219-8183-20ad44f5cbdf
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Imported-From
+# Contains the DN to the connecter from which this object is imported.
+#
+dn: CN=ms-Exch-Imported-From,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Imported-From
+distinguishedName: CN=ms-Exch-Imported-From,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.263
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32834
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Imported-From
+adminDescription: ms-Exch-Imported-From
+oMSyntax: 64
+searchFlags: 9
+lDAPDisplayName: importedFrom
+name: ms-Exch-Imported-From
+schemaIDGUID: bf96798a-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Import-Container
+#
+dn: CN=ms-Exch-Import-Container,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Import-Container
+distinguishedName: CN=ms-Exch-Import-Container,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.110
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 32954
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Import-Container
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Import-Container
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: importContainer
+name: ms-Exch-Import-Container
+schemaIDGUID: a8df740d-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Import-Container-Linked
+#
+dn: CN=ms-Exch-Import-Container-Linked,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Import-Container-Linked
+distinguishedName: CN=ms-Exch-Import-Container-Linked,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1028
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1032
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Import-Container-Linked
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Import-Container-Linked
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchImportContainerLinked
+name: ms-Exch-Import-Container-Linked
+schemaIDGUID: 9ff15c4c-1ec9-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-ACL
+# A multivalued list of access control entries (ACEs) for Instant
+# Messaging.
+#
+dn: CN=ms-Exch-IM-ACL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-ACL
+distinguishedName: CN=ms-Exch-IM-ACL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7031
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-ACL
+adminDescription: ms-Exch-IM-ACL
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchIMACL
+name: ms-Exch-IM-ACL
+schemaIDGUID: 06551010-2845-11d3-aa68-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-IM-Address
+# A representation (resembling e-mail) of the public URL for a user
+# that is enabled for Instant Messaging.
+#
+dn: CN=ms-Exch-IM-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-Address
+distinguishedName: CN=ms-Exch-IM-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7038
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Address
+adminDescription: ms-Exch-IM-Address
+oMSyntax: 19
+searchFlags: 1
+lDAPDisplayName: msExchIMAddress
+name: ms-Exch-IM-Address
+schemaIDGUID: cbbd3752-b8d8-47dc-92ee-ab488c1af969
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-DB-Log-Path
+# States the directory path root for all database transaction log
+# files.
+#
+dn: CN=ms-Exch-IM-DB-Log-Path,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-DB-Log-Path
+distinguishedName: CN=ms-Exch-IM-DB-Log-Path,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7016
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 1024
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-DB-Log-Path
+adminDescription: ms-Exch-IM-DB-Log-Path
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchIMDBLogPath
+name: ms-Exch-IM-DB-Log-Path
+schemaIDGUID: a4394164-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-IM-DB-Path
+# States the directory path root for all database files for a
+# particular server.
+#
+dn: CN=ms-Exch-IM-DB-Path,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-DB-Path
+distinguishedName: CN=ms-Exch-IM-DB-Path,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7015
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 1024
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-DB-Path
+adminDescription: ms-Exch-IM-DB-Path
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchIMDBPath
+name: ms-Exch-IM-DB-Path
+schemaIDGUID: a45aa250-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-Firewall-Type
+# Describes the type of firewall entry for this firewall object.
+#
+dn: CN=ms-Exch-IM-Firewall-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-Firewall-Type
+distinguishedName: CN=ms-Exch-IM-Firewall-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7028
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Firewall-Type
+adminDescription: ms-Exch-IM-Firewall-Type
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchIMFirewallType
+name: ms-Exch-IM-Firewall-Type
+schemaIDGUID: 06550ffc-2845-11d3-aa68-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-IM-Host-Name
+# The host name for the Instant Messaging virtual server.
+#
+dn: CN=ms-Exch-IM-Host-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-Host-Name
+distinguishedName: CN=ms-Exch-IM-Host-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7034
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Host-Name
+adminDescription: ms-Exch-IM-Host-Name
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchIMHostName
+name: ms-Exch-IM-Host-Name
+schemaIDGUID: 807b6084-439b-11d3-aa72-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-IP-Range
+# A multivalued attribute that lists IP ranges that are valid for the
+# Instant Messaging firewall.
+dn: CN=ms-Exch-IM-IP-Range,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-IP-Range
+distinguishedName: CN=ms-Exch-IM-IP-Range,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7030
+attributeSyntax: 2.5.5.16
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-IP-Range
+adminDescription: ms-Exch-IM-IP-Range
+oMSyntax: 65
+searchFlags: 0
+lDAPDisplayName: msExchIMIPRange
+name: ms-Exch-IM-IP-Range
+schemaIDGUID: 0655100b-2845-11d3-aa68-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-IM-Meta-Physical-URL
+# The public URL for a user that is enabled for Instant Messaging.
+#
+dn: CN=ms-Exch-IM-Meta-Physical-URL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-Meta-Physical-URL
+distinguishedName: CN=ms-Exch-IM-Meta-Physical-URL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7035
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Meta-Physical-URL
+adminDescription: ms-Exch-IM-Meta-Physical-URL
+oMSyntax: 19
+searchFlags: 1
+lDAPDisplayName: msExchIMMetaPhysicalURL
+name: ms-Exch-IM-Meta-Physical-URL
+schemaIDGUID: 8e7a93a3-5a7c-11d3-aa78-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-IM-Physical-URL
+# The private URL for a user that is enabled for Instant Messaging.
+#
+dn: CN=ms-Exch-IM-Physical-URL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-Physical-URL
+distinguishedName: CN=ms-Exch-IM-Physical-URL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7036
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Physical-URL
+adminDescription: ms-Exch-IM-Physical-URL
+oMSyntax: 19
+searchFlags: 1
+lDAPDisplayName: msExchIMPhysicalURL
+name: ms-Exch-IM-Physical-URL
+schemaIDGUID: 8e7a93a8-5a7c-11d3-aa78-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-Proxy
+# The proxy name for the Instant Messaging firewall.
+#
+dn: CN=ms-Exch-IM-Proxy,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-Proxy
+distinguishedName: CN=ms-Exch-IM-Proxy,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7029
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Proxy
+adminDescription: ms-Exch-IM-Proxy
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchIMProxy
+name: ms-Exch-IM-Proxy
+schemaIDGUID: 06551002-2845-11d3-aa68-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-Server-Hosts-Users
+# States whether an Instant Messaging virtual server can host users.
+#
+dn: CN=ms-Exch-IM-Server-Hosts-Users,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-Server-Hosts-Users
+distinguishedName: CN=ms-Exch-IM-Server-Hosts-Users,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7025
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Server-Hosts-Users
+adminDescription: ms-Exch-IM-Server-Hosts-Users
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchIMServerHostsUsers
+name: ms-Exch-IM-Server-Hosts-Users
+schemaIDGUID: 8d6b1af6-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-Server-IIS-Id
+# The Microsoft Internet Information Services (IIS) Web Server
+# Instance in the metabase.
+#
+dn: CN=ms-Exch-IM-Server-IIS-Id,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-Server-IIS-Id
+distinguishedName: CN=ms-Exch-IM-Server-IIS-Id,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7023
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 1
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Server-IIS-Id
+adminDescription: ms-Exch-IM-Server-IIS-Id
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchIMServerIISId
+name: ms-Exch-IM-Server-IIS-Id
+schemaIDGUID: 8d3444e0-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-Server-Name
+#
+dn: CN=ms-Exch-IM-Server-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-Server-Name
+distinguishedName: CN=ms-Exch-IM-Server-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7024
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Server-Name
+adminDescription: ms-Exch-IM-Server-Name
+oMSyntax: 64
+searchFlags: 1
+lDAPDisplayName: msExchIMServerName
+name: ms-Exch-IM-Server-Name
+schemaIDGUID: 8d4e7ebe-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IM-Virtual-Server
+# The DN of the Instant Messaging home server.
+#
+dn: CN=ms-Exch-IM-Virtual-Server,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IM-Virtual-Server
+distinguishedName: CN=ms-Exch-IM-Virtual-Server,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7037
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IM-Virtual-Server
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-IM-Virtual-Server
+oMSyntax: 127
+searchFlags: 1
+lDAPDisplayName: msExchIMVirtualServer
+name: ms-Exch-IM-Virtual-Server
+schemaIDGUID: 41e8fd82-8f37-4e56-a44a-33a3e6b7526c
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Inbound-Sites
+#
+dn: CN=ms-Exch-Inbound-Sites,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Inbound-Sites
+distinguishedName: CN=ms-Exch-Inbound-Sites,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.71
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32956
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Inbound-Sites
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Inbound-Sites
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: inboundSites
+name: ms-Exch-Inbound-Sites
+schemaIDGUID: a8df7414-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Incoming-Connection-Timeout
+# The maximum length of time for incoming connections.
+#
+dn: CN=ms-Exch-Incoming-Connection-Timeout,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Incoming-Connection-Timeout
+distinguishedName: CN=ms-Exch-Incoming-Connection-Timeout,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2015
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Incoming-Connection-Timeout
+adminDescription: ms-Exch-Incoming-Connection-Timeout
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchIncomingConnectionTimeout
+name: ms-Exch-Incoming-Connection-Timeout
+schemaIDGUID: a64cedca-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Incoming-Msg-Size-Limit
+#
+dn: CN=ms-Exch-Incoming-Msg-Size-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Incoming-Msg-Size-Limit
+distinguishedName: CN=ms-Exch-Incoming-Msg-Size-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.491
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33168
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Incoming-Msg-Size-Limit
+adminDescription: ms-Exch-Incoming-Msg-Size-Limit
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: incomingMsgSizeLimit
+name: ms-Exch-Incoming-Msg-Size-Limit
+schemaIDGUID: 1677581a-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Inconsistent-State
+#
+dn: CN=ms-Exch-Inconsistent-State,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Inconsistent-State
+distinguishedName: CN=ms-Exch-Inconsistent-State,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.96
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Inconsistent-State
+adminDescription: ms-Exch-Inconsistent-State
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchInconsistentState
+name: ms-Exch-Inconsistent-State
+schemaIDGUID: 1d80475f-e7b4-4005-af4d-82bcbf407c3c
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-INSAdmin
+#
+dn: CN=ms-Exch-INSAdmin,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-INSAdmin
+distinguishedName: CN=ms-Exch-INSAdmin,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.543
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 33221
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-INSAdmin
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-INSAdmin
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: iNSAdmin
+name: ms-Exch-INSAdmin
+schemaIDGUID: a8df7416-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Installed-Components
+# Contains a list of installed components on a given server.
+#
+dn: CN=ms-Exch-Installed-Components,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Installed-Components
+distinguishedName: CN=ms-Exch-Installed-Components,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50024
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Installed-Components
+adminDescription: ms-Exch-Installed-Components
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchInstalledComponents
+name: ms-Exch-Installed-Components
+schemaIDGUID: 99f5865d-12e8-11d3-aa58-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Install-Path
+#
+dn: CN=ms-Exch-Install-Path,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Install-Path
+distinguishedName: CN=ms-Exch-Install-Path,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50019
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Install-Path
+adminDescription: ms-Exch-Install-Path
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchInstallPath
+name: ms-Exch-Install-Path
+schemaIDGUID: 8a23df36-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Internet-Encoding
+#
+dn: CN=ms-Exch-Internet-Encoding,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Internet-Encoding
+distinguishedName: CN=ms-Exch-Internet-Encoding,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.551
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 14961
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Internet-Encoding
+adminDescription: ms-Exch-Internet-Encoding
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: internetEncoding
+name: ms-Exch-Internet-Encoding
+schemaIDGUID: 1677581d-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Internet-Name
+# The data conference Internet name.
+#
+dn: CN=ms-Exch-Internet-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Internet-Name
+distinguishedName: CN=ms-Exch-Internet-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9019
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Internet-Name
+adminDescription: ms-Exch-Internet-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchInternetName
+name: ms-Exch-Internet-Name
+schemaIDGUID: a670b110-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Inter-Org-Address-Type
+#
+#
+dn: CN=ms-Exch-Inter-Org-Address-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Inter-Org-Address-Type
+distinguishedName: CN=ms-Exch-Inter-Org-Address-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.94
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Inter-Org-Address-Type
+adminDescription: ms-Exch-Inter-Org-Address-Type
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchInterOrgAddressType
+name: ms-Exch-Inter-Org-Address-Type
+schemaIDGUID: 3836c80b-8cee-4413-9e65-e937c1aed10f
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-IP-Address
+#
+dn: CN=ms-Exch-IP-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IP-Address
+distinguishedName: CN=ms-Exch-IP-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5050
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IP-Address
+adminDescription: ms-Exch-IP-Address
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchIPAddress
+name: ms-Exch-IP-Address
+schemaIDGUID: 8b46be1a-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-IP-Security
+# Restricts IP connections to this resource.
+#
+dn: CN=ms-Exch-IP-Security,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-IP-Security
+distinguishedName: CN=ms-Exch-IP-Security,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2013
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-IP-Security
+adminDescription: ms-Exch-IP-Security
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchIPSecurity
+name: ms-Exch-IP-Security
+schemaIDGUID: a68fafa2-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Is-Bridgehead-Site
+# A flag to determine whether non-mailbox associated objects are
+# replicated over this particular connection agreement.
+#
+dn: CN=ms-Exch-Is-Bridgehead-Site,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Is-Bridgehead-Site
+distinguishedName: CN=ms-Exch-Is-Bridgehead-Site,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.35
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Is-Bridgehead-Site
+adminDescription: ms-Exch-Is-Bridgehead-Site
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchIsBridgeheadSite
+name: ms-Exch-Is-Bridgehead-Site
+schemaIDGUID: a6b1108e-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Is-Config-CA
+# Determines if this is a configuration Connection Agreement.
+#
+dn: CN=ms-Exch-Is-Config-CA,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Is-Config-CA
+distinguishedName: CN=ms-Exch-Is-Config-CA,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.79
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Is-Config-CA
+adminDescription: ms-Exch-Is-Config-CA
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchIsConfigCA
+name: ms-Exch-Is-Config-CA
+schemaIDGUID: 910f526c-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-KCC-Status
+#
+dn: CN=ms-Exch-KCC-Status,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-KCC-Status
+distinguishedName: CN=ms-Exch-KCC-Status,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.237
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+mAPIID: 32962
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-KCC-Status
+adminDescription: ms-Exch-KCC-Status
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: kCCStatus
+name: ms-Exch-KCC-Status
+schemaIDGUID: 5fd424ae-1262-11d0-a060-00aa006c33ed
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-KM-Server
+#
+dn: CN=ms-Exch-KM-Server,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-KM-Server
+distinguishedName: CN=ms-Exch-KM-Server,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.440
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 32781
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-KM-Server
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-KM-Server
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: kMServer
+name: ms-Exch-KM-Server
+schemaIDGUID: 1677581e-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-LabeledURI
+#
+#dn: CN=ms-Exch-LabeledURI,${SCHEMADN}
+#objectClass: top
+#objectClass: attributeSchema
+#cn: ms-Exch-LabeledURI
+#distinguishedName: CN=ms-Exch-LabeledURI,${SCHEMADN}
+#attributeID: 1.2.840.113556.1.2.593
+#attributeSyntax: 2.5.5.12
+#isSingleValued: FALSE
+#rangeLower: 1
+#rangeUpper: 1024
+#mAPIID: 35921
+#adminDisplayName: ms-Exch-LabeledURI
+#adminDescription: ms-Exch-LabeledURI
+#oMSyntax: 64
+#searchFlags: 0
+#lDAPDisplayName: msExchLabeledURI
+#name: ms-Exch-LabeledURI
+#schemaIDGUID: 16775820-47f3-11d1-a9c3-0000f80367c1
+#attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+#objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Language
+#
+dn: CN=ms-Exch-Language,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Language
+distinguishedName: CN=ms-Exch-Language,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.467
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33144
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Language
+adminDescription: ms-Exch-Language
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: languageCode
+name: ms-Exch-Language
+schemaIDGUID: bf967994-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Language-ISO639
+# The ISO-639 language code identifying a user's language.
+#
+dn: CN=ms-Exch-Language-ISO639,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Language-ISO639
+distinguishedName: CN=ms-Exch-Language-ISO639,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.616
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 35948
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Language-ISO639
+adminDescription: ms-Exch-Language-ISO639
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: language
+name: ms-Exch-Language-ISO639
+schemaIDGUID: 16775821-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-LDAP-Search-Cfg
+#
+dn: CN=ms-Exch-LDAP-Search-Cfg,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-LDAP-Search-Cfg
+distinguishedName: CN=ms-Exch-LDAP-Search-Cfg,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.552
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 35869
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-LDAP-Search-Cfg
+adminDescription: ms-Exch-LDAP-Search-Cfg
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: lDAPSearchCfg
+name: ms-Exch-LDAP-Search-Cfg
+schemaIDGUID: a8df7417-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Legacy-Account
+#
+dn: CN=ms-Exch-Legacy-Account,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Legacy-Account
+distinguishedName: CN=ms-Exch-Legacy-Account,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50040
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Legacy-Account
+adminDescription: ms-Exch-Legacy-Account
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchLegacyAccount
+name: ms-Exch-Legacy-Account
+schemaIDGUID: 974c99e1-33fc-11d3-aa6e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Legacy-Domain
+#
+dn: CN=ms-Exch-Legacy-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Legacy-Domain
+distinguishedName: CN=ms-Exch-Legacy-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50041
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Legacy-Domain
+adminDescription: ms-Exch-Legacy-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchLegacyDomain
+name: ms-Exch-Legacy-Domain
+schemaIDGUID: 974c99ea-33fc-11d3-aa6e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Legacy-PW
+#
+dn: CN=ms-Exch-Legacy-PW,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Legacy-PW
+distinguishedName: CN=ms-Exch-Legacy-PW,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50042
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Legacy-PW
+adminDescription: ms-Exch-Legacy-PW
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchLegacyPW
+name: ms-Exch-Legacy-PW
+schemaIDGUID: 974c99f2-33fc-11d3-aa6e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Line-Wrap
+#
+dn: CN=ms-Exch-Line-Wrap,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Line-Wrap
+distinguishedName: CN=ms-Exch-Line-Wrap,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.449
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32964
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Line-Wrap
+adminDescription: ms-Exch-Line-Wrap
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: lineWrap
+name: ms-Exch-Line-Wrap
+schemaIDGUID: a8df7418-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-List-Public
+# Lists public data conferences.
+#
+dn: CN=ms-Exch-List-Public,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-List-Public
+distinguishedName: CN=ms-Exch-List-Public,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9011
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-List-Public
+adminDescription: ms-Exch-List-Public
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchListPublic
+name: ms-Exch-List-Public
+schemaIDGUID: a6f634c0-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-List-Public-Folders
+#
+dn: CN=ms-Exch-List-Public-Folders,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-List-Public-Folders
+distinguishedName: CN=ms-Exch-List-Public-Folders,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.592
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 35920
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-List-Public-Folders
+adminDescription: ms-Exch-List-Public-Folders
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: listPublicFolders
+name: ms-Exch-List-Public-Folders
+schemaIDGUID: a8df7419-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Locales
+# The set of locales that determine client sort order.
+#
+dn: CN=ms-Exch-Locales,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Locales
+distinguishedName: CN=ms-Exch-Locales,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50017
+attributeSyntax: 2.5.5.9
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Locales
+adminDescription: ms-Exch-Locales
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchLocales
+name: ms-Exch-Locales
+schemaIDGUID: a738f698-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Local-Bridge-Head
+#
+dn: CN=ms-Exch-Local-Bridge-Head,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Local-Bridge-Head
+distinguishedName: CN=ms-Exch-Local-Bridge-Head,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.311
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 32966
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Local-Bridge-Head
+adminDescription: ms-Exch-Local-Bridge-Head
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: localBridgeHead
+name: ms-Exch-Local-Bridge-Head
+schemaIDGUID: a8df741a-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Local-Bridge-Head-Address
+#
+dn: CN=ms-Exch-Local-Bridge-Head-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Local-Bridge-Head-Address
+distinguishedName: CN=ms-Exch-Local-Bridge-Head-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.225
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 1118
+mAPIID: 32967
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Local-Bridge-Head-Address
+adminDescription: ms-Exch-Local-Bridge-Head-Address
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: localBridgeHeadAddress
+name: ms-Exch-Local-Bridge-Head-Address
+schemaIDGUID: a8df741b-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Local-Domains
+#
+dn: CN=ms-Exch-Local-Domains,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Local-Domains
+distinguishedName: CN=ms-Exch-Local-Domains,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50032
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Local-Domains
+adminDescription: ms-Exch-Local-Domains
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchLocalDomains
+name: ms-Exch-Local-Domains
+schemaIDGUID: ab3a1ac7-1df5-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Local-Initial-Turn
+#
+dn: CN=ms-Exch-Local-Initial-Turn,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Local-Initial-Turn
+distinguishedName: CN=ms-Exch-Local-Initial-Turn,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.39
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32968
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Local-Initial-Turn
+adminDescription: ms-Exch-Local-Initial-Turn
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: localInitialTurn
+name: ms-Exch-Local-Initial-Turn
+schemaIDGUID: a8df741c-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Local-Name
+# The data conference local name.
+#
+dn: CN=ms-Exch-Local-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Local-Name
+distinguishedName: CN=ms-Exch-Local-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9017
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Local-Name
+adminDescription: ms-Exch-Local-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchLocalName
+name: ms-Exch-Local-Name
+schemaIDGUID: a7153352-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Logon-ACL
+#
+dn: CN=ms-Exch-Logon-ACL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Logon-ACL
+distinguishedName: CN=ms-Exch-Logon-ACL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5057
+attributeSyntax: 2.5.5.15
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Logon-ACL
+adminDescription: ms-Exch-Logon-ACL
+oMSyntax: 66
+searchFlags: 0
+lDAPDisplayName: msExchLogonACL
+name: ms-Exch-Logon-ACL
+schemaIDGUID: 7acf216d-1f42-48ec-b1bb-6ca281fe5b00
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Logon-Method
+# Specifies the logon method for clear text logons.
+#
+dn: CN=ms-Exch-Logon-Method,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Logon-Method
+distinguishedName: CN=ms-Exch-Logon-Method,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15002
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Logon-Method
+adminDescription: ms-Exch-Logon-Method
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchLogonMethod
+name: ms-Exch-Logon-Method
+schemaIDGUID: 8bcc41ca-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Log-Filename
+#
+dn: CN=ms-Exch-Log-Filename,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Log-Filename
+distinguishedName: CN=ms-Exch-Log-Filename,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.192
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 256
+mAPIID: 32970
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Log-Filename
+adminDescription: ms-Exch-Log-Filename
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: logFilename
+name: ms-Exch-Log-Filename
+schemaIDGUID: a8df741d-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Log-Rollover-Interval
+#
+dn: CN=ms-Exch-Log-Rollover-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Log-Rollover-Interval
+distinguishedName: CN=ms-Exch-Log-Rollover-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.348
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32971
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Log-Rollover-Interval
+adminDescription: ms-Exch-Log-Rollover-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: logRolloverInterval
+name: ms-Exch-Log-Rollover-Interval
+schemaIDGUID: bf9679a7-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Log-Type
+# The log formats that this resource writes to.
+dn: CN=ms-Exch-Log-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Log-Type
+distinguishedName: CN=ms-Exch-Log-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2005
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Log-Type
+adminDescription: ms-Exch-Log-Type
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchLogType
+name: ms-Exch-Log-Type
+schemaIDGUID: a75a5784-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Mailbox-Folder-Set
+#
+dn: CN=ms-Exch-Mailbox-Folder-Set,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Folder-Set
+distinguishedName: CN=ms-Exch-Mailbox-Folder-Set,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11091
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Folder-Set
+adminDescription: ms-Exch-Mailbox-Folder-Set
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMailboxFolderSet
+name: ms-Exch-Mailbox-Folder-Set
+schemaIDGUID: d72941ba-ffd0-4d8e-bb85-97713440c8a3
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Guid
+# The GUID of the user's mailbox.
+#
+dn: CN=ms-Exch-Mailbox-Guid,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Guid
+distinguishedName: CN=ms-Exch-Mailbox-Guid,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11058
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 16
+rangeUpper: 16
+mAPIID: 35955
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Guid
+adminDescription: ms-Exch-Mailbox-Guid
+oMSyntax: 4
+searchFlags: 9
+lDAPDisplayName: msExchMailboxGuid
+name: ms-Exch-Mailbox-Guid
+schemaIDGUID: 9333af48-b09e-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Activation-Schedule
+# When the mailbox clean process should be started.
+#
+dn: CN=ms-Exch-Mailbox-Manager-Activation-Schedule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Activation-Schedule
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Activation-Schedule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50067
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 84
+rangeUpper: 84
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Activation-Schedule
+adminDescription: ms-Exch-Mailbox-Manager-Activation-Schedule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerActivationSchedule
+name: ms-Exch-Mailbox-Manager-Activation-Schedule
+schemaIDGUID: 829122d7-25b1-4be6-a2e3-d8453c950938
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Activation-Style
+#
+dn: CN=ms-Exch-Mailbox-Manager-Activation-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Activation-Style
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Activation-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50068
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Activation-Style
+adminDescription: ms-Exch-Mailbox-Manager-Activation-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerActivationStyle
+name: ms-Exch-Mailbox-Manager-Activation-Style
+schemaIDGUID: 9ea95949-7d74-49cd-af09-3db0870e535e
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Admin-Mode
+# The summary mode for this policy (MCASM_NONE, MCASM_SUMMARY_ONLY,
+# MCASM_DETAILED_REPORT).
+#
+dn: CN=ms-Exch-Mailbox-Manager-Admin-Mode,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Admin-Mode
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Admin-Mode,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50077
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Admin-Mode
+adminDescription: ms-Exch-Mailbox-Manager-Admin-Mode
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerAdminMode
+name: ms-Exch-Mailbox-Manager-Admin-Mode
+schemaIDGUID: 9a6b371e-a3e7-4266-9b7b-2ce454336f90
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Age-Limit
+# The age at which messages larger than the specified size limit are
+# deleted.
+#
+dn: CN=ms-Exch-Mailbox-Manager-Age-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Age-Limit
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Age-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50081
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Age-Limit
+adminDescription: ms-Exch-Mailbox-Manager-Age-Limit
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerAgeLimit
+name: ms-Exch-Mailbox-Manager-Age-Limit
+schemaIDGUID: cd63db2c-8aa9-4a14-941b-1b59fdcaafbd
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Custom-Message
+# Indicates that a custom message is being used.
+#
+dn: CN=ms-Exch-Mailbox-Manager-Custom-Message,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Custom-Message
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Custom-Message,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50070
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Custom-Message
+adminDescription: ms-Exch-Mailbox-Manager-Custom-Message
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerCustomMessage
+name: ms-Exch-Mailbox-Manager-Custom-Message
+schemaIDGUID: 8681f0bc-24d6-4d58-bc16-62f73cd5bedb
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Folder-Settings
+# Settings for each folder or store (Enabled, Folder-Name, Age-Limit,
+# Size-Limit). A limit of -1 should be interpreted as "Any".
+#
+dn: CN=ms-Exch-Mailbox-Manager-Folder-Settings,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Folder-Settings
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Folder-Settings,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50078
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Folder-Settings
+adminDescription: ms-Exch-Mailbox-Manager-Folder-Settings
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerFolderSettings
+name: ms-Exch-Mailbox-Manager-Folder-Settings
+schemaIDGUID: a57cf645-4b12-4ee4-a6eb-fce022068ffd
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Keep-Message-Classes
+# The message classes that should not be deleted.
+#
+dn: CN=ms-Exch-Mailbox-Manager-Keep-Message-Classes,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Keep-Message-Classes
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Keep-Message-Classes,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50074
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Keep-Message-Classes
+adminDescription: ms-Exch-Mailbox-Manager-Keep-Message-Classes
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerKeepMessageClasses
+name: ms-Exch-Mailbox-Manager-Keep-Message-Classes
+schemaIDGUID: 0044d40c-6a24-4b57-abce-f555cc724c8e
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Mode
+# Cleanup mode for this policy (MCACM_AUDIT,
+# MCACM_CLEANMCADM_DELETED_ITEMS, MCADM_SYSTEM_CLEANUP,
+# MCADM_JUST_DELETE).
+#
+dn: CN=ms-Exch-Mailbox-Manager-Mode,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Mode
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Mode,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50075
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Mode
+adminDescription: ms-Exch-Mailbox-Manager-Mode
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerMode
+name: ms-Exch-Mailbox-Manager-Mode
+schemaIDGUID: 9bd7499b-282b-4eb6-a40e-7d044d896741
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Report-Recipient
+# The recipient of summary reports.
+#
+dn: CN=ms-Exch-Mailbox-Manager-Report-Recipient,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Report-Recipient
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Report-Recipient,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50076
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Report-Recipient
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Mailbox-Manager-Report-Recipient
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerReportRecipient
+name: ms-Exch-Mailbox-Manager-Report-Recipient
+schemaIDGUID: 445791fb-e6fc-48dd-aad5-32e32c9059d9
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Send-User-Notification-Mail
+# Sends a notification to the user after a clean operation.
+#
+dn: CN=ms-Exch-Mailbox-Manager-Send-User-Notification-Mail,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Send-User-Notification-Mail
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Send-User-Notification-Mail,CN=S
+attributeID: 1.2.840.113556.1.4.7000.102.50069
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Send-User-Notification-Mail
+adminDescription: ms-Exch-Mailbox-Manager-Send-User-Notification-Mail
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerSendUserNotificationMail
+name: ms-Exch-Mailbox-Manager-Send-User-Notification-Mail
+schemaIDGUID: d2888db3-2b0d-4d6a-831e-4efdfc036584
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Size-Limit
+# Messages larger than this size will be deleted automatically when
+# their age exceeds the age limit.
+#
+dn: CN=ms-Exch-Mailbox-Manager-Size-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Size-Limit
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Size-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50080
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Size-Limit
+adminDescription: ms-Exch-Mailbox-Manager-Size-Limit
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerSizeLimit
+name: ms-Exch-Mailbox-Manager-Size-Limit
+schemaIDGUID: 92d9302b-76bd-4156-95a1-f5b6a1463eb4
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-Size-Limit-Enabled
+# Determines if a size limit is in effect.
+#
+dn: CN=ms-Exch-Mailbox-Manager-Size-Limit-Enabled,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-Size-Limit-Enabled
+distinguishedName: CN=ms-Exch-Mailbox-Manager-Size-Limit-Enabled,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50079
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-Size-Limit-Enabled
+adminDescription: ms-Exch-Mailbox-Manager-Size-Limit-Enabled
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerSizeLimitEnabled
+name: ms-Exch-Mailbox-Manager-Size-Limit-Enabled
+schemaIDGUID: 1563eae5-3ac1-4274-9e59-7d2fcc836f82
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-User-Message-Body
+# The mail notification message body.
+#
+dn: CN=ms-Exch-Mailbox-Manager-User-Message-Body,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-User-Message-Body
+distinguishedName: CN=ms-Exch-Mailbox-Manager-User-Message-Body,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50072
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-User-Message-Body
+adminDescription: ms-Exch-Mailbox-Manager-User-Message-Body
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerUserMessageBody
+name: ms-Exch-Mailbox-Manager-User-Message-Body
+schemaIDGUID: 9ec3ccac-09fa-4a22-869f-9144258d230d
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-User-Message-Footer
+# The mail notification message footer.
+#
+dn: CN=ms-Exch-Mailbox-Manager-User-Message-Footer,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-User-Message-Footer
+distinguishedName: CN=ms-Exch-Mailbox-Manager-User-Message-Footer,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50073
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-User-Message-Footer
+adminDescription: ms-Exch-Mailbox-Manager-User-Message-Footer
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerUserMessageFooter
+name: ms-Exch-Mailbox-Manager-User-Message-Footer
+schemaIDGUID: 33795abb-57ba-43ec-9f7e-a4601c2e4d4f
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Manager-User-Message-Header
+# The mail notification message header.
+#
+dn: CN=ms-Exch-Mailbox-Manager-User-Message-Header,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Manager-User-Message-Header
+distinguishedName: CN=ms-Exch-Mailbox-Manager-User-Message-Header,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50071
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Manager-User-Message-Header
+adminDescription: ms-Exch-Mailbox-Manager-User-Message-Header
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMailboxManagerUserMessageHeader
+name: ms-Exch-Mailbox-Manager-User-Message-Header
+schemaIDGUID: fbcffefe-8916-4ce6-ac76-eab226fe5440
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Retention-Period
+# The number of days to retain deleted mailboxes before purging them.
+#
+dn: CN=ms-Exch-Mailbox-Retention-Period,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Retention-Period
+distinguishedName: CN=ms-Exch-Mailbox-Retention-Period,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11060
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Retention-Period
+adminDescription: ms-Exch-Mailbox-Retention-Period
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMailboxRetentionPeriod
+name: ms-Exch-Mailbox-Retention-Period
+schemaIDGUID: 7b4a7a8a-1876-11d3-aa59-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Security-Descriptor
+# The security descriptor of the user's mailbox.
+#
+dn: CN=ms-Exch-Mailbox-Security-Descriptor,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Security-Descriptor
+distinguishedName: CN=ms-Exch-Mailbox-Security-Descriptor,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.80
+attributeSyntax: 2.5.5.15
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 65535
+mAPIID: 35956
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Security-Descriptor
+adminDescription: ms-Exch-Mailbox-Security-Descriptor
+oMSyntax: 66
+searchFlags: 8
+lDAPDisplayName: msExchMailboxSecurityDescriptor
+name: ms-Exch-Mailbox-Security-Descriptor
+schemaIDGUID: 934de926-b09e-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mailbox-Url
+# The URL to a user's mailbox.
+#
+dn: CN=ms-Exch-Mailbox-Url,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mailbox-Url
+distinguishedName: CN=ms-Exch-Mailbox-Url,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50085
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+mAPIID: 35967
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mailbox-Url
+adminDescription: ms-Exch-Mailbox-Url
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMailboxUrl
+name: ms-Exch-Mailbox-Url
+schemaIDGUID: fc1ffd10-ae3f-466c-87c7-518b91dadbd0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mail-Nickname
+#
+dn: CN=ms-Exch-Mail-Nickname,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mail-Nickname
+distinguishedName: CN=ms-Exch-Mail-Nickname,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.447
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 14848
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mail-Nickname
+adminDescription: ms-Exch-Mail-Nickname
+oMSyntax: 64
+searchFlags: 5
+lDAPDisplayName: mailNickname
+name: ms-Exch-Mail-Nickname
+schemaIDGUID: bf9679b3-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Maintenance-Schedule
+#
+dn: CN=ms-Exch-Maintenance-Schedule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Maintenance-Schedule
+distinguishedName: CN=ms-Exch-Maintenance-Schedule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1029
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 84
+rangeUpper: 84
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Maintenance-Schedule
+adminDescription: ms-Exch-Maintenance-Schedule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchMaintenanceSchedule
+name: ms-Exch-Maintenance-Schedule
+schemaIDGUID: 8fa76ef0-25d7-11d3-aa68-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Maintenance-Style
+#
+dn: CN=ms-Exch-Maintenance-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Maintenance-Style
+distinguishedName: CN=ms-Exch-Maintenance-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1030
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Maintenance-Style
+adminDescription: ms-Exch-Maintenance-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaintenanceStyle
+name: ms-Exch-Maintenance-Style
+schemaIDGUID: 8fa76ef6-25d7-11d3-aa68-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mandatory-Attributes
+#
+dn: CN=ms-Exch-Mandatory-Attributes,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mandatory-Attributes
+distinguishedName: CN=ms-Exch-Mandatory-Attributes,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50029
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mandatory-Attributes
+adminDescription: ms-Exch-Mandatory-Attributes
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMandatoryAttributes
+name: ms-Exch-Mandatory-Attributes
+schemaIDGUID: e32977be-1d31-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MAPI-Recipient
+#
+dn: CN=ms-Exch-MAPI-Recipient,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MAPI-Recipient
+distinguishedName: CN=ms-Exch-MAPI-Recipient,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.371
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 14912
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MAPI-Recipient
+adminDescription: ms-Exch-MAPI-Recipient
+oMSyntax: 1
+searchFlags: 16
+lDAPDisplayName: mAPIRecipient
+name: ms-Exch-MAPI-Recipient
+schemaIDGUID: bf9679b8-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Master-Account-Sid
+#
+dn: CN=ms-Exch-Master-Account-Sid,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Master-Account-Sid
+distinguishedName: CN=ms-Exch-Master-Account-Sid,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.81
+attributeSyntax: 2.5.5.17
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 28
+mAPIID: 35957
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Master-Account-Sid
+adminDescription: ms-Exch-Master-Account-Sid
+oMSyntax: 4
+searchFlags: 9
+lDAPDisplayName: msExchMasterAccountSid
+name: ms-Exch-Master-Account-Sid
+schemaIDGUID: 936a855e-b09e-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Master-Service
+# The Address List Service master server.
+#
+dn: CN=ms-Exch-Master-Service,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Master-Service
+distinguishedName: CN=ms-Exch-Master-Service,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.82
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1022
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Master-Service
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Master-Service
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchMasterService
+name: ms-Exch-Master-Service
+schemaIDGUID: 944d04c4-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Master-Service-BL
+# A backlink to the Address List Service master server.
+#
+dn: CN=ms-Exch-Master-Service-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Master-Service-BL
+distinguishedName: CN=ms-Exch-Master-Service-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.83
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1023
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Master-Service-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Master-Service-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchMasterServiceBL
+name: ms-Exch-Master-Service-BL
+schemaIDGUID: 946c0356-b09e-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Maximum-Object-ID
+#
+dn: CN=ms-Exch-Maximum-Object-ID,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Maximum-Object-ID
+distinguishedName: CN=ms-Exch-Maximum-Object-ID,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.458
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 22
+mAPIID: 33129
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Maximum-Object-ID
+adminDescription: ms-Exch-Maximum-Object-ID
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: maximumObjectID
+name: ms-Exch-Maximum-Object-ID
+schemaIDGUID: a8df741e-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Maximum-Recurring-Instances
+# The maximum number of instances generated per day.
+#
+dn: CN=ms-Exch-Maximum-Recurring-Instances,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Maximum-Recurring-Instances
+distinguishedName: CN=ms-Exch-Maximum-Recurring-Instances,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.10014
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Maximum-Recurring-Instances
+adminDescription: ms-Exch-Maximum-Recurring-Instances
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaximumRecurringInstances
+name: ms-Exch-Maximum-Recurring-Instances
+schemaIDGUID: a8b8d132-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Maximum-Recurring-Instances-Months
+# The maximum window of instances (months) generated by the store
+# expansion agent.
+#
+dn: CN=ms-Exch-Maximum-Recurring-Instances-Months,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Maximum-Recurring-Instances-Months
+distinguishedName: CN=ms-Exch-Maximum-Recurring-Instances-Months,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.10015
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Maximum-Recurring-Instances-Months
+adminDescription: ms-Exch-Maximum-Recurring-Instances-Months
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaximumRecurringInstancesMonths
+name: ms-Exch-Maximum-Recurring-Instances-Months
+schemaIDGUID: a8da321e-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Max-Cached-Views
+# The maximum number of restricted views cached for any given folder
+# in the MDB.
+#
+dn: CN=ms-Exch-Max-Cached-Views,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Max-Cached-Views
+distinguishedName: CN=ms-Exch-Max-Cached-Views,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11083
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Max-Cached-Views
+adminDescription: ms-Exch-Max-Cached-Views
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaxCachedViews
+name: ms-Exch-Max-Cached-Views
+schemaIDGUID: 1529cf69-2fdb-11d3-aa6d-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Max-Connections
+# Defines the maximum allowed connections.
+#
+dn: CN=ms-Exch-Max-Connections,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Max-Connections
+distinguishedName: CN=ms-Exch-Max-Connections,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9013
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Max-Connections
+adminDescription: ms-Exch-Max-Connections
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaxConnections
+name: ms-Exch-Max-Connections
+schemaIDGUID: a7c33efc-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Max-Extension-Time
+# The maximum minutes a video conference can be extended.
+#
+dn: CN=ms-Exch-Max-Extension-Time,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Max-Extension-Time
+distinguishedName: CN=ms-Exch-Max-Extension-Time,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9028
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Max-Extension-Time
+adminDescription: ms-Exch-Max-Extension-Time
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaxExtensionTime
+name: ms-Exch-Max-Extension-Time
+schemaIDGUID: 99f58668-12e8-11d3-aa58-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Max-Incoming-Connections
+# The maximum number of incoming connections allowed for this
+# resource.
+#
+dn: CN=ms-Exch-Max-Incoming-Connections,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Max-Incoming-Connections
+distinguishedName: CN=ms-Exch-Max-Incoming-Connections,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2004
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Max-Incoming-Connections
+adminDescription: ms-Exch-Max-Incoming-Connections
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaxIncomingConnections
+name: ms-Exch-Max-Incoming-Connections
+schemaIDGUID: a808632e-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Max-Participants
+# The maximum number of participants allowed in a video conference.
+#
+dn: CN=ms-Exch-Max-Participants,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Max-Participants
+distinguishedName: CN=ms-Exch-Max-Participants,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9027
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Max-Participants
+adminDescription: ms-Exch-Max-Participants
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaxParticipants
+name: ms-Exch-Max-Participants
+schemaIDGUID: 99f58663-12e8-11d3-aa58-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Max-Pool-Threads
+#
+dn: CN=ms-Exch-Max-Pool-Threads,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Max-Pool-Threads
+distinguishedName: CN=ms-Exch-Max-Pool-Threads,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11041
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Max-Pool-Threads
+adminDescription: ms-Exch-Max-Pool-Threads
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaxPoolThreads
+name: ms-Exch-Max-Pool-Threads
+schemaIDGUID: a82e88ce-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Max-Restore-Storage-Groups
+#
+dn: CN=ms-Exch-Max-Restore-Storage-Groups,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Max-Restore-Storage-Groups
+distinguishedName: CN=ms-Exch-Max-Restore-Storage-Groups,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11095
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Max-Restore-Storage-Groups
+adminDescription: ms-Exch-Max-Restore-Storage-Groups
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaxRestoreStorageGroups
+name: ms-Exch-Max-Restore-Storage-Groups
+schemaIDGUID: 3ef2a80e-ea82-421b-8a62-a12543c34141
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Max-Storage-Groups
+# The maximum number of Jet instances allowed on this computer.
+#
+dn: CN=ms-Exch-Max-Storage-Groups,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Max-Storage-Groups
+distinguishedName: CN=ms-Exch-Max-Storage-Groups,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11027
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Max-Storage-Groups
+adminDescription: ms-Exch-Max-Storage-Groups
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaxStorageGroups
+name: ms-Exch-Max-Storage-Groups
+schemaIDGUID: a84fe9ba-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Max-Stores-Per-Group
+# The maximum number of stores allowed per Jet instance on this
+# computer.
+#
+dn: CN=ms-Exch-Max-Stores-Per-Group,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Max-Stores-Per-Group
+distinguishedName: CN=ms-Exch-Max-Stores-Per-Group,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11028
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Max-Stores-Per-Group
+adminDescription: ms-Exch-Max-Stores-Per-Group
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaxStoresPerGroup
+name: ms-Exch-Max-Stores-Per-Group
+schemaIDGUID: a8714aa6-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Max-Threads
+# The maximum remote procedure call (RPC) threads for the server.
+#
+dn: CN=ms-Exch-Max-Threads,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Max-Threads
+distinguishedName: CN=ms-Exch-Max-Threads,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11042
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Max-Threads
+adminDescription: ms-Exch-Max-Threads
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMaxThreads
+name: ms-Exch-Max-Threads
+schemaIDGUID: a8950dec-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MCU-Hosts-Sites
+# A forward link to Microsoft® Windows® sites supported by the
+# specified multipoint control unit (MCU).
+#
+dn: CN=ms-Exch-MCU-Hosts-Sites,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MCU-Hosts-Sites
+distinguishedName: CN=ms-Exch-MCU-Hosts-Sites,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9031
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1038
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MCU-Hosts-Sites
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-MCU-Hosts-Sites
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchMCUHostsSites
+name: ms-Exch-MCU-Hosts-Sites
+schemaIDGUID: bd062bc7-ce32-4690-8b8e-5c63b816b516
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MCU-Hosts-Sites-BL
+# A backlink to Microsoft® Windows® sites supported by the specified multipoint control unit (MCU).
+#
+dn: CN=ms-Exch-MCU-Hosts-Sites-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MCU-Hosts-Sites-BL
+distinguishedName: CN=ms-Exch-MCU-Hosts-Sites-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9032
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1039
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MCU-Hosts-Sites-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-MCU-Hosts-Sites-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchMCUHostsSitesBL
+name: ms-Exch-MCU-Hosts-Sites-BL
+schemaIDGUID: b0ab8d77-2486-467d-a331-3e3524438a57
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MDB-Backoff-Interval
+#
+dn: CN=ms-Exch-MDB-Backoff-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MDB-Backoff-Interval
+distinguishedName: CN=ms-Exch-MDB-Backoff-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.72
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32975
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MDB-Backoff-Interval
+adminDescription: ms-Exch-MDB-Backoff-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: mDBBackoffInterval
+name: ms-Exch-MDB-Backoff-Interval
+schemaIDGUID: a8df741f-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-MDB-Msg-Time-Out-Period
+#
+dn: CN=ms-Exch-MDB-Msg-Time-Out-Period,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MDB-Msg-Time-Out-Period
+distinguishedName: CN=ms-Exch-MDB-Msg-Time-Out-Period,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.64
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32976
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MDB-Msg-Time-Out-Period
+adminDescription: ms-Exch-MDB-Msg-Time-Out-Period
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: mDBMsgTimeOutPeriod
+name: ms-Exch-MDB-Msg-Time-Out-Period
+schemaIDGUID: a8df7420-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-MDB-Over-Hard-Quota-Limit
+# The default size limit after which messages can no longer be sent or
+# received.
+#
+dn: CN=ms-Exch-MDB-Over-Hard-Quota-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MDB-Over-Hard-Quota-Limit
+distinguishedName: CN=ms-Exch-MDB-Over-Hard-Quota-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11037
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MDB-Over-Hard-Quota-Limit
+adminDescription: ms-Exch-MDB-Over-Hard-Quota-Limit
+oMSyntax: 2
+searchFlags: 16
+lDAPDisplayName: mDBOverHardQuotaLimit
+name: ms-Exch-MDB-Over-Hard-Quota-Limit
+schemaIDGUID: 8fcf1ec4-b093-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MDB-Over-Quota-Limit
+#
+dn: CN=ms-Exch-MDB-Over-Quota-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MDB-Over-Quota-Limit
+distinguishedName: CN=ms-Exch-MDB-Over-Quota-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.272
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32977
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MDB-Over-Quota-Limit
+adminDescription: ms-Exch-MDB-Over-Quota-Limit
+oMSyntax: 2
+searchFlags: 16
+lDAPDisplayName: mDBOverQuotaLimit
+name: ms-Exch-MDB-Over-Quota-Limit
+schemaIDGUID: f0f8ff91-1191-11d0-a060-00aa006c33ed
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-MDB-Storage-Quota
+#
+dn: CN=ms-Exch-MDB-Storage-Quota,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MDB-Storage-Quota
+distinguishedName: CN=ms-Exch-MDB-Storage-Quota,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.266
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32978
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MDB-Storage-Quota
+adminDescription: ms-Exch-MDB-Storage-Quota
+oMSyntax: 2
+searchFlags: 16
+lDAPDisplayName: mDBStorageQuota
+name: ms-Exch-MDB-Storage-Quota
+schemaIDGUID: f0f8ff92-1191-11d0-a060-00aa006c33ed
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-MDB-Unread-Limit
+#
+dn: CN=ms-Exch-MDB-Unread-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MDB-Unread-Limit
+distinguishedName: CN=ms-Exch-MDB-Unread-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.69
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32979
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MDB-Unread-Limit
+adminDescription: ms-Exch-MDB-Unread-Limit
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: mDBUnreadLimit
+name: ms-Exch-MDB-Unread-Limit
+schemaIDGUID: a8df7421-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MDB-Use-Defaults
+#
+dn: CN=ms-Exch-MDB-Use-Defaults,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MDB-Use-Defaults
+distinguishedName: CN=ms-Exch-MDB-Use-Defaults,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.309
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32980
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MDB-Use-Defaults
+adminDescription: ms-Exch-MDB-Use-Defaults
+oMSyntax: 1
+searchFlags: 16
+lDAPDisplayName: mDBUseDefaults
+name: ms-Exch-MDB-Use-Defaults
+schemaIDGUID: f0f8ff93-1191-11d0-a060-00aa006c33ed
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Member-Base-DN
+# Contains the base of the LDAP search that should be used to compute
+# this dynamic DL.
+#
+dn: CN=ms-Exch-Member-Base-DN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Member-Base-DN
+distinguishedName: CN=ms-Exch-Member-Base-DN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12524
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Member-Base-DN
+adminDescription: ms-Exch-Member-Base-DN
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchMemberBaseDN
+name: ms-Exch-Member-Base-DN
+schemaIDGUID: a921b8aa-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Member-Filter
+# The LDAP search filter used to generate this dynamic DL.
+#
+dn: CN=ms-Exch-Member-Filter,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Member-Filter
+distinguishedName: CN=ms-Exch-Member-Filter,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12522
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Member-Filter
+adminDescription: ms-Exch-Member-Filter
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchMemberFilter
+name: ms-Exch-Member-Filter
+schemaIDGUID: a9457bf0-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Message-Journal-Recipient
+# A pointer to the mailbox that should get a journal (copy) of all
+# messages sent on this mailbox store.
+#
+dn: CN=ms-Exch-Message-Journal-Recipient,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Message-Journal-Recipient
+distinguishedName: CN=ms-Exch-Message-Journal-Recipient,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5055
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Message-Journal-Recipient
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Message-Journal-Recipient
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchMessageJournalRecipient
+name: ms-Exch-Message-Journal-Recipient
+schemaIDGUID: a95fee9d-b634-41e9-8f8c-d3d9ac1d5941
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Message-Size-Limit
+#
+dn: CN=ms-Exch-Message-Size-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Message-Size-Limit
+distinguishedName: CN=ms-Exch-Message-Size-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.100
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32925
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Message-Size-Limit
+adminDescription: ms-Exch-Message-Size-Limit
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: messageSizeLimit
+name: ms-Exch-Message-Size-Limit
+schemaIDGUID: 167757e2-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Message-Tracking-Enabled
+#
+dn: CN=ms-Exch-Message-Tracking-Enabled,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Message-Tracking-Enabled
+distinguishedName: CN=ms-Exch-Message-Tracking-Enabled,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.453
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32981
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Message-Tracking-Enabled
+adminDescription: ms-Exch-Message-Tracking-Enabled
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: messageTrackingEnabled
+name: ms-Exch-Message-Tracking-Enabled
+schemaIDGUID: a8df7422-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Message-Track-Log-Filter
+# Defines the filter for the fields in the message tracking log. Each
+# bit controls a field.
+#
+dn: CN=ms-Exch-Message-Track-Log-Filter,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Message-Track-Log-Filter
+distinguishedName: CN=ms-Exch-Message-Track-Log-Filter,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50001
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Message-Track-Log-Filter
+adminDescription: ms-Exch-Message-Track-Log-Filter
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMessageTrackLogFilter
+name: ms-Exch-Message-Track-Log-Filter
+schemaIDGUID: a9647a82-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mime-Types
+#
+dn: CN=ms-Exch-Mime-Types,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mime-Types
+distinguishedName: CN=ms-Exch-Mime-Types,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.550
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 10240
+mAPIID: 35868
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mime-Types
+adminDescription: ms-Exch-Mime-Types
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchMimeTypes
+name: ms-Exch-Mime-Types
+schemaIDGUID: 8addd6a2-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Minimum-Threads
+# The minimum RPC threads for the server.
+#
+dn: CN=ms-Exch-Minimum-Threads,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Minimum-Threads
+distinguishedName: CN=ms-Exch-Minimum-Threads,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11043
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Minimum-Threads
+adminDescription: ms-Exch-Minimum-Threads
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMinimumThreads
+name: ms-Exch-Minimum-Threads
+schemaIDGUID: a9883dc8-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Min-Admin-Version
+#
+dn: CN=ms-Exch-Min-Admin-Version,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Min-Admin-Version
+distinguishedName: CN=ms-Exch-Min-Admin-Version,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50093
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Min-Admin-Version
+adminDescription: ms-Exch-Min-Admin-Version
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMinAdminVersion
+name: ms-Exch-Min-Admin-Version
+schemaIDGUID: 8fca497d-4ac7-4df4-b180-eec0bfef27df
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Mixed-Mode
+#
+dn: CN=ms-Exch-Mixed-Mode,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Mixed-Mode
+distinguishedName: CN=ms-Exch-Mixed-Mode,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50022
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Mixed-Mode
+adminDescription: ms-Exch-Mixed-Mode
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchMixedMode
+name: ms-Exch-Mixed-Mode
+schemaIDGUID: 8ddb297c-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitored-Configurations
+#
+dn: CN=ms-Exch-Monitored-Configurations,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitored-Configurations
+distinguishedName: CN=ms-Exch-Monitored-Configurations,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.198
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32985
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitored-Configurations
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Monitored-Configurations
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: monitoredConfigurations
+name: ms-Exch-Monitored-Configurations
+schemaIDGUID: bf9679c9-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitored-Servers
+#
+dn: CN=ms-Exch-Monitored-Servers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitored-Servers
+distinguishedName: CN=ms-Exch-Monitored-Servers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.179
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32986
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitored-Servers
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Monitored-Servers
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: monitoredServers
+name: ms-Exch-Monitored-Servers
+schemaIDGUID: a8df7426-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitored-Services
+#
+dn: CN=ms-Exch-Monitored-Services,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitored-Services
+distinguishedName: CN=ms-Exch-Monitored-Services,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.199
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 256
+mAPIID: 32987
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitored-Services
+adminDescription: ms-Exch-Monitored-Services
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: monitoredServices
+name: ms-Exch-Monitored-Services
+schemaIDGUID: bf9679ca-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Alert-Delay
+#
+dn: CN=ms-Exch-Monitoring-Alert-Delay,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Alert-Delay
+distinguishedName: CN=ms-Exch-Monitoring-Alert-Delay,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.158
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32988
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Alert-Delay
+adminDescription: ms-Exch-Monitoring-Alert-Delay
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: monitoringAlertDelay
+name: ms-Exch-Monitoring-Alert-Delay
+schemaIDGUID: a8df7427-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Alert-Units
+#
+dn: CN=ms-Exch-Monitoring-Alert-Units,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Alert-Units
+distinguishedName: CN=ms-Exch-Monitoring-Alert-Units,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.57
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 32989
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Alert-Units
+adminDescription: ms-Exch-Monitoring-Alert-Units
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: monitoringAlertUnits
+name: ms-Exch-Monitoring-Alert-Units
+schemaIDGUID: a8df7428-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Availability-Style
+#
+dn: CN=ms-Exch-Monitoring-Availability-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Availability-Style
+distinguishedName: CN=ms-Exch-Monitoring-Availability-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.450
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 3
+mAPIID: 32990
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Availability-Style
+adminDescription: ms-Exch-Monitoring-Availability-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: monitoringAvailabilityStyle
+name: ms-Exch-Monitoring-Availability-Style
+schemaIDGUID: bf9679cb-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Availability-Window
+#
+dn: CN=ms-Exch-Monitoring-Availability-Window,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Availability-Window
+distinguishedName: CN=ms-Exch-Monitoring-Availability-Window,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.200
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 84
+mAPIID: 32991
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Availability-Window
+adminDescription: ms-Exch-Monitoring-Availability-Window
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: monitoringAvailabilityWindow
+name: ms-Exch-Monitoring-Availability-Window
+schemaIDGUID: bf9679cc-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Monitoring-Cached-Via-Mail
+#
+dn: CN=ms-Exch-Monitoring-Cached-Via-Mail,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Cached-Via-Mail
+distinguishedName: CN=ms-Exch-Monitoring-Cached-Via-Mail,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.196
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32992
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Cached-Via-Mail
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Monitoring-Cached-Via-Mail
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: monitoringCachedViaMail
+name: ms-Exch-Monitoring-Cached-Via-Mail
+schemaIDGUID: bf9679cd-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Cached-Via-RPC
+#
+dn: CN=ms-Exch-Monitoring-Cached-Via-RPC,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Cached-Via-RPC
+distinguishedName: CN=ms-Exch-Monitoring-Cached-Via-RPC,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.197
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32993
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Cached-Via-RPC
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Monitoring-Cached-Via-RPC
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: monitoringCachedViaRPC
+name: ms-Exch-Monitoring-Cached-Via-RPC
+schemaIDGUID: bf9679ce-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Monitoring-Disk-Space
+#
+dn: CN=ms-Exch-Monitoring-Disk-Space,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Disk-Space
+distinguishedName: CN=ms-Exch-Monitoring-Disk-Space,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50046
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Disk-Space
+adminDescription: ms-Exch-Monitoring-Disk-Space
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMonitoringDiskSpace
+name: ms-Exch-Monitoring-Disk-Space
+schemaIDGUID: 0210cc37-34cf-11d3-aa6e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Escalation-Procedure
+#
+dn: CN=ms-Exch-Monitoring-Escalation-Procedure,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Escalation-Procedure
+distinguishedName: CN=ms-Exch-Monitoring-Escalation-Procedure,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.188
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 1064
+mAPIID: 32994
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Escalation-Procedure
+adminDescription: ms-Exch-Monitoring-Escalation-Procedure
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: monitoringEscalationProcedure
+name: ms-Exch-Monitoring-Escalation-Procedure
+schemaIDGUID: a8df7429-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Hotsite-Poll-Interval
+#
+dn: CN=ms-Exch-Monitoring-Hotsite-Poll-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Hotsite-Poll-Interval
+distinguishedName: CN=ms-Exch-Monitoring-Hotsite-Poll-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.186
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32995
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Hotsite-Poll-Interval
+adminDescription: ms-Exch-Monitoring-Hotsite-Poll-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: monitoringHotsitePollInterval
+name: ms-Exch-Monitoring-Hotsite-Poll-Interval
+schemaIDGUID: a8df742a-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Hotsite-Poll-Units
+#
+dn: CN=ms-Exch-Monitoring-Hotsite-Poll-Units,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Hotsite-Poll-Units
+distinguishedName: CN=ms-Exch-Monitoring-Hotsite-Poll-Units,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.87
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 32996
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Hotsite-Poll-Units
+adminDescription: ms-Exch-Monitoring-Hotsite-Poll-Units
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: monitoringHotsitePollUnits
+name: ms-Exch-Monitoring-Hotsite-Poll-Units
+schemaIDGUID: a8df742b-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Monitoring-Mail-Update-Interval
+#
+dn: CN=ms-Exch-Monitoring-Mail-Update-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Mail-Update-Interval
+distinguishedName: CN=ms-Exch-Monitoring-Mail-Update-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.195
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32997
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Mail-Update-Interval
+adminDescription: ms-Exch-Monitoring-Mail-Update-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: monitoringMailUpdateInterval
+name: ms-Exch-Monitoring-Mail-Update-Interval
+schemaIDGUID: bf9679cf-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Mail-Update-Units
+#
+dn: CN=ms-Exch-Monitoring-Mail-Update-Units,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Mail-Update-Units
+distinguishedName: CN=ms-Exch-Monitoring-Mail-Update-Units,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.93
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 32998
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Mail-Update-Units
+adminDescription: ms-Exch-Monitoring-Mail-Update-Units
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: monitoringMailUpdateUnits
+name: ms-Exch-Monitoring-Mail-Update-Units
+schemaIDGUID: bf9679d0-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Mode
+#
+dn: CN=ms-Exch-Monitoring-Mode,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Mode
+distinguishedName: CN=ms-Exch-Monitoring-Mode,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50060
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Mode
+adminDescription: ms-Exch-Monitoring-Mode
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMonitoringMode
+name: ms-Exch-Monitoring-Mode
+schemaIDGUID: e520be0a-d2ea-449b-9177-caaadec1a4c6
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Monitoring-Monitored-Services
+#
+dn: CN=ms-Exch-Monitoring-Monitored-Services,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Monitored-Services
+distinguishedName: CN=ms-Exch-Monitoring-Monitored-Services,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50045
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Monitored-Services
+adminDescription: ms-Exch-Monitoring-Monitored-Services
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMonitoringMonitoredServices
+name: ms-Exch-Monitoring-Monitored-Services
+schemaIDGUID: 0210cc30-34cf-11d3-aa6e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Monitoring-Normal-Poll-Interval
+#
+dn: CN=ms-Exch-Monitoring-Normal-Poll-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Normal-Poll-Interval
+distinguishedName: CN=ms-Exch-Monitoring-Normal-Poll-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.187
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 32999
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Normal-Poll-Interval
+adminDescription: ms-Exch-Monitoring-Normal-Poll-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: monitoringNormalPollInterval
+name: ms-Exch-Monitoring-Normal-Poll-Interval
+schemaIDGUID: a8df742c-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Normal-Poll-Units
+#
+dn: CN=ms-Exch-Monitoring-Normal-Poll-Units,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Normal-Poll-Units
+distinguishedName: CN=ms-Exch-Monitoring-Normal-Poll-Units,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.88
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 33000
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Normal-Poll-Units
+adminDescription: ms-Exch-Monitoring-Normal-Poll-Units
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: monitoringNormalPollUnits
+name: ms-Exch-Monitoring-Normal-Poll-Units
+schemaIDGUID: a8df742d-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Notification-Rate
+# How frequently the MAD should check whether a notification (such as
+# a mail or page) should be sent.
+#
+dn: CN=ms-Exch-Monitoring-Notification-Rate,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Notification-Rate
+distinguishedName: CN=ms-Exch-Monitoring-Notification-Rate,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50057
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Notification-Rate
+adminDescription: ms-Exch-Monitoring-Notification-Rate
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMonitoringNotificationRate
+name: ms-Exch-Monitoring-Notification-Rate
+schemaIDGUID: 8bf11686-fb18-4147-95e4-f43f8c9de87d
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Monitoring-Polling-Rate
+# The set of polling rates for each of the types of monitored
+# resources (such as queues, CPU, and disk). The syntax of each of the
+# entries will be: [TYPE],[RATE as Seconds].
+#
+dn: CN=ms-Exch-Monitoring-Polling-Rate,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Polling-Rate
+distinguishedName: CN=ms-Exch-Monitoring-Polling-Rate,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50058
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Polling-Rate
+adminDescription: ms-Exch-Monitoring-Polling-Rate
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMonitoringPollingRate
+name: ms-Exch-Monitoring-Polling-Rate
+schemaIDGUID: a3af17a5-b2bf-442c-bd04-83dcedb19ea4
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Queue-Polling-Frequency
+#
+dn: CN=ms-Exch-Monitoring-Queue-Polling-Frequency,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Queue-Polling-Frequency
+distinguishedName: CN=ms-Exch-Monitoring-Queue-Polling-Frequency,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50038
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Queue-Polling-Frequency
+adminDescription: ms-Exch-Monitoring-Queue-Polling-Frequency
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMonitoringQueuePollingFrequency
+name: ms-Exch-Monitoring-Queue-Polling-Frequency
+schemaIDGUID: 501b8818-29ae-11d3-aa69-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Monitoring-Queue-Polling-Interval
+#
+dn: CN=ms-Exch-Monitoring-Queue-Polling-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Queue-Polling-Interval
+distinguishedName: CN=ms-Exch-Monitoring-Queue-Polling-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50037
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Queue-Polling-Interval
+adminDescription: ms-Exch-Monitoring-Queue-Polling-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchMonitoringQueuePollingInterval
+name: ms-Exch-Monitoring-Queue-Polling-Interval
+schemaIDGUID: 501b880f-29ae-11d3-aa69-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Monitoring-Recipients
+#
+dn: CN=ms-Exch-Monitoring-Recipients,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Recipients
+distinguishedName: CN=ms-Exch-Monitoring-Recipients,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.159
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 33001
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Recipients
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Monitoring-Recipients
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: monitoringRecipients
+name: ms-Exch-Monitoring-Recipients
+schemaIDGUID: a8df742e-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Recipients-NDR
+#
+dn: CN=ms-Exch-Monitoring-Recipients-NDR,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Recipients-NDR
+distinguishedName: CN=ms-Exch-Monitoring-Recipients-NDR,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.387
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 33002
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Recipients-NDR
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Monitoring-Recipients-NDR
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: monitoringRecipientsNDR
+name: ms-Exch-Monitoring-Recipients-NDR
+schemaIDGUID: a8df742f-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Resources
+# The set of monitored resources (such as queues, CPU, and disk). The
+# general syntax of each of the entries will be: TYPE, ID, [Warning
+# value], [Error value]. Some TYPEs may need different formats.
+#
+dn: CN=ms-Exch-Monitoring-Resources,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Resources
+distinguishedName: CN=ms-Exch-Monitoring-Resources,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50059
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Resources
+adminDescription: ms-Exch-Monitoring-Resources
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMonitoringResources
+name: ms-Exch-Monitoring-Resources
+schemaIDGUID: c1293ac0-b228-4b41-9409-2ca7d0c19459
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Responses
+#
+dn: CN=ms-Exch-Monitoring-Responses,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Responses
+distinguishedName: CN=ms-Exch-Monitoring-Responses,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50047
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Responses
+adminDescription: ms-Exch-Monitoring-Responses
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMonitoringResponses
+name: ms-Exch-Monitoring-Responses
+schemaIDGUID: 0210cc43-34cf-11d3-aa6e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-RPC-Update-Interval
+#
+dn: CN=ms-Exch-Monitoring-RPC-Update-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-RPC-Update-Interval
+distinguishedName: CN=ms-Exch-Monitoring-RPC-Update-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.92
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33003
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-RPC-Update-Interval
+adminDescription: ms-Exch-Monitoring-RPC-Update-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: monitoringRPCUpdateInterval
+name: ms-Exch-Monitoring-RPC-Update-Interval
+schemaIDGUID: bf9679d1-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-RPC-Update-Units
+#
+dn: CN=ms-Exch-Monitoring-RPC-Update-Units,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-RPC-Update-Units
+distinguishedName: CN=ms-Exch-Monitoring-RPC-Update-Units,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.89
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 33004
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-RPC-Update-Units
+adminDescription: ms-Exch-Monitoring-RPC-Update-Units
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: monitoringRPCUpdateUnits
+name: ms-Exch-Monitoring-RPC-Update-Units
+schemaIDGUID: bf9679d2-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Warning-Delay
+#
+dn: CN=ms-Exch-Monitoring-Warning-Delay,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Warning-Delay
+distinguishedName: CN=ms-Exch-Monitoring-Warning-Delay,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.157
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33005
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Warning-Delay
+adminDescription: ms-Exch-Monitoring-Warning-Delay
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: monitoringWarningDelay
+name: ms-Exch-Monitoring-Warning-Delay
+schemaIDGUID: a8df7430-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitoring-Warning-Units
+#
+dn: CN=ms-Exch-Monitoring-Warning-Units,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitoring-Warning-Units
+distinguishedName: CN=ms-Exch-Monitoring-Warning-Units,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.56
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 33006
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitoring-Warning-Units
+adminDescription: ms-Exch-Monitoring-Warning-Units
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: monitoringWarningUnits
+name: ms-Exch-Monitoring-Warning-Units
+schemaIDGUID: a8df7431-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitor-Clock
+#
+dn: CN=ms-Exch-Monitor-Clock,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitor-Clock
+distinguishedName: CN=ms-Exch-Monitor-Clock,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.163
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32982
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitor-Clock
+adminDescription: ms-Exch-Monitor-Clock
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: monitorClock
+name: ms-Exch-Monitor-Clock
+schemaIDGUID: a8df7423-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitor-Servers
+#
+dn: CN=ms-Exch-Monitor-Servers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitor-Servers
+distinguishedName: CN=ms-Exch-Monitor-Servers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.156
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32983
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitor-Servers
+adminDescription: ms-Exch-Monitor-Servers
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: monitorServers
+name: ms-Exch-Monitor-Servers
+schemaIDGUID: a8df7424-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Monitor-Services
+#
+dn: CN=ms-Exch-Monitor-Services,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Monitor-Services
+distinguishedName: CN=ms-Exch-Monitor-Services,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.160
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 32984
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Monitor-Services
+adminDescription: ms-Exch-Monitor-Services
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: monitorServices
+name: ms-Exch-Monitor-Services
+schemaIDGUID: a8df7425-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Move-To-LSA
+#
+dn: CN=ms-Exch-Move-To-LSA,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Move-To-LSA
+distinguishedName: CN=ms-Exch-Move-To-LSA,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.88
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Move-To-LSA
+adminDescription: ms-Exch-Move-To-LSA
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchMoveToLSA
+name: ms-Exch-Move-To-LSA
+schemaIDGUID: ab4cc53c-4ba4-11d3-aa75-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-MTA-Database-Path
+#
+dn: CN=ms-Exch-MTA-Database-Path,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MTA-Database-Path
+distinguishedName: CN=ms-Exch-MTA-Database-Path,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.18001
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MTA-Database-Path
+adminDescription: ms-Exch-MTA-Database-Path
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchMTADatabasePath
+name: ms-Exch-MTA-Database-Path
+schemaIDGUID: 2f2dc2a4-242e-11d3-aa66-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MTA-Local-Cred
+#
+dn: CN=ms-Exch-MTA-Local-Cred,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MTA-Local-Cred
+distinguishedName: CN=ms-Exch-MTA-Local-Cred,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.270
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 33007
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MTA-Local-Cred
+adminDescription: ms-Exch-MTA-Local-Cred
+oMSyntax: 22
+searchFlags: 0
+lDAPDisplayName: mTALocalCred
+name: ms-Exch-MTA-Local-Cred
+schemaIDGUID: a8df7432-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-MTA-Local-Desig
+#
+dn: CN=ms-Exch-MTA-Local-Desig,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-MTA-Local-Desig
+distinguishedName: CN=ms-Exch-MTA-Local-Desig,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.271
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 33008
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-MTA-Local-Desig
+adminDescription: ms-Exch-MTA-Local-Desig
+oMSyntax: 22
+searchFlags: 0
+lDAPDisplayName: mTALocalDesig
+name: ms-Exch-MTA-Local-Desig
+schemaIDGUID: a8df7433-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Non-Authoritative-Domains
+#
+dn: CN=ms-Exch-Non-Authoritative-Domains,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Non-Authoritative-Domains
+distinguishedName: CN=ms-Exch-Non-Authoritative-Domains,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50084
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 1123
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Non-Authoritative-Domains
+adminDescription: ms-Exch-Non-Authoritative-Domains
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNonAuthoritativeDomains
+name: ms-Exch-Non-Authoritative-Domains
+schemaIDGUID: ef2c7c70-f874-4280-8643-2334f2d3340c
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Non-MIME-Character-Set
+#
+dn: CN=ms-Exch-Non-MIME-Character-Set,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Non-MIME-Character-Set
+distinguishedName: CN=ms-Exch-Non-MIME-Character-Set,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50043
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Non-MIME-Character-Set
+adminDescription: ms-Exch-Non-MIME-Character-Set
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNonMIMECharacterSet
+name: ms-Exch-Non-MIME-Character-Set
+schemaIDGUID: 974c99fe-33fc-11d3-aa6e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Connector-Mailbox
+# Name of the Lotus Notes mailbox where the connector picks up mail
+# from Notes for delivery into Exchange.
+#
+dn: CN=ms-Exch-Notes-Connector-Mailbox,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Connector-Mailbox
+distinguishedName: CN=ms-Exch-Notes-Connector-Mailbox,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1014
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Connector-Mailbox
+adminDescription: ms-Exch-Notes-Connector-Mailbox
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesConnectorMailbox
+name: ms-Exch-Notes-Connector-Mailbox
+schemaIDGUID: aa5a0cb8-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Exclude-Groups
+# A list of Lotus Notes groups to exclude from directory
+# synchronization.
+#
+dn: CN=ms-Exch-Notes-Exclude-Groups,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Exclude-Groups
+distinguishedName: CN=ms-Exch-Notes-Exclude-Groups,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1022
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Exclude-Groups
+adminDescription: ms-Exch-Notes-Exclude-Groups
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesExcludeGroups
+name: ms-Exch-Notes-Exclude-Groups
+schemaIDGUID: 0c74acba-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Export-Groups
+# A flag indicating whether Lotus Notes groups should be exported to
+# Exchange during directory synchronization.
+#
+dn: CN=ms-Exch-Notes-Export-Groups,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Export-Groups
+distinguishedName: CN=ms-Exch-Notes-Export-Groups,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1021
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Export-Groups
+adminDescription: ms-Exch-Notes-Export-Groups
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchNotesExportGroups
+name: ms-Exch-Notes-Export-Groups
+schemaIDGUID: 0eb5a5ce-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Foreign-Domain
+# The name of the Lotus Notes foreign domain that represents Exchange.
+#
+dn: CN=ms-Exch-Notes-Foreign-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Foreign-Domain
+distinguishedName: CN=ms-Exch-Notes-Foreign-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1012
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Foreign-Domain
+adminDescription: ms-Exch-Notes-Foreign-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesForeignDomain
+name: ms-Exch-Notes-Foreign-Domain
+schemaIDGUID: 137332c0-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Letterhead
+# The name of the Lotus Notes letterhead style used for messages
+# delivered into Notes from Exchange.
+#
+dn: CN=ms-Exch-Notes-Letterhead,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Letterhead
+distinguishedName: CN=ms-Exch-Notes-Letterhead,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1015
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Letterhead
+adminDescription: ms-Exch-Notes-Letterhead
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesLetterhead
+name: ms-Exch-Notes-Letterhead
+schemaIDGUID: 141552a8-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Notes-INI
+# The full path and file name of the Lotus Notes client INI file used
+# by the connector to log on to the Notes server.
+#
+dn: CN=ms-Exch-Notes-Notes-INI,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Notes-INI
+distinguishedName: CN=ms-Exch-Notes-Notes-INI,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1017
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Notes-INI
+adminDescription: ms-Exch-Notes-Notes-INI
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesNotesINI
+name: ms-Exch-Notes-Notes-INI
+schemaIDGUID: 13d02e76-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Notes-Links
+# Determines how Lotus Notes doclinks are converted in messages to
+# Exchange. Options are RTF, OLE, or URL.
+#
+dn: CN=ms-Exch-Notes-Notes-Links,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Notes-Links
+distinguishedName: CN=ms-Exch-Notes-Notes-Links,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1016
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Notes-Links
+adminDescription: ms-Exch-Notes-Notes-Links
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesNotesLinks
+name: ms-Exch-Notes-Notes-Links
+schemaIDGUID: aa7dcffe-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Notes-Server
+# The name of the Lotus Notes server to which the Connector
+# attaches. Notes format name, not server name.
+#
+dn: CN=ms-Exch-Notes-Notes-Server,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Notes-Server
+distinguishedName: CN=ms-Exch-Notes-Notes-Server,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1011
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Notes-Server
+adminDescription: ms-Exch-Notes-Notes-Server
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesNotesServer
+name: ms-Exch-Notes-Notes-Server
+schemaIDGUID: 14b51036-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Password
+#
+dn: CN=ms-Exch-Notes-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Password
+distinguishedName: CN=ms-Exch-Notes-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1010
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Password
+adminDescription: ms-Exch-Notes-Password
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchNotesPassword
+name: ms-Exch-Notes-Password
+schemaIDGUID: 593fa28d-2862-11d3-aa68-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Routable-Domains
+#
+dn: CN=ms-Exch-Notes-Routable-Domains,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Routable-Domains
+distinguishedName: CN=ms-Exch-Notes-Routable-Domains,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1023
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Routable-Domains
+adminDescription: ms-Exch-Notes-Routable-Domains
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesRoutableDomains
+name: ms-Exch-Notes-Routable-Domains
+schemaIDGUID: 90804554-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Rtr-Mailbox
+# The name of the mailbox used by the Lotus Notes mail router. This is
+# usually MAIL.BOX.
+#
+dn: CN=ms-Exch-Notes-Rtr-Mailbox,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Rtr-Mailbox
+distinguishedName: CN=ms-Exch-Notes-Rtr-Mailbox,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1013
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Rtr-Mailbox
+adminDescription: ms-Exch-Notes-Rtr-Mailbox
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesRtrMailbox
+name: ms-Exch-Notes-Rtr-Mailbox
+schemaIDGUID: 144c28be-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Source-Books
+# A list of the Lotus Notes Name and Address Books exported to
+# Exchange for directory synchronization.
+#
+dn: CN=ms-Exch-Notes-Source-Books,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Source-Books
+distinguishedName: CN=ms-Exch-Notes-Source-Books,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1020
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Source-Books
+adminDescription: ms-Exch-Notes-Source-Books
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesSourceBooks
+name: ms-Exch-Notes-Source-Books
+schemaIDGUID: 12b6d8fa-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Target-Book
+# The name of the default Name and Address Book into which Exchange
+# users are imported.
+#
+dn: CN=ms-Exch-Notes-Target-Book,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Target-Book
+distinguishedName: CN=ms-Exch-Notes-Target-Book,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1018
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Target-Book
+adminDescription: ms-Exch-Notes-Target-Book
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesTargetBook
+name: ms-Exch-Notes-Target-Book
+schemaIDGUID: 13a07f6e-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Notes-Target-Books
+# A list of domain-specific Lotus Notes Name and Address Books for
+# directory import.
+#
+dn: CN=ms-Exch-Notes-Target-Books,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Notes-Target-Books
+distinguishedName: CN=ms-Exch-Notes-Target-Books,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1019
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Notes-Target-Books
+adminDescription: ms-Exch-Notes-Target-Books
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNotesTargetBooks
+name: ms-Exch-Notes-Target-Books
+schemaIDGUID: aad1424c-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-No-PF-Connection
+# Boolean state to determine if (MAPI) clients are allowed to connect
+# to public folder content in the target routing group. By default, if
+# not set, public folder referrals will be allowed over this
+# connector.
+#
+dn: CN=ms-Exch-No-PF-Connection,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-No-PF-Connection
+distinguishedName: CN=ms-Exch-No-PF-Connection,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11067
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-No-PF-Connection
+adminDescription: ms-Exch-No-PF-Connection
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchNoPFConnection
+name: ms-Exch-No-PF-Connection
+schemaIDGUID: 9ff15c41-1ec9-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Ntds-Export-Containers
+# The GUID of NTDS containers or OUs to search in for objects to be
+# synchronized.
+#
+dn: CN=ms-Exch-Ntds-Export-Containers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Ntds-Export-Containers
+distinguishedName: CN=ms-Exch-Ntds-Export-Containers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.33
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Ntds-Export-Containers
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Ntds-Export-Containers
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchNtdsExportContainers
+name: ms-Exch-Ntds-Export-Containers
+schemaIDGUID: 155bf4d2-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Ntds-Import-Container
+# The GUID of NTDS containers or OUs to write synchronized objects to.
+#
+dn: CN=ms-Exch-Ntds-Import-Container,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Ntds-Import-Container
+distinguishedName: CN=ms-Exch-Ntds-Import-Container,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.34
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Ntds-Import-Container
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Ntds-Import-Container
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchNtdsImportContainer
+name: ms-Exch-Ntds-Import-Container
+schemaIDGUID: 1592cae8-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-NT-Account-Options
+#
+dn: CN=ms-Exch-NT-Account-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-NT-Account-Options
+distinguishedName: CN=ms-Exch-NT-Account-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.44
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-NT-Account-Options
+adminDescription: ms-Exch-NT-Account-Options
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: msExchNTAccountOptions
+name: ms-Exch-NT-Account-Options
+schemaIDGUID: 14ebe64c-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-NT-Authentication-Providers
+# A list of Security Support Provider Interface (SSPI) packages that
+# may be used to authenticate to this resource.
+#
+dn: CN=ms-Exch-NT-Authentication-Providers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-NT-Authentication-Providers
+distinguishedName: CN=ms-Exch-NT-Authentication-Providers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2009
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-NT-Authentication-Providers
+adminDescription: ms-Exch-NT-Authentication-Providers
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchNTAuthenticationProviders
+name: ms-Exch-NT-Authentication-Providers
+schemaIDGUID: 15278116-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Num-Of-Open-Retries
+#
+dn: CN=ms-Exch-Num-Of-Open-Retries,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Num-Of-Open-Retries
+distinguishedName: CN=ms-Exch-Num-Of-Open-Retries,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.148
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33012
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Num-Of-Open-Retries
+adminDescription: ms-Exch-Num-Of-Open-Retries
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: numOfOpenRetries
+name: ms-Exch-Num-Of-Open-Retries
+schemaIDGUID: a8df743a-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Num-Of-Transfer-Retries
+#
+dn: CN=ms-Exch-Num-Of-Transfer-Retries,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Num-Of-Transfer-Retries
+distinguishedName: CN=ms-Exch-Num-Of-Transfer-Retries,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.134
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33013
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Num-Of-Transfer-Retries
+adminDescription: ms-Exch-Num-Of-Transfer-Retries
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: numOfTransferRetries
+name: ms-Exch-Num-Of-Transfer-Retries
+schemaIDGUID: a8df743b-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-N-Address
+#
+dn: CN=ms-Exch-N-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-N-Address
+distinguishedName: CN=ms-Exch-N-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.282
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 50
+mAPIID: 33009
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-N-Address
+adminDescription: ms-Exch-N-Address
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: nAddress
+name: ms-Exch-N-Address
+schemaIDGUID: a8df7434-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-N-Address-Type
+#
+dn: CN=ms-Exch-N-Address-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-N-Address-Type
+distinguishedName: CN=ms-Exch-N-Address-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.222
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33010
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-N-Address-Type
+adminDescription: ms-Exch-N-Address-Type
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: nAddressType
+name: ms-Exch-N-Address-Type
+schemaIDGUID: a8df7435-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-OAB-Default
+#
+dn: CN=ms-Exch-OAB-Default,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-OAB-Default
+distinguishedName: CN=ms-Exch-OAB-Default,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.67
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-OAB-Default
+adminDescription: ms-Exch-OAB-Default
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchOABDefault
+name: ms-Exch-OAB-Default
+schemaIDGUID: 15c279f0-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-OAB-Folder
+# The entry ID of the public folder that this offline address book
+# (OAB) is stored in.
+#
+dn: CN=ms-Exch-OAB-Folder,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-OAB-Folder
+distinguishedName: CN=ms-Exch-OAB-Folder,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.68
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-OAB-Folder
+adminDescription: ms-Exch-OAB-Folder
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchOABFolder
+name: ms-Exch-OAB-Folder
+schemaIDGUID: 15f6edac-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Obj-View-Containers
+#
+dn: CN=ms-Exch-Obj-View-Containers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Obj-View-Containers
+distinguishedName: CN=ms-Exch-Obj-View-Containers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.545
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 33223
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Obj-View-Containers
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Obj-View-Containers
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: objViewContainers
+name: ms-Exch-Obj-View-Containers
+schemaIDGUID: 16775847-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Off-Line-AB-Containers
+#
+dn: CN=ms-Exch-Off-Line-AB-Containers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Off-Line-AB-Containers
+distinguishedName: CN=ms-Exch-Off-Line-AB-Containers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.391
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 33016
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Off-Line-AB-Containers
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Off-Line-AB-Containers
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: offLineABContainers
+name: ms-Exch-Off-Line-AB-Containers
+schemaIDGUID: a8df743c-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Off-Line-AB-Schedule
+#
+dn: CN=ms-Exch-Off-Line-AB-Schedule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Off-Line-AB-Schedule
+distinguishedName: CN=ms-Exch-Off-Line-AB-Schedule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.389
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 84
+rangeUpper: 84
+mAPIID: 33017
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Off-Line-AB-Schedule
+adminDescription: ms-Exch-Off-Line-AB-Schedule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: offLineABSchedule
+name: ms-Exch-Off-Line-AB-Schedule
+schemaIDGUID: a8df743d-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Off-Line-AB-Server
+#
+dn: CN=ms-Exch-Off-Line-AB-Server,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Off-Line-AB-Server
+distinguishedName: CN=ms-Exch-Off-Line-AB-Server,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.392
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 33018
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Off-Line-AB-Server
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Off-Line-AB-Server
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: offLineABServer
+name: ms-Exch-Off-Line-AB-Server
+schemaIDGUID: a8df743e-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Off-Line-AB-Style
+#
+dn: CN=ms-Exch-Off-Line-AB-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Off-Line-AB-Style
+distinguishedName: CN=ms-Exch-Off-Line-AB-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.390
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33019
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Off-Line-AB-Style
+adminDescription: ms-Exch-Off-Line-AB-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: offLineABStyle
+name: ms-Exch-Off-Line-AB-Style
+schemaIDGUID: a8df743f-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Admin-Extended-Settings
+#
+dn: CN=ms-Exch-Oma-Admin-Extended-Settings,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Admin-Extended-Settings
+distinguishedName: CN=ms-Exch-Oma-Admin-Extended-Settings,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.126
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Admin-Extended-Settings
+adminDescription: ms-Exch-Oma-Admin-Extended-Settings
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchOmaAdminExtendedSettings
+name: ms-Exch-Oma-Admin-Extended-Settings
+schemaIDGUID: e60ae80d-7ac9-4e61-9bc3-98cbc0726a99
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Admin-Wireless-Enable
+#
+dn: CN=ms-Exch-Oma-Admin-Wireless-Enable,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Admin-Wireless-Enable
+distinguishedName: CN=ms-Exch-Oma-Admin-Wireless-Enable,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.124
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Admin-Wireless-Enable
+adminDescription: ms-Exch-Oma-Admin-Wireless-Enable
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchOmaAdminWirelessEnable
+name: ms-Exch-Oma-Admin-Wireless-Enable
+schemaIDGUID: c1a7bfbe-116b-4737-8cd9-d29ef5b3690e
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Carrier-Address
+#
+dn: CN=ms-Exch-Oma-Carrier-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Carrier-Address
+distinguishedName: CN=ms-Exch-Oma-Carrier-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.139
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Carrier-Address
+adminDescription: ms-Exch-Oma-Carrier-Address
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchOmaCarrierAddress
+name: ms-Exch-Oma-Carrier-Address
+schemaIDGUID: abe858b8-3daf-407e-b1a6-3a323ed3334b
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Carrier-Type
+#
+dn: CN=ms-Exch-Oma-Carrier-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Carrier-Type
+distinguishedName: CN=ms-Exch-Oma-Carrier-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.145
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Carrier-Type
+adminDescription: ms-Exch-Oma-Carrier-Type
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchOmaCarrierType
+name: ms-Exch-Oma-Carrier-Type
+schemaIDGUID: 1fb324ad-2da3-4548-8f5a-f34457f8af4a
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Oma-Carrier-Url
+#
+dn: CN=ms-Exch-Oma-Carrier-Url,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Carrier-Url
+distinguishedName: CN=ms-Exch-Oma-Carrier-Url,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.146
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Carrier-Url
+adminDescription: ms-Exch-Oma-Carrier-Url
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchOmaCarrierUrl
+name: ms-Exch-Oma-Carrier-Url
+schemaIDGUID: aca0878d-89f1-45f5-a48f-680b7e550573
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Oma-Configuration
+#
+dn: CN=ms-Exch-Oma-Configuration,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Configuration
+distinguishedName: CN=ms-Exch-Oma-Configuration,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.137
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Configuration
+adminDescription: ms-Exch-Oma-Configuration
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchOmaConfiguration
+name: ms-Exch-Oma-Configuration
+schemaIDGUID: d7e12bc7-4288-4866-bc91-f0ee18965c15
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Oma-Deliverer
+#
+dn: CN=ms-Exch-Oma-Deliverer,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Deliverer
+distinguishedName: CN=ms-Exch-Oma-Deliverer,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.144
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Deliverer
+adminDescription: ms-Exch-Oma-Deliverer
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchOmaDeliverer
+name: ms-Exch-Oma-Deliverer
+schemaIDGUID: a231009f-9df2-403d-9fbd-99809049722d
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Oma-Delivery-Provider-DN
+#
+dn: CN=ms-Exch-Oma-Delivery-Provider-DN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Delivery-Provider-DN
+distinguishedName: CN=ms-Exch-Oma-Delivery-Provider-DN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.138
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Delivery-Provider-DN
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Oma-Delivery-Provider-DN
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchOmaDeliveryProviderDN
+name: ms-Exch-Oma-Delivery-Provider-DN
+schemaIDGUID: 1f0e1a69-d62c-4105-991d-acaff4b07d71
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Oma-Device-Capability-DN
+#
+dn: CN=ms-Exch-Oma-Device-Capability-DN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Device-Capability-DN
+distinguishedName: CN=ms-Exch-Oma-Device-Capability-DN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.133
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Device-Capability-DN
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Oma-Device-Capability-DN
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchOmaDeviceCapabilityDN
+name: ms-Exch-Oma-Device-Capability-DN
+schemaIDGUID: 0510bdc4-9b19-4d67-93a1-8dda04c15568
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Oma-Extended-Properties
+#
+dn: CN=ms-Exch-Oma-Extended-Properties,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Extended-Properties
+distinguishedName: CN=ms-Exch-Oma-Extended-Properties,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.143
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Extended-Properties
+adminDescription: ms-Exch-Oma-Extended-Properties
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchOmaExtendedProperties
+name: ms-Exch-Oma-Extended-Properties
+schemaIDGUID: 9ebe537c-f882-473d-980b-ce52202a75d8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Oma-Formatter
+#
+dn: CN=ms-Exch-Oma-Formatter,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Formatter
+distinguishedName: CN=ms-Exch-Oma-Formatter,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.135
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Formatter
+adminDescription: ms-Exch-Oma-Formatter
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchOmaFormatter
+name: ms-Exch-Oma-Formatter
+schemaIDGUID: e827cd6a-b63c-4d44-961a-781a67949a36
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Oma-Translator
+#
+dn: CN=ms-Exch-Oma-Translator,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Translator
+distinguishedName: CN=ms-Exch-Oma-Translator,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.136
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Translator
+adminDescription: ms-Exch-Oma-Translator
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchOmaTranslator
+name: ms-Exch-Oma-Translator
+schemaIDGUID: d0f2588a-701e-4649-9379-062c62b93ef6
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Oma-Validater
+#
+dn: CN=ms-Exch-Oma-Validater,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Oma-Validater
+distinguishedName: CN=ms-Exch-Oma-Validater,${SCHEMADN}
+attributeID: 1.2.840.113556.1.6.20.1.134
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Oma-Validater
+adminDescription: ms-Exch-Oma-Validater
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchOmaValidater
+name: ms-Exch-Oma-Validater
+schemaIDGUID: a87d0c40-cbbd-4da1-ba2e-704832fca5b1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-OOF-Reply-To-Originator
+# Governs whether or not Out-Of-Office notifications should be sent to
+# a sender of a message to this DL.
+#
+dn: CN=ms-Exch-OOF-Reply-To-Originator,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-OOF-Reply-To-Originator
+distinguishedName: CN=ms-Exch-OOF-Reply-To-Originator,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.438
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 33023
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-OOF-Reply-To-Originator
+adminDescription: ms-Exch-OOF-Reply-To-Originator
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: oOFReplyToOriginator
+name: ms-Exch-OOF-Reply-To-Originator
+schemaIDGUID: a8df7440-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Open-Retry-Interval
+#
+dn: CN=ms-Exch-Open-Retry-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Open-Retry-Interval
+distinguishedName: CN=ms-Exch-Open-Retry-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.143
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33024
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Open-Retry-Interval
+adminDescription: ms-Exch-Open-Retry-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: openRetryInterval
+name: ms-Exch-Open-Retry-Interval
+schemaIDGUID: a8df7441-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Originating-Forest
+#
+dn: CN=ms-Exch-Originating-Forest,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Originating-Forest
+distinguishedName: CN=ms-Exch-Originating-Forest,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50300
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Originating-Forest
+adminDescription: ms-Exch-Originating-Forest
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchOriginatingForest
+name: ms-Exch-Originating-Forest
+schemaIDGUID: 16671de6-9753-47bf-9a12-be31abe0af08
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Orig-MDB
+#
+dn: CN=ms-Exch-Orig-MDB,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Orig-MDB
+distinguishedName: CN=ms-Exch-Orig-MDB,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11093
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Orig-MDB
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Orig-MDB
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchOrigMDB
+name: ms-Exch-Orig-MDB
+schemaIDGUID: f7b66927-7726-4e66-9ea8-efdf48d65201
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Other-Authentication-Flags
+#
+dn: CN=ms-Exch-Other-Authentication-Flags,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Other-Authentication-Flags
+distinguishedName: CN=ms-Exch-Other-Authentication-Flags,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2017
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Other-Authentication-Flags
+adminDescription: ms-Exch-Other-Authentication-Flags
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchOtherAuthenticationFlags
+name: ms-Exch-Other-Authentication-Flags
+schemaIDGUID: b4c7fe67-b523-4d2e-b56e-ac57b686c7e3
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Outbound-Sites
+#
+dn: CN=ms-Exch-Outbound-Sites,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Outbound-Sites
+distinguishedName: CN=ms-Exch-Outbound-Sites,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.0
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 33029
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Outbound-Sites
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Outbound-Sites
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: outboundSites
+name: ms-Exch-Outbound-Sites
+schemaIDGUID: a8df7445-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Outgoing-Msg-Size-Limit
+#
+dn: CN=ms-Exch-Outgoing-Msg-Size-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Outgoing-Msg-Size-Limit
+distinguishedName: CN=ms-Exch-Outgoing-Msg-Size-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.490
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33167
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Outgoing-Msg-Size-Limit
+adminDescription: ms-Exch-Outgoing-Msg-Size-Limit
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: outgoingMsgSizeLimit
+name: ms-Exch-Outgoing-Msg-Size-Limit
+schemaIDGUID: a8df7446-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Overall-Age-Limit
+# Overall age limit for messages in public message databases
+# (MDBs). This is a store-wide setting.
+#
+dn: CN=ms-Exch-Overall-Age-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Overall-Age-Limit
+distinguishedName: CN=ms-Exch-Overall-Age-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11055
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Overall-Age-Limit
+adminDescription: ms-Exch-Overall-Age-Limit
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchOverallAgeLimit
+name: ms-Exch-Overall-Age-Limit
+schemaIDGUID: 9162c4ba-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-OWA-Server
+#
+dn: CN=ms-Exch-OWA-Server,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-OWA-Server
+distinguishedName: CN=ms-Exch-OWA-Server,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.608
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 128
+mAPIID: 35942
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-OWA-Server
+adminDescription: ms-Exch-OWA-Server
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: oWAServer
+name: ms-Exch-OWA-Server
+schemaIDGUID: a8df7447-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Owning-Org
+#
+dn: CN=ms-Exch-Owning-Org,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Owning-Org
+distinguishedName: CN=ms-Exch-Owning-Org,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11030
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Owning-Org
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Owning-Org
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchOwningOrg
+name: ms-Exch-Owning-Org
+schemaIDGUID: 16f86ba4-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Owning-PF-Tree
+# The GUID of the public folder tree that is replicated to this store.
+#
+dn: CN=ms-Exch-Owning-PF-Tree,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Owning-PF-Tree
+distinguishedName: CN=ms-Exch-Owning-PF-Tree,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11031
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1008
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Owning-PF-Tree
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Owning-PF-Tree
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchOwningPFTree
+name: ms-Exch-Owning-PF-Tree
+schemaIDGUID: 172a7d06-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Owning-PF-Tree-BL
+# A read-only multivalued GUID list of public MDB instances of this
+# TLH.
+#
+dn: CN=ms-Exch-Owning-PF-Tree-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Owning-PF-Tree-BL
+distinguishedName: CN=ms-Exch-Owning-PF-Tree-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11032
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1009
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Owning-PF-Tree-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Owning-PF-Tree-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchOwningPFTreeBL
+name: ms-Exch-Owning-PF-Tree-BL
+schemaIDGUID: 175a2c0e-b098-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Owning-Server
+# The DN of the Directory Service (DS) object for the server
+# containing this MDB.
+#
+dn: CN=ms-Exch-Owning-Server,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Owning-Server
+distinguishedName: CN=ms-Exch-Owning-Server,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11004
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Owning-Server
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Owning-Server
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchOwningServer
+name: ms-Exch-Owning-Server
+schemaIDGUID: 17910224-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Partner-CP
+#
+dn: CN=ms-Exch-Partner-CP,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Partner-CP
+distinguishedName: CN=ms-Exch-Partner-CP,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1007
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Partner-CP
+adminDescription: ms-Exch-Partner-CP
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchPartnerCP
+name: ms-Exch-Partner-CP
+schemaIDGUID: 8a0c07b2-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Partner-Language
+# The language (code page) of the connected foreign post office or
+# domain.
+#
+dn: CN=ms-Exch-Partner-Language,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Partner-Language
+distinguishedName: CN=ms-Exch-Partner-Language,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1006
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Partner-Language
+adminDescription: ms-Exch-Partner-Language
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchPartnerLanguage
+name: ms-Exch-Partner-Language
+schemaIDGUID: 17c7d83a-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Patch-MDB
+#
+dn: CN=ms-Exch-Patch-MDB,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Patch-MDB
+distinguishedName: CN=ms-Exch-Patch-MDB,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11086
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Patch-MDB
+adminDescription: ms-Exch-Patch-MDB
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchPatchMDB
+name: ms-Exch-Patch-MDB
+schemaIDGUID: bbdf5f8c-02d5-45ff-bab7-464d5452ebf4
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-PF-Contacts
+#
+dn: CN=ms-Exch-PF-Contacts,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-PF-Contacts
+distinguishedName: CN=ms-Exch-PF-Contacts,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.75
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32824
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-PF-Contacts
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-PF-Contacts
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: pFContacts
+name: ms-Exch-PF-Contacts
+schemaIDGUID: f0f8ff98-1191-11d0-a060-00aa006c33ed
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Pf-Creation
+#
+dn: CN=ms-Exch-Pf-Creation,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Pf-Creation
+distinguishedName: CN=ms-Exch-Pf-Creation,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.100
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Pf-Creation
+adminDescription: ms-Exch-Pf-Creation
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchPfCreation
+name: ms-Exch-Pf-Creation
+schemaIDGUID: ed1161ed-5d1e-4bb3-993f-11956d680ef6
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-PF-Default-Admin-ACL
+# On the TLH, this is the default set of rights for new Top Level
+# Folders. On the administrative group, this is the set of rights for
+# public folders that are homed on Exchange Server 5.5 that are
+# associated to this administrative group or site.
+#
+dn: CN=ms-Exch-PF-Default-Admin-ACL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-PF-Default-Admin-ACL
+distinguishedName: CN=ms-Exch-PF-Default-Admin-ACL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50035
+attributeSyntax: 2.5.5.15
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-PF-Default-Admin-ACL
+adminDescription: ms-Exch-PF-Default-Admin-ACL
+oMSyntax: 66
+searchFlags: 0
+lDAPDisplayName: msExchPFDefaultAdminACL
+name: ms-Exch-PF-Default-Admin-ACL
+schemaIDGUID: 3de926b2-22af-11d3-aa62-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-PF-DS-Container
+# The DN of the container into which message databases (MDBs) in this
+# domain will create folder objects.
+#
+dn: CN=ms-Exch-PF-DS-Container,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-PF-DS-Container
+distinguishedName: CN=ms-Exch-PF-DS-Container,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11034
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-PF-DS-Container
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-PF-DS-Container
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchPFDSContainer
+name: ms-Exch-PF-DS-Container
+schemaIDGUID: 17feae50-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Pf-Root-Url
+# The URL to a user's public folder root.
+#
+dn: CN=ms-Exch-Pf-Root-Url,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Pf-Root-Url
+distinguishedName: CN=ms-Exch-Pf-Root-Url,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50086
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+mAPIID: 35970
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Pf-Root-Url
+adminDescription: ms-Exch-Pf-Root-Url
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchPfRootUrl
+name: ms-Exch-Pf-Root-Url
+schemaIDGUID: 3f50d651-bc97-47b3-aadc-c836d7fec446
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-PF-Tree-Type
+#
+dn: CN=ms-Exch-PF-Tree-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-PF-Tree-Type
+distinguishedName: CN=ms-Exch-PF-Tree-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11035
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-PF-Tree-Type
+adminDescription: ms-Exch-PF-Tree-Type
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchPFTreeType
+name: ms-Exch-PF-Tree-Type
+schemaIDGUID: 1830bfb2-b098-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Policies-Excluded
+#
+dn: CN=ms-Exch-Policies-Excluded,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Policies-Excluded
+distinguishedName: CN=ms-Exch-Policies-Excluded,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50051
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policies-Excluded
+adminDescription: ms-Exch-Policies-Excluded
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchPoliciesExcluded
+name: ms-Exch-Policies-Excluded
+schemaIDGUID: 61c47258-454e-11d3-aa72-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Policies-Included
+#
+dn: CN=ms-Exch-Policies-Included,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Policies-Included
+distinguishedName: CN=ms-Exch-Policies-Included,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50050
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policies-Included
+adminDescription: ms-Exch-Policies-Included
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchPoliciesIncluded
+name: ms-Exch-Policies-Included
+schemaIDGUID: 61c47253-454e-11d3-aa72-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Policy-Default
+#
+dn: CN=ms-Exch-Policy-Default,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Policy-Default
+distinguishedName: CN=ms-Exch-Policy-Default,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50007
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policy-Default
+adminDescription: ms-Exch-Policy-Default
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchPolicyDefault
+name: ms-Exch-Policy-Default
+schemaIDGUID: 1865336e-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Policy-Enabled
+# Specifies whether or not policies should be applied to this recipient.
+#
+dn: CN=ms-Exch-Policy-Enabled,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Policy-Enabled
+distinguishedName: CN=ms-Exch-Policy-Enabled,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50030
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policy-Enabled
+adminDescription: ms-Exch-Policy-Enabled
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchPolicyEnabled
+name: ms-Exch-Policy-Enabled
+schemaIDGUID: e32977dc-1d31-11d3-aa5e-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Policy-Last-Applied-Time
+# The time/date that this policy was applied.
+#
+dn: CN=ms-Exch-Policy-Last-Applied-Time,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Policy-Last-Applied-Time
+distinguishedName: CN=ms-Exch-Policy-Last-Applied-Time,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50023
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policy-Last-Applied-Time
+adminDescription: ms-Exch-Policy-Last-Applied-Time
+oMSyntax: 24
+searchFlags: 0
+lDAPDisplayName: msExchPolicyLastAppliedTime
+name: ms-Exch-Policy-Last-Applied-Time
+schemaIDGUID: 92407f6c-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Policy-List
+# The list of policies a leaf object uses.
+#
+dn: CN=ms-Exch-Policy-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Policy-List
+distinguishedName: CN=ms-Exch-Policy-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50004
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1012
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policy-List
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Policy-List
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchPolicyList
+name: ms-Exch-Policy-List
+schemaIDGUID: 18cbb88c-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Policy-List-BL
+# A backlink to objects that use this policy.
+#
+dn: CN=ms-Exch-Policy-List-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Policy-List-BL
+distinguishedName: CN=ms-Exch-Policy-List-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50005
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1013
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policy-List-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Policy-List-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchPolicyListBL
+name: ms-Exch-Policy-List-BL
+schemaIDGUID: 19028ea2-b098-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Policy-LockDown
+# If this is set, this policy cannot be removed from the object this
+# policy applies to.
+#
+dn: CN=ms-Exch-Policy-LockDown,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Policy-LockDown
+distinguishedName: CN=ms-Exch-Policy-LockDown,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50008
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policy-LockDown
+adminDescription: ms-Exch-Policy-LockDown
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchPolicyLockDown
+name: ms-Exch-Policy-LockDown
+schemaIDGUID: 1934a004-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Policy-Option-List
+# The list that defines the set of property pages that are exposed on
+# this policy. Every property page (that will be policied) will be
+# assigned a GUID to uniquely identify it in this list.
+#
+dn: CN=ms-Exch-Policy-Option-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Policy-Option-List
+distinguishedName: CN=ms-Exch-Policy-Option-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50006
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policy-Option-List
+adminDescription: ms-Exch-Policy-Option-List
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchPolicyOptionList
+name: ms-Exch-Policy-Option-List
+schemaIDGUID: 1966b166-b098-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Policy-Order
+# The order in which policies will be evaluated.
+#
+dn: CN=ms-Exch-Policy-Order,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Policy-Order
+distinguishedName: CN=ms-Exch-Policy-Order,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50027
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policy-Order
+adminDescription: ms-Exch-Policy-Order
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchPolicyOrder
+name: ms-Exch-Policy-Order
+schemaIDGUID: e32977b1-1d31-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Policy-Roots
+# The list of distinguished names (DNs) of containers where policy
+# objects reside that the AL service will process.
+#
+dn: CN=ms-Exch-Policy-Roots,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Policy-Roots
+distinguishedName: CN=ms-Exch-Policy-Roots,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50028
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Policy-Roots
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Policy-Roots
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchPolicyRoots
+name: ms-Exch-Policy-Roots
+schemaIDGUID: e36ef110-1d40-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Poll-Interval
+# The polling interval between scheduled runs if "Always" is selected.
+#
+dn: CN=ms-Exch-Poll-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Poll-Interval
+distinguishedName: CN=ms-Exch-Poll-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.58
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Poll-Interval
+adminDescription: ms-Exch-Poll-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchPollInterval
+name: ms-Exch-Poll-Interval
+schemaIDGUID: 1998c2c8-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-POP-Character-Set
+#
+dn: CN=ms-Exch-POP-Character-Set,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-POP-Character-Set
+distinguishedName: CN=ms-Exch-POP-Character-Set,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.468
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 33145
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-POP-Character-Set
+adminDescription: ms-Exch-POP-Character-Set
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: pOPCharacterSet
+name: ms-Exch-POP-Character-Set
+schemaIDGUID: bf9679f8-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-POP-Content-Format
+#
+dn: CN=ms-Exch-POP-Content-Format,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-POP-Content-Format
+distinguishedName: CN=ms-Exch-POP-Content-Format,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.466
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 33143
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-POP-Content-Format
+adminDescription: ms-Exch-POP-Content-Format
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: pOPContentFormat
+name: ms-Exch-POP-Content-Format
+schemaIDGUID: bf9679f9-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Port-Number
+#
+dn: CN=ms-Exch-Port-Number,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Port-Number
+distinguishedName: CN=ms-Exch-Port-Number,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.527
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 65535
+mAPIID: 33205
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Port-Number
+adminDescription: ms-Exch-Port-Number
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: portNumber
+name: ms-Exch-Port-Number
+schemaIDGUID: a8df744a-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Preferred-Backfill-Source
+#
+dn: CN=ms-Exch-Preferred-Backfill-Source,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Preferred-Backfill-Source
+distinguishedName: CN=ms-Exch-Preferred-Backfill-Source,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11094
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Preferred-Backfill-Source
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Preferred-Backfill-Source
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchPreferredBackfillSource
+name: ms-Exch-Preferred-Backfill-Source
+schemaIDGUID: 5e03e654-d85d-4908-83a1-6141048c5c62
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Preserve-Internet-Content
+#
+dn: CN=ms-Exch-Preserve-Internet-Content,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Preserve-Internet-Content
+distinguishedName: CN=ms-Exch-Preserve-Internet-Content,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.556
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 35874
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Preserve-Internet-Content
+adminDescription: ms-Exch-Preserve-Internet-Content
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: preserveInternetContent
+name: ms-Exch-Preserve-Internet-Content
+schemaIDGUID: a8df744c-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Previous-Account-Sid
+#
+dn: CN=ms-Exch-Previous-Account-Sid,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Previous-Account-Sid
+distinguishedName: CN=ms-Exch-Previous-Account-Sid,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.93
+attributeSyntax: 2.5.5.17
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 28
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Previous-Account-Sid
+adminDescription: ms-Exch-Previous-Account-Sid
+oMSyntax: 4
+searchFlags: 9
+lDAPDisplayName: msExchPreviousAccountSid
+name: ms-Exch-Previous-Account-Sid
+schemaIDGUID: 9f7f4160-8942-4e87-a3fd-165b7711e433
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Prev-Export-DLs
+# A flag indicating whether DL names are propagated to foreign systems
+# via directory synchronization.
+#
+dn: CN=ms-Exch-Prev-Export-DLs,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Prev-Export-DLs
+distinguishedName: CN=ms-Exch-Prev-Export-DLs,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1002
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Prev-Export-DLs
+adminDescription: ms-Exch-Prev-Export-DLs
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchPrevExportDLs
+name: ms-Exch-Prev-Export-DLs
+schemaIDGUID: 48464774-30ca-11d3-aa6d-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-PRMD
+#
+dn: CN=ms-Exch-PRMD,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-PRMD
+distinguishedName: CN=ms-Exch-PRMD,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.224
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 16
+mAPIID: 33038
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-PRMD
+adminDescription: ms-Exch-PRMD
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: pRMD
+name: ms-Exch-PRMD
+schemaIDGUID: a8df744d-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Processed-Sids
+# A list of security identifiers (SIDs) that have already been
+# processed.
+#
+dn: CN=ms-Exch-Processed-Sids,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Processed-Sids
+distinguishedName: CN=ms-Exch-Processed-Sids,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.89
+attributeSyntax: 2.5.5.17
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Processed-Sids
+adminDescription: ms-Exch-Processed-Sids
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchProcessedSids
+name: ms-Exch-Processed-Sids
+schemaIDGUID: 5ab6a4b0-7d6c-4e84-848e-10d52b1eb735
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Promo-Expiration
+#
+dn: CN=ms-Exch-Promo-Expiration,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Promo-Expiration
+distinguishedName: CN=ms-Exch-Promo-Expiration,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.540
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+mAPIID: 33218
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Promo-Expiration
+adminDescription: ms-Exch-Promo-Expiration
+oMSyntax: 23
+searchFlags: 0
+lDAPDisplayName: promoExpiration
+name: ms-Exch-Promo-Expiration
+schemaIDGUID: 1677585d-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Protocol-Settings
+# Exchange Internet protocol settings.
+#
+dn: CN=ms-Exch-Protocol-Settings,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Protocol-Settings
+distinguishedName: CN=ms-Exch-Protocol-Settings,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.528
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 0
+rangeUpper: 256
+mAPIID: 33206
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Protocol-Settings
+adminDescription: ms-Exch-Protocol-Settings
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: protocolSettings
+name: ms-Exch-Protocol-Settings
+schemaIDGUID: 1677585e-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Proxy-Custom-Proxy
+#
+dn: CN=ms-Exch-Proxy-Custom-Proxy,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Proxy-Custom-Proxy
+distinguishedName: CN=ms-Exch-Proxy-Custom-Proxy,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50048
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Proxy-Custom-Proxy
+adminDescription: ms-Exch-Proxy-Custom-Proxy
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchProxyCustomProxy
+name: ms-Exch-Proxy-Custom-Proxy
+schemaIDGUID: 47bc3aa6-3634-11d3-aa6e-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Proxy-Generator-DLL
+#
+dn: CN=ms-Exch-Proxy-Generator-DLL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Proxy-Generator-DLL
+distinguishedName: CN=ms-Exch-Proxy-Generator-DLL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.328
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 255
+mAPIID: 33039
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Proxy-Generator-DLL
+adminDescription: ms-Exch-Proxy-Generator-DLL
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: proxyGeneratorDLL
+name: ms-Exch-Proxy-Generator-DLL
+schemaIDGUID: a8df744e-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Proxy-Gen-Server
+# The time/date that this policy was applied.
+#
+dn: CN=ms-Exch-Proxy-Gen-Server,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Proxy-Gen-Server
+distinguishedName: CN=ms-Exch-Proxy-Gen-Server,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50013
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Proxy-Gen-Server
+adminDescription: ms-Exch-Proxy-Gen-Server
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchProxyGenServer
+name: ms-Exch-Proxy-Gen-Server
+schemaIDGUID: 1a2a323a-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Proxy-Name
+# The data conference proxy name.
+#
+dn: CN=ms-Exch-Proxy-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Proxy-Name
+distinguishedName: CN=ms-Exch-Proxy-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9018
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Proxy-Name
+adminDescription: ms-Exch-Proxy-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchProxyName
+name: ms-Exch-Proxy-Name
+schemaIDGUID: 1a610850-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Public-Delegates
+# The DN of other mailboxes that can send on behalf of this mailbox.
+#
+dn: CN=ms-Exch-Public-Delegates,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Public-Delegates
+distinguishedName: CN=ms-Exch-Public-Delegates,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.238
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 32789
+linkID: 14
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Public-Delegates
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Public-Delegates
+oMSyntax: 127
+searchFlags: 16
+lDAPDisplayName: publicDelegates
+name: ms-Exch-Public-Delegates
+schemaIDGUID: f0f8ff9a-1191-11d0-a060-00aa006c33ed
+attributeSecurityGUID: 77b5b886-944a-11d1-aebd-0000f80367c1
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Public-Delegates-BL
+#
+dn: CN=ms-Exch-Public-Delegates-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Public-Delegates-BL
+distinguishedName: CN=ms-Exch-Public-Delegates-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.295
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 33040
+linkID: 15
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Public-Delegates-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Public-Delegates-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: publicDelegatesBL
+name: ms-Exch-Public-Delegates-BL
+schemaIDGUID: bf967a08-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Purported-Search-UI
+# Stores the UI settings that set the purported search attribute.
+#
+dn: CN=ms-Exch-Purported-Search-UI,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Purported-Search-UI
+distinguishedName: CN=ms-Exch-Purported-Search-UI,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.66
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Purported-Search-UI
+adminDescription: ms-Exch-Purported-Search-UI
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchPurportedSearchUI
+name: ms-Exch-Purported-Search-UI
+schemaIDGUID: 1d86e324-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-P-Selector
+#
+dn: CN=ms-Exch-P-Selector,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-P-Selector
+distinguishedName: CN=ms-Exch-P-Selector,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.285
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 16
+mAPIID: 33030
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-P-Selector
+adminDescription: ms-Exch-P-Selector
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: pSelector
+name: ms-Exch-P-Selector
+schemaIDGUID: a8df7448-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-P-Selector-Inbound
+#
+dn: CN=ms-Exch-P-Selector-Inbound,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-P-Selector-Inbound
+distinguishedName: CN=ms-Exch-P-Selector-Inbound,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.52
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 16
+mAPIID: 33031
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-P-Selector-Inbound
+adminDescription: ms-Exch-P-Selector-Inbound
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: pSelectorInbound
+name: ms-Exch-P-Selector-Inbound
+schemaIDGUID: a8df7449-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Query-Base-DN
+# Defines the scope for client queries on address lists.
+#
+dn: CN=ms-Exch-Query-Base-DN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Query-Base-DN
+distinguishedName: CN=ms-Exch-Query-Base-DN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15008
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Query-Base-DN
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Query-Base-DN
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchQueryBaseDN
+name: ms-Exch-Query-Base-DN
+schemaIDGUID: 399eb12c-e120-473c-b0f7-97ae7ca4988b
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Queuing-MDB
+#
+dn: CN=ms-Exch-Queuing-MDB,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Queuing-MDB
+distinguishedName: CN=ms-Exch-Queuing-MDB,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11054
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Queuing-MDB
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Queuing-MDB
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchQueuingMDB
+name: ms-Exch-Queuing-MDB
+schemaIDGUID: 8afa72da-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Quota-Notification-Schedule
+#
+dn: CN=ms-Exch-Quota-Notification-Schedule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Quota-Notification-Schedule
+distinguishedName: CN=ms-Exch-Quota-Notification-Schedule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.98
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 84
+rangeUpper: 84
+mAPIID: 33041
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Quota-Notification-Schedule
+adminDescription: ms-Exch-Quota-Notification-Schedule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: quotaNotificationSchedule
+name: ms-Exch-Quota-Notification-Schedule
+schemaIDGUID: a8df744f-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Quota-Notification-Style
+#
+dn: CN=ms-Exch-Quota-Notification-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Quota-Notification-Style
+distinguishedName: CN=ms-Exch-Quota-Notification-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.388
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 33042
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Quota-Notification-Style
+adminDescription: ms-Exch-Quota-Notification-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: quotaNotificationStyle
+name: ms-Exch-Quota-Notification-Style
+schemaIDGUID: a8df7450-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-RAS-Callback-Number
+#
+dn: CN=ms-Exch-RAS-Callback-Number,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-RAS-Callback-Number
+distinguishedName: CN=ms-Exch-RAS-Callback-Number,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.315
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 48
+mAPIID: 33045
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RAS-Callback-Number
+adminDescription: ms-Exch-RAS-Callback-Number
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: rASCallbackNumber
+name: ms-Exch-RAS-Callback-Number
+schemaIDGUID: a8df7452-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-RAS-Phonebook-Entry-Name
+#
+dn: CN=ms-Exch-RAS-Phonebook-Entry-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-RAS-Phonebook-Entry-Name
+distinguishedName: CN=ms-Exch-RAS-Phonebook-Entry-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.313
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 256
+mAPIID: 33047
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RAS-Phonebook-Entry-Name
+adminDescription: ms-Exch-RAS-Phonebook-Entry-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: rASPhonebookEntryName
+name: ms-Exch-RAS-Phonebook-Entry-Name
+schemaIDGUID: a8df7455-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-RAS-Phone-Number
+#
+dn: CN=ms-Exch-RAS-Phone-Number,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-RAS-Phone-Number
+distinguishedName: CN=ms-Exch-RAS-Phone-Number,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.314
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 128
+mAPIID: 33046
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RAS-Phone-Number
+adminDescription: ms-Exch-RAS-Phone-Number
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: rASPhoneNumber
+name: ms-Exch-RAS-Phone-Number
+schemaIDGUID: a8df7454-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-RAS-Remote-SRVR-Name
+#
+dn: CN=ms-Exch-RAS-Remote-SRVR-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-RAS-Remote-SRVR-Name
+distinguishedName: CN=ms-Exch-RAS-Remote-SRVR-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.78
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 15
+mAPIID: 33048
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RAS-Remote-SRVR-Name
+adminDescription: ms-Exch-RAS-Remote-SRVR-Name
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: rASRemoteSRVRName
+name: ms-Exch-RAS-Remote-SRVR-Name
+schemaIDGUID: a8df7456-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Recip-Limit
+# The maximum number of recipients this user may send to, or a global
+# maximum for the organization.
+#
+dn: CN=ms-Exch-Recip-Limit,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Recip-Limit
+distinguishedName: CN=ms-Exch-Recip-Limit,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12523
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Recip-Limit
+adminDescription: ms-Exch-Recip-Limit
+oMSyntax: 2
+searchFlags: 16
+lDAPDisplayName: msExchRecipLimit
+name: ms-Exch-Recip-Limit
+schemaIDGUID: 1dd7f318-b098-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Recip-Turf-List-Names
+#
+dn: CN=ms-Exch-Recip-Turf-List-Names,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Recip-Turf-List-Names
+distinguishedName: CN=ms-Exch-Recip-Turf-List-Names,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5070
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Recip-Turf-List-Names
+adminDescription: ms-Exch-Recip-Turf-List-Names
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchRecipTurfListNames
+name: ms-Exch-Recip-Turf-List-Names
+schemaIDGUID: 2e0a68e1-bdd7-4899-8bb2-d6ea007558c7
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Recip-Turf-List-Options
+#
+dn: CN=ms-Exch-Recip-Turf-List-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Recip-Turf-List-Options
+distinguishedName: CN=ms-Exch-Recip-Turf-List-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5071
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Recip-Turf-List-Options
+adminDescription: ms-Exch-Recip-Turf-List-Options
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchRecipTurfListOptions
+name: ms-Exch-Recip-Turf-List-Options
+schemaIDGUID: 870b36b3-d035-402d-b873-ced07b173763
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Recovery
+# If recovery is on, log files are generated.
+#
+dn: CN=ms-Exch-Recovery,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Recovery
+distinguishedName: CN=ms-Exch-Recovery,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11046
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Recovery
+adminDescription: ms-Exch-Recovery
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchRecovery
+name: ms-Exch-Recovery
+schemaIDGUID: 1e007b12-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Referral-List
+#
+dn: CN=ms-Exch-Referral-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Referral-List
+distinguishedName: CN=ms-Exch-Referral-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.510
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 33187
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Referral-List
+adminDescription: ms-Exch-Referral-List
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: referralList
+name: ms-Exch-Referral-List
+schemaIDGUID: a8df7457-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Remote-Bridge-Head
+#
+dn: CN=ms-Exch-Remote-Bridge-Head,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Remote-Bridge-Head
+distinguishedName: CN=ms-Exch-Remote-Bridge-Head,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.191
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 33050
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Remote-Bridge-Head
+adminDescription: ms-Exch-Remote-Bridge-Head
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: remoteBridgeHead
+name: ms-Exch-Remote-Bridge-Head
+schemaIDGUID: a8df7458-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Remote-Bridge-Head-Address
+#
+dn: CN=ms-Exch-Remote-Bridge-Head-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Remote-Bridge-Head-Address
+distinguishedName: CN=ms-Exch-Remote-Bridge-Head-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.94
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 1118
+mAPIID: 33051
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Remote-Bridge-Head-Address
+adminDescription: ms-Exch-Remote-Bridge-Head-Address
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: remoteBridgeHeadAddress
+name: ms-Exch-Remote-Bridge-Head-Address
+schemaIDGUID: a8df7459-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Remote-Private-IS-List
+# A flat delimited set of distinguished names (DNs) of remote Exchange
+# private stores. Used to set home-mdb on user objects.
+#
+dn: CN=ms-Exch-Remote-Private-IS-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Remote-Private-IS-List
+distinguishedName: CN=ms-Exch-Remote-Private-IS-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.46
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Remote-Private-IS-List
+adminDescription: ms-Exch-Remote-Private-IS-List
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchRemotePrivateISList
+name: ms-Exch-Remote-Private-IS-List
+schemaIDGUID: 1e29030c-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Remote-Server-List
+# A flat delimited set of distinguished names (DNs) of remote Exchange
+# servers. Used to set home-mta on DL objects.
+#
+dn: CN=ms-Exch-Remote-Server-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Remote-Server-List
+distinguishedName: CN=ms-Exch-Remote-Server-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.45
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Remote-Server-List
+adminDescription: ms-Exch-Remote-Server-List
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchRemoteServerList
+name: ms-Exch-Remote-Server-List
+schemaIDGUID: 1e58b214-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Remote-Site
+#
+dn: CN=ms-Exch-Remote-Site,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Remote-Site
+distinguishedName: CN=ms-Exch-Remote-Site,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.27
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 33053
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Remote-Site
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Remote-Site
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: remoteSite
+name: ms-Exch-Remote-Site
+schemaIDGUID: a8df745b-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Replicated-Object-Version
+#
+dn: CN=ms-Exch-Replicated-Object-Version,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Replicated-Object-Version
+distinguishedName: CN=ms-Exch-Replicated-Object-Version,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.604
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 35938
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Replicated-Object-Version
+adminDescription: ms-Exch-Replicated-Object-Version
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: replicatedObjectVersion
+name: ms-Exch-Replicated-Object-Version
+schemaIDGUID: 1677586c-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Replicate-Now
+# A flag that notifies the service to replicate this connection
+# agreement immediately.
+#
+dn: CN=ms-Exch-Replicate-Now,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Replicate-Now
+distinguishedName: CN=ms-Exch-Replicate-Now,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.53
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Replicate-Now
+adminDescription: ms-Exch-Replicate-Now
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchReplicateNow
+name: ms-Exch-Replicate-Now
+schemaIDGUID: 1eac2462-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Replication-Mail-Msg-Size
+#
+dn: CN=ms-Exch-Replication-Mail-Msg-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Replication-Mail-Msg-Size
+distinguishedName: CN=ms-Exch-Replication-Mail-Msg-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.103
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33128
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Replication-Mail-Msg-Size
+adminDescription: ms-Exch-Replication-Mail-Msg-Size
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: replicationMailMsgSize
+name: ms-Exch-Replication-Mail-Msg-Size
+schemaIDGUID: a8df745c-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Replication-Msg-Size
+# The replication message size limit.
+dn: CN=ms-Exch-Replication-Msg-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Replication-Msg-Size
+distinguishedName: CN=ms-Exch-Replication-Msg-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11047
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Replication-Msg-Size
+adminDescription: ms-Exch-Replication-Msg-Size
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchReplicationMsgSize
+name: ms-Exch-Replication-Msg-Size
+schemaIDGUID: 1ed70eb6-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Replication-Schedule
+# The schedule of when to replicate public folder changes.
+#
+dn: CN=ms-Exch-Replication-Schedule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Replication-Schedule
+distinguishedName: CN=ms-Exch-Replication-Schedule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11048
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Replication-Schedule
+adminDescription: ms-Exch-Replication-Schedule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchReplicationSchedule
+name: ms-Exch-Replication-Schedule
+schemaIDGUID: 1f01f90a-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Replication-Sensitivity
+# Used by Exchange on legacy Exchange Server 5.5 connectors to govern
+# their use by replication.
+#
+dn: CN=ms-Exch-Replication-Sensitivity,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Replication-Sensitivity
+distinguishedName: CN=ms-Exch-Replication-Sensitivity,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.223
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 100
+mAPIID: 33054
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Replication-Sensitivity
+adminDescription: ms-Exch-Replication-Sensitivity
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: replicationSensitivity
+name: ms-Exch-Replication-Sensitivity
+schemaIDGUID: bf967a1b-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Replication-Signature
+# Signature used for replication purposes by the Active Directory Connector.
+#
+dn: CN=ms-Exch-Replication-Signature,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Replication-Signature
+distinguishedName: CN=ms-Exch-Replication-Signature,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.52
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Replication-Signature
+adminDescription: ms-Exch-Replication-Signature
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: replicationSignature
+name: ms-Exch-Replication-Signature
+schemaIDGUID: 9909d92a-b093-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Replication-Stagger
+#
+dn: CN=ms-Exch-Replication-Stagger,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Replication-Stagger
+distinguishedName: CN=ms-Exch-Replication-Stagger,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.349
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33055
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Replication-Stagger
+adminDescription: ms-Exch-Replication-Stagger
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: replicationStagger
+name: ms-Exch-Replication-Stagger
+schemaIDGUID: a8df745d-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Replication-Style
+# The style for replicating public folder changes, such as Always or Never.
+#
+dn: CN=ms-Exch-Replication-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Replication-Style
+distinguishedName: CN=ms-Exch-Replication-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11049
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Replication-Style
+adminDescription: ms-Exch-Replication-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchReplicationStyle
+name: ms-Exch-Replication-Style
+schemaIDGUID: 1f2ce35e-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Report-To-Originator
+#
+dn: CN=ms-Exch-Report-To-Originator,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Report-To-Originator
+distinguishedName: CN=ms-Exch-Report-To-Originator,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.206
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 33056
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Report-To-Originator
+adminDescription: ms-Exch-Report-To-Originator
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: reportToOriginator
+name: ms-Exch-Report-To-Originator
+schemaIDGUID: a8df745e-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Report-To-Owner
+# Governs whether or not read receipts and delivery receipts will be sent to the sender of messages sent to this DL.
+#
+dn: CN=ms-Exch-Report-To-Owner,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Report-To-Owner
+distinguishedName: CN=ms-Exch-Report-To-Owner,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.207
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 33057
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Report-To-Owner
+adminDescription: ms-Exch-Report-To-Owner
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: reportToOwner
+name: ms-Exch-Report-To-Owner
+schemaIDGUID: a8df745f-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-RequireAuthToSendTo
+#
+dn: CN=ms-Exch-RequireAuthToSendTo,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-RequireAuthToSendTo
+distinguishedName: CN=ms-Exch-RequireAuthToSendTo,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.5062
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RequireAuthToSendTo
+adminDescription: ms-Exch-RequireAuthToSendTo
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchRequireAuthToSendTo
+name: ms-Exch-RequireAuthToSendTo
+schemaIDGUID: f533eb3b-f75b-4fb3-b2fb-08cd537a84d1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Require-SSL
+#
+dn: CN=ms-Exch-Require-SSL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Require-SSL
+distinguishedName: CN=ms-Exch-Require-SSL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.560
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 35877
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Require-SSL
+adminDescription: ms-Exch-Require-SSL
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: requireSSL
+name: ms-Exch-Require-SSL
+schemaIDGUID: a8df7461-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Req-Seq
+#
+dn: CN=ms-Exch-Req-Seq,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Req-Seq
+distinguishedName: CN=ms-Exch-Req-Seq,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.173
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33058
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Req-Seq
+adminDescription: ms-Exch-Req-Seq
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: reqSeq
+name: ms-Exch-Req-Seq
+schemaIDGUID: a8df7460-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Resolve-P2
+#
+dn: CN=ms-Exch-Resolve-P2,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Resolve-P2
+distinguishedName: CN=ms-Exch-Resolve-P2,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12538
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Resolve-P2
+adminDescription: ms-Exch-Resolve-P2
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchResolveP2
+name: ms-Exch-Resolve-P2
+schemaIDGUID: e24d7aa1-439d-11d3-aa72-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Resource-GUID
+# The CTP GUID.
+#
+dn: CN=ms-Exch-Resource-GUID,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Resource-GUID
+distinguishedName: CN=ms-Exch-Resource-GUID,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9001
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Resource-GUID
+adminDescription: ms-Exch-Resource-GUID
+oMSyntax: 64
+searchFlags: 17
+lDAPDisplayName: msExchResourceGUID
+name: ms-Exch-Resource-GUID
+schemaIDGUID: 1f57cdb2-b098-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Resource-Properties
+# Resource values specific to the CTP.
+#
+dn: CN=ms-Exch-Resource-Properties,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Resource-Properties
+distinguishedName: CN=ms-Exch-Resource-Properties,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9025
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Resource-Properties
+adminDescription: ms-Exch-Resource-Properties
+oMSyntax: 64
+searchFlags: 16
+lDAPDisplayName: msExchResourceProperties
+name: ms-Exch-Resource-Properties
+schemaIDGUID: 912beea4-b09e-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Responsible-Local-DXA
+#
+dn: CN=ms-Exch-Responsible-Local-DXA,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Responsible-Local-DXA
+distinguishedName: CN=ms-Exch-Responsible-Local-DXA,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.298
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 33059
+linkID: 122
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Responsible-Local-DXA
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Responsible-Local-DXA
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: responsibleLocalDXA
+name: ms-Exch-Responsible-Local-DXA
+schemaIDGUID: a8df7462-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Responsible-MTA-Server
+#
+dn: CN=ms-Exch-Responsible-MTA-Server,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Responsible-MTA-Server
+distinguishedName: CN=ms-Exch-Responsible-MTA-Server,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50033
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1030
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Responsible-MTA-Server
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Responsible-MTA-Server
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchResponsibleMTAServer
+name: ms-Exch-Responsible-MTA-Server
+schemaIDGUID: 9ff15c37-1ec9-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Responsible-MTA-Server-BL
+#
+dn: CN=ms-Exch-Responsible-MTA-Server-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Responsible-MTA-Server-BL
+distinguishedName: CN=ms-Exch-Responsible-MTA-Server-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50034
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1031
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Responsible-MTA-Server-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Responsible-MTA-Server-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchResponsibleMTAServerBL
+name: ms-Exch-Responsible-MTA-Server-BL
+schemaIDGUID: 9ff15c3c-1ec9-11d3-aa5e-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Restore
+#
+dn: CN=ms-Exch-Restore,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Restore
+distinguishedName: CN=ms-Exch-Restore,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11092
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Restore
+adminDescription: ms-Exch-Restore
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchRestore
+name: ms-Exch-Restore
+schemaIDGUID: a1edcb4c-5c45-4d4a-b128-880392e9dcc6
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Return-Exact-Msg-Size
+#
+dn: CN=ms-Exch-Return-Exact-Msg-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Return-Exact-Msg-Size
+distinguishedName: CN=ms-Exch-Return-Exact-Msg-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.594
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 35922
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Return-Exact-Msg-Size
+adminDescription: ms-Exch-Return-Exact-Msg-Size
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: returnExactMsgSize
+name: ms-Exch-Return-Exact-Msg-Size
+schemaIDGUID: a8df7463-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Rid-Server
+# A pointer to the server that maintains the Gateway Address
+# Resolution Table (GWART) for this site or administrative group.
+#
+dn: CN=ms-Exch-Rid-Server,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Rid-Server
+distinguishedName: CN=ms-Exch-Rid-Server,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.346
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 33060
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Rid-Server
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Rid-Server
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: ridServer
+name: ms-Exch-Rid-Server
+schemaIDGUID: a8df7464-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Role-Includes
+# The set of other roles that this role includes.
+#
+dn: CN=ms-Exch-Role-Includes,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Role-Includes
+distinguishedName: CN=ms-Exch-Role-Includes,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50020
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Role-Includes
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Role-Includes
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchRoleIncludes
+name: ms-Exch-Role-Includes
+schemaIDGUID: 1f8055ac-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Role-Localized-Names
+# The OAB that this mailbox store or this user uses.
+#
+dn: CN=ms-Exch-Role-Localized-Names,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Role-Localized-Names
+distinguishedName: CN=ms-Exch-Role-Localized-Names,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50021
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Role-Localized-Names
+adminDescription: ms-Exch-Role-Localized-Names
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchRoleLocalizedNames
+name: ms-Exch-Role-Localized-Names
+schemaIDGUID: 1fa8dda6-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Role-Rights
+# The set of rights, per objectClass, that this role includes.
+#
+dn: CN=ms-Exch-Role-Rights,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Role-Rights
+distinguishedName: CN=ms-Exch-Role-Rights,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50018
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Role-Rights
+adminDescription: ms-Exch-Role-Rights
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchRoleRights
+name: ms-Exch-Role-Rights
+schemaIDGUID: 1fd165a0-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Root-Newsgroups-Folder-ID
+#
+dn: CN=ms-Exch-Root-Newsgroups-Folder-ID,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Root-Newsgroups-Folder-ID
+distinguishedName: CN=ms-Exch-Root-Newsgroups-Folder-ID,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.524
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 33202
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Root-Newsgroups-Folder-ID
+adminDescription: ms-Exch-Root-Newsgroups-Folder-ID
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: rootNewsgroupsFolderID
+name: ms-Exch-Root-Newsgroups-Folder-ID
+schemaIDGUID: a8df7466-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Routing-Accept-Message-Type
+#
+dn: CN=ms-Exch-Routing-Accept-Message-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-Accept-Message-Type
+distinguishedName: CN=ms-Exch-Routing-Accept-Message-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12517
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Accept-Message-Type
+adminDescription: ms-Exch-Routing-Accept-Message-Type
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchRoutingAcceptMessageType
+name: ms-Exch-Routing-Accept-Message-Type
+schemaIDGUID: 881759de-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Routing-Disallow-Priority
+#
+dn: CN=ms-Exch-Routing-Disallow-Priority,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-Disallow-Priority
+distinguishedName: CN=ms-Exch-Routing-Disallow-Priority,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12529
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Disallow-Priority
+adminDescription: ms-Exch-Routing-Disallow-Priority
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchRoutingDisallowPriority
+name: ms-Exch-Routing-Disallow-Priority
+schemaIDGUID: 909a7f32-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Routing-Display-Sender-Enabled
+#
+dn: CN=ms-Exch-Routing-Display-Sender-Enabled,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-Display-Sender-Enabled
+distinguishedName: CN=ms-Exch-Routing-Display-Sender-Enabled,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12519
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Display-Sender-Enabled
+adminDescription: ms-Exch-Routing-Display-Sender-Enabled
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchRoutingDisplaySenderEnabled
+name: ms-Exch-Routing-Display-Sender-Enabled
+schemaIDGUID: 88dadab2-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Routing-Enabled
+# This flag enables or disables the routing for the entire
+# organization.
+#
+dn: CN=ms-Exch-Routing-Enabled,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-Enabled
+distinguishedName: CN=ms-Exch-Routing-Enabled,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12528
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Enabled
+adminDescription: ms-Exch-Routing-Enabled
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchRoutingEnabled
+name: ms-Exch-Routing-Enabled
+schemaIDGUID: 89f1cdd4-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Routing-ETRN-Domains
+# Contains the list of domain names (such as example.com) for which an
+# ETRN command should be issued.
+#
+dn: CN=ms-Exch-Routing-ETRN-Domains,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-ETRN-Domains
+distinguishedName: CN=ms-Exch-Routing-ETRN-Domains,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12530
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-ETRN-Domains
+adminDescription: ms-Exch-Routing-ETRN-Domains
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchRoutingETRNDomains
+name: ms-Exch-Routing-ETRN-Domains
+schemaIDGUID: 62a383c0-2d9d-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Routing-Group-Members-BL
+#
+dn: CN=ms-Exch-Routing-Group-Members-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-Group-Members-BL
+distinguishedName: CN=ms-Exch-Routing-Group-Members-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12540
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1051
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Group-Members-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Routing-Group-Members-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchRoutingGroupMembersBL
+name: ms-Exch-Routing-Group-Members-BL
+schemaIDGUID: fa9635c0-4acb-47de-ad00-1880b590481b
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Routing-Group-Members-DN
+# Pointers to virtual servers of servers in a Exchange Routing Group.
+#
+dn: CN=ms-Exch-Routing-Group-Members-DN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-Group-Members-DN
+distinguishedName: CN=ms-Exch-Routing-Group-Members-DN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12506
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1000
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Group-Members-DN
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Routing-Group-Members-DN
+oMSyntax: 127
+searchFlags: 1
+lDAPDisplayName: msExchRoutingGroupMembersDN
+name: ms-Exch-Routing-Group-Members-DN
+schemaIDGUID: 1ff9ed9a-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Routing-List
+# The address space of addresses allowed to be used on the connector.
+#
+dn: CN=ms-Exch-Routing-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-List
+distinguishedName: CN=ms-Exch-Routing-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.354
+attributeSyntax: 2.5.5.4
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 2243
+mAPIID: 33062
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-List
+adminDescription: ms-Exch-Routing-List
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: routingList
+name: ms-Exch-Routing-List
+schemaIDGUID: a8df7467-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Routing-Master-DN
+# A pointer to the virtual server of the master of the Exchange
+# Routing Group.
+#
+dn: CN=ms-Exch-Routing-Master-DN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-Master-DN
+distinguishedName: CN=ms-Exch-Routing-Master-DN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12505
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Master-DN
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Routing-Master-DN
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchRoutingMasterDN
+name: ms-Exch-Routing-Master-DN
+schemaIDGUID: 2024d7ee-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Routing-Oversized-Schedule
+#
+dn: CN=ms-Exch-Routing-Oversized-Schedule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-Oversized-Schedule
+distinguishedName: CN=ms-Exch-Routing-Oversized-Schedule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12520
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Oversized-Schedule
+adminDescription: ms-Exch-Routing-Oversized-Schedule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchRoutingOversizedSchedule
+name: ms-Exch-Routing-Oversized-Schedule
+schemaIDGUID: 88f51490-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Routing-Oversized-Style
+#
+dn: CN=ms-Exch-Routing-Oversized-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-Oversized-Style
+distinguishedName: CN=ms-Exch-Routing-Oversized-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12521
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Oversized-Style
+adminDescription: ms-Exch-Routing-Oversized-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchRoutingOversizedStyle
+name: ms-Exch-Routing-Oversized-Style
+schemaIDGUID: 89141322-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Routing-Triggered-Schedule
+#
+dn: CN=ms-Exch-Routing-Triggered-Schedule,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-Triggered-Schedule
+distinguishedName: CN=ms-Exch-Routing-Triggered-Schedule,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12526
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Triggered-Schedule
+adminDescription: ms-Exch-Routing-Triggered-Schedule
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchRoutingTriggeredSchedule
+name: ms-Exch-Routing-Triggered-Schedule
+schemaIDGUID: 892e4d00-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Routing-Triggered-Style
+#
+dn: CN=ms-Exch-Routing-Triggered-Style,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Routing-Triggered-Style
+distinguishedName: CN=ms-Exch-Routing-Triggered-Style,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12525
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Routing-Triggered-Style
+adminDescription: ms-Exch-Routing-Triggered-Style
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchRoutingTriggeredStyle
+name: ms-Exch-Routing-Triggered-Style
+schemaIDGUID: 894ae938-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-RTS-Checkpoint-Size
+#
+dn: CN=ms-Exch-RTS-Checkpoint-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-RTS-Checkpoint-Size
+distinguishedName: CN=ms-Exch-RTS-Checkpoint-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.152
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 100
+mAPIID: 33063
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RTS-Checkpoint-Size
+adminDescription: ms-Exch-RTS-Checkpoint-Size
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: rTSCheckpointSize
+name: ms-Exch-RTS-Checkpoint-Size
+schemaIDGUID: a8df7468-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-RTS-Recovery-Timeout
+#
+dn: CN=ms-Exch-RTS-Recovery-Timeout,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-RTS-Recovery-Timeout
+distinguishedName: CN=ms-Exch-RTS-Recovery-Timeout,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.151
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33064
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RTS-Recovery-Timeout
+adminDescription: ms-Exch-RTS-Recovery-Timeout
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: rTSRecoveryTimeout
+name: ms-Exch-RTS-Recovery-Timeout
+schemaIDGUID: a8df7469-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-RTS-Window-Size
+#
+dn: CN=ms-Exch-RTS-Window-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-RTS-Window-Size
+distinguishedName: CN=ms-Exch-RTS-Window-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.153
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 10
+mAPIID: 33065
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-RTS-Window-Size
+adminDescription: ms-Exch-RTS-Window-Size
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: rTSWindowSize
+name: ms-Exch-RTS-Window-Size
+schemaIDGUID: a8df746a-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Runs-On
+#
+dn: CN=ms-Exch-Runs-On,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Runs-On
+distinguishedName: CN=ms-Exch-Runs-On,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.185
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 33066
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Runs-On
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Runs-On
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: runsOn
+name: ms-Exch-Runs-On
+schemaIDGUID: a8df746b-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Sasl-Logon-Domain
+# The logon domain used for SASL.
+dn: CN=ms-Exch-Sasl-Logon-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Sasl-Logon-Domain
+distinguishedName: CN=ms-Exch-Sasl-Logon-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2008
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Sasl-Logon-Domain
+adminDescription: ms-Exch-Sasl-Logon-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSaslLogonDomain
+name: ms-Exch-Sasl-Logon-Domain
+schemaIDGUID: 209c0d82-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-SASL-Mechanisms
+#
+dn: CN=ms-Exch-SASL-Mechanisms,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-SASL-Mechanisms
+distinguishedName: CN=ms-Exch-SASL-Mechanisms,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2018
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-SASL-Mechanisms
+adminDescription: ms-Exch-SASL-Mechanisms
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSASLMechanisms
+name: ms-Exch-SASL-Mechanisms
+schemaIDGUID: d93571b4-c99a-4cfc-aaba-2d809fd68e79
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Sched-Plus-AG-Only
+#
+dn: CN=ms-Exch-Sched-Plus-AG-Only,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Sched-Plus-AG-Only
+distinguishedName: CN=ms-Exch-Sched-Plus-AG-Only,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1191
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Sched-Plus-AG-Only
+adminDescription: ms-Exch-Sched-Plus-AG-Only
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchSchedPlusAGOnly
+name: ms-Exch-Sched-Plus-AG-Only
+schemaIDGUID: b1fce956-1d44-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Sched-Plus-Full-Update
+#
+dn: CN=ms-Exch-Sched-Plus-Full-Update,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Sched-Plus-Full-Update
+distinguishedName: CN=ms-Exch-Sched-Plus-Full-Update,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1190
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Sched-Plus-Full-Update
+adminDescription: ms-Exch-Sched-Plus-Full-Update
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchSchedPlusFullUpdate
+name: ms-Exch-Sched-Plus-Full-Update
+schemaIDGUID: b1fce950-1d44-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Sched-Plus-Schedist
+#
+dn: CN=ms-Exch-Sched-Plus-Schedist,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Sched-Plus-Schedist
+distinguishedName: CN=ms-Exch-Sched-Plus-Schedist,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1192
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Sched-Plus-Schedist
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Sched-Plus-Schedist
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchSchedPlusSchedist
+name: ms-Exch-Sched-Plus-Schedist
+schemaIDGUID: b1fce94c-1d44-11d3-aa5e-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Schema-Policy-Consumers
+# A link to all CAs that use this schema policy.
+#
+dn: CN=ms-Exch-Schema-Policy-Consumers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Schema-Policy-Consumers
+distinguishedName: CN=ms-Exch-Schema-Policy-Consumers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.57
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1007
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Schema-Policy-Consumers
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Schema-Policy-Consumers
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchSchemaPolicyConsumers
+name: ms-Exch-Schema-Policy-Consumers
+schemaIDGUID: 20c6f7d6-b098-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Schema-Version-Adc
+#
+dn: CN=ms-Exch-Schema-Version-Adc,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Schema-Version-Adc
+distinguishedName: CN=ms-Exch-Schema-Version-Adc,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.98
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 4197
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Schema-Version-Adc
+adminDescription: ms-Exch-Schema-Version-Adc
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSchemaVersionAdc
+name: ms-Exch-Schema-Version-Adc
+schemaIDGUID: 60735c93-c60e-405e-b5ea-cb31f68ad548
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Schema-Version-Pt
+#
+dn: CN=ms-Exch-Schema-Version-Pt,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Schema-Version-Pt
+distinguishedName: CN=ms-Exch-Schema-Version-Pt,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.97
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 6870
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Schema-Version-Pt
+adminDescription: ms-Exch-Schema-Version-Pt
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSchemaVersionPt
+name: ms-Exch-Schema-Version-Pt
+schemaIDGUID: 5f8198d5-e7c9-4560-b166-08dc7cfc17c1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Scope-Mask
+# Defines the networks that will accept and send client connections.
+#
+dn: CN=ms-Exch-Scope-Mask,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Scope-Mask
+distinguishedName: CN=ms-Exch-Scope-Mask,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9014
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Scope-Mask
+adminDescription: ms-Exch-Scope-Mask
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchScopeMask
+name: ms-Exch-Scope-Mask
+schemaIDGUID: 20fb6b92-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Search-Base
+#
+dn: CN=ms-Exch-Search-Base,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Search-Base
+distinguishedName: CN=ms-Exch-Search-Base,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.91
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Search-Base
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Search-Base
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchSearchBase
+name: ms-Exch-Search-Base
+schemaIDGUID: 1884a3fe-efcb-47b0-bbd4-a91ef8cd4cb4
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Search-Scope
+#
+dn: CN=ms-Exch-Search-Scope,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Search-Scope
+distinguishedName: CN=ms-Exch-Search-Scope,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.92
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Search-Scope
+adminDescription: ms-Exch-Search-Scope
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSearchScope
+name: ms-Exch-Search-Scope
+schemaIDGUID: 05ed1e50-31c8-4ed2-b01e-732dbf6dd344
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Secure-Bindings
+# The IP port binding for non-secure connections.
+#
+dn: CN=ms-Exch-Secure-Bindings,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Secure-Bindings
+distinguishedName: CN=ms-Exch-Secure-Bindings,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2002
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 512
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Secure-Bindings
+adminDescription: ms-Exch-Secure-Bindings
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSecureBindings
+name: ms-Exch-Secure-Bindings
+schemaIDGUID: 216ddc72-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Security-Password
+# Password for outbound security.
+#
+dn: CN=ms-Exch-Security-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Security-Password
+distinguishedName: CN=ms-Exch-Security-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5052
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Security-Password
+adminDescription: ms-Exch-Security-Password
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchSecurityPassword
+name: ms-Exch-Security-Password
+schemaIDGUID: b8d47e4e-4b78-11d3-aa75-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Security-Policy
+#
+dn: CN=ms-Exch-Security-Policy,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Security-Policy
+distinguishedName: CN=ms-Exch-Security-Policy,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.589
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 32767
+mAPIID: 35911
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Security-Policy
+adminDescription: ms-Exch-Security-Policy
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: securityPolicy
+name: ms-Exch-Security-Policy
+schemaIDGUID: 1677587b-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Security-Protocol
+#
+dn: CN=ms-Exch-Security-Protocol,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Security-Protocol
+distinguishedName: CN=ms-Exch-Security-Protocol,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.82
+attributeSyntax: 2.5.5.10
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 32823
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Security-Protocol
+adminDescription: ms-Exch-Security-Protocol
+oMSyntax: 4
+searchFlags: 16
+lDAPDisplayName: securityProtocol
+name: ms-Exch-Security-Protocol
+schemaIDGUID: bf967a30-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Send-EMail-Message
+#
+dn: CN=ms-Exch-Send-EMail-Message,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Send-EMail-Message
+distinguishedName: CN=ms-Exch-Send-EMail-Message,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.566
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 35889
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Send-EMail-Message
+adminDescription: ms-Exch-Send-EMail-Message
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: sendEMailMessage
+name: ms-Exch-Send-EMail-Message
+schemaIDGUID: a8df746e-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Send-TNEF
+# Determines whether or not Exchange Rich Text is sent to the domain
+# specified in the domain content configuration object.
+#
+dn: CN=ms-Exch-Send-TNEF,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Send-TNEF
+distinguishedName: CN=ms-Exch-Send-TNEF,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.492
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 33169
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Send-TNEF
+adminDescription: ms-Exch-Send-TNEF
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: sendTNEF
+name: ms-Exch-Send-TNEF
+schemaIDGUID: a8df746f-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server1-Always-Create-As
+# How X.500 objects are synchronized to this directory.
+#
+dn: CN=ms-Exch-Server1-Always-Create-As,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Always-Create-As
+distinguishedName: CN=ms-Exch-Server1-Always-Create-As,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.27
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Always-Create-As
+adminDescription: ms-Exch-Server1-Always-Create-As
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: msExchServer1AlwaysCreateAs
+name: ms-Exch-Server1-Always-Create-As
+schemaIDGUID: 222efaec-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server1-Authentication-Credentials
+# The user name to use to log on to the server for this directory.
+#
+dn: CN=ms-Exch-Server1-Authentication-Credentials,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Authentication-Credentials
+distinguishedName: CN=ms-Exch-Server1-Authentication-Credentials,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Authentication-Credentials
+adminDescription: ms-Exch-Server1-Authentication-Credentials
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer1AuthenticationCredentials
+name: ms-Exch-Server1-Authentication-Credentials
+schemaIDGUID: 225ea9f4-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server1-Authentication-Password
+# The password for the credentials specified for this directory.
+#
+dn: CN=ms-Exch-Server1-Authentication-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Authentication-Password
+distinguishedName: CN=ms-Exch-Server1-Authentication-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Authentication-Password
+adminDescription: ms-Exch-Server1-Authentication-Password
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchServer1AuthenticationPassword
+name: ms-Exch-Server1-Authentication-Password
+schemaIDGUID: 228bf6a2-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Server1-Authentication-Type
+# The type of authentication to the server for this directory.
+#
+dn: CN=ms-Exch-Server1-Authentication-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Authentication-Type
+distinguishedName: CN=ms-Exch-Server1-Authentication-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.7
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 5
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Authentication-Type
+adminDescription: ms-Exch-Server1-Authentication-Type
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: msExchServer1AuthenticationType
+name: ms-Exch-Server1-Authentication-Type
+schemaIDGUID: 22b94350-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server1-Deletion-Option
+# A flag used to determine how deletions are synchronized into this directory.
+#
+dn: CN=ms-Exch-Server1-Deletion-Option,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Deletion-Option
+distinguishedName: CN=ms-Exch-Server1-Deletion-Option,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.21
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Deletion-Option
+adminDescription: ms-Exch-Server1-Deletion-Option
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: msExchServer1DeletionOption
+name: ms-Exch-Server1-Deletion-Option
+schemaIDGUID: 22edb70c-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server1-Export-Containers
+# The DN of the default container to search for objects to synchronize.
+#
+dn: CN=ms-Exch-Server1-Export-Containers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Export-Containers
+distinguishedName: CN=ms-Exch-Server1-Export-Containers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.13
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Export-Containers
+adminDescription: ms-Exch-Server1-Export-Containers
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer1ExportContainers
+name: ms-Exch-Server1-Export-Containers
+schemaIDGUID: 231b03ba-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server1-Flags
+# Flags used for transitive replication work.
+#
+dn: CN=ms-Exch-Server1-Flags,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Flags
+distinguishedName: CN=ms-Exch-Server1-Flags,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.61
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Flags
+adminDescription: ms-Exch-Server1-Flags
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchServer1Flags
+name: ms-Exch-Server1-Flags
+schemaIDGUID: 234d151c-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server1-Highest-USN
+# The highwater mark update sequence number (USN) from the last
+# successful synchronization from this directory.
+#
+dn: CN=ms-Exch-Server1-Highest-USN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Highest-USN
+distinguishedName: CN=ms-Exch-Server1-Highest-USN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.29
+attributeSyntax: 2.5.5.16
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Highest-USN
+adminDescription: ms-Exch-Server1-Highest-USN
+oMSyntax: 65
+searchFlags: 0
+lDAPDisplayName: msExchServer1HighestUSN
+name: ms-Exch-Server1-Highest-USN
+schemaIDGUID: 237f267e-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server1-Highest-USN-Vector
+# Stores the vectors of update sequence numbers (USNs) and servers for
+# a given naming context (NC).
+#
+dn: CN=ms-Exch-Server1-Highest-USN-Vector,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Highest-USN-Vector
+distinguishedName: CN=ms-Exch-Server1-Highest-USN-Vector,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.86
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Highest-USN-Vector
+adminDescription: ms-Exch-Server1-Highest-USN-Vector
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer1HighestUSNVector
+name: ms-Exch-Server1-Highest-USN-Vector
+schemaIDGUID: 7fb58cd4-2a6e-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server1-Import-Container
+# The DN of the default container to write synchronized objects to.
+#
+dn: CN=ms-Exch-Server1-Import-Container,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Import-Container
+distinguishedName: CN=ms-Exch-Server1-Import-Container,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Import-Container
+adminDescription: ms-Exch-Server1-Import-Container
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer1ImportContainer
+name: ms-Exch-Server1-Import-Container
+schemaIDGUID: 23aed586-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server1-Is-Bridgehead
+# A flag to determine whether non-mailbox associated objects are
+# replicated over this particular connection agreement.
+#
+dn: CN=ms-Exch-Server1-Is-Bridgehead,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Is-Bridgehead
+distinguishedName: CN=ms-Exch-Server1-Is-Bridgehead,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.77
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Is-Bridgehead
+adminDescription: ms-Exch-Server1-Is-Bridgehead
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchServer1IsBridgehead
+name: ms-Exch-Server1-Is-Bridgehead
+schemaIDGUID: 90b71b6a-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server1-Last-Update-Time
+# The time of the most recent update from the last successful
+# synchronization from this directory.
+#
+dn: CN=ms-Exch-Server1-Last-Update-Time,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Last-Update-Time
+distinguishedName: CN=ms-Exch-Server1-Last-Update-Time,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.31
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Last-Update-Time
+adminDescription: ms-Exch-Server1-Last-Update-Time
+oMSyntax: 24
+searchFlags: 0
+lDAPDisplayName: msExchServer1LastUpdateTime
+name: ms-Exch-Server1-Last-Update-Time
+schemaIDGUID: 23e34942-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Server1-Network-Address
+# The network address of the server participating in this connection
+# agreement.
+#
+dn: CN=ms-Exch-Server1-Network-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Network-Address
+distinguishedName: CN=ms-Exch-Server1-Network-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.3
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 65535
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Network-Address
+adminDescription: ms-Exch-Server1-Network-Address
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer1NetworkAddress
+name: ms-Exch-Server1-Network-Address
+schemaIDGUID: 2412f84a-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server1-NT-Account-Domain
+# Domain in which Active Directory accounts should be created.
+#
+dn: CN=ms-Exch-Server1-NT-Account-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-NT-Account-Domain
+distinguishedName: CN=ms-Exch-Server1-NT-Account-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-NT-Account-Domain
+adminDescription: ms-Exch-Server1-NT-Account-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer1NTAccountDomain
+name: ms-Exch-Server1-NT-Account-Domain
+schemaIDGUID: 2449ce60-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server1-Object-Match
+# Contains the matching rules for this server.
+#
+dn: CN=ms-Exch-Server1-Object-Match,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Object-Match
+distinguishedName: CN=ms-Exch-Server1-Object-Match,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.54
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Object-Match
+adminDescription: ms-Exch-Server1-Object-Match
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer1ObjectMatch
+name: ms-Exch-Server1-Object-Match
+schemaIDGUID: 247bdfc2-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server1-Page-Size
+# The page size to request when searching this directory.
+#
+dn: CN=ms-Exch-Server1-Page-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Page-Size
+distinguishedName: CN=ms-Exch-Server1-Page-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.25
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 65535
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Page-Size
+adminDescription: ms-Exch-Server1-Page-Size
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchServer1PageSize
+name: ms-Exch-Server1-Page-Size
+schemaIDGUID: 24b0537e-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server1-Port
+# The LDAP port of the server for this directory.
+#
+dn: CN=ms-Exch-Server1-Port,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Port
+distinguishedName: CN=ms-Exch-Server1-Port,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 65535
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Port
+adminDescription: ms-Exch-Server1-Port
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchServer1Port
+name: ms-Exch-Server1-Port
+schemaIDGUID: 24e264e0-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server1-Schema-Map
+# The schema map to use when mapping from Active Directory to the
+# Exchange Directory Service (DS).
+#
+dn: CN=ms-Exch-Server1-Schema-Map,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Schema-Map
+distinguishedName: CN=ms-Exch-Server1-Schema-Map,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.17
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Schema-Map
+adminDescription: ms-Exch-Server1-Schema-Map
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer1SchemaMap
+name: ms-Exch-Server1-Schema-Map
+schemaIDGUID: 25193af6-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server1-Search-Filter
+# The search filter to use when searching this directory.
+#
+dn: CN=ms-Exch-Server1-Search-Filter,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Search-Filter
+distinguishedName: CN=ms-Exch-Server1-Search-Filter,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.19
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Search-Filter
+adminDescription: ms-Exch-Server1-Search-Filter
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer1SearchFilter
+name: ms-Exch-Server1-Search-Filter
+schemaIDGUID: 254daeb2-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server1-SSL-Port
+# The port to connect to for Secure Sockets Layer (SSL) connections.
+#
+dn: CN=ms-Exch-Server1-SSL-Port,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-SSL-Port
+distinguishedName: CN=ms-Exch-Server1-SSL-Port,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.39
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 65535
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-SSL-Port
+adminDescription: ms-Exch-Server1-SSL-Port
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchServer1SSLPort
+name: ms-Exch-Server1-SSL-Port
+schemaIDGUID: 258484c8-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Server1-Type
+# Identifies the type of server being connected to.
+#
+dn: CN=ms-Exch-Server1-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server1-Type
+distinguishedName: CN=ms-Exch-Server1-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.23
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 5
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server1-Type
+adminDescription: ms-Exch-Server1-Type
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: msExchServer1Type
+name: ms-Exch-Server1-Type
+schemaIDGUID: 25bb5ade-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server2-Always-Create-As
+# How X.500 objects are synchronized to this directory.
+#
+dn: CN=ms-Exch-Server2-Always-Create-As,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Always-Create-As
+distinguishedName: CN=ms-Exch-Server2-Always-Create-As,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.28
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Always-Create-As
+adminDescription: ms-Exch-Server2-Always-Create-As
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: msExchServer2AlwaysCreateAs
+name: ms-Exch-Server2-Always-Create-As
+schemaIDGUID: 25f95802-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server2-Authentication-Credentials
+# The user name to use to log on to the server for this directory.
+dn: CN=ms-Exch-Server2-Authentication-Credentials,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Authentication-Credentials
+distinguishedName: CN=ms-Exch-Server2-Authentication-Credentials,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.10
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Authentication-Credentials
+adminDescription: ms-Exch-Server2-Authentication-Credentials
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer2AuthenticationCredentials
+name: ms-Exch-Server2-Authentication-Credentials
+schemaIDGUID: 26329072-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server2-Authentication-Password
+# The password for the credentials specified for this directory.
+dn: CN=ms-Exch-Server2-Authentication-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Authentication-Password
+distinguishedName: CN=ms-Exch-Server2-Authentication-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Authentication-Password
+adminDescription: ms-Exch-Server2-Authentication-Password
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchServer2AuthenticationPassword
+name: ms-Exch-Server2-Authentication-Password
+schemaIDGUID: 266bc8e2-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server2-Authentication-Type
+# The type of authentication to the server for this directory.
+#
+dn: CN=ms-Exch-Server2-Authentication-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Authentication-Type
+distinguishedName: CN=ms-Exch-Server2-Authentication-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.8
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 5
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Authentication-Type
+adminDescription: ms-Exch-Server2-Authentication-Type
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: msExchServer2AuthenticationType
+name: ms-Exch-Server2-Authentication-Type
+schemaIDGUID: 26a50152-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server2-Deletion-Option
+# A flag used to determine how deletions are synchronized into this
+# directory.
+#
+dn: CN=ms-Exch-Server2-Deletion-Option,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Deletion-Option
+distinguishedName: CN=ms-Exch-Server2-Deletion-Option,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.22
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Deletion-Option
+adminDescription: ms-Exch-Server2-Deletion-Option
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: msExchServer2DeletionOption
+name: ms-Exch-Server2-Deletion-Option
+schemaIDGUID: 26e09c1c-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Server2-Export-Containers
+# The DN of the default container to search for objects to
+# synchronize.
+#
+dn: CN=ms-Exch-Server2-Export-Containers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Export-Containers
+distinguishedName: CN=ms-Exch-Server2-Export-Containers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.14
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Export-Containers
+adminDescription: ms-Exch-Server2-Export-Containers
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer2ExportContainers
+name: ms-Exch-Server2-Export-Containers
+schemaIDGUID: 27cca4ea-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server2-Flags
+# Flags for transitive replication work.
+#
+dn: CN=ms-Exch-Server2-Flags,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Flags
+distinguishedName: CN=ms-Exch-Server2-Flags,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.62
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Flags
+adminDescription: ms-Exch-Server2-Flags
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchServer2Flags
+name: ms-Exch-Server2-Flags
+schemaIDGUID: 28083fb4-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server2-Highest-USN
+# The highwater mark update sequence number (USN) from the last
+# successful synchronization from this directory.
+#
+dn: CN=ms-Exch-Server2-Highest-USN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Highest-USN
+distinguishedName: CN=ms-Exch-Server2-Highest-USN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.30
+attributeSyntax: 2.5.5.16
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Highest-USN
+adminDescription: ms-Exch-Server2-Highest-USN
+oMSyntax: 65
+searchFlags: 0
+lDAPDisplayName: msExchServer2HighestUSN
+name: ms-Exch-Server2-Highest-USN
+schemaIDGUID: 283a5116-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server2-Highest-USN-Vector
+# Stores the vectors of update sequence numbers (USNs) and servers for
+# a given naming context (NC).
+#
+dn: CN=ms-Exch-Server2-Highest-USN-Vector,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Highest-USN-Vector
+distinguishedName: CN=ms-Exch-Server2-Highest-USN-Vector,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.87
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Highest-USN-Vector
+adminDescription: ms-Exch-Server2-Highest-USN-Vector
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer2HighestUSNVector
+name: ms-Exch-Server2-Highest-USN-Vector
+schemaIDGUID: 7fb58cda-2a6e-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server2-Import-Container
+# The DN of the default container to write syncronized objects to.
+#
+dn: CN=ms-Exch-Server2-Import-Container,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Import-Container
+distinguishedName: CN=ms-Exch-Server2-Import-Container,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.16
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Import-Container
+adminDescription: ms-Exch-Server2-Import-Container
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer2ImportContainer
+name: ms-Exch-Server2-Import-Container
+schemaIDGUID: 286c6278-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server2-Is-Bridgehead
+# A flag to determine whether non-mailbox associated objects are
+# replicated over this particular connection agreement.
+#
+dn: CN=ms-Exch-Server2-Is-Bridgehead,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Is-Bridgehead
+distinguishedName: CN=ms-Exch-Server2-Is-Bridgehead,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.78
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Is-Bridgehead
+adminDescription: ms-Exch-Server2-Is-Bridgehead
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchServer2IsBridgehead
+name: ms-Exch-Server2-Is-Bridgehead
+schemaIDGUID: 90d619fc-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server2-Last-Update-Time
+# The time of the most recent update from last successful
+# syncronization from this directory.
+#
+dn: CN=ms-Exch-Server2-Last-Update-Time,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Last-Update-Time
+distinguishedName: CN=ms-Exch-Server2-Last-Update-Time,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.32
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Last-Update-Time
+adminDescription: ms-Exch-Server2-Last-Update-Time
+oMSyntax: 24
+searchFlags: 0
+lDAPDisplayName: msExchServer2LastUpdateTime
+name: ms-Exch-Server2-Last-Update-Time
+schemaIDGUID: 28a3388e-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server2-Network-Address
+# The network address of the server participating in the connection
+# agreement.
+#
+dn: CN=ms-Exch-Server2-Network-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Network-Address
+distinguishedName: CN=ms-Exch-Server2-Network-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.4
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 65535
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Network-Address
+adminDescription: ms-Exch-Server2-Network-Address
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer2NetworkAddress
+name: ms-Exch-Server2-Network-Address
+schemaIDGUID: 28d549f0-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Server2-NT-Account-Domain
+# The domain in which Active Directory accounts should be created.
+#
+dn: CN=ms-Exch-Server2-NT-Account-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-NT-Account-Domain
+distinguishedName: CN=ms-Exch-Server2-NT-Account-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.51
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-NT-Account-Domain
+adminDescription: ms-Exch-Server2-NT-Account-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer2NTAccountDomain
+name: ms-Exch-Server2-NT-Account-Domain
+schemaIDGUID: 2909bdac-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server2-Object-Match
+# Contains the matching rules for this server.
+#
+dn: CN=ms-Exch-Server2-Object-Match,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Object-Match
+distinguishedName: CN=ms-Exch-Server2-Object-Match,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.55
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Object-Match
+adminDescription: ms-Exch-Server2-Object-Match
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer2ObjectMatch
+name: ms-Exch-Server2-Object-Match
+schemaIDGUID: 293e3168-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server2-Page-Size
+# The page size to request when searching this directory.
+#
+dn: CN=ms-Exch-Server2-Page-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Page-Size
+distinguishedName: CN=ms-Exch-Server2-Page-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.26
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 65535
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Page-Size
+adminDescription: ms-Exch-Server2-Page-Size
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchServer2PageSize
+name: ms-Exch-Server2-Page-Size
+schemaIDGUID: 296de070-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server2-Port
+# The LDAP port of the server for this directory.
+#
+dn: CN=ms-Exch-Server2-Port,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Port
+distinguishedName: CN=ms-Exch-Server2-Port,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.6
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 65535
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Port
+adminDescription: ms-Exch-Server2-Port
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchServer2Port
+name: ms-Exch-Server2-Port
+schemaIDGUID: 29a4b686-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server2-Schema-Map
+# The schema map to use when mapping from the Exchange Directory
+# Service (DS) to Active Directory.
+#
+dn: CN=ms-Exch-Server2-Schema-Map,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Schema-Map
+distinguishedName: CN=ms-Exch-Server2-Schema-Map,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.18
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Schema-Map
+adminDescription: ms-Exch-Server2-Schema-Map
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer2SchemaMap
+name: ms-Exch-Server2-Schema-Map
+schemaIDGUID: 29d6c7e8-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server2-Search-Filter
+# The search filter to use when searching this directory.
+#
+dn: CN=ms-Exch-Server2-Search-Filter,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Search-Filter
+distinguishedName: CN=ms-Exch-Server2-Search-Filter,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.20
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Search-Filter
+adminDescription: ms-Exch-Server2-Search-Filter
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServer2SearchFilter
+name: ms-Exch-Server2-Search-Filter
+schemaIDGUID: 2a0b3ba4-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server2-SSL-Port
+# The port to connect to for SSL connections.
+#
+dn: CN=ms-Exch-Server2-SSL-Port,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-SSL-Port
+distinguishedName: CN=ms-Exch-Server2-SSL-Port,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.40
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 65535
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-SSL-Port
+adminDescription: ms-Exch-Server2-SSL-Port
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchServer2SSLPort
+name: ms-Exch-Server2-SSL-Port
+schemaIDGUID: 2a3faf60-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server2-Type
+# Identifies the type of server being connected to.
+#
+dn: CN=ms-Exch-Server2-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server2-Type
+distinguishedName: CN=ms-Exch-Server2-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.24
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 5
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server2-Type
+adminDescription: ms-Exch-Server2-Type
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: msExchServer2Type
+name: ms-Exch-Server2-Type
+schemaIDGUID: 2a74231c-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server-Auto-Start
+# Starts the service when the operating system is booted.
+dn: CN=ms-Exch-Server-Auto-Start,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server-Auto-Start
+distinguishedName: CN=ms-Exch-Server-Auto-Start,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2007
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server-Auto-Start
+adminDescription: ms-Exch-Server-Auto-Start
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchServerAutoStart
+name: ms-Exch-Server-Auto-Start
+schemaIDGUID: 21cf9cdc-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server-Bindings
+# The IP port binding for SSL connections.
+#
+dn: CN=ms-Exch-Server-Bindings,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server-Bindings
+distinguishedName: CN=ms-Exch-Server-Bindings,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.2001
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 512
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server-Bindings
+adminDescription: ms-Exch-Server-Bindings
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServerBindings
+name: ms-Exch-Server-Bindings
+schemaIDGUID: 2201ae3e-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server-Bindings-Filtering
+#
+dn: CN=ms-Exch-Server-Bindings-Filtering,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server-Bindings-Filtering
+distinguishedName: CN=ms-Exch-Server-Bindings-Filtering,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5072
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server-Bindings-Filtering
+adminDescription: ms-Exch-Server-Bindings-Filtering
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServerBindingsFiltering
+name: ms-Exch-Server-Bindings-Filtering
+schemaIDGUID: 61aedffa-34b4-4170-8bab-b8794e1cb4f4
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server-Bindings-Turflist
+#
+dn: CN=ms-Exch-Server-Bindings-Turflist,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server-Bindings-Turflist
+distinguishedName: CN=ms-Exch-Server-Bindings-Turflist,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12533
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server-Bindings-Turflist
+adminDescription: ms-Exch-Server-Bindings-Turflist
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServerBindingsTurflist
+name: ms-Exch-Server-Bindings-Turflist
+schemaIDGUID: 0b836d98-3b20-11d3-aa6f-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server-Global-Groups
+#
+dn: CN=ms-Exch-Server-Global-Groups,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server-Global-Groups
+distinguishedName: CN=ms-Exch-Server-Global-Groups,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50083
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server-Global-Groups
+adminDescription: ms-Exch-Server-Global-Groups
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchServerGlobalGroups
+name: ms-Exch-Server-Global-Groups
+schemaIDGUID: 419f00f6-fb22-4ea9-8113-ed928767baa5
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server-Groups
+# A link to all Exchange server groups within the organization.
+#
+dn: CN=ms-Exch-Server-Groups,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server-Groups
+distinguishedName: CN=ms-Exch-Server-Groups,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50055
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server-Groups
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Server-Groups
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchServerGroups
+name: ms-Exch-Server-Groups
+schemaIDGUID: 5fd75fb9-3819-4d25-b18e-7bce391d4767
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server-Local-Groups
+# Contains the domain local groups for each prepared domain.
+#
+dn: CN=ms-Exch-Server-Local-Groups,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server-Local-Groups
+distinguishedName: CN=ms-Exch-Server-Local-Groups,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50082
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server-Local-Groups
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Server-Local-Groups
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchServerLocalGroups
+name: ms-Exch-Server-Local-Groups
+schemaIDGUID: 924a0b14-ea4f-4627-abd1-adbc801c4b0b
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Server-Public-Key
+#
+dn: CN=ms-Exch-Server-Public-Key,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server-Public-Key
+distinguishedName: CN=ms-Exch-Server-Public-Key,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50063
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server-Public-Key
+adminDescription: ms-Exch-Server-Public-Key
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchServerPublicKey
+name: ms-Exch-Server-Public-Key
+schemaIDGUID: b83df2df-c304-4563-90fd-d38ec81b04cb
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Server-Role
+# Determines if this server is a front-end or back-end server.
+dn: CN=ms-Exch-Server-Role,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Server-Role
+distinguishedName: CN=ms-Exch-Server-Role,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15006
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Server-Role
+adminDescription: ms-Exch-Server-Role
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchServerRole
+name: ms-Exch-Server-Role
+schemaIDGUID: 8c8fc29e-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Service-Action-First
+#
+dn: CN=ms-Exch-Service-Action-First,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Service-Action-First
+distinguishedName: CN=ms-Exch-Service-Action-First,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.161
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 33073
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Service-Action-First
+adminDescription: ms-Exch-Service-Action-First
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: serviceActionFirst
+name: ms-Exch-Service-Action-First
+schemaIDGUID: a8df7470-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Service-Action-Other
+#
+dn: CN=ms-Exch-Service-Action-Other,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Service-Action-Other
+distinguishedName: CN=ms-Exch-Service-Action-Other,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.59
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 33074
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Service-Action-Other
+adminDescription: ms-Exch-Service-Action-Other
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: serviceActionOther
+name: ms-Exch-Service-Action-Other
+schemaIDGUID: a8df7471-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Service-Action-Second
+#
+dn: CN=ms-Exch-Service-Action-Second,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Service-Action-Second
+distinguishedName: CN=ms-Exch-Service-Action-Second,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.60
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+mAPIID: 33075
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Service-Action-Second
+adminDescription: ms-Exch-Service-Action-Second
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: serviceActionSecond
+name: ms-Exch-Service-Action-Second
+schemaIDGUID: a8df7472-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Service-Restart-Delay
+#
+dn: CN=ms-Exch-Service-Restart-Delay,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Service-Restart-Delay
+distinguishedName: CN=ms-Exch-Service-Restart-Delay,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.162
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33076
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Service-Restart-Delay
+adminDescription: ms-Exch-Service-Restart-Delay
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: serviceRestartDelay
+name: ms-Exch-Service-Restart-Delay
+schemaIDGUID: a8df7473-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Service-Restart-Message
+#
+dn: CN=ms-Exch-Service-Restart-Message,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Service-Restart-Message
+distinguishedName: CN=ms-Exch-Service-Restart-Message,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.58
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 120
+mAPIID: 33077
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Service-Restart-Message
+adminDescription: ms-Exch-Service-Restart-Message
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: serviceRestartMessage
+name: ms-Exch-Service-Restart-Message
+schemaIDGUID: a8df7474-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Session-Disconnect-Timer
+#
+dn: CN=ms-Exch-Session-Disconnect-Timer,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Session-Disconnect-Timer
+distinguishedName: CN=ms-Exch-Session-Disconnect-Timer,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.154
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33078
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Session-Disconnect-Timer
+adminDescription: ms-Exch-Session-Disconnect-Timer
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: sessionDisconnectTimer
+name: ms-Exch-Session-Disconnect-Timer
+schemaIDGUID: a8df7475-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Site-Folder-GUID
+# Contains a random unused GUID which is used by the store when
+# creating the public folder for this OAB.
+#
+dn: CN=ms-Exch-Site-Folder-GUID,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Site-Folder-GUID
+distinguishedName: CN=ms-Exch-Site-Folder-GUID,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.456
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+mAPIID: 33126
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Site-Folder-GUID
+adminDescription: ms-Exch-Site-Folder-GUID
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: siteFolderGUID
+name: ms-Exch-Site-Folder-GUID
+schemaIDGUID: a8df7477-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Site-Folder-Server
+#
+dn: CN=ms-Exch-Site-Folder-Server,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Site-Folder-Server
+distinguishedName: CN=ms-Exch-Site-Folder-Server,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.457
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+mAPIID: 33127
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Site-Folder-Server
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Site-Folder-Server
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: siteFolderServer
+name: ms-Exch-Site-Folder-Server
+schemaIDGUID: a8df7478-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Site-Proxy-Space
+#
+dn: CN=ms-Exch-Site-Proxy-Space,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Site-Proxy-Space
+distinguishedName: CN=ms-Exch-Site-Proxy-Space,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.385
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 1123
+mAPIID: 33080
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Site-Proxy-Space
+adminDescription: ms-Exch-Site-Proxy-Space
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: siteProxySpace
+name: ms-Exch-Site-Proxy-Space
+schemaIDGUID: a8df7479-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-SLV-File
+# The database file location for this store.
+dn: CN=ms-Exch-SLV-File,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-SLV-File
+distinguishedName: CN=ms-Exch-SLV-File,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11036
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-SLV-File
+adminDescription: ms-Exch-SLV-File
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchSLVFile
+name: ms-Exch-SLV-File
+schemaIDGUID: 2aaaf932-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-SMIME-Alg-List-NA
+# The list of supported algorithms in North America by Microsoft
+# Outlook clients. This list should never be modified.
+#
+dn: CN=ms-Exch-SMIME-Alg-List-NA,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-SMIME-Alg-List-NA
+distinguishedName: CN=ms-Exch-SMIME-Alg-List-NA,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.568
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 35891
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-SMIME-Alg-List-NA
+adminDescription: ms-Exch-SMIME-Alg-List-NA
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: sMIMEAlgListNA
+name: ms-Exch-SMIME-Alg-List-NA
+schemaIDGUID: a8df747a-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-SMIME-Alg-List-Other
+# The list of non-North America algorithms supported by Outlook.
+#
+dn: CN=ms-Exch-SMIME-Alg-List-Other,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-SMIME-Alg-List-Other
+distinguishedName: CN=ms-Exch-SMIME-Alg-List-Other,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.569
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 35892
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-SMIME-Alg-List-Other
+adminDescription: ms-Exch-SMIME-Alg-List-Other
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: sMIMEAlgListOther
+name: ms-Exch-SMIME-Alg-List-Other
+schemaIDGUID: a8df747b-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-SMIME-Alg-Selected-NA
+# The currently-selected algorithm for North America Outlook users.
+#
+dn: CN=ms-Exch-SMIME-Alg-Selected-NA,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-SMIME-Alg-Selected-NA
+distinguishedName: CN=ms-Exch-SMIME-Alg-Selected-NA,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.570
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 35893
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-SMIME-Alg-Selected-NA
+adminDescription: ms-Exch-SMIME-Alg-Selected-NA
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: sMIMEAlgSelectedNA
+name: ms-Exch-SMIME-Alg-Selected-NA
+schemaIDGUID: a8df747c-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-SMIME-Alg-Selected-Other
+# The selected algorithm for non-North America Outlook users.
+#
+dn: CN=ms-Exch-SMIME-Alg-Selected-Other,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-SMIME-Alg-Selected-Other
+distinguishedName: CN=ms-Exch-SMIME-Alg-Selected-Other,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.571
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 35894
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-SMIME-Alg-Selected-Other
+adminDescription: ms-Exch-SMIME-Alg-Selected-Other
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: sMIMEAlgSelectedOther
+name: ms-Exch-SMIME-Alg-Selected-Other
+schemaIDGUID: a8df747d-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Authorized-TRN-Accounts
+# The list of all accounts that are authorized to use TRN.
+#
+dn: CN=ms-Exch-Smtp-Authorized-TRN-Accounts,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Authorized-TRN-Accounts
+distinguishedName: CN=ms-Exch-Smtp-Authorized-TRN-Accounts,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5047
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Authorized-TRN-Accounts
+adminDescription: ms-Exch-Smtp-Authorized-TRN-Accounts
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpAuthorizedTRNAccounts
+name: ms-Exch-Smtp-Authorized-TRN-Accounts
+schemaIDGUID: 2b164304-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Smtp-Bad-Mail-Directory
+# Location where bad mail messages are stored.
+#
+dn: CN=ms-Exch-Smtp-Bad-Mail-Directory,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Bad-Mail-Directory
+distinguishedName: CN=ms-Exch-Smtp-Bad-Mail-Directory,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5025
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Bad-Mail-Directory
+adminDescription: ms-Exch-Smtp-Bad-Mail-Directory
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpBadMailDirectory
+name: ms-Exch-Smtp-Bad-Mail-Directory
+schemaIDGUID: 2b5904dc-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Connection-Rules-Priority
+#
+dn: CN=ms-Exch-Smtp-Connection-Rules-Priority,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Connection-Rules-Priority
+distinguishedName: CN=ms-Exch-Smtp-Connection-Rules-Priority,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5064
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Connection-Rules-Priority
+adminDescription: ms-Exch-Smtp-Connection-Rules-Priority
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchSmtpConnectionRulesPriority
+name: ms-Exch-Smtp-Connection-Rules-Priority
+schemaIDGUID: 86c24f8c-259b-4f19-88b9-9c9445936121
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Connection-Turf-List-Display
+#
+dn: CN=ms-Exch-Smtp-Connection-Turf-List-Display,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Connection-Turf-List-Display
+distinguishedName: CN=ms-Exch-Smtp-Connection-Turf-List-Display,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5065
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Connection-Turf-List-Display
+adminDescription: ms-Exch-Smtp-Connection-Turf-List-Display
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpConnectionTurfListDisplay
+name: ms-Exch-Smtp-Connection-Turf-List-Display
+schemaIDGUID: 73fb04ac-b2d4-4a4d-8520-757dd3c9261a
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Connection-Turf-List-DNS
+#
+dn: CN=ms-Exch-Smtp-Connection-Turf-List-DNS,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Connection-Turf-List-DNS
+distinguishedName: CN=ms-Exch-Smtp-Connection-Turf-List-DNS,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5067
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Connection-Turf-List-DNS
+adminDescription: ms-Exch-Smtp-Connection-Turf-List-DNS
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpConnectionTurfListDNS
+name: ms-Exch-Smtp-Connection-Turf-List-DNS
+schemaIDGUID: 3fee7de6-d3e5-43cb-8459-f7a072ae3789
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Connection-Turf-List-Mask
+#
+dn: CN=ms-Exch-Smtp-Connection-Turf-List-Mask,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Connection-Turf-List-Mask
+distinguishedName: CN=ms-Exch-Smtp-Connection-Turf-List-Mask,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5069
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Connection-Turf-List-Mask
+adminDescription: ms-Exch-Smtp-Connection-Turf-List-Mask
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpConnectionTurfListMask
+name: ms-Exch-Smtp-Connection-Turf-List-Mask
+schemaIDGUID: bc0241af-9d38-4c40-842e-51d802506de5
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Connection-Turf-List-Options
+#
+dn: CN=ms-Exch-Smtp-Connection-Turf-List-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Connection-Turf-List-Options
+distinguishedName: CN=ms-Exch-Smtp-Connection-Turf-List-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5066
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Connection-Turf-List-Options
+adminDescription: ms-Exch-Smtp-Connection-Turf-List-Options
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpConnectionTurfListOptions
+name: ms-Exch-Smtp-Connection-Turf-List-Options
+schemaIDGUID: 5ae62360-1105-4d8b-8a1e-a2c793b4d57d
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Connection-Turf-List-Response
+#
+dn: CN=ms-Exch-Smtp-Connection-Turf-List-Response,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Connection-Turf-List-Response
+distinguishedName: CN=ms-Exch-Smtp-Connection-Turf-List-Response,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5068
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Connection-Turf-List-Response
+adminDescription: ms-Exch-Smtp-Connection-Turf-List-Response
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpConnectionTurfListResponse
+name: ms-Exch-Smtp-Connection-Turf-List-Response
+schemaIDGUID: eeddd98f-da01-4ecb-a65e-5f016f1d8032
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Connection-Whitelist
+#
+dn: CN=ms-Exch-Smtp-Connection-Whitelist,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Connection-Whitelist
+distinguishedName: CN=ms-Exch-Smtp-Connection-Whitelist,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5063
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Connection-Whitelist
+adminDescription: ms-Exch-Smtp-Connection-Whitelist
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpConnectionWhitelist
+name: ms-Exch-Smtp-Connection-Whitelist
+schemaIDGUID: 87cf463a-561e-45ce-a0ba-6d528f111d23
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Domain-String
+# The drop directory of the domain or route domain.
+#
+dn: CN=ms-Exch-Smtp-Domain-String,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Domain-String
+distinguishedName: CN=ms-Exch-Smtp-Domain-String,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5033
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Domain-String
+adminDescription: ms-Exch-Smtp-Domain-String
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpDomainString
+name: ms-Exch-Smtp-Domain-String
+schemaIDGUID: 2bd03a70-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Do-Masquerade
+# If set, use the Masquerade domain.
+#
+dn: CN=ms-Exch-Smtp-Do-Masquerade,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Do-Masquerade
+distinguishedName: CN=ms-Exch-Smtp-Do-Masquerade,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5022
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Do-Masquerade
+adminDescription: ms-Exch-Smtp-Do-Masquerade
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchSmtpDoMasquerade
+name: ms-Exch-Smtp-Do-Masquerade
+schemaIDGUID: 2b949fa6-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Drop-Directory
+# The directory where mail messages are being dropped.
+#
+dn: CN=ms-Exch-Smtp-Drop-Directory,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Drop-Directory
+distinguishedName: CN=ms-Exch-Smtp-Drop-Directory,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5032
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Drop-Directory
+adminDescription: ms-Exch-Smtp-Drop-Directory
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpDropDirectory
+name: ms-Exch-Smtp-Drop-Directory
+schemaIDGUID: 2c260f18-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Ds-Data-Directory
+# The data directory for DSAccess.
+#
+dn: CN=ms-Exch-Smtp-Ds-Data-Directory,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Ds-Data-Directory
+distinguishedName: CN=ms-Exch-Smtp-Ds-Data-Directory,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5036
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Ds-Data-Directory
+adminDescription: ms-Exch-Smtp-Ds-Data-Directory
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpDsDataDirectory
+name: ms-Exch-Smtp-Ds-Data-Directory
+schemaIDGUID: 2c6d95a4-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Ds-Default-Mail-Root
+# The default mail root for DSAccess.
+#
+dn: CN=ms-Exch-Smtp-Ds-Default-Mail-Root,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Ds-Default-Mail-Root
+distinguishedName: CN=ms-Exch-Smtp-Ds-Default-Mail-Root,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5037
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Ds-Default-Mail-Root
+adminDescription: ms-Exch-Smtp-Ds-Default-Mail-Root
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpDsDefaultMailRoot
+name: ms-Exch-Smtp-Ds-Default-Mail-Root
+schemaIDGUID: 2cadf522-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Ds-Domain
+# The default mail root for DSAccess.
+#
+dn: CN=ms-Exch-Smtp-Ds-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Ds-Domain
+distinguishedName: CN=ms-Exch-Smtp-Ds-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5038
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Ds-Domain
+adminDescription: ms-Exch-Smtp-Ds-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpDsDomain
+name: ms-Exch-Smtp-Ds-Domain
+schemaIDGUID: 2ce72d92-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Ds-Flags
+#
+dn: CN=ms-Exch-Smtp-Ds-Flags,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Ds-Flags
+distinguishedName: CN=ms-Exch-Smtp-Ds-Flags,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5049
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Ds-Flags
+adminDescription: ms-Exch-Smtp-Ds-Flags
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpDsFlags
+name: ms-Exch-Smtp-Ds-Flags
+schemaIDGUID: 2d206602-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Ds-Host
+# The host to connect in DSAccess.
+#
+dn: CN=ms-Exch-Smtp-Ds-Host,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Ds-Host
+distinguishedName: CN=ms-Exch-Smtp-Ds-Host,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5042
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Ds-Host
+adminDescription: ms-Exch-Smtp-Ds-Host
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpDsHost
+name: ms-Exch-Smtp-Ds-Host
+schemaIDGUID: 2d599e72-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Ds-Port
+# The port to use in DSAccess.
+#
+dn: CN=ms-Exch-Smtp-Ds-Port,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Ds-Port
+distinguishedName: CN=ms-Exch-Smtp-Ds-Port,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5017
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Ds-Port
+adminDescription: ms-Exch-Smtp-Ds-Port
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpDsPort
+name: ms-Exch-Smtp-Ds-Port
+schemaIDGUID: 2d92d6e2-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Enable-EXPN
+#
+dn: CN=ms-Exch-Smtp-Enable-EXPN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Enable-EXPN
+distinguishedName: CN=ms-Exch-Smtp-Enable-EXPN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12537
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Enable-EXPN
+adminDescription: ms-Exch-Smtp-Enable-EXPN
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchSmtpEnableEXPN
+name: ms-Exch-Smtp-Enable-EXPN
+schemaIDGUID: e24d7a86-439d-11d3-aa72-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Smtp-Enable-Ldap-Routing
+# Configures the directory that this resource uses to route mail.
+#
+dn: CN=ms-Exch-Smtp-Enable-Ldap-Routing,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Enable-Ldap-Routing
+distinguishedName: CN=ms-Exch-Smtp-Enable-Ldap-Routing,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5019
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Enable-Ldap-Routing
+adminDescription: ms-Exch-Smtp-Enable-Ldap-Routing
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpEnableLdapRouting
+name: ms-Exch-Smtp-Enable-Ldap-Routing
+schemaIDGUID: 2dce71ac-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Enable-VRFY
+#
+dn: CN=ms-Exch-Smtp-Enable-VRFY,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Enable-VRFY
+distinguishedName: CN=ms-Exch-Smtp-Enable-VRFY,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12536
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Enable-VRFY
+adminDescription: ms-Exch-Smtp-Enable-VRFY
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchSmtpEnableVRFY
+name: ms-Exch-Smtp-Enable-VRFY
+schemaIDGUID: e24d7a80-439d-11d3-aa72-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-External-DNS-Servers
+# Contains the IP addresses of DNS servers that should be used by this
+# SMTP virtual server.
+#
+dn: CN=ms-Exch-Smtp-External-DNS-Servers,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-External-DNS-Servers
+distinguishedName: CN=ms-Exch-Smtp-External-DNS-Servers,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5056
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-External-DNS-Servers
+adminDescription: ms-Exch-Smtp-External-DNS-Servers
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpExternalDNSServers
+name: ms-Exch-Smtp-External-DNS-Servers
+schemaIDGUID: a1826432-f85e-42b6-b55d-1249ed2f78a3
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Fully-Qualified-Domain-Name
+# The Fully Qualified Domain Name for this virtual server.
+#
+dn: CN=ms-Exch-Smtp-Fully-Qualified-Domain-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Fully-Qualified-Domain-Name
+distinguishedName: CN=ms-Exch-Smtp-Fully-Qualified-Domain-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5029
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Fully-Qualified-Domain-Name
+adminDescription: ms-Exch-Smtp-Fully-Qualified-Domain-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpFullyQualifiedDomainName
+name: ms-Exch-Smtp-Fully-Qualified-Domain-Name
+schemaIDGUID: 2e0547c2-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-SMTP-Global-IP-Accept-List
+#
+dn: CN=ms-Exch-SMTP-Global-IP-Accept-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-SMTP-Global-IP-Accept-List
+distinguishedName: CN=ms-Exch-SMTP-Global-IP-Accept-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5073
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-SMTP-Global-IP-Accept-List
+adminDescription: ms-Exch-SMTP-Global-IP-Accept-List
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchSMTPGlobalIPAcceptList
+name: ms-Exch-SMTP-Global-IP-Accept-List
+schemaIDGUID: 752cd028-a935-40aa-8f8b-14aeb4433c93
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-SMTP-Global-IP-Deny-List
+#
+dn: CN=ms-Exch-SMTP-Global-IP-Deny-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-SMTP-Global-IP-Deny-List
+distinguishedName: CN=ms-Exch-SMTP-Global-IP-Deny-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5074
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-SMTP-Global-IP-Deny-List
+adminDescription: ms-Exch-SMTP-Global-IP-Deny-List
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchSMTPGlobalIPDenyList
+name: ms-Exch-SMTP-Global-IP-Deny-List
+schemaIDGUID: 61e731dc-484d-4566-8aac-c54747f13cc4
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Inbound-Command-Support-Options
+# The TLF encryption flag used for basic authentication.
+#
+dn: CN=ms-Exch-Smtp-Inbound-Command-Support-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Inbound-Command-Support-Options
+distinguishedName: CN=ms-Exch-Smtp-Inbound-Command-Support-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5018
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Inbound-Command-Support-Options
+adminDescription: ms-Exch-Smtp-Inbound-Command-Support-Options
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpInboundCommandSupportOptions
+name: ms-Exch-Smtp-Inbound-Command-Support-Options
+schemaIDGUID: 2e40e28c-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Ldap-Account
+# The LDAP account to use in DSAccess.
+dn: CN=ms-Exch-Smtp-Ldap-Account,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Ldap-Account
+distinguishedName: CN=ms-Exch-Smtp-Ldap-Account,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5044
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Ldap-Account
+adminDescription: ms-Exch-Smtp-Ldap-Account
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpLdapAccount
+name: ms-Exch-Smtp-Ldap-Account
+schemaIDGUID: 2e7c7d56-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Ldap-Bind-Type
+# The bind type to use in DSAccess.
+dn: CN=ms-Exch-Smtp-Ldap-Bind-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Ldap-Bind-Type
+distinguishedName: CN=ms-Exch-Smtp-Ldap-Bind-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5040
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Ldap-Bind-Type
+adminDescription: ms-Exch-Smtp-Ldap-Bind-Type
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpLdapBindType
+name: ms-Exch-Smtp-Ldap-Bind-Type
+schemaIDGUID: 2ebcdcd4-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Ldap-Naming-Context
+# The naming context to use in DSAccess.
+#
+dn: CN=ms-Exch-Smtp-Ldap-Naming-Context,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Ldap-Naming-Context
+distinguishedName: CN=ms-Exch-Smtp-Ldap-Naming-Context,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5043
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Ldap-Naming-Context
+adminDescription: ms-Exch-Smtp-Ldap-Naming-Context
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpLdapNamingContext
+name: ms-Exch-Smtp-Ldap-Naming-Context
+schemaIDGUID: 2ef61544-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Ldap-Password
+# The LDAP password to use in DSAccess.
+#
+dn: CN=ms-Exch-Smtp-Ldap-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Ldap-Password
+distinguishedName: CN=ms-Exch-Smtp-Ldap-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5045
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Ldap-Password
+adminDescription: ms-Exch-Smtp-Ldap-Password
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpLdapPassword
+name: ms-Exch-Smtp-Ldap-Password
+schemaIDGUID: 2f2f4db4-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Ldap-Schema-Type
+# The schema type to use in DSAccess.
+dn: CN=ms-Exch-Smtp-Ldap-Schema-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Ldap-Schema-Type
+distinguishedName: CN=ms-Exch-Smtp-Ldap-Schema-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5041
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Ldap-Schema-Type
+adminDescription: ms-Exch-Smtp-Ldap-Schema-Type
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpLdapSchemaType
+name: ms-Exch-Smtp-Ldap-Schema-Type
+schemaIDGUID: 2f688624-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Local-Queue-Delay-Notification
+# The time at which this resource should send a notification regarding
+# a local undelivered message.
+#
+dn: CN=ms-Exch-Smtp-Local-Queue-Delay-Notification,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Local-Queue-Delay-Notification
+distinguishedName: CN=ms-Exch-Smtp-Local-Queue-Delay-Notification,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5011
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Local-Queue-Delay-Notification
+adminDescription: ms-Exch-Smtp-Local-Queue-Delay-Notification
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpLocalQueueDelayNotification
+name: ms-Exch-Smtp-Local-Queue-Delay-Notification
+schemaIDGUID: 2f9f5c3a-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Smtp-Local-Queue-Expiration-Timeout
+# The time at which this resource should expire a local undelivered message.
+#
+dn: CN=ms-Exch-Smtp-Local-Queue-Expiration-Timeout,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Local-Queue-Expiration-Timeout
+distinguishedName: CN=ms-Exch-Smtp-Local-Queue-Expiration-Timeout,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5010
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Local-Queue-Expiration-Timeout
+adminDescription: ms-Exch-Smtp-Local-Queue-Expiration-Timeout
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpLocalQueueExpirationTimeout
+name: ms-Exch-Smtp-Local-Queue-Expiration-Timeout
+schemaIDGUID: 40bd7e66-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Masquerade-Domain
+# The domain that mail outbound from this resource is masqueraded as.
+#
+dn: CN=ms-Exch-Smtp-Masquerade-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Masquerade-Domain
+distinguishedName: CN=ms-Exch-Smtp-Masquerade-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5026
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Masquerade-Domain
+adminDescription: ms-Exch-Smtp-Masquerade-Domain
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpMasqueradeDomain
+name: ms-Exch-Smtp-Masquerade-Domain
+schemaIDGUID: 40eacb14-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Max-Hop-Count
+# The maximum number of hops that the message transported by this
+# resource can take.
+#
+dn: CN=ms-Exch-Smtp-Max-Hop-Count,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Max-Hop-Count
+distinguishedName: CN=ms-Exch-Smtp-Max-Hop-Count,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5006
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Max-Hop-Count
+adminDescription: ms-Exch-Smtp-Max-Hop-Count
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpMaxHopCount
+name: ms-Exch-Smtp-Max-Hop-Count
+schemaIDGUID: 411817c2-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Smtp-Max-Message-Size
+# The maximum size that a message delivered by this resource can be.
+#
+dn: CN=ms-Exch-Smtp-Max-Message-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Max-Message-Size
+distinguishedName: CN=ms-Exch-Smtp-Max-Message-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5007
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Max-Message-Size
+adminDescription: ms-Exch-Smtp-Max-Message-Size
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpMaxMessageSize
+name: ms-Exch-Smtp-Max-Message-Size
+schemaIDGUID: 4147c6ca-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain
+# The maximum number of messages delivered for connections outgoing
+# from each domain of this resource.
+#
+dn: CN=ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain
+distinguishedName: CN=ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5015
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain
+adminDescription: ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpMaxOutboundMsgPerDomain
+name: ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain
+schemaIDGUID: 417775d2-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain-Flag
+# The maximum number of outbound messages per domain.
+#
+dn: CN=ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain-Flag,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain-Flag
+distinguishedName: CN=ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain-Flag,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5023
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain-Flag
+adminDescription: ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain-Flag
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchSmtpMaxOutboundMsgPerDomainFlag
+name: ms-Exch-Smtp-Max-Outbound-Msg-Per-Domain-Flag
+schemaIDGUID: 41a724da-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Max-Outgoing-Connections
+# The maximum number of connections outgoing from this resource.
+#
+dn: CN=ms-Exch-Smtp-Max-Outgoing-Connections,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Max-Outgoing-Connections
+distinguishedName: CN=ms-Exch-Smtp-Max-Outgoing-Connections,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5001
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Max-Outgoing-Connections
+adminDescription: ms-Exch-Smtp-Max-Outgoing-Connections
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpMaxOutgoingConnections
+name: ms-Exch-Smtp-Max-Outgoing-Connections
+schemaIDGUID: 41d9363c-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Max-Outgoing-Connections-Per-Domain
+# The maximum length of time for connections outgoing from each domain
+# of this resource.
+#
+dn: CN=ms-Exch-Smtp-Max-Outgoing-Connections-Per-Domain,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Max-Outgoing-Connections-Per-Domain
+distinguishedName: CN=ms-Exch-Smtp-Max-Outgoing-Connections-Per-Domain,CN=Sche
+attributeID: 1.2.840.113556.1.4.7000.102.5003
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Max-Outgoing-Connections-Per-Domain
+adminDescription: ms-Exch-Smtp-Max-Outgoing-Connections-Per-Domain
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpMaxOutgoingConnectionsPerDomain
+name: ms-Exch-Smtp-Max-Outgoing-Connections-Per-Domain
+schemaIDGUID: 420b479e-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Max-Recipients
+# The maximum number of recipients allowed on a message transferred by
+# this resource.
+#
+dn: CN=ms-Exch-Smtp-Max-Recipients,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Max-Recipients
+distinguishedName: CN=ms-Exch-Smtp-Max-Recipients,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5009
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Max-Recipients
+adminDescription: ms-Exch-Smtp-Max-Recipients
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpMaxRecipients
+name: ms-Exch-Smtp-Max-Recipients
+schemaIDGUID: 423af6a6-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Max-Session-Size
+#
+dn: CN=ms-Exch-Smtp-Max-Session-Size,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Max-Session-Size
+distinguishedName: CN=ms-Exch-Smtp-Max-Session-Size,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5008
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Max-Session-Size
+adminDescription: ms-Exch-Smtp-Max-Session-Size
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpMaxSessionSize
+name: ms-Exch-Smtp-Max-Session-Size
+schemaIDGUID: 426aa5ae-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Outbound-Security-Flag
+# Configures which authentication is used when connecting outbound
+# from this resource.
+#
+dn: CN=ms-Exch-Smtp-Outbound-Security-Flag,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Outbound-Security-Flag
+distinguishedName: CN=ms-Exch-Smtp-Outbound-Security-Flag,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5016
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Outbound-Security-Flag
+adminDescription: ms-Exch-Smtp-Outbound-Security-Flag
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpOutboundSecurityFlag
+name: ms-Exch-Smtp-Outbound-Security-Flag
+schemaIDGUID: 429cb710-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Outbound-Security-Password
+# The password for outbound security.
+#
+dn: CN=ms-Exch-Smtp-Outbound-Security-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Outbound-Security-Password
+distinguishedName: CN=ms-Exch-Smtp-Outbound-Security-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5035
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Outbound-Security-Password
+adminDescription: ms-Exch-Smtp-Outbound-Security-Password
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpOutboundSecurityPassword
+name: ms-Exch-Smtp-Outbound-Security-Password
+schemaIDGUID: 42edc704-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Outbound-Security-User-Name
+# User name for outbound security.
+#
+dn: CN=ms-Exch-Smtp-Outbound-Security-User-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Outbound-Security-User-Name
+distinguishedName: CN=ms-Exch-Smtp-Outbound-Security-User-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5034
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Outbound-Security-User-Name
+adminDescription: ms-Exch-Smtp-Outbound-Security-User-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpOutboundSecurityUserName
+name: ms-Exch-Smtp-Outbound-Security-User-Name
+schemaIDGUID: 43249d1a-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Outgoing-Connection-Timeout
+# The maximum length of time for connections outgoing from this resource.
+#
+dn: CN=ms-Exch-Smtp-Outgoing-Connection-Timeout,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Outgoing-Connection-Timeout
+distinguishedName: CN=ms-Exch-Smtp-Outgoing-Connection-Timeout,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5002
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Outgoing-Connection-Timeout
+adminDescription: ms-Exch-Smtp-Outgoing-Connection-Timeout
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpOutgoingConnectionTimeout
+name: ms-Exch-Smtp-Outgoing-Connection-Timeout
+schemaIDGUID: 436037e4-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Smtp-Outgoing-Port
+# The outbound connection port number.
+#
+dn: CN=ms-Exch-Smtp-Outgoing-Port,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Outgoing-Port
+distinguishedName: CN=ms-Exch-Smtp-Outgoing-Port,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5004
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Outgoing-Port
+adminDescription: ms-Exch-Smtp-Outgoing-Port
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpOutgoingPort
+name: ms-Exch-Smtp-Outgoing-Port
+schemaIDGUID: 43b3aa32-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+#
+# ms-Exch-Smtp-Outgoing-Secure-Port
+# The outbound connection SSL port number.
+#
+dn: CN=ms-Exch-Smtp-Outgoing-Secure-Port,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Outgoing-Secure-Port
+distinguishedName: CN=ms-Exch-Smtp-Outgoing-Secure-Port,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5005
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Outgoing-Secure-Port
+adminDescription: ms-Exch-Smtp-Outgoing-Secure-Port
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpOutgoingSecurePort
+name: ms-Exch-Smtp-Outgoing-Secure-Port
+schemaIDGUID: 43f1a756-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Perform-Reverse-Dns-Lookup
+# Performs reverse DNS lookup for delivery.
+#
+dn: CN=ms-Exch-Smtp-Perform-Reverse-Dns-Lookup,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Perform-Reverse-Dns-Lookup
+distinguishedName: CN=ms-Exch-Smtp-Perform-Reverse-Dns-Lookup,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5021
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Perform-Reverse-Dns-Lookup
+adminDescription: ms-Exch-Smtp-Perform-Reverse-Dns-Lookup
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchSmtpPerformReverseDnsLookup
+name: ms-Exch-Smtp-Perform-Reverse-Dns-Lookup
+schemaIDGUID: 441ef404-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Pickup-Directory
+# The directory from which mail messages are being picked up.
+#
+dn: CN=ms-Exch-Smtp-Pickup-Directory,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Pickup-Directory
+distinguishedName: CN=ms-Exch-Smtp-Pickup-Directory,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5030
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Pickup-Directory
+adminDescription: ms-Exch-Smtp-Pickup-Directory
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpPickupDirectory
+name: ms-Exch-Smtp-Pickup-Directory
+schemaIDGUID: 444054f0-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Queue-Directory
+# The directory where mail messages are being queued.
+#
+dn: CN=ms-Exch-Smtp-Queue-Directory,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Queue-Directory
+distinguishedName: CN=ms-Exch-Smtp-Queue-Directory,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5031
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Queue-Directory
+adminDescription: ms-Exch-Smtp-Queue-Directory
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpQueueDirectory
+name: ms-Exch-Smtp-Queue-Directory
+schemaIDGUID: 4468dcea-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Relay-For-Auth
+# Checks if the relay IP requires authentication.
+#
+dn: CN=ms-Exch-Smtp-Relay-For-Auth,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Relay-For-Auth
+distinguishedName: CN=ms-Exch-Smtp-Relay-For-Auth,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5020
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Relay-For-Auth
+adminDescription: ms-Exch-Smtp-Relay-For-Auth
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchSmtpRelayForAuth
+name: ms-Exch-Smtp-Relay-For-Auth
+schemaIDGUID: 449164e4-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Relay-Ip-List
+# List of Internet Protocols (IPs) for relay restriction.
+#
+dn: CN=ms-Exch-Smtp-Relay-Ip-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Relay-Ip-List
+distinguishedName: CN=ms-Exch-Smtp-Relay-Ip-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5048
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Relay-Ip-List
+adminDescription: ms-Exch-Smtp-Relay-Ip-List
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchSmtpRelayIpList
+name: ms-Exch-Smtp-Relay-Ip-List
+schemaIDGUID: 44b5282a-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Remote-Queue-Delay-Notification
+# The time at which this resource should send a notification regarding
+# an undelivered outbound message.
+#
+dn: CN=ms-Exch-Smtp-Remote-Queue-Delay-Notification,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Remote-Queue-Delay-Notification
+distinguishedName: CN=ms-Exch-Smtp-Remote-Queue-Delay-Notification,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5013
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Remote-Queue-Delay-Notification
+adminDescription: ms-Exch-Smtp-Remote-Queue-Delay-Notification
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpRemoteQueueDelayNotification
+name: ms-Exch-Smtp-Remote-Queue-Delay-Notification
+schemaIDGUID: 44ddb024-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Remote-Queue-Expiration-Timeout
+# The time at which this resource should expire an undelivered
+# outbound message.
+#
+dn: CN=ms-Exch-Smtp-Remote-Queue-Expiration-Timeout,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Remote-Queue-Expiration-Timeout
+distinguishedName: CN=ms-Exch-Smtp-Remote-Queue-Expiration-Timeout,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5012
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Remote-Queue-Expiration-Timeout
+adminDescription: ms-Exch-Smtp-Remote-Queue-Expiration-Timeout
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpRemoteQueueExpirationTimeout
+name: ms-Exch-Smtp-Remote-Queue-Expiration-Timeout
+schemaIDGUID: 4501736a-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Remote-Queue-Retries
+# The first, second, third, and subsequent retries for remote mail
+# delivery.
+#
+dn: CN=ms-Exch-Smtp-Remote-Queue-Retries,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Remote-Queue-Retries
+distinguishedName: CN=ms-Exch-Smtp-Remote-Queue-Retries,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5046
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Remote-Queue-Retries
+adminDescription: ms-Exch-Smtp-Remote-Queue-Retries
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpRemoteQueueRetries
+name: ms-Exch-Smtp-Remote-Queue-Retries
+schemaIDGUID: 4527990a-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Routing-Table-Type
+# The routing table type for DSAccess.
+#
+dn: CN=ms-Exch-Smtp-Routing-Table-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Routing-Table-Type
+distinguishedName: CN=ms-Exch-Smtp-Routing-Table-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5039
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Routing-Table-Type
+adminDescription: ms-Exch-Smtp-Routing-Table-Type
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpRoutingTableType
+name: ms-Exch-Smtp-Routing-Table-Type
+schemaIDGUID: 454dbeaa-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Smtp-Send-Badmail-To
+# The address to send bad mail to.
+#
+dn: CN=ms-Exch-Smtp-Send-Badmail-To,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Send-Badmail-To
+distinguishedName: CN=ms-Exch-Smtp-Send-Badmail-To,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5028
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Send-Badmail-To
+adminDescription: ms-Exch-Smtp-Send-Badmail-To
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpSendBadmailTo
+name: ms-Exch-Smtp-Send-Badmail-To
+schemaIDGUID: 4586f71a-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Send-NDR-To
+# The address to send a non-delivery report to.
+#
+dn: CN=ms-Exch-Smtp-Send-NDR-To,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Send-NDR-To
+distinguishedName: CN=ms-Exch-Smtp-Send-NDR-To,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5027
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Send-NDR-To
+adminDescription: ms-Exch-Smtp-Send-NDR-To
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpSendNDRTo
+name: ms-Exch-Smtp-Send-NDR-To
+schemaIDGUID: 45bb6ad6-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Smart-Host
+# Sets a Smart Host route domain for mail outbound from this resource.
+#
+dn: CN=ms-Exch-Smtp-Smart-Host,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Smart-Host
+distinguishedName: CN=ms-Exch-Smtp-Smart-Host,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5024
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Smart-Host
+adminDescription: ms-Exch-Smtp-Smart-Host
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpSmartHost
+name: ms-Exch-Smtp-Smart-Host
+schemaIDGUID: 45e19076-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-Smart-Host-Type
+# The Smart Host type.
+#
+dn: CN=ms-Exch-Smtp-Smart-Host-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-Smart-Host-Type
+distinguishedName: CN=ms-Exch-Smtp-Smart-Host-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5014
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-Smart-Host-Type
+adminDescription: ms-Exch-Smtp-Smart-Host-Type
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchSmtpSmartHostType
+name: ms-Exch-Smtp-Smart-Host-Type
+schemaIDGUID: 46008f08-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Smtp-TRN-Smart-Host
+# Contains an alternate Smart Host to which the server should issue
+# the TURN or ETRN command.
+#
+dn: CN=ms-Exch-Smtp-TRN-Smart-Host,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Smtp-TRN-Smart-Host
+distinguishedName: CN=ms-Exch-Smtp-TRN-Smart-Host,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12531
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Smtp-TRN-Smart-Host
+adminDescription: ms-Exch-Smtp-TRN-Smart-Host
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchSmtpTRNSmartHost
+name: ms-Exch-Smtp-TRN-Smart-Host
+schemaIDGUID: be41789c-2da8-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Source-BH-Address
+#
+dn: CN=ms-Exch-Source-BH-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Source-BH-Address
+distinguishedName: CN=ms-Exch-Source-BH-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12509
+attributeSyntax: 2.5.5.4
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 255
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Source-BH-Address
+adminDescription: ms-Exch-Source-BH-Address
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchSourceBHAddress
+name: ms-Exch-Source-BH-Address
+schemaIDGUID: 203d2f32-b099-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Source-Bridgehead-Servers-DN
+# Pointers to SMTP virtual servers of servers in bridgehead on the
+# local side of Exchange Connector.
+#
+dn: CN=ms-Exch-Source-Bridgehead-Servers-DN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Source-Bridgehead-Servers-DN
+distinguishedName: CN=ms-Exch-Source-Bridgehead-Servers-DN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12511
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1002
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Source-Bridgehead-Servers-DN
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Source-Bridgehead-Servers-DN
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchSourceBridgeheadServersDN
+name: ms-Exch-Source-Bridgehead-Servers-DN
+schemaIDGUID: 206f4094-b099-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Space-Last-Computed
+# The time at which the site-proxy-space was last computed.
+#
+dn: CN=ms-Exch-Space-Last-Computed,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Space-Last-Computed
+distinguishedName: CN=ms-Exch-Space-Last-Computed,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.386
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+mAPIID: 33081
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Space-Last-Computed
+adminDescription: ms-Exch-Space-Last-Computed
+oMSyntax: 23
+searchFlags: 0
+lDAPDisplayName: spaceLastComputed
+name: ms-Exch-Space-Last-Computed
+schemaIDGUID: 9928d7bc-b093-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Submission-Cont-Length
+# Contains the maximum size message allowed to be submitted, either
+# globally or by this user.
+#
+dn: CN=ms-Exch-Submission-Cont-Length,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Submission-Cont-Length
+distinguishedName: CN=ms-Exch-Submission-Cont-Length,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.280
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33084
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Submission-Cont-Length
+adminDescription: ms-Exch-Submission-Cont-Length
+oMSyntax: 2
+searchFlags: 16
+lDAPDisplayName: submissionContLength
+name: ms-Exch-Submission-Cont-Length
+schemaIDGUID: bf967a3e-0de6-11d0-a285-00aa003049e2
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-SubmitRelaySD
+#
+dn: CN=ms-Exch-SubmitRelaySD,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-SubmitRelaySD
+distinguishedName: CN=ms-Exch-SubmitRelaySD,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.5060
+attributeSyntax: 2.5.5.15
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-SubmitRelaySD
+adminDescription: ms-Exch-SubmitRelaySD
+oMSyntax: 66
+searchFlags: 0
+lDAPDisplayName: msExchSubmitRelaySD
+name: ms-Exch-SubmitRelaySD
+schemaIDGUID: e2cefbcc-dcc1-45a5-bab8-d5f4bd78884d
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Supported-Algorithms
+#
+dn: CN=ms-Exch-Supported-Algorithms,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Supported-Algorithms
+distinguishedName: CN=ms-Exch-Supported-Algorithms,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.597
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32767
+mAPIID: 35925
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Supported-Algorithms
+adminDescription: ms-Exch-Supported-Algorithms
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: supportedAlgorithms
+name: ms-Exch-Supported-Algorithms
+schemaIDGUID: 1677588e-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Supporting-Stack
+#
+dn: CN=ms-Exch-Supporting-Stack,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Supporting-Stack
+distinguishedName: CN=ms-Exch-Supporting-Stack,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.28
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 33086
+linkID: 132
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Supporting-Stack
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Supporting-Stack
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: supportingStack
+name: ms-Exch-Supporting-Stack
+schemaIDGUID: a8df7480-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Supporting-Stack-BL
+#
+dn: CN=ms-Exch-Supporting-Stack-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Supporting-Stack-BL
+distinguishedName: CN=ms-Exch-Supporting-Stack-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.357
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 33087
+linkID: 133
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Supporting-Stack-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Supporting-Stack-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: supportingStackBL
+name: ms-Exch-Supporting-Stack-BL
+schemaIDGUID: 16775891-47f3-11d1-a9c3-0000f80367c1
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Support-SMIME-Signatures
+#
+dn: CN=ms-Exch-Support-SMIME-Signatures,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Support-SMIME-Signatures
+distinguishedName: CN=ms-Exch-Support-SMIME-Signatures,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.590
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 35912
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Support-SMIME-Signatures
+adminDescription: ms-Exch-Support-SMIME-Signatures
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: supportSMIMESignatures
+name: ms-Exch-Support-SMIME-Signatures
+schemaIDGUID: a8df747f-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Synchronization-Direction
+# The direction in which the directories will be synchronized.
+#
+dn: CN=ms-Exch-Synchronization-Direction,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Synchronization-Direction
+distinguishedName: CN=ms-Exch-Synchronization-Direction,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.1
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Synchronization-Direction
+adminDescription: ms-Exch-Synchronization-Direction
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: msExchSynchronizationDirection
+name: ms-Exch-Synchronization-Direction
+schemaIDGUID: 20a151f6-b099-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-S-Selector
+#
+dn: CN=ms-Exch-S-Selector,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-S-Selector
+distinguishedName: CN=ms-Exch-S-Selector,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.284
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 16
+mAPIID: 33067
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-S-Selector
+adminDescription: ms-Exch-S-Selector
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: sSelector
+name: ms-Exch-S-Selector
+schemaIDGUID: a8df746c-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-S-Selector-Inbound
+#
+dn: CN=ms-Exch-S-Selector-Inbound,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-S-Selector-Inbound
+distinguishedName: CN=ms-Exch-S-Selector-Inbound,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.46
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 16
+mAPIID: 33068
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-S-Selector-Inbound
+adminDescription: ms-Exch-S-Selector-Inbound
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: sSelectorInbound
+name: ms-Exch-S-Selector-Inbound
+schemaIDGUID: a8df746d-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Target-Address
+# Contains the destination address for this object.
+dn: CN=ms-Exch-Target-Address,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Target-Address
+distinguishedName: CN=ms-Exch-Target-Address,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.352
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1123
+mAPIID: 32785
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Target-Address
+adminDescription: ms-Exch-Target-Address
+oMSyntax: 64
+searchFlags: 1
+lDAPDisplayName: targetAddress
+name: ms-Exch-Target-Address
+schemaIDGUID: f0f8ff9f-1191-11d0-a060-00aa006c33ed
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Target-Bridgehead-Servers-DN
+# Pointers to bridgehead SMTP virtual servers in the connector target
+# routing group (RG).
+#
+dn: CN=ms-Exch-Target-Bridgehead-Servers-DN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Target-Bridgehead-Servers-DN
+distinguishedName: CN=ms-Exch-Target-Bridgehead-Servers-DN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12514
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1004
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Target-Bridgehead-Servers-DN
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Target-Bridgehead-Servers-DN
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchTargetBridgeheadServersDN
+name: ms-Exch-Target-Bridgehead-Servers-DN
+schemaIDGUID: 20da8a66-b099-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Target-MTAs
+# Used by Exchange Server 5.5 to indicate the message transfer agents
+# (MTAs) on the remote side of a connector.
+#
+dn: CN=ms-Exch-Target-MTAs,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Target-MTAs
+distinguishedName: CN=ms-Exch-Target-MTAs,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.259
+attributeSyntax: 2.5.5.4
+isSingleValued: FALSE
+rangeLower: 1
+rangeUpper: 36
+mAPIID: 33090
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Target-MTAs
+adminDescription: ms-Exch-Target-MTAs
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: targetMTAs
+name: ms-Exch-Target-MTAs
+schemaIDGUID: a8df7483-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Telephone-Assistant
+# The telephone number of the assistant that corresponds to this user.
+#
+dn: CN=ms-Exch-Telephone-Assistant,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Telephone-Assistant
+distinguishedName: CN=ms-Exch-Telephone-Assistant,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.79
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 64
+mAPIID: 14894
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Telephone-Assistant
+adminDescription: ms-Exch-Telephone-Assistant
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: telephoneAssistant
+name: ms-Exch-Telephone-Assistant
+schemaIDGUID: a8df7484-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Telephone-Personal-Pager
+#
+dn: CN=ms-Exch-Telephone-Personal-Pager,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Telephone-Personal-Pager
+distinguishedName: CN=ms-Exch-Telephone-Personal-Pager,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.612
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 128
+mAPIID: 35944
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Telephone-Personal-Pager
+adminDescription: ms-Exch-Telephone-Personal-Pager
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: personalPager
+name: ms-Exch-Telephone-Personal-Pager
+schemaIDGUID: a8df7487-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Template-RDNs
+# The Relative Distinguished Names (RDNs) to the child template
+# objects.
+#
+dn: CN=ms-Exch-Template-RDNs,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Template-RDNs
+distinguishedName: CN=ms-Exch-Template-RDNs,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.65
+attributeSyntax: 2.5.5.4
+isSingleValued: FALSE
+mAPIID: 65528
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Template-RDNs
+adminDescription: ms-Exch-Template-RDNs
+oMSyntax: 20
+searchFlags: 0
+lDAPDisplayName: msExchTemplateRDNs
+name: ms-Exch-Template-RDNs
+schemaIDGUID: 211fae98-b099-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Temp-Assoc-Threshold
+#
+dn: CN=ms-Exch-Temp-Assoc-Threshold,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Temp-Assoc-Threshold
+distinguishedName: CN=ms-Exch-Temp-Assoc-Threshold,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.329
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32767
+mAPIID: 33092
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Temp-Assoc-Threshold
+adminDescription: ms-Exch-Temp-Assoc-Threshold
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: tempAssocThreshold
+name: ms-Exch-Temp-Assoc-Threshold
+schemaIDGUID: a8df7488-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Tracking-Log-Path-Name
+#
+dn: CN=ms-Exch-Tracking-Log-Path-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Tracking-Log-Path-Name
+distinguishedName: CN=ms-Exch-Tracking-Log-Path-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.347
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 256
+mAPIID: 33094
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Tracking-Log-Path-Name
+adminDescription: ms-Exch-Tracking-Log-Path-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: trackingLogPathName
+name: ms-Exch-Tracking-Log-Path-Name
+schemaIDGUID: bf967a57-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Track-Duplicates
+# The number of hours for which information about received messages
+# will be kept and duplicates will be eliminated.
+#
+dn: CN=ms-Exch-Track-Duplicates,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Track-Duplicates
+distinguishedName: CN=ms-Exch-Track-Duplicates,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.11006
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Track-Duplicates
+adminDescription: ms-Exch-Track-Duplicates
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchTrackDuplicates
+name: ms-Exch-Track-Duplicates
+schemaIDGUID: 2196e42c-b099-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Transfer-Retry-Interval
+#
+dn: CN=ms-Exch-Transfer-Retry-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Transfer-Retry-Interval
+distinguishedName: CN=ms-Exch-Transfer-Retry-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.133
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33097
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Transfer-Retry-Interval
+adminDescription: ms-Exch-Transfer-Retry-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: transferRetryInterval
+name: ms-Exch-Transfer-Retry-Interval
+schemaIDGUID: a8df748c-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Transfer-Timeout-Non-Urgent
+#
+dn: CN=ms-Exch-Transfer-Timeout-Non-Urgent,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Transfer-Timeout-Non-Urgent
+distinguishedName: CN=ms-Exch-Transfer-Timeout-Non-Urgent,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.136
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33098
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Transfer-Timeout-Non-Urgent
+adminDescription: ms-Exch-Transfer-Timeout-Non-Urgent
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: transferTimeoutNonUrgent
+name: ms-Exch-Transfer-Timeout-Non-Urgent
+schemaIDGUID: a8df748d-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Transfer-Timeout-Normal
+#
+dn: CN=ms-Exch-Transfer-Timeout-Normal,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Transfer-Timeout-Normal
+distinguishedName: CN=ms-Exch-Transfer-Timeout-Normal,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.137
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33099
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Transfer-Timeout-Normal
+adminDescription: ms-Exch-Transfer-Timeout-Normal
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: transferTimeoutNormal
+name: ms-Exch-Transfer-Timeout-Normal
+schemaIDGUID: a8df748e-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Transfer-Timeout-Urgent
+#
+dn: CN=ms-Exch-Transfer-Timeout-Urgent,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Transfer-Timeout-Urgent
+distinguishedName: CN=ms-Exch-Transfer-Timeout-Urgent,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.142
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33100
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Transfer-Timeout-Urgent
+adminDescription: ms-Exch-Transfer-Timeout-Urgent
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: transferTimeoutUrgent
+name: ms-Exch-Transfer-Timeout-Urgent
+schemaIDGUID: a8df748f-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Translation-Table-Used
+#
+dn: CN=ms-Exch-Translation-Table-Used,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Translation-Table-Used
+distinguishedName: CN=ms-Exch-Translation-Table-Used,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.396
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33101
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Translation-Table-Used
+adminDescription: ms-Exch-Translation-Table-Used
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: translationTableUsed
+name: ms-Exch-Translation-Table-Used
+schemaIDGUID: a8df7490-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Transport-Expedited-Data
+#
+dn: CN=ms-Exch-Transport-Expedited-Data,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Transport-Expedited-Data
+distinguishedName: CN=ms-Exch-Transport-Expedited-Data,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.150
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 33102
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Transport-Expedited-Data
+adminDescription: ms-Exch-Transport-Expedited-Data
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: transportExpeditedData
+name: ms-Exch-Transport-Expedited-Data
+schemaIDGUID: a8df7491-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Trans-Retry-Mins
+#
+dn: CN=ms-Exch-Trans-Retry-Mins,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Trans-Retry-Mins
+distinguishedName: CN=ms-Exch-Trans-Retry-Mins,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.219
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33095
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Trans-Retry-Mins
+adminDescription: ms-Exch-Trans-Retry-Mins
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: transRetryMins
+name: ms-Exch-Trans-Retry-Mins
+schemaIDGUID: a8df748a-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Trans-Timeout-Mins
+#
+dn: CN=ms-Exch-Trans-Timeout-Mins,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Trans-Timeout-Mins
+distinguishedName: CN=ms-Exch-Trans-Timeout-Mins,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.220
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+mAPIID: 33096
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Trans-Timeout-Mins
+adminDescription: ms-Exch-Trans-Timeout-Mins
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: transTimeoutMins
+name: ms-Exch-Trans-Timeout-Mins
+schemaIDGUID: a8df748b-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Trk-Log-Cleaning-Interval
+# The number of days after which to remove a tracking log file.
+#
+dn: CN=ms-Exch-Trk-Log-Cleaning-Interval,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Trk-Log-Cleaning-Interval
+distinguishedName: CN=ms-Exch-Trk-Log-Cleaning-Interval,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.50016
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Trk-Log-Cleaning-Interval
+adminDescription: ms-Exch-Trk-Log-Cleaning-Interval
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchTrkLogCleaningInterval
+name: ms-Exch-Trk-Log-Cleaning-Interval
+schemaIDGUID: 21d27ef6-b099-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Trust-Level
+#
+dn: CN=ms-Exch-Trust-Level,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Trust-Level
+distinguishedName: CN=ms-Exch-Trust-Level,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.70
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 100
+mAPIID: 33103
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Trust-Level
+adminDescription: ms-Exch-Trust-Level
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: trustLevel
+name: ms-Exch-Trust-Level
+schemaIDGUID: a8df7492-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-TUI-Password
+# The user logon authentication password when accessed by phone.
+#
+dn: CN=ms-Exch-TUI-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-TUI-Password
+distinguishedName: CN=ms-Exch-TUI-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.17025
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-TUI-Password
+adminDescription: ms-Exch-TUI-Password
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: msExchTUIPassword
+name: ms-Exch-TUI-Password
+schemaIDGUID: 567d521f-2f6a-11d3-aa6c-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-TUI-Speed
+# The speed at which to play text to speech.
+#
+dn: CN=ms-Exch-TUI-Speed,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-TUI-Speed
+distinguishedName: CN=ms-Exch-TUI-Speed,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.17027
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-TUI-Speed
+adminDescription: ms-Exch-TUI-Speed
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchTUISpeed
+name: ms-Exch-TUI-Speed
+schemaIDGUID: 567d522a-2f6a-11d3-aa6c-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-TUI-Volume
+# The volume at which to play voice mail and text-to-speech mail via
+# Telephone User Interface (TUI).
+#
+dn: CN=ms-Exch-TUI-Volume,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-TUI-Volume
+distinguishedName: CN=ms-Exch-TUI-Volume,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.17026
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-TUI-Volume
+adminDescription: ms-Exch-TUI-Volume
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchTUIVolume
+name: ms-Exch-TUI-Volume
+schemaIDGUID: 567d5225-2f6a-11d3-aa6c-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Turf-List
+#
+dn: CN=ms-Exch-Turf-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Turf-List
+distinguishedName: CN=ms-Exch-Turf-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5051
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Turf-List
+adminDescription: ms-Exch-Turf-List
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: msExchTurfList
+name: ms-Exch-Turf-List
+schemaIDGUID: 8b60f7f8-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Turf-List-Action
+#
+dn: CN=ms-Exch-Turf-List-Action,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Turf-List-Action
+distinguishedName: CN=ms-Exch-Turf-List-Action,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12535
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Turf-List-Action
+adminDescription: ms-Exch-Turf-List-Action
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchTurfListAction
+name: ms-Exch-Turf-List-Action
+schemaIDGUID: 0b836daa-3b20-11d3-aa6f-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Turf-List-Names
+#
+dn: CN=ms-Exch-Turf-List-Names,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Turf-List-Names
+distinguishedName: CN=ms-Exch-Turf-List-Names,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12534
+attributeSyntax: 2.5.5.12
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Turf-List-Names
+adminDescription: ms-Exch-Turf-List-Names
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchTurfListNames
+name: ms-Exch-Turf-List-Names
+schemaIDGUID: 0b836da0-3b20-11d3-aa6f-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Turf-List-Options
+#
+dn: CN=ms-Exch-Turf-List-Options,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Turf-List-Options
+distinguishedName: CN=ms-Exch-Turf-List-Options,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.5054
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Turf-List-Options
+adminDescription: ms-Exch-Turf-List-Options
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchTurfListOptions
+name: ms-Exch-Turf-List-Options
+schemaIDGUID: 01dbe64c-bfeb-47cd-9939-8911946bdd6d
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Turn-Request-Threshold
+#
+dn: CN=ms-Exch-Turn-Request-Threshold,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Turn-Request-Threshold
+distinguishedName: CN=ms-Exch-Turn-Request-Threshold,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.38
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33104
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Turn-Request-Threshold
+adminDescription: ms-Exch-Turn-Request-Threshold
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: turnRequestThreshold
+name: ms-Exch-Turn-Request-Threshold
+schemaIDGUID: a8df7493-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Two-Way-Alternate-Facility
+#
+dn: CN=ms-Exch-Two-Way-Alternate-Facility,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Two-Way-Alternate-Facility
+distinguishedName: CN=ms-Exch-Two-Way-Alternate-Facility,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.40
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 33105
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Two-Way-Alternate-Facility
+adminDescription: ms-Exch-Two-Way-Alternate-Facility
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: twoWayAlternateFacility
+name: ms-Exch-Two-Way-Alternate-Facility
+schemaIDGUID: a8df7494-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Type
+#
+dn: CN=ms-Exch-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Type
+distinguishedName: CN=ms-Exch-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.573
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 35896
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Type
+adminDescription: ms-Exch-Type
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: type
+name: ms-Exch-Type
+schemaIDGUID: 167758aa-47f3-11d1-a9c3-0000f80367c1
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-T-Selector
+#
+dn: CN=ms-Exch-T-Selector,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-T-Selector
+distinguishedName: CN=ms-Exch-T-Selector,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.283
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 32
+mAPIID: 33088
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-T-Selector
+adminDescription: ms-Exch-T-Selector
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: tSelector
+name: ms-Exch-T-Selector
+schemaIDGUID: a8df7481-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Uce-Block-Threshold
+#
+dn: CN=ms-Exch-Uce-Block-Threshold,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Uce-Block-Threshold
+distinguishedName: CN=ms-Exch-Uce-Block-Threshold,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12601
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Uce-Block-Threshold
+adminDescription: ms-Exch-Uce-Block-Threshold
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchUceBlockThreshold
+name: ms-Exch-Uce-Block-Threshold
+schemaIDGUID: 9f297c14-d715-4631-a259-bf51dc52eac1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Uce-Enabled
+#
+dn: CN=ms-Exch-Uce-Enabled,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Uce-Enabled
+distinguishedName: CN=ms-Exch-Uce-Enabled,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12600
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Uce-Enabled
+adminDescription: ms-Exch-Uce-Enabled
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchUceEnabled
+name: ms-Exch-Uce-Enabled
+schemaIDGUID: 15e2db2e-7206-4109-9b94-830f4def1b05
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Uce-Store-Action-Threshold
+#
+dn: CN=ms-Exch-Uce-Store-Action-Threshold,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Uce-Store-Action-Threshold
+distinguishedName: CN=ms-Exch-Uce-Store-Action-Threshold,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.12602
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Uce-Store-Action-Threshold
+adminDescription: ms-Exch-Uce-Store-Action-Threshold
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchUceStoreActionThreshold
+name: ms-Exch-Uce-Store-Action-Threshold
+schemaIDGUID: 44ccbd60-6ede-46f0-8f13-931a9bb5b8e8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Unauth-Orig
+# Contains objects that may not send to this recipient.
+#
+dn: CN=ms-Exch-Unauth-Orig,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Unauth-Orig
+distinguishedName: CN=ms-Exch-Unauth-Orig,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.221
+attributeSyntax: 2.5.5.7
+isSingleValued: FALSE
+linkID: 114
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Unauth-Orig
+oMObjectClass:: VgYBAgULHQ==
+adminDescription: ms-Exch-Unauth-Orig
+oMSyntax: 127
+searchFlags: 16
+lDAPDisplayName: unauthOrig
+name: ms-Exch-Unauth-Orig
+schemaIDGUID: a8df7495-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Unauth-Orig-BL
+# A backlink to ms-Exch-Unauth-Orig.
+#
+dn: CN=ms-Exch-Unauth-Orig-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Unauth-Orig-BL
+distinguishedName: CN=ms-Exch-Unauth-Orig-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.292
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+mAPIID: 33106
+linkID: 115
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Unauth-Orig-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Unauth-Orig-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: unauthOrigBL
+name: ms-Exch-Unauth-Orig-BL
+schemaIDGUID: a8df7496-c5ea-11d1-bbcb-0080c76670c0
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+systemFlags: 1
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-UNC-Password
+# Specifies the encrypted password used to gain access to Universal
+# Naming Convention (UNC) virtual roots.
+#
+dn: CN=ms-Exch-UNC-Password,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-UNC-Password
+distinguishedName: CN=ms-Exch-UNC-Password,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15004
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-UNC-Password
+adminDescription: ms-Exch-UNC-Password
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchUNCPassword
+name: ms-Exch-UNC-Password
+schemaIDGUID: 8c07dc94-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-UNC-Username
+# Specifies the user name for UNC virtual roots.
+#
+dn: CN=ms-Exch-UNC-Username,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-UNC-Username
+distinguishedName: CN=ms-Exch-UNC-Username,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15003
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-UNC-Username
+adminDescription: ms-Exch-UNC-Username
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchUNCUsername
+name: ms-Exch-UNC-Username
+schemaIDGUID: 8be8de02-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Unmerged-Atts
+# A set of DN syntax attribute values that were not set on the target
+# object because the object they pointed to was not found in the
+# target directory.
+#
+dn: CN=ms-Exch-Unmerged-Atts,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Unmerged-Atts
+distinguishedName: CN=ms-Exch-Unmerged-Atts,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.48
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Unmerged-Atts
+adminDescription: ms-Exch-Unmerged-Atts
+oMSyntax: 4
+searchFlags: 1
+lDAPDisplayName: unmergedAtts
+name: ms-Exch-Unmerged-Atts
+schemaIDGUID: 9947d64e-b093-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Unmerged-Atts-Pt
+# Exchange-specific unmerged attributes.
+#
+dn: CN=ms-Exch-Unmerged-Atts-Pt,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Unmerged-Atts-Pt
+distinguishedName: CN=ms-Exch-Unmerged-Atts-Pt,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.90
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Unmerged-Atts-Pt
+adminDescription: ms-Exch-Unmerged-Atts-Pt
+oMSyntax: 4
+searchFlags: 1
+lDAPDisplayName: msExchUnmergedAttsPt
+name: ms-Exch-Unmerged-Atts-Pt
+schemaIDGUID: a5924ad4-c597-4db1-8f9d-1799909dc166
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Usenet-Site-Name
+#
+dn: CN=ms-Exch-Usenet-Site-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Usenet-Site-Name
+distinguishedName: CN=ms-Exch-Usenet-Site-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.484
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 33161
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Usenet-Site-Name
+adminDescription: ms-Exch-Usenet-Site-Name
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: usenetSiteName
+name: ms-Exch-Usenet-Site-Name
+schemaIDGUID: f0f8ffa8-1191-11d0-a060-00aa006c33ed
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-User-Account-Control
+#
+dn: CN=ms-Exch-User-Account-Control,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-User-Account-Control
+distinguishedName: CN=ms-Exch-User-Account-Control,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.101
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-User-Account-Control
+adminDescription: ms-Exch-User-Account-Control
+oMSyntax: 2
+searchFlags: 25
+lDAPDisplayName: msExchUserAccountControl
+name: ms-Exch-User-Account-Control
+schemaIDGUID: 07c31f12-a3e8-4fa0-af8e-4932c75b2241
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Use-OAB
+# The OAB that this mailbox store or this user uses.
+#
+dn: CN=ms-Exch-Use-OAB,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Use-OAB
+distinguishedName: CN=ms-Exch-Use-OAB,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.69
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 1014
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Use-OAB
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Use-OAB
+oMSyntax: 127
+searchFlags: 16
+lDAPDisplayName: msExchUseOAB
+name: ms-Exch-Use-OAB
+schemaIDGUID: 2209550c-b099-11d2-aa06-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Use-OAB-BL
+#
+dn: CN=ms-Exch-Use-OAB-BL,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Use-OAB-BL
+distinguishedName: CN=ms-Exch-Use-OAB-BL,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.70
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+linkID: 1015
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Use-OAB-BL
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: ms-Exch-Use-OAB-BL
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: msExchUseOABBL
+name: ms-Exch-Use-OAB-BL
+schemaIDGUID: 22428d7c-b099-11d2-aa06-00c04f8eedd8
+systemFlags: 1
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Use-Site-Values
+#
+dn: CN=ms-Exch-Use-Site-Values,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Use-Site-Values
+distinguishedName: CN=ms-Exch-Use-Site-Values,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.478
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 33155
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Use-Site-Values
+adminDescription: ms-Exch-Use-Site-Values
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: useSiteValues
+name: ms-Exch-Use-Site-Values
+schemaIDGUID: a8df7497-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Visibility-Mask
+# The data conference visibility mask.
+dn: CN=ms-Exch-Visibility-Mask,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Visibility-Mask
+distinguishedName: CN=ms-Exch-Visibility-Mask,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.9016
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Visibility-Mask
+adminDescription: ms-Exch-Visibility-Mask
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: msExchVisibilityMask
+name: ms-Exch-Visibility-Mask
+schemaIDGUID: 22770138-b099-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-Voice-Mailbox-ID
+# The telephone extension of a user's mailbox ID when accessed by phone.
+#
+dn: CN=ms-Exch-Voice-Mailbox-ID,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Voice-Mailbox-ID
+distinguishedName: CN=ms-Exch-Voice-Mailbox-ID,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.17019
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Voice-Mailbox-ID
+adminDescription: ms-Exch-Voice-Mailbox-ID
+oMSyntax: 64
+searchFlags: 1
+lDAPDisplayName: msExchVoiceMailboxID
+name: ms-Exch-Voice-Mailbox-ID
+schemaIDGUID: 567d5200-2f6a-11d3-aa6c-00c04f8eedd8
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-VPIM-Convert-Inbound
+# Convert inbound Voice Profile for Internet Mail (VPIM) messages via
+# SMTP to Multimedia Message format.
+#
+dn: CN=ms-Exch-VPIM-Convert-Inbound,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-VPIM-Convert-Inbound
+distinguishedName: CN=ms-Exch-VPIM-Convert-Inbound,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.17008
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-VPIM-Convert-Inbound
+adminDescription: ms-Exch-VPIM-Convert-Inbound
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchVPIMConvertInbound
+name: ms-Exch-VPIM-Convert-Inbound
+schemaIDGUID: 2d0977eb-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-VPIM-Convert-Outbound
+# Convert outbound Multimedia Message format to Voice Profile for
+# Internet Mail (VPIM) based on address or non-delivery report (NDR).
+#
+dn: CN=ms-Exch-VPIM-Convert-Outbound,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-VPIM-Convert-Outbound
+distinguishedName: CN=ms-Exch-VPIM-Convert-Outbound,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.17009
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-VPIM-Convert-Outbound
+adminDescription: ms-Exch-VPIM-Convert-Outbound
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: msExchVPIMConvertOutbound
+name: ms-Exch-VPIM-Convert-Outbound
+schemaIDGUID: 2d0977f1-2b54-11d3-aa6b-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-Web-Access-Name
+# The name through which users will access Exchange data via HTTP.
+#
+dn: CN=ms-Exch-Web-Access-Name,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-Web-Access-Name
+distinguishedName: CN=ms-Exch-Web-Access-Name,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.7000.102.15007
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-Web-Access-Name
+adminDescription: ms-Exch-Web-Access-Name
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: msExchWebAccessName
+name: ms-Exch-Web-Access-Name
+schemaIDGUID: 8df7c5b4-b09e-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-X25-Call-User-Data-Incoming
+#
+dn: CN=ms-Exch-X25-Call-User-Data-Incoming,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-X25-Call-User-Data-Incoming
+distinguishedName: CN=ms-Exch-X25-Call-User-Data-Incoming,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.316
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 128
+mAPIID: 33113
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X25-Call-User-Data-Incoming
+adminDescription: ms-Exch-X25-Call-User-Data-Incoming
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: x25CallUserDataIncoming
+name: ms-Exch-X25-Call-User-Data-Incoming
+schemaIDGUID: a8df749b-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-X25-Call-User-Data-Outgoing
+#
+dn: CN=ms-Exch-X25-Call-User-Data-Outgoing,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-X25-Call-User-Data-Outgoing
+distinguishedName: CN=ms-Exch-X25-Call-User-Data-Outgoing,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.317
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 128
+mAPIID: 33114
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X25-Call-User-Data-Outgoing
+adminDescription: ms-Exch-X25-Call-User-Data-Outgoing
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: x25CallUserDataOutgoing
+name: ms-Exch-X25-Call-User-Data-Outgoing
+schemaIDGUID: a8df749c-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-X25-Facilities-Data-Incoming
+#
+dn: CN=ms-Exch-X25-Facilities-Data-Incoming,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-X25-Facilities-Data-Incoming
+distinguishedName: CN=ms-Exch-X25-Facilities-Data-Incoming,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.318
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 109
+mAPIID: 33115
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X25-Facilities-Data-Incoming
+adminDescription: ms-Exch-X25-Facilities-Data-Incoming
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: x25FacilitiesDataIncoming
+name: ms-Exch-X25-Facilities-Data-Incoming
+schemaIDGUID: a8df749d-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-X25-Facilities-Data-Outgoing
+#
+dn: CN=ms-Exch-X25-Facilities-Data-Outgoing,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-X25-Facilities-Data-Outgoing
+distinguishedName: CN=ms-Exch-X25-Facilities-Data-Outgoing,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.319
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 109
+mAPIID: 33116
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X25-Facilities-Data-Outgoing
+adminDescription: ms-Exch-X25-Facilities-Data-Outgoing
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: x25FacilitiesDataOutgoing
+name: ms-Exch-X25-Facilities-Data-Outgoing
+schemaIDGUID: a8df749e-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# ms-Exch-X25-Leased-Line-Port
+#
+dn: CN=ms-Exch-X25-Leased-Line-Port,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-X25-Leased-Line-Port
+distinguishedName: CN=ms-Exch-X25-Leased-Line-Port,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.321
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 3
+mAPIID: 33117
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X25-Leased-Line-Port
+adminDescription: ms-Exch-X25-Leased-Line-Port
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: x25LeasedLinePort
+name: ms-Exch-X25-Leased-Line-Port
+schemaIDGUID: a8df749f-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-X25-Leased-Or-Switched
+#
+dn: CN=ms-Exch-X25-Leased-Or-Switched,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-X25-Leased-Or-Switched
+distinguishedName: CN=ms-Exch-X25-Leased-Or-Switched,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.372
+attributeSyntax: 2.5.5.8
+isSingleValued: TRUE
+mAPIID: 33118
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X25-Leased-Or-Switched
+adminDescription: ms-Exch-X25-Leased-Or-Switched
+oMSyntax: 1
+searchFlags: 0
+lDAPDisplayName: x25LeasedOrSwitched
+name: ms-Exch-X25-Leased-Or-Switched
+schemaIDGUID: a8df74a0-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-X25-Remote-MTA-Phone
+#
+dn: CN=ms-Exch-X25-Remote-MTA-Phone,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-X25-Remote-MTA-Phone
+distinguishedName: CN=ms-Exch-X25-Remote-MTA-Phone,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.373
+attributeSyntax: 2.5.5.5
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 55
+mAPIID: 33119
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X25-Remote-MTA-Phone
+adminDescription: ms-Exch-X25-Remote-MTA-Phone
+oMSyntax: 19
+searchFlags: 0
+lDAPDisplayName: x25RemoteMTAPhone
+name: ms-Exch-X25-Remote-MTA-Phone
+schemaIDGUID: a8df74a1-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-X400-Attachment-Type
+#
+dn: CN=ms-Exch-X400-Attachment-Type,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-X400-Attachment-Type
+distinguishedName: CN=ms-Exch-X400-Attachment-Type,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.99
+attributeSyntax: 2.5.5.10
+isSingleValued: TRUE
+mAPIID: 33120
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X400-Attachment-Type
+adminDescription: ms-Exch-X400-Attachment-Type
+oMSyntax: 4
+searchFlags: 0
+lDAPDisplayName: x400AttachmentType
+name: ms-Exch-X400-Attachment-Type
+schemaIDGUID: a8df74a2-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-X400-Selector-Syntax
+#
+dn: CN=ms-Exch-X400-Selector-Syntax,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-X400-Selector-Syntax
+distinguishedName: CN=ms-Exch-X400-Selector-Syntax,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.443
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 1
+mAPIID: 33121
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X400-Selector-Syntax
+adminDescription: ms-Exch-X400-Selector-Syntax
+oMSyntax: 10
+searchFlags: 0
+lDAPDisplayName: x400SelectorSyntax
+name: ms-Exch-X400-Selector-Syntax
+schemaIDGUID: a8df74a3-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-X500-NC
+#
+dn: CN=ms-Exch-X500-NC,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-X500-NC
+distinguishedName: CN=ms-Exch-X500-NC,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.509
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 1024
+mAPIID: 33186
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X500-NC
+adminDescription: ms-Exch-X500-NC
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: dnQualifier
+name: ms-Exch-X500-NC
+schemaIDGUID: 167758c6-47f3-11d1-a9c3-0000f80367c1
+attributeSecurityGUID: e48d0154-bcf8-11d1-8702-00c04fb96050
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-X500-RDN
+#
+dn: CN=ms-Exch-X500-RDN,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-X500-RDN
+distinguishedName: CN=ms-Exch-X500-RDN,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.508
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 1
+rangeUpper: 256
+mAPIID: 33185
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-X500-RDN
+adminDescription: ms-Exch-X500-RDN
+oMSyntax: 64
+searchFlags: 0
+lDAPDisplayName: x500RDN
+name: ms-Exch-X500-RDN
+schemaIDGUID: bf967a7d-0de6-11d0-a285-00aa003049e2
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-XMIT-Timeout-Non-Urgent
+#
+dn: CN=ms-Exch-XMIT-Timeout-Non-Urgent,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-XMIT-Timeout-Non-Urgent
+distinguishedName: CN=ms-Exch-XMIT-Timeout-Non-Urgent,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.84
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33123
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-XMIT-Timeout-Non-Urgent
+adminDescription: ms-Exch-XMIT-Timeout-Non-Urgent
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: xMITTimeoutNonUrgent
+name: ms-Exch-XMIT-Timeout-Non-Urgent
+schemaIDGUID: a8df74a4-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-XMIT-Timeout-Normal
+#
+dn: CN=ms-Exch-XMIT-Timeout-Normal,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-XMIT-Timeout-Normal
+distinguishedName: CN=ms-Exch-XMIT-Timeout-Normal,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.67
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33124
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-XMIT-Timeout-Normal
+adminDescription: ms-Exch-XMIT-Timeout-Normal
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: xMITTimeoutNormal
+name: ms-Exch-XMIT-Timeout-Normal
+schemaIDGUID: a8df74a5-c5ea-11d1-bbcb-0080c76670c0
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+#
+# ms-Exch-XMIT-Timeout-Urgent
+#
+dn: CN=ms-Exch-XMIT-Timeout-Urgent,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: ms-Exch-XMIT-Timeout-Urgent
+distinguishedName: CN=ms-Exch-XMIT-Timeout-Urgent,${SCHEMADN}
+attributeID: 1.2.840.113556.1.2.53
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 32767
+mAPIID: 33125
+showInAdvancedViewOnly: TRUE
+adminDisplayName: ms-Exch-XMIT-Timeout-Urgent
+adminDescription: ms-Exch-XMIT-Timeout-Urgent
+oMSyntax: 2
+searchFlags: 0
+lDAPDisplayName: xMITTimeoutUrgent
+name: ms-Exch-XMIT-Timeout-Urgent
+schemaIDGUID: 1482fed4-b098-11d2-aa06-00c04f8eedd8
+isMemberOfPartialAttributeSet: FALSE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+
+
+
+
+
+
+##############################################################################
+##############################################################################
+
+
+
+#
+# Specifies the trees of address book containers to appear in MAPI
+# address book
+#
+dn: CN=Address-Book-Roots,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: Address-Book-Roots
+distinguishedName: CN=Address-Book-Roots,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.1244
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Address-Book-Roots
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: Address-Book-Roots
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: addressBookRoots
+name: Address-Book-Roots
+schemaIDGUID: f70b6e48-06f4-11d2-aa53-00c04fd7d83a
+systemOnly: FALSE
+systemFlags: 16
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# Store the distinguished name of a newly created global address list
+# (GAL)
+#
+dn: CN=Global-Address-List,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: Global-Address-List
+distinguishedName: CN=Global-Address-List,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.1245
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Global-Address-List
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: Global-Address-List
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: globalAddressList
+name: Global-Address-List
+schemaIDGUID:f754c748-06f4-11d2-aa53-00c04fd7d83a
+systemOnly: FALSE
+systemFlags: 16
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+#
+# Specifies an attribute used on the Exchange Server configuration
+# container to indicate where the template containers are stored
+#
+dn: CN=Template-Roots,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: Template-Roots
+distinguishedName: CN=Template-Roots,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.1346
+attributeSyntax: 2.5.5.1
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Template-Roots
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: Template-Roots
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: templateRoots
+name: Template-Roots
+schemaIDGUID: ed9de9a0-7041-11d2-9905-0000f87a57d4
+systemOnly: FALSE
+systemFlags: 16
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
Added: trunk/openchange/setup/AD/oc_provision_schema_ADSC.ldif
===================================================================
--- trunk/openchange/setup/AD/oc_provision_schema_ADSC.ldif (rev 0)
+++ trunk/openchange/setup/AD/oc_provision_schema_ADSC.ldif 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,249 @@
+#
+# Address-Book-Container
+# description: holding members of an address book view
+#
+dn: CN=Address-Book-Container,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: Address-Book-Container
+distinguishedName: CN=Address-Book-Container,${SCHEMADN}
+possSuperiors: msExchConfigurationContainer
+possSuperiors: container
+subClassOf: top
+governsID: 1.2.840.113556.1.5.125
+mayContain: msExchMinAdminVersion
+mayContain: msExchAddressListOU
+mayContain: msExchSearchScope
+mayContain: msExchSearchBase
+mayContain: msExchEnableInternalEvaluator
+mayContain: msExchPurportedSearchUI
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Address-Book-Container
+adminDescription: Address-Book-Container
+objectClassCategory: 1
+lDAPDisplayName: addressBookContainer
+name: Address-Book-Container
+schemaIDGUID: 3e74f60f-3e73-11d1-a9c0-0000f80367c1
+systemOnly: FALSE
+systemPossSuperiors: addressBookContainer
+systemPossSuperiors: configuration
+systemMayContain: purportedSearch
+systemMustContain: displayName
+defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCD
+systemFlags: 16
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=Address-Book-Container,${SCHEMADN}
+
+
+
+#
+# Contact
+# description: contains information about a person or company that
+# users may often contact
+#
+dn: CN=Contact,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: Contact
+distinguishedName: CN=Contact,${SCHEMADN}
+subClassOf: organizationalPerson
+governsID: 1.2.840.113556.1.5.15
+mayContain: msExchOriginatingForest
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Contact
+adminDescription: Contact
+auxiliaryClass: msExchMultiMediaUser
+auxiliaryClass: msExchCertificateInformation
+auxiliaryClass: msExchBaseClass
+auxiliaryClass: msExchCustomAttributes
+objectClassCategory: 1
+lDAPDisplayName: contact
+name: Contact
+schemaIDGUID: 5cb41ed0-0e4c-11d0-a286-00aa003049e2
+systemOnly: FALSE
+systemPossSuperiors: organizationalUnit
+systemPossSuperiors: domainDNS
+systemMayContain: notes
+systemMustContain: cn
+systemAuxiliaryClass: mailRecipient
+defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCD
+systemFlags: 16
+defaultHidingValue: FALSE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=Person,${SCHEMADN}
+
+
+
+#
+# DisplayTemplate
+# description: specifies information for an address template.
+#
+dn: CN=Display-Template,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: Display-Template
+distinguishedName: CN=Display-Template,${SCHEMADN}
+subClassOf: top
+governsID: 1.2.840.113556.1.3.59
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Display-Template
+adminDescription: Display-Template
+auxiliaryClass: msExchBaseClass
+objectClassCategory: 1
+lDAPDisplayName: displayTemplate
+name: Display-Template
+schemaIDGUID: 5fd4250c-1262-11d0-a060-00aa006c33ed
+systemOnly: FALSE
+systemPossSuperiors: container
+systemMayContain: originalDisplayTableMSDOS
+systemMayContain: originalDisplayTable
+systemMayContain: helpFileName
+systemMayContain: helpData32
+systemMayContain: helpData16
+systemMayContain: addressEntryDisplayTableMSDOS
+systemMayContain: addressEntryDisplayTable
+systemMustContain: cn
+defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCD
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=Display-Template,${SCHEMADN}
+
+
+
+#
+# DSA
+# description: Directory service only uses the subclass MSFT-DSA
+#
+dn: CN=DSA,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: DSA
+distinguishedName: CN=DSA,${SCHEMADN}
+subClassOf: applicationEntity
+governsID: 2.5.6.13
+mayContain: fileVersion
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: DSA
+adminDescription: DSA
+objectClassCategory: 1
+lDAPDisplayName: dSA
+name: DSA
+schemaIDGUID: 3fdfee52-47f4-11d1-a9c3-0000f80367c1
+systemOnly: FALSE
+systemPossSuperiors: server
+systemPossSuperiors: computer
+systemMayContain: knowledgeInformation
+defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCD
+systemFlags: 16
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=DSA,${SCHEMADN}
+
+
+
+#
+# Group-Of-Names
+# description: Used to define entries representing an unordered set of
+# names that represent individual objects or other groups of names.
+#
+dn: CN=Group-Of-Names,${SCHEMADN}
+objectClass: top
+objectClass: classSchema
+cn: Group-Of-Names
+distinguishedName: CN=Group-Of-Names,${SCHEMADN}
+subClassOf: top
+governsID: 2.5.6.9
+mayContain: reportToOwner
+mayContain: reportToOriginator
+mayContain: oOFReplyToOriginator
+mayContain: hideDLMembership
+mayContain: dLMemberRule
+rDNAttID: cn
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Group-Of-Names
+adminDescription: Group-Of-Names
+objectClassCategory: 0
+lDAPDisplayName: groupOfNames
+name: Group-Of-Names
+schemaIDGUID: bf967a9d-0de6-11d0-a285-00aa003049e2
+systemOnly: FALSE
+systemPossSuperiors: organizationalUnit
+systemPossSuperiors: locality
+systemPossSuperiors: organization
+systemPossSuperiors: container
+systemMayContain: seeAlso
+systemMayContain: owner
+systemMayContain: ou
+systemMayContain: o
+systemMayContain: businessCategory
+systemMustContain: member
+systemMustContain: cn
+defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCD
+systemFlags: 16
+defaultHidingValue: TRUE
+objectCategory: CN=Class-Schema,${SCHEMADN}
+defaultObjectCategory: CN=Group-Of-Names,${SCHEMADN}
+
+
+
+#
+# PurportedSearch
+# description: This attribute specifies the search argument for an
+# address book view.
+#
+dn: CN=Purported-Search,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: Purported-Search
+distinguishedName: CN=Purported-Search,${SCHEMADN}
+attributeID: 1.2.840.113556.1.4.886
+attributeSyntax: 2.5.5.12
+isSingleValued: TRUE
+rangeLower: 0
+rangeUpper: 2048
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Purported-Search
+adminDescription: Purported-Search
+oMSyntax: 64
+searchFlags: 8
+lDAPDisplayName: purportedSearch
+name: Purported-Search
+schemaIDGUID: b4b54e50-943a-11d1-aebd-0000f80367c1
+systemOnly: FALSE
+systemFlags: 16
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
+
+
+
+#
+# Owner
+# description: The distinguished name of an object that has ownership
+# of an object.
+#
+dn: CN=Owner,${SCHEMADN}
+objectClass: top
+objectClass: attributeSchema
+cn: Owner
+distinguishedName: CN=Owner,${SCHEMADN}
+attributeID: 2.5.4.32
+attributeSyntax: 2.5.5.1
+isSingleValued: TRUE
+linkID: 44
+showInAdvancedViewOnly: TRUE
+adminDisplayName: Owner
+oMObjectClass:: KwwCh3McAIVK
+adminDescription: Owner
+oMSyntax: 127
+searchFlags: 0
+lDAPDisplayName: owner
+name: Owner
+schemaIDGUID: bf9679f3-0de6-11d0-a285-00aa003049e2
+systemOnly: FALSE
+systemFlags: 16
+isMemberOfPartialAttributeSet: TRUE
+objectCategory: CN=Attribute-Schema,${SCHEMADN}
Added: trunk/openchange/setup/AD/oc_provision_schema_modify.ldif
===================================================================
--- trunk/openchange/setup/AD/oc_provision_schema_modify.ldif (rev 0)
+++ trunk/openchange/setup/AD/oc_provision_schema_modify.ldif 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,674 @@
+# Some of the classes Exchange needs to extend do not exist in
+# Samba4. These classes are added in oc_provision_schema_ADSC.ldif
+#
+# Classes Added:
+# * Address-Book-Container
+# * Contact
+# * Display-Template
+# * DSA
+# * Group-Of-Names
+#
+# ms-Exch-Configuraion-Container class: see oc_provision_schema.ldif
+#
+
+
+#
+# Computer class
+# Represents a computer account in the domain
+#
+dn: CN=Computer,${SCHEMADN}
+changetype: modify
+add: mayContain
+mayContain: msExchExchangeServerLink
+mayContain: logRolloverInterval
+mayContain: monitoredConfigurations
+mayContain: monitoredServices
+mayContain: monitoringAvailabilityStyle
+mayContain: monitoringAvailabilityWindow
+mayContain: monitoringCachedViaMail
+mayContain: monitoringCachedViaRPC
+mayContain: monitoringMailUpdateInterval
+mayContain: monitoringMailUpdateUnits
+mayContain: monitoringRPCUpdateInterval
+mayContain: monitoringRPCUpdateUnits
+mayContain: ms-Exch-Policy-List Attribute
+mayContain: ms-Exch-Policy-Option-List Attribute
+mayContain: promoExpiration
+mayContain: securityProtocol
+mayContain: trackingLogPathName
+mayContain: type
+
+
+
+#
+# Container Class
+# Used to hold other classes
+dn: CN=Container,${SCHEMADN}
+changetype: modify
+add: auxiliaryClass
+add: possSuperiors
+add: mayContain
+auxiliaryClass: msExchBaseClass
+possSuperiors: protocolCfgSharedServer
+mayContain: containerInfo
+mayContain: msExchPolicyList
+mayContain: msExchTemplateRDNs
+mayContain: x500RDN
+mayContain: msExchExportContainersBL
+
+
+
+#
+# Domain-DNS
+# Windows NT domain with DNS-based (DC=) naming.
+#
+dn: CN=Domain-DNS,${SCHEMADN}
+changetype: modify
+add: mayContain
+mayContain: msExchPolicyList
+
+
+
+#
+# Group
+# Stores a list of user names. Used to apply security principals on
+# resources.
+#
+dn: CN=Group,${SCHEMADN}
+changetype: modify
+add: auxiliaryClass
+add: mayContain
+auxiliaryClass: msExchCustomAttributes
+auxiliaryClass: msExchBaseClass
+auxiliaryClass: msExchIMRecipient
+mayContain: hideDLMembership
+mayContain: oOFReplyToOriginator
+mayContain: reportToOriginator
+mayContain: reportToOwner
+mayContain: dLMemberRule
+mayContain: owner
+mayContain: msExchOriginatingForest
+
+
+
+#
+# Mail-Recipient
+# Stores e-mail configuration information.
+#
+dn: CN=Mail-Recipient,${SCHEMADN}
+changetype: modify
+add: mayContain
+mayContain: assistant
+mayContain: altRecipient
+mayContain: authOrig
+mayContain: autoReplyMessage
+mayContain: delivContLength
+mayContain: deliverAndRedirect
+mayContain: dLMemRejectPerms
+mayContain: dLMemSubmitPerms
+mayContain: enabledProtocols
+mayContain: msExchExpansionServerName
+mayContain: expirationTime
+mayContain: folderPathname
+mayContain: formData
+mayContain: forwardingAddress
+mayContain: homeMTA
+mayContain: internetEncoding
+mayContain: languageCode
+mayContain: language
+mayContain: mailNickname
+mayContain: mAPIRecipient
+mayContain: pOPCharacterSet
+mayContain: pOPContentFormat
+mayContain: protocolSettings
+mayContain: publicDelegates
+mayContain: replicationSensitivity
+mayContain: securityProtocol
+mayContain: submissionContLength
+mayContain: targetAddress
+mayContain: unauthOrig
+mayContain: dnQualifier
+mayContain: msExchMailboxSecurityDescriptor
+mayContain: msExchMasterAccountSid
+mayContain: importedFrom
+mayContain: versionNumber
+mayContain: msExchPreviousAccountSid
+mayContain: msExchCustomProxyAddresses
+mayContain: dLMemDefault
+mayContain: mail
+mayContain: deliveryMechanism
+mayContain: extensionData
+mayContain: delivExtContTypes
+mayContain: msExchFBURL
+mayContain: msExchRecipLimit
+mayContain: altRecipientBL
+mayContain: authOrigBL
+mayContain: dLMemRejectPermsBL
+mayContain: dLMemSubmitPermsBL
+mayContain: publicDelegatesBL
+mayContain: unauthOrigBL
+mayContain: msExchPoliciesExcluded
+mayContain: msExchPoliciesIncluded
+mayContain: msExchPolicyEnabled
+mayContain: msExchPolicyOptionList
+mayContain: msExchProxyCustomProxy
+mayContain: msExchUserAccountControl
+mayContain: msExchMailboxFolderSet
+mayContain: msExchRequireAuthToSendTo
+
+
+
+#
+# NTDS-DSA
+# Represents the Active Directory DSA process on the server.
+#
+dn: CN=NTDS-DSA,${SCHEMADN}
+changetype: modify
+add: mayContain
+mayContain: deliveryMechanism
+mayContain: diagnosticRegKey
+
+
+
+#
+# Organizational-Person
+# Contains organizational information about a user.
+#
+dn: CN=Organizational-Person,${SCHEMADN}
+changetype: modify
+add: mayContain
+mayContain: employeeType
+mayContain: businessRoles
+mayContain: telephoneAssistant
+mayContain: personalPager
+mayContain: employeeNumber
+
+
+
+
+#
+# Organizational-Unit
+# A container for storing users, computers, and other account objects.
+#
+dn: CN=Organizational-Unit,${SCHEMADN}
+changetype: modify
+add: auxiliaryClass
+add: mayContain
+auxiliaryClass: msExchBaseClass
+mayContain: msExchPolicyList
+
+
+
+#
+# Sam-Domain
+# Auxiliary class holding common properties for Windows NT domains.
+#
+dn: CN=Sam-Domain,${SCHEMADN}
+changetype: modify
+add: mayContain
+mayContain: msExchAddGroupsToToken
+
+
+
+#
+# Server
+# Represents a server computer within a site.
+#
+dn: CN=Server,${SCHEMADN}
+changetype: modify
+add: mayContain
+mayContain: activationSchedule
+mayContain: activationStyle
+mayContain: type
+mayContain: networkAddress
+
+
+#
+# Site
+# A container for storing server objects. Represents a physical
+# location containing computers. Used to manage replication.
+#
+dn: CN=Site,${SCHEMADN}
+changetype: modify
+add: mayContain
+mayContain: msExchConferenceZoneBL
+mayContain: msExchMCUHostsSitesBL
+
+
+#
+# User
+# Used to store information about an employee or contractor who works
+# for an organization. Can also be applied to long-term visitors.
+#
+dn: CN=User,${SCHEMADN}
+changetype: modify
+add: auxiliaryClass
+add: possSuperiors
+add: mayContain
+auxiliaryClass: msExchCustomAttributes
+auxiliaryClass: msExchMailStorage
+auxiliaryClass: msExchBaseClass
+auxiliaryClass: msExchMultiMediaUser
+auxiliaryClass: msExchCertificateInformation
+auxiliaryClass: msExchIMRecipient
+auxiliaryClass: msExchOmaUser
+possSuperiors: msExchSystemObjectsContainer
+mayContain: msExchQueryBaseDN
+mayContain: msExchControllingZone
+mayContain: msExchResourceGUID
+mayContain: msExchResourceProperties
+mayContain: msExchConferenceMailboxBL
+mayContain: kMServer
+mayContain: msExchIMAPOWAURLPrefixOverride
+mayContain: msExchOriginatingForest
+
+
+
+##################################################################
+# Attributes
+##################################################################
+
+
+#
+# Address
+# The user's address
+#
+dn: CN=Address,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+#
+# Admin-Display-Name
+# The name to be displayed on administrator screens.
+#
+dn: CN=Admin-Display-Name,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+#
+# Attribute-Syntax
+# The object identifier (OID) for the syntax for this attribute.
+#
+dn: CN=Attribute-Syntax,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Comment
+# The user's comments. Can be a null string.
+#
+dn: CN=Comment,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Company
+# The user's company name.
+#
+dn: CN=Company,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Department
+# Contains the name for the department in which the user works.
+#
+dn: CN=Department,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Display-Name-Printable
+# The name displayed in the address book for a particular
+# user. Usually the combination of the user's first name, middle
+# initial, and last name.
+#
+dn: CN=Display-Name-Printable,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# E-mail-Addresses
+# The list of e-mail addresses for a contact.
+#
+dn: CN=E-mail-Addresses,${SCHEMADN}
+changetype: modify
+replace: searchFlags
+searchFlags: 5
+
+
+
+#
+# Facsimile-Telephone-Number
+# Contains the telephone number of the user's business fax machine.
+#
+dn: CN=Facsimile-Telephone-Number,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Garbage-Coll-Period
+# Located on the CN=Directory Service,CN=Windows
+# NT,CN=Services,CN=Configuration,... object. Represents the period in
+# hours between Directory Service (DS) garbage collection runs.
+#
+dn: CN=Garbage-Coll-Period,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+replace: searchFlags
+isMemberOfPartialAttributeSet: TRUE
+searchFlags: 16
+
+
+
+#
+# Given-Name
+# Contains the given name (first name) of the user.
+#
+#dn: CN=Given-Name,${SCHEMADN}
+#changetype: modify
+#add: isMemberOfPartialAttributeSet
+#isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Initials
+# Contains the initials for parts of the user's full name. May be used
+# as the middle initial in the Windows Address Book.
+#
+dn: CN=Initials,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Managed-By
+# The distinguished name of the user that is assigned to manage this
+# object.
+#
+dn: CN=Managed-By,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Network-Address
+# The TCP/IP address for a network segment. Also called the subnet
+# address.
+#
+dn: CN=Network-Address,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# NT-Mixed-Domain
+# Indicates that the domain is in native mode or mixed mode. Found in
+# the domainDNS (head) object for the domain.
+#
+dn: CN=NT-Mixed-Domain,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# OM-Syntax
+# A number representing the OM type for the attribute.
+#
+dn: CN=OM-Syntax,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Phone-Fax-Other
+# A list of alternate facsimile numbers.
+#
+dn: CN=Phone-Fax-Other,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Phone-Home-Other
+# A list of alternate home phone numbers.
+#
+dn: CN=Phone-Home-Other,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Phone-Mobile-Other
+# A list of alternate cell phone numbers.
+#
+dn: CN=Phone-Mobile-Other,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Phone-Mobile-Primary
+# The primary cell phone number
+#
+dn: CN=Phone-Mobile-Primary,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Phone-Office-Other
+# A list of alternate office phone numbers
+#
+dn: CN=Phone-Office-Other,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Phone-Pager-Other
+# A list of alternate pager numbers
+#
+dn: CN=Phone-Pager-Other,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Phone-Pager-Primary
+# The primary pager number
+#
+dn: CN=Phone-Pager-Primary,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Physical-Delivery-Office-Name
+# Contains the office location of the user's place of business.
+#
+dn: CN=Physical-Delivery-Office-Name,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Postal-Code
+# The postal or zip code for mail delivery.
+#
+dn: CN=Postal-Code,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Post-Office-Box
+# The post office box number for this object.
+#
+dn: CN=Post-Office-Box,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Proxy-Addresses
+# Address by which a Microsoft Exchange Server recipient object is
+# recognized in a foreign mail system. Required not just for users,
+# but for all recipient objects such as custom recipients and
+# distribution lists.
+#
+dn: CN=Proxy-Addresses,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+replace: searchFlags
+isMemberOfPartialAttributeSet: TRUE
+searchFlags: 13
+
+
+
+#
+# Show-In-Address-Book
+#
+dn: CN=Show-In-Address-Book,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Sub-Class-Of
+# The parent class of a class
+#
+dn: CN=Sub-Class-Of,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Text-Country
+# The country/region in which the user is located.
+#
+dn: CN=Text-Country,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# Text-Encoded-Or-Address
+#
+dn: CN=Text-Encoded-Or-Address,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+replace: searchFlags
+replace: attributeSecurityGuid
+isMemberOfPartialAttributeSet: TRUE
+searchFlags: 1
+attributeSecurityGuid: e48d0154-bcf8-11d1-8702-00c04fb96050
+
+
+
+#
+# Title
+# Contains the user's job title. Property commonly used to indicate
+# the formal job title, such as Senior Programmer, rather than
+# occupational class, such as programmer. Not typically used for
+# suffix titles such as Esq. or D.D.S.
+#
+dn: CN=Title,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+replace: searchFlags
+isMemberOfPartialAttributeSet: TRUE
+searchFlags: 16
+
+
+
+#
+# Version-Number
+# A general-purpose version number.
+#
+dn: CN=Version-Number,${SCHEMADN}
+changetype: modify
+replace: searchFlags
+searchFlags: 8
+
+
+
+#
+# WWW-Home-Page
+# The primary Web page
+#
+dn: CN=WWW-Home-Page,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
+
+
+#
+# WWW-Page-Other
+# A list of alternate Web pages
+#
+dn: CN=WWW-Page-Other,${SCHEMADN}
+changetype: modify
+add: isMemberOfPartialAttributeSet
+isMemberOfPartialAttributeSet: TRUE
+
Added: trunk/openchange/setup/AD/prefixMap.txt
===================================================================
--- trunk/openchange/setup/AD/prefixMap.txt (rev 0)
+++ trunk/openchange/setup/AD/prefixMap.txt 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,39 @@
+0:2.5.4
+1:2.5.6
+2:1.2.840.113556.1.2
+3:1.2.840.113556.1.3
+4:2.16.840.1.101.2.2.1
+5:2.16.840.1.101.2.2.3
+6:2.16.840.1.101.2.1.5
+7:2.16.840.1.101.2.1.4
+8:2.5.5
+9:1.2.840.113556.1.4
+10:1.2.840.113556.1.5
+19:0.9.2342.19200300.100
+20:2.16.840.1.113730.3
+21:0.9.2342.19200300.100.1
+22:2.16.840.1.113730.3.1
+23:1.2.840.113556.1.5.7000
+24:2.5.21
+25:2.5.18
+26:2.5.20
+11:1.2.840.113556.1.4.260
+12:1.2.840.113556.1.5.56
+13:1.2.840.113556.1.4.262
+14:1.2.840.113556.1.5.57
+15:1.2.840.113556.1.4.263
+16:1.2.840.113556.1.5.58
+17:1.2.840.113556.1.5.73
+18:1.2.840.113556.1.4.305
+27:1.3.6.1.4.1.1466.101.119
+28:2.16.840.1.113730.3.2
+29:1.3.6.1.4.1.250.1
+30:1.2.840.113549.1.9
+31:0.9.2342.19200300.100.4
+32:1.3.6.1.4.1.7165.4.1
+33:1.3.6.1.4.1.7165.4.2
+34:1.2.840.113556.1.5.7000.62
+35:1.2.840.113556.1.4.7000.102
+36:1.2.840.113556.1.6.20.1
+37:1.2.840.113556.1.6.20.2
+
Added: trunk/openchange/setup/AD/provision_schema_basedn_modify.ldif
===================================================================
--- trunk/openchange/setup/AD/provision_schema_basedn_modify.ldif (rev 0)
+++ trunk/openchange/setup/AD/provision_schema_basedn_modify.ldif 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,14 @@
+###############################
+# Schema Naming Context
+###############################
+dn: ${SCHEMADN}
+changetype: modify
+replace: fSMORoleOwner
+fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
+-
+replace: objectVersion
+objectVersion: 30
+-
+replace: prefixMap
+prefixMap:: ${PREFIXMAP_B64}
+
Added: trunk/openchange/setup/openchange_newuser
===================================================================
--- trunk/openchange/setup/openchange_newuser (rev 0)
+++ trunk/openchange/setup/openchange_newuser 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,74 @@
+#!/usr/bin/python
+# OpenChange provision script
+#
+# Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2008
+#
+# 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/>.
+#
+
+import optparse
+import os,sys
+
+# To allow running from the source directory
+sys.path.append("python")
+
+from openchange import find_samba_python_path
+samba_path = find_samba_python_path()
+if samba_path is not None:
+ sys.path.append(samba_path)
+
+import samba
+import samba.getopt as options
+from samba.auth import system_session
+import openchange.provision as openchange
+
+parser = optparse.OptionParser("openchange_newuser [options] <username>")
+
+sambaopts = options.SambaOptions(parser)
+parser.add_option_group(sambaopts)
+
+credopts = options.CredentialsOptions(parser)
+parser.add_option_group(credopts)
+parser.add_option("--enable", action="store_true", metavar="ENABLE",
+ help="Enable access to OpenChange server")
+parser.add_option("--disable", action="store_true", metavar="DISABLE",
+ help="Disable access to OpenChange server")
+parser.add_option("--create", action="store_true", metavar="CREATE",
+ help="Create the OpenChange user account")
+parser.add_option("--mailbox", action="store_true", metavar="MAILBOX",
+ help="Create the OpenChange user mailbox")
+
+opts, args = parser.parse_args()
+
+if len(args) == 0:
+ parser.print_usage()
+ sys.exit(1)
+
+lp = sambaopts.get_loadparm()
+creds = credopts.get_credentials(lp)
+
+def setup_path(*args):
+ return os.path.join(os.path.dirname(__file__), *args)
+
+if opts.enable == True:
+ openchange.accountcontrol(lp, creds, username=args[0], value=0)
+
+if opts.disable == True:
+ openchange.accountcontrol(lp, creds, username=args[0], value=2)
+
+if opts.create == True:
+ openchange.newuser(lp, creds, username=args[0])
+
+if opts.mailbox == True:
+ openchange.newmailbox(lp, username=args[0], firstorg=None, firstou=None)
Property changes on: trunk/openchange/setup/openchange_newuser
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/setup/openchange_provision
===================================================================
--- trunk/openchange/setup/openchange_provision (rev 0)
+++ trunk/openchange/setup/openchange_provision 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+# OpenChange provision script
+#
+# Copyright (C) Jelmer Vernooij <jelmer at openchange.org> 2008
+#
+# 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/>.
+#
+
+import optparse
+import os,sys
+
+# To allow running from the source directory
+sys.path.append("python")
+
+from openchange import find_samba_python_path
+samba_path = find_samba_python_path()
+if samba_path is not None:
+ sys.path.append(samba_path)
+
+import samba
+import samba.getopt as options
+from samba.auth import system_session
+import openchange.provision as openchange
+
+parser = optparse.OptionParser("openchange_provision [options]")
+
+sambaopts = options.SambaOptions(parser)
+parser.add_option_group(sambaopts)
+
+credopts = options.CredentialsOptions(parser)
+parser.add_option_group(credopts)
+parser.add_option("--firstorg", type="string", metavar="FIRSTORG",
+ help="set OpenChange First Organization (otherwise First Organization)")
+parser.add_option("--firstou", type="string", metavar="FIRSTOU",
+ help="set OpenChange First Organization Unit (otherwise First Organization Unit)")
+parser.add_option("--openchangedb", action="store_true", help="Initialize OpenChange dispatcher database")
+
+opts,args = parser.parse_args()
+if len(args) != 0:
+ parser.print_usage()
+ sys.exit(1)
+
+lp = sambaopts.get_loadparm()
+creds = credopts.get_credentials(lp)
+
+def setup_path(*args):
+ return os.path.join(os.path.dirname(__file__), *args)
+
+if not opts.openchangedb:
+ openchange.provision(setup_path, lp, creds, firstorg=opts.firstorg, firstou=opts.firstou)
+else:
+ openchange.openchangedb_provision(lp, firstorg=opts.firstorg, firstou=opts.firstou)
Property changes on: trunk/openchange/setup/openchange_provision
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/setup/openchangedb/oc_provision_openchange_init.ldif
===================================================================
--- trunk/openchange/setup/openchangedb/oc_provision_openchange_init.ldif (rev 0)
+++ trunk/openchange/setup/openchangedb/oc_provision_openchange_init.ldif 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,9 @@
+dn: @OPTIONS
+checkBaseOnSearch: TRUE
+
+dn: @INDEXLIST
+ at IDXATTR: cn
+
+dn: @ATTRIBUTES
+cn: CASE_INSENSITIVE
+dn: CASE_INSENSITIVE
\ No newline at end of file
Added: trunk/openchange/setup/openchangedb/oc_provision_openchange_mailbox.ldif
===================================================================
--- trunk/openchange/setup/openchangedb/oc_provision_openchange_mailbox.ldif (rev 0)
+++ trunk/openchange/setup/openchangedb/oc_provision_openchange_mailbox.ldif 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,4 @@
+dn: CN=${FOLDER_IDX},${USERDN}
+cn: ${FOLDER_IDX}
+fid: ${FOLDER_IDX}
+name: ${NAME}
Added: trunk/openchange/setup/profiles/oc_profiles_init.ldif
===================================================================
--- trunk/openchange/setup/profiles/oc_profiles_init.ldif (rev 0)
+++ trunk/openchange/setup/profiles/oc_profiles_init.ldif 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,7 @@
+dn: @ATTRIBUTES
+dnsDomain: CASE_INSENSITIVE
+cn: CASE_INSENSITIVE
+dc: CASE_INSENSITIVE
+name: CASE_INSENSITIVE
+dn: CASE_INSENSITIVE
+objectClass: CASE_INSENSITIVE
Added: trunk/openchange/setup/profiles/oc_profiles_schema.ldif
===================================================================
--- trunk/openchange/setup/profiles/oc_profiles_schema.ldif (rev 0)
+++ trunk/openchange/setup/profiles/oc_profiles_schema.ldif 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,219 @@
+#
+# Exchange organization
+#
+dn: CN=Organization
+objectClass: top
+objectClass: attributeSchema
+name: Organization
+CN: Organization
+description: Exchange Organization
+isSingleValued: TRUE
+
+#
+# Exchange organization unit
+#
+dn: CN=OrganizationUnit
+objectClass: top
+objectClass: attributeSchema
+name: OrganizationUnit
+CN: OrganizationUnit
+description: Exchange Organization Unit
+isSingleValued: TRUE
+
+#
+# User display name
+#
+dn: CN=DisplayName
+objectClass: top
+objectClass: attributeSchema
+name: DisplayName
+CN: DisplayName
+description: User display name
+isSingleValued: TRUE
+
+#
+# Office Telephone Number
+#
+dn: CN=OfficeTelephoneNumber
+objectClass: top
+objectClass: attributeSchema
+name: OfficeTelephoneNumber
+CN: OfficeTelephoneNumber
+description: Office Telephone Number
+isSingleValued: TRUE
+
+#
+# Office Location
+#
+dn: CN=OfficeLocation
+objectClass: top
+objectClass: attributeSchema
+name: OfficeLocation
+CN: OfficeLocation
+description: Office Location
+isSingleValued: TRUE
+
+#
+# User title
+#
+dn: CN=Title
+objectClass: top
+objectClass: attributeSchema
+name: Title
+CN: Title
+description: User Title
+isSingleValued: TRUE
+
+#
+# Company Name
+#
+dn: CN=CompanyName
+objectClass: top
+objectClass: attributeSchema
+name: CompanyName
+CN: CompanyName
+description: Company Name
+isSingleValued: TRUE
+
+#
+# User account name
+#
+dn: CN=AccountName
+objectClass: top
+objectClass: attributeSchema
+name: AccountName
+CN: AccountName
+description: User account name
+isSingleValued: TRUE
+
+#
+# User email address
+#
+dn: CN=EmailAddress
+objectClass: top
+objectClass: attributeSchema
+name: EmailAddress
+CN: EmailAddress
+description: User email address
+isSingleValued: TRUE
+
+#
+# Email Address type
+#
+dn: CN=AddrType
+objectClass: top
+objectClass: attributeSchema
+name: AddrType
+CN: AddrType
+description: User Email Address Type
+isSingleValued: TRUE
+
+#
+# Entry ID
+#
+dn: CN=EntryID
+objectClass: top
+objectClass: attributeSchema
+name: EntryID
+CN: ENtryID
+description: Unique identifier for the given object
+isSingleValued: TRUE
+
+#
+# Object Type
+#
+dn: CN=ObjectType
+objectClass: top
+objectClass: attributeSchema
+name: ObjectType
+CN: ObjectType
+description: Object Type
+isSingleValued: TRUE
+
+#
+# Home MDB
+#
+dn: CN=HomeMDB
+objectClass: top
+objectClass: attributeSchema
+name: HomeMDB
+CN: HomeMDB
+description: Path to the user Mailbox
+isSingleValued: TRUE
+
+#
+# User Proxy addresses for different connectors
+#
+dn: CN=ProxyAddress
+objectClass: top
+objectClass: attributeSchema
+name: ProxyAddress
+CN: ProxyAddress
+description: Proxy addresses for other connectors
+isSingleValued: FALSE
+
+#
+# PR_DEFAULT_PROFILE
+#
+dn: CN=PR_DEFAULT_PROFILE
+objectClass: top
+objectClass: attributeSchema
+name: PR_DEFAULT_PROFILE
+CN: PR_DEFAULT_PROFILE
+description: Indicates if the profile is the default one
+isSingleValued: TRUE
+
+########################################################
+# Attributes for Exchange Servers containers
+########################################################
+
+#
+# Exchange server binding strings
+#
+dn: CN=NetworkAddress
+objectClass: top
+objectClass: attributeSchema
+name: NetworkAddress
+CN: NetworkAddress
+description: binding string we can use to connect to the Exchange Server
+isSingleValued: FALSE
+
+#
+# Container flags
+#
+dn: CN=ContainerFlags
+objectClass: top
+objectClass: attributeSchema
+name: ContainerFlags
+CN: ContainerFlags
+isSingleValued: TRUE
+
+#
+# Depth
+#
+dn: CN=Depth
+objectClass: top
+objectClass: attributeSchema
+name: Depth
+CN: Depth
+isSingleValued: TRUE
+
+#
+# AB Container ID
+#
+dn: CN=ABContainerID
+objectClass: top
+objectClass: attributeSchema
+name: ABContainerID
+CN: ABContainerID
+isSingleValued: TRUE
+
+#
+# AB is Master
+#
+dn: CN=ABIsMaster
+objectClass: top
+objectClass: attributeSchema
+name: ABIsMaster
+CN: ABIsMaster
+isSingleValued: TRUE
\ No newline at end of file
Added: trunk/openchange/swig/perl/Makefile
===================================================================
--- trunk/openchange/swig/perl/Makefile (rev 0)
+++ trunk/openchange/swig/perl/Makefile 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,63 @@
+#Makefile for libmapi Perl bindings
+#Writen by Julien Kerihuel <j.kerihuel at openchange.org>, 2007.
+
+include ../../config.mk
+
+top_builddir = ../..
+
+CFLAGS+=`perl -MExtUtils::Embed -e ccopts` -D_SAMBA_UTIL_H_
+
+# Portability hack...
+CFLAGS+=-Duint_t="unsigned int"
+
+CFLAGS+=-I$(top_builddir)
+
+all:: swig_mapitags.h \
+ swig_mapicodes.h \
+ mapi_wrap.c \
+ mapi.$(SHLIBEXT)
+
+clean::
+ rm -f *.o
+ rm -f *.pm
+ rm -f mapi_wrap.c
+ rm -f swig_mapicodes.h swig_mapitags.h
+ rm -f mapi.$(SHLIBEXT)
+
+distclean:: clean
+ rm -f *.so
+
+install:: all
+ cp mapi.pm $(PERL5DIR)
+ cp mapi.so $(PERL5DIR)
+
+uninstall::
+ rm -f $(PERL5DIR)/mapi.pm
+ rm -f $(PERL5DIR)/mapi.so
+
+mapi_wrap.c: mapi.i
+ @echo "Swigify $<"
+ @$(SWIG) -Wall -Werror -perl5 $<
+
+swig_mapitags.h:
+ @echo "Generating Headers (swig_mapitags.h)"
+ @$(top_builddir)/libmapi/conf/mparse.pl --parser=swig_mapitags --outputdir=./ $(top_builddir)/libmapi/conf/mapi-properties
+
+swig_mapicodes.h:
+ @echo "Generating Headers (swig_mapicodes.h)"
+ @$(top_builddir)/libmapi/conf/mparse.pl --parser=swig_mapicodes --outputdir=./ $(top_builddir)/libmapi/conf/mapi-codes
+
+.SUFFIXES: .po
+
+.c.po:
+ @echo "Compiling $< with -fPIC"
+ @$(CC) $(CFLAGS) -DDEFAULT_LDIF=\"$(DESTDIR)$(datadir)/setup\" -fPIC -c $< -o $@
+
+mapi.$(SHLIBEXT): mapi_wrap.po \
+ lwmapi.po \
+ ../../libmapi/utf8_convert.yy.po \
+ ../../libmapi/*.po \
+ ../../gen_ndr/*.po \
+ ../../*.po
+ @echo "Compiling $<"
+ @$(CC) -o $@ $(DSOOPT) $^ $(LIBS)
Added: trunk/openchange/swig/perl/lwmapi.c
===================================================================
--- trunk/openchange/swig/perl/lwmapi.c (rev 0)
+++ trunk/openchange/swig/perl/lwmapi.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,45 @@
+/*
+ OpenChange Perl bindings wrappers
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <stdint.h>
+
+typedef uint64_t NTTIME;
+struct ipv4_addr;
+
+#include <libmapi/libmapi.h>
+
+/**
+ * Note: Most of these wrapper functions are useless and are just here
+ * cause we don't use swig properly.
+ */
+
+void lw_dumpdata(void)
+{
+ global_mapi_ctx->dumpdata = true;
+}
+
+const uint64_t *lw_getID(struct SRowSet *SRowSet, uint32_t ulPropTag,
+ uint32_t idx)
+{
+ struct SPropValue *lpProp;
+ uint64_t *id;
+
+ lpProp = get_SPropValue_SRow((&SRowSet->aRow[idx]), ulPropTag);
+ return get_SPropValue(lpProp, ulPropTag);
+}
Added: trunk/openchange/swig/perl/mapi.i
===================================================================
--- trunk/openchange/swig/perl/mapi.i (rev 0)
+++ trunk/openchange/swig/perl/mapi.i 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,124 @@
+/*
+ OpenChange MAPI library bindings for Perl
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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/>.
+*/
+
+%module mapi
+%{
+typedef uint64_t NTTIME;
+struct ipv4_addr;
+
+#include <libmapi/libmapi.h>
+#include <libmapi/proto.h>
+
+%}
+
+%include "typemaps.i"
+%include "cstring.i"
+%include "cpointer.i"
+%include "carrays.i"
+%import "stdint.i"
+
+%include "../../libmapi/mapidefs.h"
+%include "swig_mapitags.h"
+%include "swig_mapicodes.h"
+
+%nodefaultctor SPropTagArray;
+%nodefaultdtor SPropTagArray;
+
+%array_functions(uint32_t,aulPropTag);
+struct SPropTagArray {
+ uint32_t *aulPropTag;
+ uint32_t cValues;
+};
+
+%inline %{
+ struct SPropTagArray *new_SPropTagArray(int nb)
+ {
+ struct SPropTagArray *result = 0;
+
+ result = (struct SPropTagArray *)(struct SPropTagArray *) calloc(1, sizeof(struct SPropTagArray));
+ result->cValues = nb;
+ result->aulPropTag = new_aulPropTag(nb);
+
+ return result;
+ }
+
+ void delete_SPropTagArray(struct SPropTagArray *s)
+ {
+ delete_aulPropTag(s->aulPropTag);
+ free((struct SPropTagArray *)s);
+ }
+%}
+
+
+%nodefaultctor mapi_object;
+%nodefaultdtor mapi_object;
+%inline %{
+ mapi_object_t *new_mapi_object()
+ {
+ mapi_object_t *obj;
+
+ obj = malloc(sizeof(mapi_object_t));
+ mapi_object_init(obj);
+
+ return obj;
+ }
+
+ static void delete_mapi_object(mapi_object_t *obj)
+ {
+ mapi_object_release(obj);
+ free((mapi_object_t *)obj);
+ }
+%}
+
+struct SRowSet {
+ uint32_t cRows;
+ struct SRow *aRow;
+};
+
+%pointer_functions(uint64_t, int64);
+%pointer_functions(uint32_t, int32);
+%pointer_functions(struct mapi_SPropValue_array, mapi_SPropValue_array);
+%pointer_functions(struct mapi_session *, mapi_session_t);
+
+extern void lw_dumpdata(void);
+extern uint64_t *lw_getID(struct SRowSet *SRowSet, uint32_t tag, uint32_t idx);
+
+extern uint32_t MAPIInitialize(const char *profile);
+extern void MAPIUninitialize(void);
+extern uint32_t MapiLogonEx(struct mapi_session **session, char *profile, char *password);
+extern uint32_t GetLastError(void);
+extern void mapi_errstr(const char *function, uint32_t mapi_code);
+
+%cstring_output_allocate(char **s, $1);
+extern uint32_t GetDefaultProfile(const char **s);
+
+extern uint32_t GetDefaultFolder(mapi_object_t *obj, uint64_t *folder, const uint32_t folder_id);
+extern uint32_t OpenFolder(mapi_object_t *obj, uint64_t folder, mapi_object_t *obj2);
+extern uint32_t GetFolderItemsCount(mapi_object_t *obj, uint32_t *unread, uint32_t *total);
+extern uint32_t GetContentsTable(mapi_object_t *obj, mapi_object_t *obj2, uint8_t TableFlags, uint32_t *RowCount);
+extern uint32_t SetColumns(mapi_object_t *obj, struct SPropTagArray *lpProps);
+extern uint32_t QueryRows(mapi_object_t *obj, uint32_t nb, uint32_t flg, struct SRowSet *SRowSet);
+extern uint32_t QueryPosition(mapi_object_t *obj, uint32_t *Numerator, uint32_t *Denominator);
+extern uint32_t OpenMsgStore(struct mapi_session *session, mapi_object_t *obj);
+extern uint32_t OpenMessage(mapi_object_t *obj, uint64_t fid, uint64_t mid, mapi_object_t *obj_msg, uint8_t flag);
+extern uint32_t GetPropsAll(mapi_object_t *obj, struct mapi_SPropValue_array *mlpProps);
+
+extern void mapidump_SPropTagArray(struct SPropTagArray *lpProps);
+extern void mapidump_SRowSet(struct SRowSet *SRowSet, const char *sep);
+extern void mapidump_message(struct mapi_SPropValue_array *mlpProps, char *);
Added: trunk/openchange/swig/perl/tests/fetchmail.pl
===================================================================
--- trunk/openchange/swig/perl/tests/fetchmail.pl (rev 0)
+++ trunk/openchange/swig/perl/tests/fetchmail.pl 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,132 @@
+#!/usr/bin/perl -w
+
+##############################################
+# Perl bindings test suite:
+#
+# o Fetch emails from Exchange Server
+#
+# Copyright Julien Kerihuel 2007.
+# <j.kerihuel at openchange.org>
+#
+# released under GNU GPL
+
+
+use strict;
+use mapi;
+
+package mapi;
+
+my $retval;
+
+sub mapi_init()
+{
+ my $profdb;
+ my $profname;
+ my $password = ();
+ my $flag = 0;
+ my $session = new_mapi_session_t();
+
+ print "Initializing MAPI\n";
+ $profdb = sprintf("%s/.openchange/profiles.ldb", $ENV{HOME});
+
+ # Initialize MAPI library
+ $retval = MAPIInitialize($profdb);
+ mapi_errstr("MAPIInitialize", GetLastError());
+
+ # Activate MAPI decoding
+ #lw_dumpdata();
+
+ # Retrieve default profile name
+ ($retval, $profname) = GetDefaultProfile();
+ mapi_errstr("GetDefaultProfile", GetLastError());
+
+ $retval = MapiLogonEx($session, $profname, $password);
+ mapi_errstr("MapiLogonEx", $retval);
+
+ return $session;
+}
+
+sub mapi_finalize()
+{
+ MAPIUninitialize();
+}
+
+sub mapi_fetchmail($)
+{
+ my $session = shift;
+ my $inbox_id = new_int64();
+ my $cRows;
+ my $count = new_int32();
+ my $unread = new_int32();
+ my $total = new_int32();
+ my $SRowSet = new mapi::SRowSet();
+
+ ## Open Message Store
+ my $obj_store = new_mapi_object();
+ $retval = OpenMsgStore(mapi_session_t_value($session), $obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+
+ ## Open Inbox
+ my $obj_inbox = new_mapi_object();
+ $retval = GetDefaultFolder($obj_store, $inbox_id, $mapi::olFolderInbox);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+
+ $retval = OpenFolder($obj_store, int64_value($inbox_id), $obj_inbox);
+ mapi_errstr("OpenFolder", GetLastError());
+
+ ## Count messages
+ $retval = GetFolderItemsCount($obj_inbox, $unread, $total);
+ mapi_errstr("GetFolderItemsCount", GetLastError());
+
+ print "Mailbox:\n";
+ print "\t => Unread(" . int32_value($unread) . ")\n";
+ print "\t => Total(" . int32_value($total) . ")\n";
+
+ ## GetContentsTable
+ my $obj_table = new_mapi_object();
+ $retval = GetContentsTable($obj_inbox, $obj_table, 0, $count);
+ mapi_errstr("GetContentsTable", GetLastError());
+
+ ## Prepare MAPI table creation
+ my $SPropTagArray = new_SPropTagArray(5);
+ aulPropTag_setitem($SPropTagArray->{aulPropTag}, 0, $mapi::PR_FID);
+ aulPropTag_setitem($SPropTagArray->{aulPropTag}, 1, $mapi::PR_MID);
+ aulPropTag_setitem($SPropTagArray->{aulPropTag}, 2, $mapi::PR_INST_ID);
+ aulPropTag_setitem($SPropTagArray->{aulPropTag}, 3, $mapi::PR_INSTANCE_NUM);
+ aulPropTag_setitem($SPropTagArray->{aulPropTag}, 4, $mapi::PR_SUBJECT);
+
+ $retval = SetColumns($obj_table, $SPropTagArray);
+ delete_SPropTagArray($SPropTagArray);
+ mapi_errstr("SetColumns", GetLastError());
+
+ ## Get table rows
+ while (($retval = QueryRows($obj_table, int32_value($count), 0, $SRowSet)) != $mapi::MAPI_E_NOT_FOUND
+ && $SRowSet->{cRows})
+ {
+
+ for (my $i = 0; $i != $SRowSet->{cRows}; $i++) {
+
+ my $fid = int64_value(lw_getID($SRowSet, $mapi::PR_FID, $i));
+ my $mid = int64_value(lw_getID($SRowSet, $mapi::PR_MID, $i));
+
+ my $obj_message = new_mapi_object();
+ $retval = OpenMessage($obj_store, $fid, $mid, $obj_message, $mapi::MAPI_CREATE|$mapi::MAPI_MODIFY);
+
+ if (GetLastError() != $mapi::MAPI_E_NOT_FOUND) {
+ my $props = new_mapi_SPropValue_array();
+
+ $retval = GetPropsAll($obj_message, $props);
+ mapidump_message($props, "");
+ delete_mapi_object($obj_message);
+ }
+ }
+ }
+
+ delete_mapi_object($obj_table);
+ delete_mapi_object($obj_inbox);
+ delete_mapi_object($obj_store);
+}
+
+my $session = &mapi_init();
+&mapi_fetchmail($session);
+&mapi_finalize();
Property changes on: trunk/openchange/swig/perl/tests/fetchmail.pl
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/testprogs/blackbox/subunit.sh
===================================================================
--- trunk/openchange/testprogs/blackbox/subunit.sh (rev 0)
+++ trunk/openchange/testprogs/blackbox/subunit.sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,67 @@
+#
+# subunit.sh: shell functions to report test status via the subunit protocol.
+# Copyright (C) 2006 Robert Collins <robertc at robertcollins.net>
+# Copyright (C) 2008 Jelmer Vernooij <jelmer at samba.org>
+#
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+subunit_start_test () {
+ # emit the current protocol start-marker for test $1
+ echo "test: $1"
+}
+
+
+subunit_pass_test () {
+ # emit the current protocol test passed marker for test $1
+ echo "success: $1"
+}
+
+
+subunit_fail_test () {
+ # emit the current protocol fail-marker for test $1, and emit stdin as
+ # the error text.
+ # we use stdin because the failure message can be arbitrarily long, and this
+ # makes it convenient to write in scripts (using <<END syntax.
+ echo "failure: $1 ["
+ cat -
+ echo "]"
+}
+
+
+subunit_error_test () {
+ # emit the current protocol error-marker for test $1, and emit stdin as
+ # the error text.
+ # we use stdin because the failure message can be arbitrarily long, and this
+ # makes it convenient to write in scripts (using <<END syntax.
+ echo "error: $1 ["
+ cat -
+ echo "]"
+}
+
+testit () {
+ name="$1"
+ shift
+ cmdline="$*"
+ subunit_start_test "$name"
+ output=`$cmdline 2>&1`
+ status=$?
+ if [ x$status = x0 ]; then
+ subunit_pass_test "$name"
+ else
+ echo "$output" | subunit_fail_test "$name"
+ fi
+ return $status
+}
Property changes on: trunk/openchange/testprogs/blackbox/subunit.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/testprogs/blackbox/test_mapiprofile.sh
===================================================================
--- trunk/openchange/testprogs/blackbox/test_mapiprofile.sh (rev 0)
+++ trunk/openchange/testprogs/blackbox/test_mapiprofile.sh 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,53 @@
+#!/bin/sh
+# Black tests for mapiprofile
+# Copyright (C) 2009 Julien Kerihuel <j.kerihuel at openchange.org>
+
+if [ $# -lt 4 ]; then
+cat <<EOF
+Usage: mapiprofile.sh SERVER USERNAME PASSWORD DOMAIN
+EOF
+exit 1;
+fi
+
+SERVER=$1
+USERNAME=$2
+PASSWORD=$3
+DOMAIN=$4
+shift 4
+failed=0
+
+ocbindir=`dirname $0`/../../bin
+mapiprofile=$ocbindir/mapiprofile
+profdb=`dirname $0`/profiles.ldb
+
+. `dirname $0`/subunit.sh
+
+testit "create new database" $VALGRIND $mapiprofile --newdb --database=$profdb || failed=`expr $failed + 1`
+
+testit "create new profile" $VALGRIND $mapiprofile --database=$profdb -P mapiprofile --create --username=$USERNAME --password=$PASSWORD -I $SERVER -D $DOMAIN || failed=`expr $failed + 1`
+
+testit "list profiles" $VALGRIND $mapiprofile --database=$profdb --list || failed=`expr $failed + 1`
+
+testit "set it as default" $VALGRIND $mapiprofile --database=$profdb -P mapiprofile -S || failed=`expr $failed + 1`
+
+# Check if the default profile has the proper name
+list_test=`mapiprofile --list --database=$profdb | grep default | cut -d= -f2 | sed 's/\[default\]//' | sed 's/\s*//' | sed 's/ //'`
+if [ "$list_test" != "mapiprofile" ]; then
+ subunit_fail_test "\"$list_test\" is not the default profile"
+ failed=`expr $failed + 1`
+fi
+
+testit "rename profile" $VALGRIND $mapiprofile --database=$profdb -P mapiprofile --rename=mapiprofile_rename || failed=`expr $failed + 1`
+
+# Check if the new profile has the proper name
+rename=`mapiprofile --list --database=$profdb | grep default | cut -d= -f2 | sed 's/\[default\]//' | sed 's/\s*//' | sed 's/ //'`
+if [ "$rename" != "mapiprofile_rename" ]; then
+ subunit_fail_test "mapiprofile was not renamed to mapiprofile_rename"
+ failed=`expr $failed + 1`
+fi
+
+testit "get FQDN" $VALGRIND $mapiprofile --database=$profdb -P mapiprofile_rename --getfqdn || failed=`expr $failed + 1`
+
+testit "delete profile" $VALGRIND $mapiprofile --database=$profdb -P mapiprofile_rename --delete || failed=`expr $failed + 1`
+
+rm -f profiles.ldb
\ No newline at end of file
Property changes on: trunk/openchange/testprogs/blackbox/test_mapiprofile.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/torture/exchange_createuser.c
===================================================================
--- trunk/openchange/torture/exchange_createuser.c (rev 0)
+++ trunk/openchange/torture/exchange_createuser.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,523 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Create an Exchange user
+
+ Copyright (C) Julien Kerihuel 2006 - 2007.
+
+ 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/>.
+ */
+
+/*
+ Several functions are forked from Samba4 trunk for convenient
+ purposes:
+ - DeleteUser_byname
+ - torture_join_user_sid
+ - torture_create_testuser
+ - torture_leave_domain
+ */
+
+#include <libmapi/libmapi.h>
+#include <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+#include <ldb.h>
+#include <ldb_errors.h>
+#include <ldb_wrap.h>
+#include <ldap_ndr.h>
+#include <util_ldb.h>
+#include <gen_ndr/ndr_samr.h>
+#include <gen_ndr/ndr_samr_c.h>
+#include <time.h>
+#include <core/error.h>
+#include <tevent.h>
+
+struct tce_async_context {
+ int found;
+};
+
+static int tce_search_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+ struct tce_async_context *actx = talloc_get_type(req->context, struct tce_async_context);
+ int ret;
+
+ switch (ares->type) {
+
+ case LDB_REPLY_ENTRY:
+ if (ldb_msg_find_element(ares->message, "msExchMailboxGuid") != NULL) {
+ actx->found = 1;
+ }
+ break;
+
+ case LDB_REPLY_DONE:
+ ret = 0;
+ break;
+
+ default:
+ fprintf(stderr, "unknown Reply Type ignore it\n");
+ return LDB_ERR_OTHER;
+ }
+
+ if (talloc_free(ares) == -1) {
+ fprintf(stderr, "talloc_free failed\n");
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ return LDB_SUCCESS;
+}
+
+NTSTATUS torture_exchange_createuser(TALLOC_CTX *mem_ctx, const char *username,
+ const struct dom_sid *dom_sid)
+{
+ enum MAPISTATUS retval;
+ struct tevent_context *ev = NULL;
+ struct mapi_profile *profile;
+ struct ldb_context *remote_ldb;
+ struct ldb_request *req;
+ struct ldb_message *msg;
+ struct ldb_message **res;
+ struct tce_async_context *tce_ctx;
+ char *remote_ldb_url;
+ const char * const dom_attrs[] = { "objectSid", NULL };
+ int ret;
+ uint32_t count;
+ char **values;
+
+ profile = global_mapi_ctx->session->profile;
+
+ ev = tevent_context_init(talloc_autofree_context());
+
+ /* open LDAP connection */
+ remote_ldb_url = talloc_asprintf(mem_ctx, "ldap://%s", profile->server);
+ remote_ldb = ldb_wrap_connect(mem_ctx, ev, global_mapi_ctx->lp_ctx, remote_ldb_url,
+ NULL, cmdline_credentials, 0, NULL);
+ if (!remote_ldb) return NT_STATUS_UNSUCCESSFUL;
+
+ /* search the user's record using the user dom_sid */
+ ret = gendb_search(remote_ldb, mem_ctx, NULL, &res,
+ dom_attrs, "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
+ if (ret == -1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ if (ret == 0) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ /* Prepare a new message for modify */
+ msg = ldb_msg_new(mem_ctx);
+ if (!msg) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ msg->dn = res[0]->dn;
+
+ {
+ int rtn;
+ const char *exch_attrs[7];
+
+ exch_attrs[0] = talloc_strdup(mem_ctx, username);
+ rtn = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "givenName", exch_attrs[0]);
+ if (rtn == -1) return NT_STATUS_NO_MEMORY;
+
+ exch_attrs[1] = talloc_asprintf(mem_ctx, "513");
+ rtn = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "userAccountControl", exch_attrs[1]);
+ if (rtn == -1) return NT_STATUS_NO_MEMORY;
+
+ {
+ int i;
+ char *realm = NULL;
+
+ retval = GetProfileAttr(profile, "ProxyAddress", &count, &values);
+ if (retval != MAPI_E_SUCCESS) return NT_STATUS_UNSUCCESSFUL;
+ for (i = 0; i < count; i++) {
+ if (values[i] && !strncasecmp("smtp", values[i], 4)) {
+ realm = strchr(values[i], '@');
+ realm += 1;
+ }
+ }
+ if (!realm) return NT_STATUS_UNSUCCESSFUL;
+
+ exch_attrs[2] = talloc_asprintf(mem_ctx, "%s@%s", username, realm);
+ rtn = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "mail", exch_attrs[2]);
+ if (rtn == -1) return NT_STATUS_NO_MEMORY;
+ }
+
+ exch_attrs[3] = talloc_strdup(mem_ctx, username);
+ rtn = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "mailNickname", exch_attrs[3]);
+ if (rtn == -1) return NT_STATUS_NO_MEMORY;
+
+ exch_attrs[4] = talloc_asprintf(mem_ctx, "TRUE");
+ rtn = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "mDBUseDefaults", exch_attrs[4]);
+ if (rtn == -1) return NT_STATUS_NO_MEMORY;
+
+ {
+ char *org;
+
+ org = talloc_strndup(mem_ctx, profile->mailbox,
+ strlen(profile->mailbox) - strlen(profile->username));
+ exch_attrs[5] = talloc_asprintf(mem_ctx, "%s%s", org, username);
+ talloc_free(org);
+ rtn = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "legacyExchangeDN", exch_attrs[5]);
+ if (rtn == -1) return NT_STATUS_NO_MEMORY;
+ }
+
+ exch_attrs[6] = talloc_strdup(mem_ctx, profile->homemdb);
+ rtn = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "msExchHomeServerName", exch_attrs[6]);
+ if (rtn == -1) return NT_STATUS_NO_MEMORY;
+
+ /* Prior we call ldb_modify, set up async ldb request on
+ * msExchMailboxGuid
+ */
+
+ req = talloc_zero(mem_ctx, struct ldb_request);
+ req->operation = LDB_SEARCH;
+ req->op.search.base = res[0]->dn;
+ req->op.search.scope = LDB_SCOPE_BASE;
+ req->op.search.tree = ldb_parse_tree(remote_ldb, "(objectclass=*)");
+ req->op.search.attrs = NULL;
+ ldb_request_add_control(req, LDB_CONTROL_NOTIFICATION_OID, false, NULL);
+
+ tce_ctx = talloc_zero(mem_ctx, struct tce_async_context);
+ req->context = tce_ctx;
+ req->callback = tce_search_callback;
+ ldb_set_timeout(mem_ctx, req, 60);
+
+ rtn = ldb_request(remote_ldb, req);
+ if (rtn != LDB_SUCCESS) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ DEBUG(0, ("async ldb request on msExchMailboxGuid sent\n"));
+
+ /* We modify the user record with Exchange attributes */
+ rtn = ldb_modify(remote_ldb, msg);
+ if (rtn != 0) return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ DEBUG(0, ("Extending AD user record with Exchange attributes\n"));
+ }
+ {
+ int rtn;
+
+ DEBUG(0, ("Waiting for Exchange mailbox creation\n"));
+ rtn = ldb_wait(req->handle, LDB_WAIT_NONE);
+ if (rtn != LDB_SUCCESS) {
+ printf("rtn = %d (loop - unsuccessful)\n", rtn);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ if (!tce_ctx->found) { /* timeout */
+ printf("Timeout\n");
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ DEBUG(0, ("User mailbox generated\n"));
+ }
+
+ /* replace UserAccountControl attr in the user record */
+ talloc_free(msg);
+ msg = ldb_msg_new(mem_ctx);
+ if (!msg) return NT_STATUS_NO_MEMORY;
+ msg->dn = res[0]->dn;
+
+ {
+ const char *UserAccountControl;
+ int rtn;
+
+ UserAccountControl = talloc_asprintf(mem_ctx, "66048");
+ rtn = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "UserAccountControl", UserAccountControl);
+ if (rtn == -1) return NT_STATUS_NO_MEMORY;
+
+ rtn = samdb_replace(remote_ldb, mem_ctx, msg);
+ if (rtn != 0) return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ DEBUG(0, ("ACB flags reset: password never expires\n"));
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ struct policy_handle *handle, const char *name)
+{
+ NTSTATUS status;
+ struct samr_DeleteUser d;
+ struct policy_handle user_handle;
+ uint32_t rid;
+ struct samr_LookupNames n;
+ struct lsa_String sname;
+ struct samr_OpenUser r;
+
+ sname.string = name;
+
+ n.in.domain_handle = handle;
+ n.in.num_names = 1;
+ n.in.names = &sname;
+
+ status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
+ if (NT_STATUS_IS_OK(status)) {
+ rid = n.out.rids->ids[0];
+ } else {
+ return status;
+ }
+
+ r.in.domain_handle = handle;
+ r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ r.in.rid = rid;
+ r.out.user_handle = &user_handle;
+
+ status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("OpenUser(%s) failed - %s\n", name, nt_errstr(status));
+ return status;
+ }
+
+ d.in.user_handle = &user_handle;
+ d.out.user_handle = &user_handle;
+ status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ return NT_STATUS_OK;
+}
+
+const struct dom_sid *torture_join_user_sid(struct test_join *join)
+{
+ return join->user_sid;
+}
+
+struct test_join *torture_create_testuser(struct torture_context *torture,
+ const char *username,
+ const char *domain,
+ uint16_t acct_type,
+ const char **random_password)
+{
+ NTSTATUS status;
+ struct samr_Connect c;
+ struct samr_CreateUser2 r;
+ struct samr_OpenDomain o;
+ struct samr_LookupDomain l;
+ struct samr_GetUserPwInfo pwp;
+ struct samr_SetUserInfo s;
+ union samr_UserInfo u;
+ struct policy_handle handle;
+ struct policy_handle domain_handle;
+ uint32_t access_granted;
+ uint32_t rid;
+ DATA_BLOB session_key;
+ struct lsa_String name;
+
+ int policy_min_pw_len = 0;
+ struct test_join *join;
+ char *random_pw;
+ const char *dc_binding = lp_parm_string(torture->lp_ctx,
+ NULL, "torture", "dc_binding");
+
+ join = talloc(NULL, struct test_join);
+ if (join == NULL) {
+ return NULL;
+ }
+
+ ZERO_STRUCTP(join);
+
+ printf("Connecting to SAMR\n");
+
+ if (dc_binding) {
+ status = dcerpc_pipe_connect(join,
+ &join->p,
+ dc_binding,
+ &ndr_table_samr,
+ cmdline_credentials,
+ NULL, torture->lp_ctx);
+
+ } else {
+ status = torture_rpc_connection(torture,
+ &join->p,
+ &ndr_table_samr);
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ return NULL;
+ }
+
+ c.in.system_name = NULL;
+ c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ c.out.connect_handle = &handle;
+
+ status = dcerpc_samr_Connect(join->p, join, &c);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *errstr = nt_errstr(status);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+ errstr = dcerpc_errstr(join, join->p->last_fault_code);
+ }
+ printf("samr_Connect failed - %s\n", errstr);
+ return NULL;
+ }
+
+ printf("Opening domain %s\n", domain);
+
+ name.string = domain;
+ l.in.connect_handle = &handle;
+ l.in.domain_name = &name;
+
+ status = dcerpc_samr_LookupDomain(join->p, join, &l);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("LookupDomain failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ talloc_steal(join, l.out.sid);
+ join->dom_sid = *l.out.sid;
+ join->dom_netbios_name = talloc_strdup(join, domain);
+ if (!join->dom_netbios_name) goto failed;
+
+ o.in.connect_handle = &handle;
+ o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ o.in.sid = *l.out.sid;
+ o.out.domain_handle = &domain_handle;
+
+ status = dcerpc_samr_OpenDomain(join->p, join, &o);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("OpenDomain failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ printf("Creating account %s\n", username);
+
+again:
+ name.string = username;
+ r.in.domain_handle = &domain_handle;
+ r.in.account_name = &name;
+ r.in.acct_flags = acct_type;
+ r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ r.out.user_handle = &join->user_handle;
+ r.out.access_granted = &access_granted;
+ r.out.rid = &rid;
+
+ status = dcerpc_samr_CreateUser2(join->p, join, &r);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
+ status = DeleteUser_byname(join->p, join, &domain_handle, name.string);
+ if (NT_STATUS_IS_OK(status)) {
+ goto again;
+ }
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("CreateUser2 failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ join->user_sid = dom_sid_add_rid(join, join->dom_sid, rid);
+
+ pwp.in.user_handle = &join->user_handle;
+
+ status = dcerpc_samr_GetUserPwInfo(join->p, join, &pwp);
+ if (NT_STATUS_IS_OK(status)) {
+ policy_min_pw_len = pwp.out.info->min_password_length;
+ }
+
+
+ random_pw = generate_random_str(join, MAX(8, policy_min_pw_len));
+
+ printf("Setting account password '%s'\n", random_pw);
+
+ ZERO_STRUCT(u);
+ s.in.user_handle = &join->user_handle;
+ s.in.info = &u;
+ s.in.level = 24;
+
+ encode_pw_buffer(u.info24.password.data, random_pw, STR_UNICODE);
+ u.info24.password_expired = 0;
+
+ status = dcerpc_fetch_session_key(join->p, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo level %u - no session key - %s\n",
+ s.in.level, nt_errstr(status));
+ torture_leave_domain(join);
+ goto failed;
+ }
+
+ arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
+
+ status = dcerpc_samr_SetUserInfo(join->p, join, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ ZERO_STRUCT(u);
+ s.in.user_handle = &join->user_handle;
+ s.in.info = &u;
+ s.in.level = 21;
+
+ u.info21.acct_flags = acct_type | ACB_PWNOEXP;
+ u.info21.fields_present = SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME;
+
+ u.info21.comment.string = talloc_asprintf(join,
+ "Tortured by Samba4: %s",
+ timestring(join, time(NULL)));
+
+ u.info21.full_name.string = talloc_asprintf(join,
+ "Torture account for Samba4: %s",
+ timestring(join, time(NULL)));
+
+ u.info21.description.string = talloc_asprintf(join,
+ "Samba4 torture account created by host %s: %s",
+ lp_netbios_name(torture->lp_ctx),
+ timestring(join, time(NULL)));
+
+ printf("Resetting ACB flags, force pw change time\n");
+
+ status = dcerpc_samr_SetUserInfo(join->p, join, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ if (random_password) {
+ *random_password = random_pw;
+ }
+
+ return join;
+
+failed:
+ torture_leave_domain(join);
+ return NULL;
+}
+
+/*
+ leave the domain, deleting the machine acct
+*/
+
+_PUBLIC_ void torture_leave_domain(struct test_join *join)
+{
+ struct samr_DeleteUser d;
+ NTSTATUS status;
+
+ if (!join) {
+ return;
+ }
+ d.in.user_handle = &join->user_handle;
+ d.out.user_handle = &join->user_handle;
+
+ /* Delete machine account */
+
+ status = dcerpc_samr_DeleteUser(join->p, join, &d);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Delete of machine account failed\n");
+ } else {
+ printf("Delete of machine account was successful.\n");
+ }
+
+ talloc_free(join);
+}
Added: trunk/openchange/torture/mapi_bookmark.c
===================================================================
--- trunk/openchange/torture/mapi_bookmark.c (rev 0)
+++ trunk/openchange/torture/mapi_bookmark.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,145 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Bookmark related operations torture
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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/defs_private.h>
+#include <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+
+bool torture_rpc_mapi_bookmark(struct torture_context *torture)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_ctable;
+ mapi_id_t id_folder;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ struct mapi_session *session;
+ uint32_t bookmark;
+ const char *subject = NULL;
+ uint64_t mid = 0;
+ uint32_t row;
+ uint32_t count;
+ uint32_t i = 0;
+ uint32_t halfcount;
+
+ /* init torture test */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_bookmark");
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* Open Message Store */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve Inbox folder ID */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Open Inbox folder */
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve the Contents Table */
+ mapi_object_init(&obj_ctable);
+ retval = GetContentsTable(&obj_folder, &obj_ctable, 0, &count);
+ mapi_errstr("GetContentsTable", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Customize the table view */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x2, PR_MID, PR_SUBJECT);
+ retval = SetColumns(&obj_ctable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ mapi_errstr("SetColumns", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ halfcount = count / 2;
+
+ /* Position the cursor at the desired position */
+ retval = SeekRow(&obj_ctable, BOOKMARK_BEGINNING, halfcount, &row);
+ mapi_errstr("SeekRow: BOOKMARK_BEGINNING + offset", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Fetch the associated row */
+ retval = QueryRows(&obj_ctable, 1, TBL_NOADVANCE, &SRowSet);
+ mapi_errstr("QueryRows", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Create the Bookmark */
+ mid = SRowSet.aRow[i].lpProps[0].value.d;
+ subject = SRowSet.aRow[i].lpProps[1].value.lpszA;
+
+ retval = CreateBookmark(&obj_ctable, &bookmark);
+ mapi_errstr("CreateBookmark", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Position the cursor at the beginning of the table */
+ retval = SeekRow(&obj_ctable, BOOKMARK_BEGINNING, 0, &row);
+ mapi_errstr("SeekRow: BOOKMARK_BEGINNING", GetLastError());
+
+ /* SeekRowBookmark */
+ retval = SeekRowBookmark(&obj_ctable, bookmark, 0, &row);
+ mapi_errstr("SeekRowBookmark", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* QueryRows a single column */
+ retval = QueryRows(&obj_ctable, 1, TBL_NOADVANCE, &SRowSet);
+ mapi_errstr("QueryRows", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ if (SRowSet.cRows == 0) {
+ DEBUG(0, ("QueryRows returned no rows\n"));
+ return false;
+ }
+
+ DEBUG(0, ("[1] mid: %"PRIx64", subject = %s\n", mid, subject));
+ DEBUG(0, ("[2] mid: %"PRIx64", subject = %s\n", SRowSet.aRow[0].lpProps[0].value.d,
+ SRowSet.aRow[0].lpProps[1].value.lpszA));
+
+ if (mid == SRowSet.aRow[0].lpProps[0].value.d) {
+ DEBUG(0, ("[SUCCESS] Message ID are the same\n"));
+ } else {
+ DEBUG(0, ("[FAILURE] Message ID are different\n"));
+ return false;
+ }
+
+ /* Free the bookmark */
+ retval = FreeBookmark(&obj_ctable, bookmark);
+ mapi_errstr("FreeBookmark", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_release(&obj_ctable);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ return true;
+}
Added: trunk/openchange/torture/mapi_common.c
===================================================================
--- trunk/openchange/torture/mapi_common.c (rev 0)
+++ trunk/openchange/torture/mapi_common.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,377 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Common MAPI and torture related operations
+
+ Copyright (C) Julien Kerihuel 2007.
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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 <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <torture/mapi_torture.h>
+#include <param.h>
+
+const char *get_filename(const char *filename)
+{
+ const char *substr;
+
+ substr = rindex(filename, '/');
+ if (substr) return substr;
+
+ return filename;
+}
+
+const char **get_cmdline_recipients(TALLOC_CTX *mem_ctx, const char *type)
+{
+ const char **usernames;
+ const char *recipients;
+ char *tmp = NULL;
+ uint32_t j = 0;
+
+ if (!type) {
+ return 0;
+ }
+
+ recipients = lp_parm_string(global_mapi_ctx->lp_ctx, NULL, "mapi", type);
+
+ /* no recipients */
+ if (recipients == 0) {
+ printf("no recipients specified for %s\n", type);
+ return 0;
+ }
+
+ if ((tmp = strtok((char *)recipients, ",")) == NULL) {
+ DEBUG(2, ("Invalid mapi:%s string format\n", type));
+ return NULL;
+ }
+
+ usernames = talloc_array(mem_ctx, const char *, 2);
+ usernames[0] = strdup(tmp);
+
+ for (j = 1; (tmp = strtok(NULL, ",")) != NULL; j++) {
+ usernames = talloc_realloc(mem_ctx, usernames, const char *, j+2);
+ usernames[j] = strdup(tmp);
+ }
+ usernames[j] = 0;
+
+ return usernames;
+}
+
+const char **collapse_recipients(TALLOC_CTX *mem_ctx, const char **to, const char **cc, const char **bcc)
+{
+ uint32_t count;
+ uint32_t i;
+ const char **usernames;
+
+ if (!to && !cc && !bcc) return NULL;
+
+ count = 0;
+ for (i = 0; to && to[i]; i++, count++);
+ for (i = 0; cc && cc[i]; i++, count++);
+ for (i = 0; bcc && bcc[i]; i++, count++);
+
+ usernames = talloc_array(mem_ctx, const char *, count + 1);
+ count = 0;
+
+ for (i = 0; to && to[i]; i++, count++) {
+ usernames[count] = talloc_strdup(mem_ctx, to[i]);
+ }
+
+ for (i = 0; cc && cc[i]; i++, count++) {
+ usernames[count] = talloc_strdup(mem_ctx, cc[i]);
+ }
+
+ for (i = 0; bcc && bcc[i]; i++, count++) {
+ usernames[count] = talloc_strdup(mem_ctx, bcc[i]);
+ }
+
+ usernames[count++] = 0;
+
+ return usernames;
+}
+
+static bool set_external_recipients(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, const char *username, enum ulRecipClass RecipClass)
+{
+ uint32_t last;
+ struct SPropValue SPropValue;
+
+ SRowSet->aRow = talloc_realloc(mem_ctx, SRowSet->aRow, struct SRow, SRowSet->cRows + 2);
+ last = SRowSet->cRows;
+ SRowSet->aRow[last].cValues = 0;
+ SRowSet->aRow[last].lpProps = talloc_zero(mem_ctx, struct SPropValue);
+
+ /* PR_OBJECT_TYPE */
+ SPropValue.ulPropTag = PR_OBJECT_TYPE;
+ SPropValue.value.l = MAPI_MAILUSER;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_DISPLAY_TYPE */
+ SPropValue.ulPropTag = PR_DISPLAY_TYPE;
+ SPropValue.value.l = 0;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_GIVEN_NAME */
+ SPropValue.ulPropTag = PR_GIVEN_NAME;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_DISPLAY_NAME */
+ SPropValue.ulPropTag = PR_DISPLAY_NAME;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_7BIT_DISPLAY_NAME */
+ SPropValue.ulPropTag = PR_7BIT_DISPLAY_NAME;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_SMTP_ADDRESS */
+ SPropValue.ulPropTag = PR_SMTP_ADDRESS;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_ADDRTYPE */
+ SPropValue.ulPropTag = PR_ADDRTYPE;
+ SPropValue.value.lpszA = "SMTP";
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ SetRecipientType(&(SRowSet->aRow[last]), RecipClass);
+
+ SRowSet->cRows += 1;
+ return true;
+}
+
+bool set_usernames_RecipientType(TALLOC_CTX *mem_ctx, uint32_t *index, struct SRowSet *rowset,
+ const char **usernames, struct SPropTagArray *flaglist,
+ enum ulRecipClass RecipClass)
+{
+ uint32_t i;
+ uint32_t count = *index;
+ static uint32_t counter = 0;
+
+ if (count == 0) counter = 0;
+ if (!usernames) return false;
+
+ for (i = 0; usernames[i]; i++) {
+ if (flaglist->aulPropTag[count] == MAPI_UNRESOLVED) {
+ set_external_recipients(mem_ctx, rowset, usernames[i], RecipClass);
+ }
+ if (flaglist->aulPropTag[count] == MAPI_RESOLVED) {
+ SetRecipientType(&(rowset->aRow[counter]), RecipClass);
+ counter++;
+ }
+ count++;
+ }
+
+ *index = count;
+
+ return true;
+}
+
+/**
+ * Initialize MAPI and Load Profile
+ *
+ */
+enum MAPISTATUS torture_load_profile(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ struct mapi_session **s)
+{
+ enum MAPISTATUS retval;
+ const char *profdb;
+ char *profname;
+ struct mapi_session *session = NULL;
+
+ profdb = lp_parm_string(lp_ctx, NULL, "mapi", "profile_store");
+ if (!profdb) {
+ profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB_PATH, getenv("HOME"));
+ if (!profdb) {
+ DEBUG(0, ("Specify a valid MAPI profile store\n"));
+ return MAPI_E_NOT_FOUND;
+ }
+ }
+
+ retval = MAPIInitialize(profdb);
+ mapi_errstr("MAPIInitialize", GetLastError());
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ profname = talloc_strdup(mem_ctx, lp_parm_string(lp_ctx, NULL, "mapi", "profile"));
+ if (!profname) {
+ retval = GetDefaultProfile(&profname);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+ }
+
+ /* MapiLogonProvider returns MAPI_E_NO_SUPPORT: reset errno */
+ retval = MapiLogonProvider(&session, profname, NULL, PROVIDER_ID_NSPI);
+ talloc_free(profname);
+ errno = 0;
+
+ retval = LoadProfile(session->profile);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ *s = session;
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * Initialize MAPI and logs on the EMSMDB pipe with the default
+ * profile
+ */
+
+struct mapi_session *torture_init_mapi(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx)
+{
+ enum MAPISTATUS retval;
+ struct mapi_session *session;
+ const char *profdb;
+ char *profname;
+ const char *password;
+
+ profdb = lp_parm_string(lp_ctx, NULL, "mapi", "profile_store");
+ if (!profdb) {
+ profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB_PATH, getenv("HOME"));
+ if (!profdb) {
+ DEBUG(0, ("Specify a valid MAPI profile store\n"));
+ return NULL;
+ }
+ }
+
+ retval = MAPIInitialize(profdb);
+ mapi_errstr("MAPIInitialize", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return NULL;
+
+
+ profname = talloc_strdup(mem_ctx, lp_parm_string(lp_ctx, NULL, "mapi", "profile"));
+ if (!profname) {
+ retval = GetDefaultProfile(&profname);
+ if (retval != MAPI_E_SUCCESS) {
+ DEBUG(0, ("Please specify a valid profile\n"));
+ return NULL;
+ }
+ }
+
+ password = lp_parm_string(lp_ctx, NULL, "mapi", "password");
+ retval = MapiLogonEx(&session, profname, password);
+ talloc_free(profname);
+ mapi_errstr("MapiLogonEx", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return NULL;
+
+ return session;
+}
+
+enum MAPISTATUS torture_simplemail_fromme(struct loadparm_context *lp_ctx,
+ mapi_object_t *obj_parent,
+ const char *subject, const char *body,
+ uint32_t flags)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ mapi_object_t obj_message;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SPropValue SPropValue;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ struct SPropValue props[3];
+ struct mapi_session *session = NULL;
+ const char **usernames;
+ uint32_t index = 0;
+
+ mem_ctx = talloc_named(NULL, 0, "torture_simplemail");
+
+ session = mapi_object_get_session(obj_parent);
+ MAPI_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, NULL);
+
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(obj_parent, &obj_message);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_7BIT_DISPLAY_NAME,
+ PR_DISPLAY_NAME,
+ PR_SMTP_ADDRESS,
+ PR_GIVEN_NAME);
+
+ lp_set_cmdline(lp_ctx, "mapi:to", session->profile->username);
+ usernames = get_cmdline_recipients(mem_ctx, "to");
+
+ retval = ResolveNames(session, usernames, SPropTagArray, &SRowSet, &flaglist, 0);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ if (!SRowSet) {
+ SRowSet = talloc_zero(mem_ctx, struct SRowSet);
+ }
+
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, usernames, flaglist, MAPI_TO);
+
+ SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
+ SPropValue.value.l = 0;
+ SRowSet_propcpy(mem_ctx, SRowSet, SPropValue);
+
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = MAPIFreeBuffer(SRowSet);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+ retval = MAPIFreeBuffer(flaglist);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ set_SPropValue_proptag(&props[0], PR_SUBJECT, (const void *)subject);
+ set_SPropValue_proptag(&props[1], PR_BODY, (const void *)body);
+ set_SPropValue_proptag(&props[2], PR_MESSAGE_FLAGS, (const void *)&flags);
+ retval = SetProps(&obj_message, props, 3);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = SaveChangesMessage(obj_parent, &obj_message, KeepOpenReadOnly);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ mapi_object_release(&obj_message);
+
+ talloc_free(mem_ctx);
+ return MAPI_E_SUCCESS;
+}
+
+uint32_t get_permission_from_name(const char *role)
+{
+ if (!role) return -1;
+
+ if (!strncasecmp(role, "RightsNone", strlen(role))) return 0x0;
+ if (!strncasecmp(role, "RightsReadItems", strlen(role))) return 0x1;
+ if (!strncasecmp(role, "RightsCreateItems", strlen(role))) return 0x2;
+ if (!strncasecmp(role, "RightsEditOwn", strlen(role))) return 0x8;
+ if (!strncasecmp(role, "RightsDeleteOwn", strlen(role))) return 0x10;
+ if (!strncasecmp(role, "RightsEditAll", strlen(role))) return 0x20;
+ if (!strncasecmp(role, "RightsDeleteAll", strlen(role))) return 0x40;
+ if (!strncasecmp(role, "RightsCreateSubfolders", strlen(role))) return 0x80;
+ if (!strncasecmp(role, "RightsFolderOwner", strlen(role))) return 0x100;
+ if (!strncasecmp(role, "RightsFolderContact", strlen(role))) return 0x200;
+ if (!strncasecmp(role, "RoleNone", strlen(role))) return 0x400;
+ if (!strncasecmp(role, "RoleReviewer", strlen(role))) return 0x401;
+ if (!strncasecmp(role, "RoleContributor", strlen(role))) return 0x402;
+ if (!strncasecmp(role, "RoleNoneditingAuthor", strlen(role))) return 0x413;
+ if (!strncasecmp(role, "RoleAuthor", strlen(role))) return 0x41B;
+ if (!strncasecmp(role, "RoleEditor", strlen(role))) return 0x47B;
+ if (!strncasecmp(role, "RolePublishAuthor", strlen(role))) return 0x49B;
+ if (!strncasecmp(role, "RolePublishEditor", strlen(role))) return 0x4FB;
+ if (!strncasecmp(role, "RightsAll", strlen(role))) return 0x5FB;
+ if (!strncasecmp(role, "RoleOwner", strlen(role))) return 0x7FB;
+
+ return -1;
+}
Added: trunk/openchange/torture/mapi_copymail.c
===================================================================
--- trunk/openchange/torture/mapi_copymail.c (rev 0)
+++ trunk/openchange/torture/mapi_copymail.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,130 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Copy message from a folder to another
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+bool torture_rpc_mapi_copymail(struct torture_context *torture)
+{
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_dir_src;
+ mapi_object_t obj_dir_dst;
+ mapi_object_t obj_table;
+ mapi_id_t id_src;
+ mapi_id_t id_dst;
+ mapi_id_array_t msg_id_array;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SRowSet rowset;
+ int i;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_copymail");
+ status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_dir_src);
+ mapi_object_init(&obj_dir_dst);
+ mapi_object_init(&obj_table);
+
+ /* OpenMsgStore */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Get Inbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_src, olFolderInbox);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(&obj_store, id_src, &obj_dir_src);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Get Deleted Items folder */
+ retval = GetDefaultFolder(&obj_store, &id_dst, olFolderDrafts);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(&obj_store, id_dst, &obj_dir_dst);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+
+ retval = GetContentsTable(&obj_dir_src, &obj_table, 0, NULL);
+ mapi_errstr("GetContentsTable", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ mapi_errstr("SetColumns", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_id_array_init(&msg_id_array);
+
+ while ((retval = QueryRows(&obj_table, 0xa, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND && rowset.cRows) {
+ for (i = 0; i < rowset.cRows; i++) {
+ mapi_id_array_add_id(&msg_id_array, rowset.aRow[i].lpProps[1].value.d);
+ }
+ retval = MoveCopyMessages(&obj_dir_src, &obj_dir_dst, &msg_id_array, 1);
+ mapi_errstr("MoveCopyMessages", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+
+ /* release mapi objects
+ */
+ mapi_id_array_release(&msg_id_array);
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_dir_src);
+ mapi_object_release(&obj_dir_dst);
+ mapi_object_release(&obj_store);
+
+ /* uninitialize mapi
+ */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return true;
+}
Added: trunk/openchange/torture/mapi_createuser.c
===================================================================
--- trunk/openchange/torture/mapi_createuser.c (rev 0)
+++ trunk/openchange/torture/mapi_createuser.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,76 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Create an Exchange User
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+#include <gen_ndr/samr.h>
+
+bool torture_mapi_createuser(struct torture_context *torture)
+{
+ NTSTATUS ntstatus;
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_profile *profile;
+ struct test_join *user_ctx = (struct test_join *) NULL;
+ const char *username = lp_parm_string(torture->lp_ctx, NULL, "exchange", "username");
+ const char *user_password = lp_parm_string(torture->lp_ctx, NULL, "exchange", "password");
+ struct mapi_session *session;
+
+ /* sanity checks */
+ if (!username) {
+ printf("Specify the username to create with exchange:username\n");
+ return false;
+ }
+
+ /* init mapi */
+ mem_ctx = talloc_named(NULL, 0, "torture_mapi_createuser");
+ retval = torture_load_profile(mem_ctx, torture->lp_ctx, &session);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ profile = session->profile;
+
+ /* Create the user in the AD */
+ user_ctx = torture_create_testuser(torture, username,
+ profile->domain,
+ ACB_NORMAL,
+ (const char **)&user_password);
+
+ if (!user_ctx) {
+ printf("Failed to create the user\n");
+ return false;
+ }
+
+ /* We extend the user with Exchange attributes */
+ ntstatus = torture_exchange_createuser(mem_ctx, username, torture_join_user_sid(user_ctx));
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ torture_leave_domain(user_ctx);
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ return true;
+}
Added: trunk/openchange/torture/mapi_criteria.c
===================================================================
--- trunk/openchange/torture/mapi_criteria.c (rev 0)
+++ trunk/openchange/torture/mapi_criteria.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,146 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Test Restrictions
+
+ Copyright (C) Julien Kerihuel 2007 - 2008.
+
+ 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/defs_private.h>
+#include <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+/*
+ 1. Create a search folder within Top Information Store
+ 2. SetCriteria with RES_CONTENT PR_SUBJECT FL_SUBSTRING criteria
+ 3. QueryRows and check if it worked ;-)
+ */
+
+bool torture_rpc_mapi_criteria(struct torture_context *torture)
+{
+ NTSTATUS ntstatus;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_searchdir;
+ mapi_object_t obj_search;
+ mapi_id_t id_search;
+ mapi_id_t id_tis;
+ mapi_id_array_t id;
+ struct mapi_SRestriction res;
+ struct SPropValue lpProps[1];
+ uint32_t ulSearchFlags;
+ uint16_t count;
+ mapi_id_t *fid;
+ uint32_t i;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_criteria");
+ ntstatus = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* Open Message Store */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Get Top Information Store ID */
+ retval = GetDefaultFolder(&obj_store, &id_tis, olFolderTopInformationStore);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Open Search folder */
+ retval = GetDefaultFolder(&obj_store, &id_search, olFolderFinder);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_init(&obj_search);
+ retval = OpenFolder(&obj_store, id_search, &obj_search);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Create the Search folder */
+ mapi_object_init(&obj_searchdir);
+ retval = CreateFolder(&obj_search, FOLDER_SEARCH, "torture_search",
+ "Torture Search Folder", OPEN_IF_EXISTS,
+ &obj_searchdir);
+ mapi_errstr("CreateFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Set Props */
+ lpProps[0].ulPropTag = PR_CONTAINER_CLASS;
+ lpProps[0].value.lpszA = "IPF.Note";
+ retval = SetProps(&obj_searchdir, lpProps, 1);
+ mapi_errstr("SetProps", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Set Search criteria on this folder */
+ mapi_id_array_init(&id);
+ mapi_id_array_add_id(&id, id_tis);
+
+ res.rt = RES_CONTENT;
+ res.res.resContent.fuzzy = FL_SUBSTRING;
+ res.res.resContent.ulPropTag = PR_SUBJECT;
+ res.res.resContent.lpProp.ulPropTag = PR_SUBJECT;
+ res.res.resContent.lpProp.value.lpszA = "criteria";
+
+ retval = SetSearchCriteria(&obj_searchdir, &res,
+ BACKGROUND_SEARCH|RECURSIVE_SEARCH,
+ &id);
+ mapi_errstr("SetSearchCriteria", GetLastError());
+ mapi_id_array_release(&id);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Get Search criteria for this folder */
+ retval = GetSearchCriteria(&obj_searchdir, &res, &ulSearchFlags, &count, &fid);
+ mapi_errstr("GetSearchCriteria", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ printf("ulSearchFlags = 0x%x\n", ulSearchFlags);
+ printf("res.rt = %d\n", res.rt);
+ printf("count = %d\n", count);
+ for (i = 0; i < count; i++) {
+ printf("lpContainerList[%d] = 0x%"PRIx64"\n", i, fid[i]);
+ }
+
+ /* Delete folder */
+ retval = DeleteFolder(&obj_search, mapi_object_get_id(&obj_searchdir),
+ DEL_MESSAGES|DEL_FOLDERS|DELETE_HARD_DELETE, NULL);
+ mapi_errstr("DeleteFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_release(&obj_searchdir);
+ mapi_object_release(&obj_search);
+ mapi_object_release(&obj_store);
+ talloc_free(mem_ctx);
+
+ return true;
+}
Added: trunk/openchange/torture/mapi_deletemail.c
===================================================================
--- trunk/openchange/torture/mapi_deletemail.c (rev 0)
+++ trunk/openchange/torture/mapi_deletemail.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,141 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Delete mail from an Exchange server
+
+ Copyright (C) Fabien Le Mentec 2007
+
+ 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/defs_private.h>
+#include <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+
+#define CN_ROWS 0x100
+
+
+bool torture_rpc_mapi_deletemail(struct torture_context *torture)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ const char *s_subject = lp_parm_string(torture->lp_ctx, NULL, "mapi", "subject");
+ int len_subject;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_table;
+ mapi_id_t id_inbox;
+ mapi_id_t *id_messages;
+ unsigned long cn_messages;
+ struct SRowSet rowset;
+ unsigned long i_row;
+ unsigned long cn_rows;
+ struct SPropTagArray *SPropTagArray;
+
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_deletemail");
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objets */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_inbox);
+ mapi_object_init(&obj_table);
+
+ /* session::OpenMsgStore() */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+ mapi_object_debug(&obj_store);
+
+ /* id_inbox = store->GetReceiveFolder */
+ retval = GetReceiveFolder(&obj_store, &id_inbox, NULL);
+ mapi_errstr("GetReceiveFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* inbox = store->OpenFolder()
+ */
+ retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+ mapi_object_debug(&obj_inbox);
+
+ /* table = inbox->GetContentsTable() */
+ retval = GetContentsTable(&obj_inbox, &obj_table, 0, NULL);
+ mapi_errstr("GetContentsTable", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+ mapi_object_debug(&obj_table);
+
+ /* rowset = table->QueryRows() */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ mapi_errstr("SetColumns", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ while ((retval = QueryRows(&obj_table, CN_ROWS, TBL_ADVANCE, &rowset)) == MAPI_E_SUCCESS) {
+ cn_rows = rowset.cRows;
+ if (!cn_rows) break;
+ id_messages = talloc_array(mem_ctx, uint64_t, cn_rows);
+ cn_messages = 0;
+
+ if (s_subject == 0)
+ s_subject = "default_subject";
+ len_subject = strlen(s_subject);
+
+ for (i_row = 0; i_row < cn_rows; ++i_row) {
+ if (strncmp(rowset.aRow[i_row].lpProps[4].value.lpszA, s_subject, len_subject) == 0) {
+ id_messages[cn_messages] = rowset.aRow[i_row].lpProps[1].value.d;
+ ++cn_messages;
+ DEBUG(0, ("delete(%"PRIx64")\n", id_messages[cn_messages - 1]));
+ }
+ }
+
+ /* IMessage::DeleteMessages() */
+ if (cn_messages) {
+ retval = DeleteMessage(&obj_inbox, id_messages, cn_messages);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("DeleteMessages", GetLastError());
+ }
+ }
+ }
+
+ /* release objects
+ */
+ mapi_object_release(&obj_store);
+ mapi_object_release(&obj_inbox);
+ mapi_object_release(&obj_table);
+
+ /* uninitialize mapi
+ */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return (ret);
+}
Added: trunk/openchange/torture/mapi_fetchappointment.c
===================================================================
--- trunk/openchange/torture/mapi_fetchappointment.c (rev 0)
+++ trunk/openchange/torture/mapi_fetchappointment.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,129 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Fetch appointments from an Exchange server
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+bool torture_rpc_mapi_fetchappointment(struct torture_context *torture)
+{
+ NTSTATUS nt_status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ struct mapi_session *session;
+ uint64_t id_calendar;
+ mapi_object_t obj_store;
+ mapi_object_t obj_calendar;
+ mapi_object_t obj_cal_table;
+ struct SRowSet SRowSet;
+ struct SPropTagArray *SPropTagArray;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_fetchappointment");
+ nt_status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_calendar);
+ mapi_object_init(&obj_cal_table);
+
+ /* session::OpenMsgStore */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve the default calendar folder id */
+ retval = GetDefaultFolder(&obj_store, &id_calendar, olFolderCalendar);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* We now open the calendar folder */
+ retval = OpenFolder(&obj_store, id_calendar, &obj_calendar);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Operations on the calendar folder */
+ retval = GetContentsTable(&obj_calendar, &obj_cal_table, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x8,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT,
+ PR_MESSAGE_CLASS,
+ PR_RULE_MSG_PROVIDER,
+ PR_RULE_MSG_NAME);
+ retval = SetColumns(&obj_cal_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryRows(&obj_cal_table, 0x32, TBL_ADVANCE, &SRowSet);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ {
+ int i;
+ mapi_object_t obj_message;
+ struct mapi_SPropValue_array properties_array;
+
+ printf("We have %d appointments in the table\n", SRowSet.cRows);
+ for (i = 0; i < SRowSet.cRows; i++) {
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(&obj_calendar,
+ SRowSet.aRow[i].lpProps[0].value.d,
+ SRowSet.aRow[i].lpProps[1].value.d,
+ &obj_message, 0);
+ if (retval != MAPI_E_NOT_FOUND) {
+ retval = GetPropsAll(&obj_message, &properties_array);
+ if (retval == MAPI_E_SUCCESS) {
+ mapidump_appointment(&properties_array, NULL);
+ mapi_object_release(&obj_message);
+ }
+ }
+ }
+ }
+
+ mapi_object_release(&obj_cal_table);
+ mapi_object_release(&obj_calendar);
+ mapi_object_release(&obj_store);
+
+ /* uninitialize mapi
+ */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return (ret);
+}
Added: trunk/openchange/torture/mapi_fetchattach.c
===================================================================
--- trunk/openchange/torture/mapi_fetchattach.c (rev 0)
+++ trunk/openchange/torture/mapi_fetchattach.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,230 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Fetch attachments from an Exchange server
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+
+static enum MAPISTATUS read_attach_stream(TALLOC_CTX *ctx_mem,
+ mapi_object_t *obj_attach,
+ mapi_object_t *obj_stream,
+ uint8_t** buf_data,
+ uint32_t* sz_data)
+{
+ uint16_t cn_read;
+ uint32_t off_data;
+ enum MAPISTATUS status;
+ int done;
+ struct SPropTagArray *proptags;
+ struct SPropValue *vals;
+ uint32_t cn_vals;
+
+ /* Reset
+ */
+ *buf_data = 0;
+ *sz_data = 0;
+ off_data = 0;
+ done = 0;
+
+ /* Get Attachment size
+ */
+ proptags = set_SPropTagArray(ctx_mem, 0x1, PR_ATTACH_SIZE);
+ status = GetProps(obj_attach, proptags, &vals, &cn_vals);
+ mapi_errstr("GetProps", GetLastError());
+ if (status != MAPI_E_SUCCESS) return status;
+
+ /* Alloc buffer
+ */
+ *sz_data = (uint32_t)vals[0].value.b;
+ *buf_data = talloc_size(ctx_mem, *sz_data);
+ if (*buf_data == 0)
+ return -1;
+
+ /* Read attachment
+ */
+ while (done == 0) {
+ status = ReadStream(obj_stream,
+ (*buf_data) + off_data,
+ (*sz_data) - off_data,
+ &cn_read);
+ mapi_errstr("ReadStream", GetLastError());
+ if ((status != MAPI_E_SUCCESS) || (cn_read == 0)) {
+ done = 1;
+ }
+ else {
+ off_data += cn_read;
+ if (off_data >= *sz_data)
+ done = 1;
+ }
+ }
+
+ *sz_data = off_data;
+
+ return status;
+}
+
+bool torture_rpc_mapi_fetchattach(struct torture_context *torture)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_message;
+ mapi_object_t obj_tb_contents;
+ mapi_object_t obj_tb_attach;
+ mapi_object_t obj_attach;
+ mapi_object_t obj_stream;
+ mapi_id_t id_inbox;
+ mapi_id_t id_folder;
+ mapi_id_t id_message;
+ struct SPropTagArray *proptags;
+ struct SRowSet rows_msgs;
+ struct SRowSet rows_attach;
+ uint32_t i_msg;
+ uint32_t i_row_attach;
+ uint32_t num_attach;
+ uint8_t *buf_attach;
+ uint32_t sz_attach;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_fetchattach");
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_inbox);
+ mapi_object_init(&obj_message);
+ mapi_object_init(&obj_tb_contents);
+ mapi_object_init(&obj_tb_attach);
+ mapi_object_init(&obj_attach);
+ mapi_object_init(&obj_stream);
+
+ /* session::OpenMsgStore() */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* id_inbox = store->GetReceiveFolder */
+ retval = GetReceiveFolder(&obj_store, &id_inbox, NULL);
+ mapi_errstr("GetReceiveFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* inbox = store->OpenFolder() */
+ retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* table = inbox->GetContentsTable() */
+ retval = GetContentsTable(&obj_inbox, &obj_tb_contents, 0, NULL);
+ mapi_errstr("GetContentsTable", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ proptags = set_SPropTagArray(mem_ctx, 0x5,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT);
+ retval = SetColumns(&obj_tb_contents, proptags);
+ mapi_errstr("SetColumns", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryRows(&obj_tb_contents, 0xa, TBL_ADVANCE, &rows_msgs);
+ mapi_errstr("QueryRows", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* foreach message get attachment table
+ foreach attachment, get PR_NUM
+ foreach PR_NUM, open attachment
+ */
+
+ for (i_msg = 0; i_msg < rows_msgs.cRows; i_msg++) {
+
+ /* open message
+ */
+ id_folder = rows_msgs.aRow[i_msg].lpProps[0].value.d;
+ id_message = rows_msgs.aRow[i_msg].lpProps[1].value.d;
+ retval = OpenMessage(&obj_store,
+ id_folder,
+ id_message,
+ &obj_message, 0);
+ mapi_errstr("OpenMessage", GetLastError());
+ if (retval == MAPI_E_SUCCESS) {
+
+ /* open attachment table */
+ retval = GetAttachmentTable(&obj_message, &obj_tb_attach);
+ mapi_errstr("GetAttachmentTable", GetLastError());
+
+ /* foreach attachment, open by PR_ATTACH_NUM */
+ if (retval == MAPI_E_SUCCESS) {
+ proptags = set_SPropTagArray(mem_ctx, 0x1, PR_ATTACH_NUM);
+ retval = SetColumns(&obj_tb_attach, proptags);
+ mapi_errstr("SetColumns", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryRows(&obj_tb_attach, 0xa, TBL_ADVANCE, &rows_attach);
+ mapi_errstr("QueryRows", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* get a stream on PR_ATTACH_DATA_BIN */
+ for (i_row_attach = 0; i_row_attach < rows_attach.cRows; i_row_attach++) {
+ num_attach = rows_attach.aRow[i_row_attach].lpProps[0].value.l;
+ retval = OpenAttach(&obj_message, num_attach, &obj_attach);
+ mapi_errstr("OpenAttach", GetLastError());
+ if (retval == MAPI_E_SUCCESS) {
+ retval = OpenStream(&obj_attach, PR_ATTACH_DATA_BIN, 0, &obj_stream);
+ mapi_errstr("OpenStream", GetLastError());
+
+ /* read stream content */
+ if (retval == MAPI_E_SUCCESS) {
+ read_attach_stream(mem_ctx,
+ &obj_attach, &obj_stream, &buf_attach,
+ &sz_attach);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ mapi_object_release(&obj_store);
+ mapi_object_release(&obj_inbox);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_tb_contents);
+ mapi_object_release(&obj_tb_attach);
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_stream);
+
+ MAPIUninitialize();
+
+ talloc_free(mem_ctx);
+ return (ret);
+}
Added: trunk/openchange/torture/mapi_fetchcontacts.c
===================================================================
--- trunk/openchange/torture/mapi_fetchcontacts.c (rev 0)
+++ trunk/openchange/torture/mapi_fetchcontacts.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,126 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Fetch contacts from an Exchange server
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+bool torture_rpc_mapi_fetchcontacts(struct torture_context *torture)
+{
+ NTSTATUS nt_status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ struct mapi_session *session;
+ uint64_t id_contacts;
+ mapi_object_t obj_store;
+ mapi_object_t obj_contacts;
+ mapi_object_t obj_table;
+ struct SRowSet SRowSet;
+ struct SPropTagArray *SPropTagArray;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_fetchmail");
+ nt_status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_contacts);
+ mapi_object_init(&obj_table);
+
+ /* session::OpenMsgStore */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve the contacts Folder ID */
+ retval = GetDefaultFolder(&obj_store, &id_contacts, olFolderContacts);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* We now open the contacts folder */
+ retval = OpenFolder(&obj_store, id_contacts, &obj_contacts);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Operations on the contacts folder */
+ retval = GetContentsTable(&obj_contacts, &obj_table, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x8,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT,
+ PR_MESSAGE_CLASS,
+ PR_RULE_MSG_PROVIDER,
+ PR_RULE_MSG_NAME);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryRows(&obj_table, 0x32, TBL_ADVANCE, &SRowSet);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ {
+ int i;
+ mapi_object_t obj_message;
+ struct mapi_SPropValue_array properties_array;
+
+ for (i = 0; i < SRowSet.cRows; i++) {
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(&obj_contacts,
+ SRowSet.aRow[i].lpProps[0].value.d,
+ SRowSet.aRow[i].lpProps[1].value.d,
+ &obj_message, 0);
+ if (retval != MAPI_E_NOT_FOUND) {
+ retval = GetPropsAll(&obj_message, &properties_array);
+ mapidump_contact(&properties_array, NULL);
+ mapi_object_release(&obj_message);
+ }
+ }
+ }
+
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_contacts);
+ mapi_object_release(&obj_store);
+
+ /* uninitialize mapi
+ */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return (ret);
+}
Added: trunk/openchange/torture/mapi_fetchmail.c
===================================================================
--- trunk/openchange/torture/mapi_fetchmail.c (rev 0)
+++ trunk/openchange/torture/mapi_fetchmail.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,139 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Fetch emails from an Exchange server
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+
+bool torture_rpc_mapi_fetchmail(struct torture_context *torture)
+{
+ NTSTATUS nt_status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_message;
+ mapi_object_t obj_table;
+ uint64_t id_inbox;
+ struct SPropTagArray *SPropTagArray;
+ struct mapi_SPropValue_array properties_array;
+ struct SRowSet rowset;
+ uint32_t i;
+ uint32_t count;
+ uint32_t unread;
+ uint32_t total;
+
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_fetchmail");
+ nt_status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_inbox);
+ mapi_object_init(&obj_message);
+ mapi_object_init(&obj_table);
+
+ /* session::OpenMsgStore()
+ */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* id_inbox = store->GetReceiveFolder */
+ retval = GetReceiveFolder(&obj_store, &id_inbox, NULL);
+ mapi_errstr("GetReceiveFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Open Inbox folder */
+ retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve message count summary from the folder */
+ retval = GetFolderItemsCount(&obj_inbox, &unread, &total);
+ mapi_errstr("GetFolderItemsCount", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* table = inbox->GetContentsTable()
+ */
+ retval = GetContentsTable(&obj_inbox, &obj_table, 0, &count);
+ mapi_errstr("GetContentsTable", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ talloc_free(SPropTagArray);
+ mapi_errstr("SetColumns", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ printf("Inbox: Total(%d) Unread(%d)\n", total, unread);
+
+ while ((retval = QueryRows(&obj_table, 0xa, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND && rowset.cRows) {
+ for (i = 0; i < rowset.cRows; i++) {
+ retval = OpenMessage(&obj_store,
+ rowset.aRow[i].lpProps[0].value.d,
+ rowset.aRow[i].lpProps[1].value.d,
+ &obj_message, 0);
+
+ if (GetLastError() != MAPI_E_NOT_FOUND) {
+ retval = GetPropsAll(&obj_message, &properties_array);
+ mapidump_message(&properties_array, NULL);
+ mapi_object_release(&obj_message);
+ }
+ }
+ }
+
+ /* release mapi objects
+ */
+ mapi_object_release(&obj_store);
+ mapi_object_release(&obj_inbox);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_table);
+
+ /* uninitialize mapi
+ */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return (ret);
+}
Added: trunk/openchange/torture/mapi_fetchtasks.c
===================================================================
--- trunk/openchange/torture/mapi_fetchtasks.c (rev 0)
+++ trunk/openchange/torture/mapi_fetchtasks.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,129 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Fetch tasks from an Exchange server
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+bool torture_rpc_mapi_fetchtasks(struct torture_context *torture)
+{
+ NTSTATUS nt_status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ struct mapi_session *session;
+ uint64_t id_tasks;
+ mapi_object_t obj_store;
+ mapi_object_t obj_tasks;
+ mapi_object_t obj_tasks_table;
+ struct SRowSet SRowSet;
+ struct SPropTagArray *SPropTagArray;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_fetchtasks");
+ nt_status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_tasks);
+ mapi_object_init(&obj_tasks_table);
+
+ /* session::OpenMsgStore */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve the tasks Folder ID */
+ retval = GetDefaultFolder(&obj_store, &id_tasks, olFolderTasks);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* We now open the tasks folder */
+ retval = OpenFolder(&obj_store, id_tasks, &obj_tasks);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Operations on the tasks folder */
+ retval = GetContentsTable(&obj_tasks, &obj_tasks_table, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x8,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT,
+ PR_MESSAGE_CLASS,
+ PR_RULE_MSG_PROVIDER,
+ PR_RULE_MSG_NAME);
+ retval = SetColumns(&obj_tasks_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryRows(&obj_tasks_table, 0x32, TBL_ADVANCE, &SRowSet);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ {
+ int i;
+ mapi_object_t obj_message;
+ struct mapi_SPropValue_array properties_array;
+
+ printf("We have %d tasks in the table\n", SRowSet.cRows);
+ for (i = 0; i < SRowSet.cRows; i++) {
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(&obj_tasks,
+ SRowSet.aRow[i].lpProps[0].value.d,
+ SRowSet.aRow[i].lpProps[1].value.d,
+ &obj_message, 0);
+ if (retval != MAPI_E_NOT_FOUND) {
+ retval = GetPropsAll(&obj_message, &properties_array);
+ if (retval == MAPI_E_SUCCESS) {
+ mapidump_task(&properties_array, NULL);
+ mapi_object_release(&obj_message);
+ }
+ }
+ }
+ }
+
+ mapi_object_release(&obj_tasks_table);
+ mapi_object_release(&obj_tasks);
+ mapi_object_release(&obj_store);
+
+ /* uninitialize mapi
+ */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return (ret);
+}
Added: trunk/openchange/torture/mapi_namedprops.c
===================================================================
--- trunk/openchange/torture/mapi_namedprops.c (rev 0)
+++ trunk/openchange/torture/mapi_namedprops.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,283 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Test Named properties and IMAPIProp associated functions
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+#define NAMEDPROP_NAME "torture_namedprops"
+#define NAMEDPROP_VALUE "Can you see me?"
+
+bool torture_rpc_mapi_namedprops(struct torture_context *torture)
+{
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ struct mapi_session *session;
+ mapi_id_t id_folder;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_table;
+ mapi_object_t obj_message;
+ struct SRowSet SRowSet;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *propvals;
+ struct mapi_SPropValue_array props_array;
+ uint32_t i;
+ uint32_t propID;
+ uint16_t count;
+ struct MAPINAMEID *nameid;
+ uint16_t *propIDs;
+ uint32_t cn_propvals;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_namedprops");
+ status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* OpenMsgStore */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve the specified folder ID */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Open the folder */
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve the folder contents */
+ mapi_object_init(&obj_table);
+ retval = GetContentsTable(&obj_folder, &obj_table, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x8,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT,
+ PR_MESSAGE_CLASS,
+ PR_RULE_MSG_PROVIDER,
+ PR_RULE_MSG_NAME);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryRows(&obj_table, 0x32, TBL_ADVANCE, &SRowSet);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* We just need to open the first message for this test */
+ if (SRowSet.cRows == 0) {
+ printf("No messages in Mailbox\n");
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(&obj_folder,
+ SRowSet.aRow[0].lpProps[0].value.d,
+ SRowSet.aRow[0].lpProps[1].value.d,
+ &obj_message, MAPI_MODIFY|MAPI_CREATE);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = GetPropsAll(&obj_message, &props_array);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* loop through properties, search for named properties
+ * (0x8000-0xFFFE range) and call GetNamesFromIDs
+ */
+ printf("\n\n1. GetNamesFromIDs\n");
+ for (i = 0; i < props_array.cValues; i++) {
+ propID = props_array.lpProps[i].ulPropTag >> 16;
+ if (propID >= 0x8000 && propID <= 0xFFFE) {
+ propID = props_array.lpProps[i].ulPropTag;
+ propID = (propID & 0xFFFF0000) | PT_NULL;
+ nameid = talloc_zero(mem_ctx, struct MAPINAMEID);
+ retval = GetNamesFromIDs(&obj_message, propID, &count, &nameid);
+ if (retval != MAPI_E_SUCCESS) return false;
+ switch (nameid->ulKind) {
+ case MNID_ID:
+ printf("\t0x%.8x mapped to 0x%.4x\n",
+ propID | (props_array.lpProps[i].ulPropTag & 0xFFFF), nameid->kind.lid);
+ break;
+ case MNID_STRING:
+ printf("\t0x%.8x mapped to %s\n",
+ propID, nameid->kind.lpwstr.Name);
+ break;
+ }
+ talloc_free(nameid);
+ }
+ }
+
+ /*
+ * Retrieve all the named properties for the current object
+ * This function seems to be the only one accepting 0 for
+ * input ulPropTag and returning the whole set of named properties
+ */
+ printf("\n\n2. QueryNamedProperties\n");
+ nameid = talloc_zero(mem_ctx, struct MAPINAMEID);
+ propIDs = talloc_zero(mem_ctx, uint16_t);
+ retval = QueryNamedProperties(&obj_message, 0, NULL, &count, &propIDs, &nameid);
+ mapi_errstr("QueryNamedProperties", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ for (i = 0; i < count; i++) {
+ char *guid;
+
+ printf("0x%.4x:\n", propIDs[i]);
+
+ guid = GUID_string(mem_ctx, &nameid[i].lpguid);
+ printf("\tguid: %s\n", guid);
+ talloc_free(guid);
+
+ switch (nameid[i].ulKind) {
+ case MNID_ID:
+ printf("\tmapped to 0x%.4x\n", nameid[i].kind.lid);
+ break;
+ case MNID_STRING:
+ printf("\tmapped to %s\n", nameid[i].kind.lpwstr.Name);
+ break;
+ }
+ }
+ talloc_free(propIDs);
+
+ /*
+ * finally call GetIDsFromNames with the Names retrieved in
+ * the previous call
+ */
+ printf("\n\n3. GetIDsFromNames\n");
+ for (i = 0; i < count; i++) {
+ SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
+ retval = GetIDsFromNames(&obj_folder, 1, &nameid[i], 0, &SPropTagArray);
+ switch (nameid[i].ulKind) {
+ case MNID_ID:
+ printf("0x%.4x mapped to ", nameid[i].kind.lid);
+ break;
+ case MNID_STRING:
+ printf("%s mapped to ", nameid[i].kind.lpwstr.Name);
+ break;
+ }
+ mapidump_SPropTagArray(SPropTagArray);
+ talloc_free(SPropTagArray);
+ }
+
+ talloc_free(nameid);
+
+ /*
+ * Try to create a named property
+ */
+ {
+ struct GUID guid;
+
+ printf("\n\n4. GetIDsFromNames (Create named property)\n");
+ GUID_from_string(PS_INTERNET_HEADERS, &guid);
+ nameid = talloc_zero(mem_ctx, struct MAPINAMEID);
+ SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
+
+ nameid[0].lpguid = guid;
+ nameid[0].ulKind = MNID_STRING;
+ nameid[0].kind.lpwstr.Name = NAMEDPROP_NAME;
+ nameid[0].kind.lpwstr.NameSize = strlen(NAMEDPROP_NAME) * 2 + 2;
+ retval = GetIDsFromNames(&obj_folder, 1, &nameid[0], MAPI_CREATE, &SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+ mapi_errstr("GetIDsFromNames", GetLastError());
+
+ printf("%s mapped to 0x%.8x\n", NAMEDPROP_NAME, SPropTagArray->aulPropTag[0]);
+ propID = SPropTagArray->aulPropTag[0] | PT_STRING8;
+
+ talloc_free(nameid);
+ talloc_free(SPropTagArray);
+ }
+
+ /*
+ * Assign its value with SetProps and save changes
+ */
+ {
+ struct SPropValue props[1];
+ const char *testval = NAMEDPROP_VALUE;
+
+ printf("\n\n5. Assigning %s to %s\n", NAMEDPROP_VALUE, NAMEDPROP_NAME);
+
+ set_SPropValue_proptag(&props[0], propID, (const void *)testval);
+ retval = SetProps(&obj_message, props, 1);
+ if (retval != MAPI_E_SUCCESS) return false;
+ mapi_errstr("SetProps", GetLastError());
+
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ mapi_errstr("SaveChangesMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+
+ printf("\n\n6. GetNamesFromIDs (Fetch torture_namedprops property)\n");
+ propID = (propID & 0xFFFF0000)| PT_NULL;
+ retval = GetNamesFromIDs(&obj_message, propID, &count, &nameid);
+ mapi_errstr("GetNamesFromIDs", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+ switch (nameid->ulKind) {
+ case MNID_ID:
+ printf("\t0x%.8x mapped to 0x%.4x\n",
+ propID | (props_array.lpProps[i].ulPropTag & 0xFFFF), nameid->kind.lid);
+ break;
+ case MNID_STRING:
+ printf("\t0x%.8x mapped to %s\n",
+ propID, nameid->kind.lpwstr.Name);
+ break;
+ }
+ talloc_free(nameid);
+
+ printf("\n\n7. GetProps (torture_namedprops property)\n");
+ propID = (propID & 0xFFFF0000) | PT_STRING8;
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, propID);
+ retval = GetProps(&obj_message, SPropTagArray, &propvals, &cn_propvals);
+ MAPIFreeBuffer(SPropTagArray);
+ mapi_errstr("GetProps", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapidump_SPropValue(propvals[0], "\t");
+ MAPIFreeBuffer(propvals);
+
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ /* Uninitialize MAPI */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return ret;
+}
Added: trunk/openchange/torture/mapi_newmail.c
===================================================================
--- trunk/openchange/torture/mapi_newmail.c (rev 0)
+++ trunk/openchange/torture/mapi_newmail.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,122 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ New mail notifications
+
+ Copyright (C) Julien Kerihuel 2007.
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+
+static int callback(uint32_t NotificationType, void *NotificationData, void *private_data)
+{
+ struct NewMailNotification *newmail;
+
+ switch(NotificationType) {
+ case fnevNewMail:
+ printf("[+]New mail Received!!!!\n");
+ newmail = (struct NewMailNotification *) NotificationData;
+ mapidump_newmail(newmail, "\t");
+ break;
+ case fnevObjectCreated:
+ printf("[+]Object Created!!!\n");
+ break;
+ }
+
+ return 0;
+}
+
+bool torture_rpc_mapi_newmail(struct torture_context *torture)
+{
+ NTSTATUS nt_status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_inbox;
+ uint64_t id_inbox;
+ uint32_t ulEventMask;
+ uint32_t ulConnection;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_newmail");
+ nt_status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_inbox);
+
+ /* session::OpenMsgStore() */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Register notification */
+ retval = RegisterNotification(fnevTableModified);
+ mapi_errstr("RegisterNotification", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Open Inbox */
+ retval = GetDefaultFolder(&obj_store, &id_inbox, olFolderInbox);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* newmail and created|modified object notifications in inbox */
+ ulEventMask = fnevObjectCreated;
+ retval = Subscribe(&obj_inbox, &ulConnection, ulEventMask, false, (mapi_notify_callback_t)callback);
+ mapi_errstr("Subscribe", GetLastError());
+
+ ulEventMask = fnevNewMail;
+ retval = Subscribe(&obj_inbox, &ulConnection, ulEventMask, false, (mapi_notify_callback_t)callback);
+ mapi_errstr("Subscribe", GetLastError());
+
+
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* wait for notifications */
+ MonitorNotification(mapi_object_get_session(&obj_inbox),(void *)&obj_store);
+
+ mapi_object_release(&obj_inbox);
+ mapi_object_release(&obj_store);
+
+ /* uninitialize mapi */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return (ret);
+}
Added: trunk/openchange/torture/mapi_permissions.c
===================================================================
--- trunk/openchange/torture/mapi_permissions.c (rev 0)
+++ trunk/openchange/torture/mapi_permissions.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,133 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Test MAPI Permissions
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+bool torture_rpc_mapi_permissions(struct torture_context *torture)
+{
+ NTSTATUS ntstatus;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_table;
+ mapi_id_t id_inbox;
+ struct SRowSet SRowSet;
+ struct SPropTagArray *proptags;
+ uint32_t i;
+ const char *operation = lp_parm_string(torture->lp_ctx, NULL, "mapi", "operation");
+ const char *role = lp_parm_string(torture->lp_ctx, NULL, "mapi", "role");
+ uint32_t permission;
+ const char *username = lp_parm_string(torture->lp_ctx, NULL, "mapi", "username");
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_permissions");
+ ntstatus = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve the default inbox folder id */
+ retval = GetDefaultFolder(&obj_store, &id_inbox, olFolderInbox);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_init(&obj_inbox);
+ retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ if (!strncasecmp(operation, "add", strlen(operation))) {
+ permission = get_permission_from_name(role);
+ retval = AddUserPermission(&obj_inbox, username, permission);
+ mapi_errstr("AddUserPermission", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+ if (!strncasecmp(operation, "modify", strlen(operation))) {
+ permission = get_permission_from_name(role);
+ retval = ModifyUserPermission(&obj_inbox, username, permission);
+ mapi_errstr("ModifyUserPermission", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+ if (!strncasecmp(operation, "remove", strlen(operation))) {
+ retval = RemoveUserPermission(&obj_inbox, username);
+ mapi_errstr("RemoveUserPermission", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+ if (!strncasecmp(operation, "list", strlen(operation))) {
+ mapi_object_init(&obj_table);
+ retval = GetTable(&obj_inbox, &obj_table);
+ mapi_errstr("GetTable", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ proptags = set_SPropTagArray(mem_ctx, 4,
+ PR_MEMBER_ID,
+ PR_MEMBER_NAME,
+ PR_MEMBER_RIGHTS,
+ PR_ENTRYID);
+ retval = SetColumns(&obj_table, proptags);
+ mapi_errstr("SetColumns", GetLastError());
+ MAPIFreeBuffer(proptags);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryRows(&obj_table, 0x32, TBL_ADVANCE, &SRowSet);
+ mapi_errstr("QueryRows", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ for (i = 0; i < SRowSet.cRows; i++) {
+ struct SPropValue *lpProp;
+ uint32_t *rights;
+
+ lpProp = get_SPropValue_SRow(&(SRowSet.aRow[i]), PR_MEMBER_NAME);
+ printf(" %-25s: %s\n", "Username", lpProp->value.lpszA ? lpProp->value.lpszA : "Default");
+ lpProp = get_SPropValue_SRow(&(SRowSet.aRow[i]), PR_MEMBER_RIGHTS);
+ rights = &(lpProp->value.l);
+ ndr_print_debug((ndr_print_fn_t)ndr_print_ACLRIGHTS, "Rights", (void *)rights);
+ printf("\n");
+ }
+
+ mapi_object_release(&obj_table);
+ }
+ mapi_object_release(&obj_inbox);
+ mapi_object_release(&obj_store);
+
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+ return true;
+}
Added: trunk/openchange/torture/mapi_recipient.c
===================================================================
--- trunk/openchange/torture/mapi_recipient.c (rev 0)
+++ trunk/openchange/torture/mapi_recipient.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,143 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Fetch emails recipients from an Exchange server Inbox
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+
+bool torture_rpc_mapi_recipient(struct torture_context *torture)
+{
+ NTSTATUS ntstatus;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_message;
+ mapi_object_t obj_table;
+ mapi_id_t id_inbox;
+ struct SRowSet SRowSet;
+ struct SPropTagArray *SPropTagArray;
+ uint32_t count = 0;
+ uint32_t i;
+ uint32_t j;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_recipient");
+ ntstatus = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* Open Message Store */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Get Receive Folder */
+ mapi_object_init(&obj_inbox);
+ retval = GetReceiveFolder(&obj_store, &id_inbox, NULL);
+ mapi_errstr("GetReceiveFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Get Contents Table */
+ mapi_object_init(&obj_table);
+ retval = GetContentsTable(&obj_inbox, &obj_table, 0, &count);
+ mapi_errstr("GetContentsTable", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Customize table view */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x3,
+ PR_FID,
+ PR_MID,
+ PR_SUBJECT);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ mapi_errstr("SetColumns", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ while (((retval = QueryRows(&obj_table, count, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND) && SRowSet.cRows) {
+ count -= SRowSet.cRows;
+ for (i = 0; i < SRowSet.cRows; i++) {
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(&obj_store,
+ SRowSet.aRow[i].lpProps[0].value.d,
+ SRowSet.aRow[i].lpProps[1].value.d,
+ &obj_message, 0);
+ if (GetLastError() != MAPI_E_NOT_FOUND) {
+ struct SRowSet props;
+ struct SPropTagArray proptags;
+
+
+
+ retval = GetRecipientTable(&obj_message, &props, &proptags);
+ if (retval == MAPI_E_SUCCESS) {
+ if (SRowSet.aRow[i].lpProps[2].value.lpszA) {
+ printf("\n\nSubject: %s\n", SRowSet.aRow[i].lpProps[2].value.lpszA);
+ fflush(0);
+ }
+
+ printf("\nSPropTagArray:\n");
+ fflush(0);
+ mapidump_SPropTagArray(&proptags);
+
+ printf("\nSRowSet:\n");
+ fflush(0);
+
+ for (j = 0; j < props.cRows; j++) {
+ printf("===\n");
+ fflush(0);
+ mapidump_SRow(&props.aRow[j], "SRow: ");
+ }
+
+ printf("\n\n");
+ fflush(0);
+ }
+ mapi_object_release(&obj_message);
+ }
+ }
+ }
+
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_inbox);
+ mapi_object_release(&obj_store);
+
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return true;
+}
Added: trunk/openchange/torture/mapi_restrictions.c
===================================================================
--- trunk/openchange/torture/mapi_restrictions.c (rev 0)
+++ trunk/openchange/torture/mapi_restrictions.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,374 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Test Restrictions
+
+ Copyright (C) Julien Kerihuel 2007 - 2008.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+#define SAME_SUBJECT "Same subject"
+#define SAME_SUBJECT_BODY "Same subject and body"
+#define UNIQUE_BODY "The secret word is OpenChange and is hidden"
+
+bool torture_create_environment(struct loadparm_context *lp_ctx,
+ TALLOC_CTX *mem_ctx,
+ mapi_object_t *parent,
+ mapi_object_t *child)
+{
+ enum MAPISTATUS retval;
+ char *subject = NULL;
+ char *body = NULL;
+ uint32_t i;
+
+ /* Create the test directory */
+ mapi_object_init(child);
+ retval = CreateFolder(parent, FOLDER_GENERIC,
+ "torture_restrictions",
+ "MAPI restrictions torture test",
+ OPEN_IF_EXISTS, child);
+ if (retval != MAPI_E_SUCCESS) return false;
+ DEBUG(0, ("[+] torture restrictions directory created\n"));
+
+ retval = EmptyFolder(child);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Send 5 mails with MSGFLAG_READ set */
+ for (i = 0; i < 5; i++) {
+ subject = talloc_asprintf(mem_ctx, "Subject: %s %d",
+ "MSGFLAG_READ: Sample mail", i);
+ retval = torture_simplemail_fromme(lp_ctx, child, subject,
+ "This is sample content",
+ MSGFLAG_READ|MSGFLAG_SUBMIT);
+ talloc_free(subject);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+ DEBUG(0, ("[+] 5 mails created with MSGFLAG_READ set\n"));
+
+ /* Send 5 mails with MSGFLAG_UNREAD set */
+ for (i = 0; i < 5; i++) {
+ subject = talloc_asprintf(mem_ctx, "Subject: %s %d",
+ "Sample mail", i);
+ retval = torture_simplemail_fromme(lp_ctx, child, subject,
+ "This is sample content",
+ MSGFLAG_SUBMIT);
+ talloc_free(subject);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+ DEBUG(0, ("[+] 5 unread mails created\n"));
+
+ /* Create 2 mails with the same subject */
+ for (i = 0; i < 2; i++) {
+ retval = torture_simplemail_fromme(lp_ctx, child, SAME_SUBJECT,
+ "Different content",
+ MSGFLAG_SUBMIT);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+ DEBUG(0, ("[+] 2 mails unread with same subject but different body\n"));
+
+
+ /* Create 3 mails with the same subject and same body */
+ for (i = 0; i < 3; i++) {
+ retval = torture_simplemail_fromme(lp_ctx, child, SAME_SUBJECT_BODY,
+ SAME_SUBJECT_BODY,
+ MSGFLAG_SUBMIT);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+ DEBUG(0, ("[+] 3 mails unread with same subject and body\n"));
+
+
+ /* Create 1 mail with a long body */
+ body = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
+ retval = torture_simplemail_fromme(lp_ctx, child, "Long body", body, MSGFLAG_SUBMIT);
+ if (retval != MAPI_E_SUCCESS) return false;
+ DEBUG(0, ("[+] 1 mail with body > 39 chars\n"));
+
+ /* Create 1 mail with a unique body content */
+ retval = torture_simplemail_fromme(lp_ctx, child, "Unique content", UNIQUE_BODY, MSGFLAG_SUBMIT);
+ if (retval != MAPI_E_SUCCESS) return false;
+ DEBUG(0, ("[+] 1 mail with unique body: %s\n", UNIQUE_BODY));
+
+
+ return true;
+}
+
+bool torture_rpc_mapi_restrictions(struct torture_context *torture)
+{
+ NTSTATUS nt_status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_table;
+ mapi_object_t obj_testdir;
+ mapi_id_t id_inbox;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ struct SRowSet SRowSet_row;
+ struct mapi_SRestriction res;
+ uint32_t total;
+ uint32_t Numerator;
+ uint32_t Denominator;
+ uint32_t row_idx;
+ uint32_t bookmark;
+
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_restrictions");
+ nt_status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_inbox);
+ mapi_object_init(&obj_table);
+
+ /* Open Message Store */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = GetDefaultFolder(&obj_store, &id_inbox, olFolderInbox);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Open Inbox folder */
+ retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Create test environment */
+ if (torture_create_environment(torture->lp_ctx, mem_ctx, &obj_inbox, &obj_testdir) != true) {
+ return false;
+ }
+
+ /* Get Contents Table */
+ retval = GetContentsTable(&obj_testdir, &obj_table, 0, &total);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ DEBUG(0, ("Total number of mails = %d\n", total));
+
+ /* Filter contents table on subject */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT,
+ PR_MESSAGE_FLAGS);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ DEBUG(0, ("\nStep 1. Test Restrict MAPI call\n"));
+ DEBUG(0, ("===============================\n"));
+
+ /* RES_PROPERTY test */
+ res.rt = RES_PROPERTY;
+ res.res.resProperty.relop = RES_PROPERTY;
+ res.res.resProperty.ulPropTag = PR_SUBJECT;
+ res.res.resProperty.lpProp.ulPropTag = PR_SUBJECT;
+ res.res.resProperty.lpProp.value.lpszA = "Same subject";
+
+ retval = Restrict(&obj_table, &res, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryPosition(&obj_table, &Numerator, &Denominator);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ DEBUG(0, ("\no Restriction: RES_PROPERTY\n"));
+ DEBUG(0, (" -------------------------\n"));
+ DEBUG(0, ("\tFilter on PR_SUBJECT\n"));
+ DEBUG(0, (("\tCheck for subject eq \"%s\"\n"), SAME_SUBJECT));
+ DEBUG(0, ("\tCursor is at %d / %d\n", Numerator, Denominator));
+
+ /* RES_BITMASK test */
+ res.rt = RES_BITMASK;
+ res.res.resBitmask.relMBR = BMR_NEZ;
+ res.res.resBitmask.ulPropTag = PR_MESSAGE_FLAGS;
+ res.res.resBitmask.ulMask = MSGFLAG_READ;
+
+ retval = Restrict(&obj_table, &res, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryPosition(&obj_table, &Numerator, &Denominator);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ DEBUG(0, ("\no Restriction: RES_BITMASK\n"));
+ DEBUG(0, (" --------------------------\n"));
+ DEBUG(0, ("\tFilter on PR_MESSAGE_FLAG bitmask\n"));
+ DEBUG(0, ("\tCheck for all emails with MSGFLAG_READ set\n"));
+ DEBUG(0, ("\tCursor is at %d / %d\n", Numerator, Denominator));
+
+ /* RES_SIZE test */
+ res.rt = RES_SIZE;
+ res.res.resSize.relop = RELOP_GT;
+ res.res.resSize.ulPropTag = PR_BODY;
+ res.res.resSize.size = 30;
+
+ retval = Restrict(&obj_table, &res, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryPosition(&obj_table, &Numerator, &Denominator);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ DEBUG(0, ("\no Restriction: RES_SIZE\n"));
+ DEBUG(0, (" --------------------------\n"));
+ DEBUG(0, ("\tFilter on property size\n"));
+ DEBUG(0, ("\tCheck for all emails with PR_BODY size > 30 chars\n"));
+ DEBUG(0, ("\tCursor is at %d / %d\n", Numerator, Denominator));
+
+ /* RES_EXIST test */
+ res.rt = RES_EXIST;
+ res.res.resExist.ulPropTag = PR_HTML;
+
+ retval = Restrict(&obj_table, &res, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryPosition(&obj_table, &Numerator, &Denominator);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ DEBUG(0, ("\no Restriction: RES_EXIST\n"));
+ DEBUG(0, (" --------------------------\n"));
+ DEBUG(0, ("\tFilter on an existing property\n"));
+ DEBUG(0, ("\tCheck for all emails with PR_HTML\n"));
+ DEBUG(0, ("\tCursor is at %d / %d\n", Numerator, Denominator));
+
+
+ /* RES_COMPAREPROPS */
+ res.rt = RES_COMPAREPROPS;
+ res.res.resCompareProps.relop = RELOP_EQ;
+ res.res.resCompareProps.ulPropTag1 = PR_BODY;
+ res.res.resCompareProps.ulPropTag2 = PR_SUBJECT;
+ retval = Restrict(&obj_table, &res, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryPosition(&obj_table, &Numerator, &Denominator);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ DEBUG(0, ("\no Restriction: RES_COMPAREPROPS\n"));
+ DEBUG(0, (" --------------------------\n"));
+ DEBUG(0, ("\tFilter on properties comparison\n"));
+ DEBUG(0, ("\tCheck for all emails with PR_SUBJECT == PR_BODY\n"));
+ DEBUG(0, ("\tCursor is at %d / %d\n", Numerator, Denominator));
+
+ /* RES_CONTENT */
+ res.rt = RES_CONTENT;
+ res.res.resContent.fuzzy = FL_SUBSTRING|FL_LOOSE;
+ res.res.resContent.ulPropTag = PR_BODY;
+ res.res.resContent.lpProp.ulPropTag = PR_BODY;
+ res.res.resContent.lpProp.value.lpszA = "openchange";
+ retval = Restrict(&obj_table, &res, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = QueryPosition(&obj_table, &Numerator, &Denominator);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ DEBUG(0, ("\no Restriction: RES_CONTENT\n"));
+ DEBUG(0, (" --------------------------\n"));
+ DEBUG(0, ("\tFilter on insensitive substring within content\n"));
+ DEBUG(0, ("\tCheck for all emails with PR_SUBJECT contained \"openchange\"\n"));
+ DEBUG(0, ("\tCursor is at %d / %d\n", Numerator, Denominator));
+
+ /* We now test the FindRow MAPI call */
+
+ DEBUG(0, ("\nStep 2. Test FindRow MAPI call\n"));
+ DEBUG(0, ("==============================\n"));
+
+ /* Approximatively position at half the contents table */
+ retval = SeekRowApprox(&obj_table, 1, 2);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Create a bookmark */
+ retval = CreateBookmark(&obj_table, &bookmark);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Fetch row data */
+ retval = QueryRows(&obj_table, 1, TBL_NOADVANCE, &SRowSet_row);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Position table cursor to the beginning of the table */
+ retval = SeekRow(&obj_table, BOOKMARK_BEGINNING, 0, &row_idx);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ res.rt = RES_CONTENT;
+ res.res.resContent.fuzzy = FL_SUBSTRING|FL_LOOSE;
+ res.res.resContent.ulPropTag = PR_BODY;
+ res.res.resContent.lpProp.ulPropTag = PR_BODY;
+ res.res.resContent.lpProp.value.lpszA = "openchange";
+ retval = FindRow(&obj_table, &res, 0, 0, &SRowSet);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ DEBUG(0, ("\no FindRow: RES_CONTENT\n"));
+ DEBUG(0, ("----------------------\n"));
+ mapidump_SRowSet(&SRowSet, "\t[+] ");
+ MAPIFreeBuffer(SRowSet.aRow);
+
+ DEBUG(0, ("\n"));
+ mapi_object_bookmark_debug(&obj_table);
+
+ retval = FindRow(&obj_table, &res, bookmark, 0, &SRowSet);
+ if (retval != MAPI_E_SUCCESS) return false;
+ DEBUG(0, ("\no FindRow: RES_CONTENT BOOKMARK_USER (%.2d)\n", bookmark));
+ DEBUG(0, ("--------------------------------------------\n"));
+ mapidump_SRowSet(&SRowSet, "\t[+] ");
+ DEBUG(0, ("=============\n"));
+ mapidump_SRowSet(&SRowSet_row, "\t[+] ");
+
+ if (SRowSet.aRow[0].lpProps[1].value.d == SRowSet_row.aRow[0].lpProps[1].value.d) {
+ DEBUG(0, ("PR_MID matches\n"));
+ }
+ MAPIFreeBuffer(SRowSet.aRow);
+
+ /* Clean up test environment */
+ retval = EmptyFolder(&obj_testdir);
+ if (retval != MAPI_E_SUCCESS) return false;
+ DEBUG(0, ("\n[+] Removing messages from testdir\n"));
+
+ retval = DeleteFolder(&obj_inbox, mapi_object_get_id(&obj_testdir),
+ DEL_MESSAGES|DEL_FOLDERS|DELETE_HARD_DELETE, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+ DEBUG(0, ("[+] Deleting testdir folder\n"));
+
+ /* release mapi objects */
+
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_inbox);
+ mapi_object_release(&obj_store);
+
+ /* uninitialize mapi
+ */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return (ret);
+}
Added: trunk/openchange/torture/mapi_sendappointment.c
===================================================================
--- trunk/openchange/torture/mapi_sendappointment.c (rev 0)
+++ trunk/openchange/torture/mapi_sendappointment.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,180 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Send appointments to an Exchange server
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+#include <time.h>
+
+#define DATE_FORMAT "%Y-%m-%d %H:%M:%S"
+
+#define CN_PROPS 14
+
+bool torture_rpc_mapi_sendappointment(struct torture_context *torture)
+{
+ NTSTATUS nt_status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ const char *appointment = lp_parm_string(torture->lp_ctx, NULL, "mapi", "appointment");
+ const char *body = lp_parm_string(torture->lp_ctx, NULL, "mapi", "body");
+ const char *location = lp_parm_string(torture->lp_ctx, NULL, "mapi", "location");
+ const char *start = lp_parm_string(torture->lp_ctx, NULL, "mapi", "start");
+ const char *end = lp_parm_string(torture->lp_ctx, NULL, "mapi", "end");
+ uint32_t busy_status = lp_parm_int(torture->lp_ctx, NULL, "mapi", "busystatus", 0);
+ uint32_t label = lp_parm_int(torture->lp_ctx, NULL, "mapi", "label", 0);
+ struct mapi_session *session;
+ uint64_t id_calendar;
+ mapi_object_t obj_store;
+ mapi_object_t obj_calendar;
+ mapi_object_t obj_message;
+ struct SPropValue props[CN_PROPS];
+ struct mapi_nameid *nameid;
+ struct SPropTagArray *SPropTagArray;
+ NTTIME nt;
+ struct tm tm;
+ struct FILETIME *start_date;
+ struct FILETIME *end_date;
+ uint32_t flag;
+ uint8_t flag2;
+
+ if (!appointment) return false;
+ if (busy_status > 3) return false;
+ if (!start || !end) return false;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_sendappointment");
+ nt_status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_calendar);
+
+ /* session::OpenMsgStore */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = GetDefaultFolder(&obj_store, &id_calendar, olFolderCalendar);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* We now open the calendar folder */
+ retval = OpenFolder(&obj_store, id_calendar, &obj_calendar);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Operations on the calendar folder */
+ retval = CreateMessage(&obj_calendar, &obj_message);
+ mapi_errstr("CreateMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Build the list of named properties we want to set */
+ nameid = mapi_nameid_new(mem_ctx);
+ mapi_nameid_OOM_add(nameid, "Location", PSETID_Appointment);
+ mapi_nameid_OOM_add(nameid, "BusyStatus", PSETID_Appointment);
+ mapi_nameid_OOM_add(nameid, "ApptStateFlags", PSETID_Appointment);
+ mapi_nameid_OOM_add(nameid, "CommonStart", PSETID_Common);
+ mapi_nameid_OOM_add(nameid, "CommonEnd", PSETID_Common);
+ mapi_nameid_OOM_add(nameid, "Label", PSETID_Appointment);
+ mapi_nameid_OOM_add(nameid, "ReminderDelta", PSETID_Common);
+
+ /* GetIDsFromNames and map property types */
+ SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
+ retval = GetIDsFromNames(&obj_calendar, nameid->count,
+ nameid->nameid, 0, &SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+ mapi_nameid_SPropTagArray(nameid, SPropTagArray);
+ MAPIFreeBuffer(nameid);
+
+ if (!strptime(start, DATE_FORMAT, &tm)) {
+ printf("Invalid date format: yyyy-mm-dd hh:mm:ss (e.g.: 2007-09-17 10:00:00)\n");
+ return false;
+ }
+ unix_to_nt_time(&nt, mktime(&tm));
+ start_date = talloc(mem_ctx, struct FILETIME);
+ start_date->dwLowDateTime = (nt << 32) >> 32;
+ start_date->dwHighDateTime = (nt >> 32);
+
+ if (!strptime(end, DATE_FORMAT, &tm)) {
+ printf("Invalid date format: yyyy-mm-dd hh:mm:ss (e.g.:2007-09-17 18:30:00)\n");
+ return false;
+ }
+ unix_to_nt_time(&nt, mktime(&tm));
+ end_date = talloc(mem_ctx, struct FILETIME);
+ end_date->dwLowDateTime = (nt << 32) >> 32;
+ end_date->dwHighDateTime = (nt >> 32);
+
+ set_SPropValue_proptag(&props[0], PR_CONVERSATION_TOPIC,
+ (const void *) appointment);
+ set_SPropValue_proptag(&props[1], PR_NORMALIZED_SUBJECT,
+ (const void *) appointment);
+ set_SPropValue_proptag(&props[2], PR_START_DATE, (const void *) start_date);
+ set_SPropValue_proptag(&props[3], PR_END_DATE, (const void *) end_date);
+ set_SPropValue_proptag(&props[4], PR_MESSAGE_CLASS, (const void *)"IPM.Appointment");
+ flag = 1;
+ set_SPropValue_proptag(&props[5], PR_MESSAGE_FLAGS, (const void *) &flag);
+ set_SPropValue_proptag(&props[6], SPropTagArray->aulPropTag[0], (const void *)(location?location:""));
+ set_SPropValue_proptag(&props[7], SPropTagArray->aulPropTag[1], (const void *) &busy_status);
+ flag= MEETING_STATUS_NONMEETING;
+ set_SPropValue_proptag(&props[8], SPropTagArray->aulPropTag[2], (const void *) &flag);
+ flag2 = true;
+ set_SPropValue_proptag(&props[9], SPropTagArray->aulPropTag[3], (const void *) start_date);
+ set_SPropValue_proptag(&props[10], SPropTagArray->aulPropTag[4], (const void *) end_date);
+ set_SPropValue_proptag(&props[11], SPropTagArray->aulPropTag[5], (const void *)&label);
+ flag = 30;
+ set_SPropValue_proptag(&props[12], SPropTagArray->aulPropTag[6], (const void *)&flag);
+ set_SPropValue_proptag(&props[13], PR_BODY, (const void *)(body?body:""));
+ retval = SetProps(&obj_message, props, CN_PROPS);
+ mapi_errstr("SetProps", GetLastError());
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+
+ retval = SaveChangesMessage(&obj_calendar, &obj_message, KeepOpenReadOnly);
+ mapi_errstr("SaveChangesMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+
+ mapi_object_release(&obj_calendar);
+ mapi_object_release(&obj_store);
+
+ /* uninitialize mapi
+ */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return (ret);
+}
Added: trunk/openchange/torture/mapi_sendattach.c
===================================================================
--- trunk/openchange/torture/mapi_sendattach.c (rev 0)
+++ trunk/openchange/torture/mapi_sendattach.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,236 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Send attach to an Exchange server
+
+ Copyright (C) Julien Kerihuel 2007.
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+#define CN_MSG_PROPS 3
+
+bool torture_rpc_mapi_sendattach(struct torture_context *torture)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ const char *subject = lp_parm_string(torture->lp_ctx, NULL, "mapi", "subject");
+ const char *body = lp_parm_string(torture->lp_ctx, NULL, "mapi", "body");
+ const char *filename = lp_parm_string(torture->lp_ctx, NULL, "mapi", "attachment");
+ const char **usernames;
+ const char **usernames_to;
+ const char **usernames_cc;
+ const char **usernames_bcc;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_outbox;
+ mapi_object_t obj_message;
+ mapi_object_t obj_attach;
+ mapi_object_t obj_stream;
+ uint64_t id_outbox;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ uint32_t index = 0;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue SPropValue;
+ struct SPropValue props_attach[3];
+ unsigned long cn_props_attach;
+ struct SPropValue props[CN_MSG_PROPS];
+ uint32_t msgflag;
+ DATA_BLOB blob;
+
+ /* get the attachment filename */
+ if (!filename) {
+ DEBUG(0, ("No filename specified with mapi:attachment\n"));
+ return false;
+ }
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_sendmail");
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_outbox);
+ mapi_object_init(&obj_message);
+ mapi_object_init(&obj_attach);
+
+ /* default if null */
+ if (subject == 0) subject = "";
+ if (body == 0) body = "";
+
+ /* session::OpenMsgStore() */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* id_outbox = store->GeOutboxFolder() */
+ retval = GetOutboxFolder(&obj_store, &id_outbox);
+ mapi_errstr("GetOutboxFodler", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* outbox = store->OpenFolder(id_outbox) */
+ retval = OpenFolder(&obj_store, id_outbox, &obj_outbox);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* message = outbox->CreateMessage() */
+ retval = CreateMessage(&obj_outbox, &obj_message);
+ mapi_errstr("CreateMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_7BIT_DISPLAY_NAME,
+ PR_DISPLAY_NAME,
+ PR_SMTP_ADDRESS,
+ PR_GIVEN_NAME);
+
+ usernames_to = get_cmdline_recipients(mem_ctx, "to");
+ usernames_cc = get_cmdline_recipients(mem_ctx, "cc");
+ usernames_bcc = get_cmdline_recipients(mem_ctx, "bcc");
+ usernames = collapse_recipients(mem_ctx, usernames_to, usernames_cc, usernames_bcc);
+
+ retval = ResolveNames(mapi_object_get_session(&obj_outbox), usernames,
+ SPropTagArray, &SRowSet, &flaglist, 0);
+ mapi_errstr("ResolveNames", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ if (!SRowSet) {
+ SRowSet = talloc_zero(mem_ctx, struct SRowSet);
+ }
+
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, usernames_to, flaglist, MAPI_TO);
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, usernames_cc, flaglist, MAPI_CC);
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, usernames_bcc, flaglist, MAPI_BCC);
+
+
+ SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
+ SPropValue.value.l = 0;
+ SRowSet_propcpy(mem_ctx, &SRowSet[0], SPropValue);
+
+ /* message->ModifyRecipients() */
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapi_errstr("ModifyRecipients", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = MAPIFreeBuffer(SRowSet);
+ mapi_errstr("MAPIFreeBuffer: SRowSet", GetLastError());
+
+ retval = MAPIFreeBuffer(flaglist);
+ mapi_errstr("MAPIFreeBuffer: flaglist", GetLastError());
+
+ /* message->SetProps()
+ */
+ msgflag = MSGFLAG_UNSENT;
+ set_SPropValue_proptag(&props[0], PR_SUBJECT, (const void *)subject);
+ set_SPropValue_proptag(&props[1], PR_BODY, (const void *)body);
+ set_SPropValue_proptag(&props[2], PR_MESSAGE_FLAGS, (const void *)&msgflag);
+ retval = SetProps(&obj_message, props, CN_MSG_PROPS);
+ mapi_errstr("SetProps", GetLastError());
+
+ /* CreateAttach */
+ retval = CreateAttach(&obj_message, &obj_attach);
+ mapi_errstr("CreateAttach", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* send by value */
+ props_attach[0].ulPropTag = PR_ATTACH_METHOD;
+ props_attach[0].value.l = ATTACH_BY_VALUE;
+ props_attach[1].ulPropTag = PR_RENDERING_POSITION;
+ props_attach[1].value.l = 0;
+ props_attach[2].ulPropTag = PR_ATTACH_FILENAME;
+ props_attach[2].value.lpszA = get_filename(filename);
+ cn_props_attach = 3;
+
+ /* SetProps */
+ retval = SetProps(&obj_attach, props_attach, cn_props_attach);
+ mapi_errstr("SetProps", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* OpenStream on CreateAttach handle */
+ retval = OpenStream(&obj_attach, PR_ATTACH_DATA_BIN, 2, &obj_stream);
+ mapi_errstr("OpenStream", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* WriteStream */
+ {
+ int fd;
+ struct stat sb;
+ uint32_t read_size;
+ uint16_t buf_readsize;
+ uint8_t buf[0x7000];
+
+ if (stat(filename, &sb) != 0) return false;
+
+ if ((fd = open(filename, O_RDONLY)) == -1) {
+ DEBUG(0, ("Error while opening %s\n", filename));
+ return false;
+ }
+
+ while ((read_size = read(fd, buf, 0x4000))) {
+ /* We reset errno due to read */
+ blob.length = read_size;
+ blob.data = talloc_size(mem_ctx, read_size);
+ memcpy(blob.data, buf, read_size);
+
+ errno = 0;
+ retval = WriteStream(&obj_stream, &blob, &buf_readsize);
+ mapi_errstr("WriteStream", GetLastError());
+ talloc_free(blob.data);
+ }
+ close(fd);
+ }
+
+ /* message->SaveChangesAttachment() */
+ retval = SaveChangesAttachment(&obj_message, &obj_attach, KeepOpenReadOnly);
+ mapi_errstr("SaveChangesAttachment", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* message->SubmitMessage() */
+ retval = SubmitMessage(&obj_message);
+ mapi_errstr("SubmitMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* objects->Release()
+ */
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_outbox);
+ mapi_object_release(&obj_store);
+
+ /* session::Uninitialize()
+ */
+ MAPIUninitialize();
+
+ talloc_free(mem_ctx);
+ return ret;
+}
Added: trunk/openchange/torture/mapi_sendcontacts.c
===================================================================
--- trunk/openchange/torture/mapi_sendcontacts.c (rev 0)
+++ trunk/openchange/torture/mapi_sendcontacts.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,127 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Send contacts to an Exchange server
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+bool torture_rpc_mapi_sendcontacts(struct torture_context *torture)
+{
+ NTSTATUS nt_status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ const char *cardname = lp_parm_string(torture->lp_ctx, NULL, "mapi", "cardname");
+ const char *fullname = lp_parm_string(torture->lp_ctx, NULL, "mapi", "fullname");
+ struct mapi_session *session;
+ uint64_t id_contacts;
+ mapi_object_t obj_store;
+ mapi_object_t obj_contacts;
+ mapi_object_t obj_table;
+ mapi_object_t obj_message;
+ struct SPropValue props[5];
+ struct mapi_nameid *nameid;
+ struct SPropTagArray *SPropTagArray;
+
+ if (!cardname) return false;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_fetchmail");
+ nt_status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_contacts);
+ mapi_object_init(&obj_table);
+
+ /* session::OpenMsgStore */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve the contacts Folder ID */
+ retval = GetDefaultFolder(&obj_store, &id_contacts, olFolderContacts);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* We now open the contacts folder */
+ retval = OpenFolder(&obj_store, id_contacts, &obj_contacts);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Operations on the contacts folder */
+ retval = CreateMessage(&obj_contacts, &obj_message);
+ mapi_errstr("CreateMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Build the list of named properties we want to set */
+ nameid = mapi_nameid_new(mem_ctx);
+ mapi_nameid_OOM_add(nameid, "FileUnder", PSETID_Address);
+ mapi_nameid_string_add(nameid, "urn:schemas:contacts:fileas", PS_PUBLIC_STRINGS);
+
+
+ /* GetIDsFromNames and map property types */
+ SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
+ retval = GetIDsFromNames(&obj_contacts, nameid->count,
+ nameid->nameid, 0, &SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+ mapi_nameid_SPropTagArray(nameid, SPropTagArray);
+ MAPIFreeBuffer(nameid);
+
+ set_SPropValue_proptag(&props[0], SPropTagArray->aulPropTag[0], (const void *) cardname);
+ set_SPropValue_proptag(&props[1], PR_DISPLAY_NAME, (const void *) fullname);
+ set_SPropValue_proptag(&props[2], PR_MESSAGE_CLASS, (const void *)"IPM.Contact");
+ set_SPropValue_proptag(&props[3], PR_NORMALIZED_SUBJECT, (const void *) cardname);
+ set_SPropValue_proptag(&props[4], SPropTagArray->aulPropTag[1], (const void *) cardname);
+ retval = SetProps(&obj_message, props, 5);
+ mapi_errstr("SetProps", GetLastError());
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = SaveChangesMessage(&obj_contacts, &obj_message, KeepOpenReadOnly);
+ mapi_errstr("SaveChangesMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_contacts);
+ mapi_object_release(&obj_store);
+
+ /* uninitialize mapi
+ */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return (ret);
+}
Added: trunk/openchange/torture/mapi_sendmail.c
===================================================================
--- trunk/openchange/torture/mapi_sendmail.c (rev 0)
+++ trunk/openchange/torture/mapi_sendmail.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,165 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Send emails to an Exchange server
+
+ Copyright (C) Julien Kerihuel 2007.
+ Copyright (C) Fabien Le Mentec 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+
+#define CN_MSG_PROPS 3
+
+bool torture_rpc_mapi_sendmail(struct torture_context *torture)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ const char *subject = lp_parm_string(torture->lp_ctx, NULL, "mapi", "subject");
+ const char *body = lp_parm_string(torture->lp_ctx, NULL, "mapi", "body");
+ const char **usernames;
+ const char **usernames_to;
+ const char **usernames_cc;
+ const char **usernames_bcc;
+ uint32_t index = 0;
+ mapi_object_t obj_message;
+ mapi_object_t obj_store;
+ mapi_object_t obj_outbox;
+ mapi_id_t id_outbox;
+ struct mapi_session *session;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue SPropValue;
+ struct SPropValue props[CN_MSG_PROPS];
+ uint32_t msgflag;
+
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_sendmail");
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* default if null */
+ if (subject == NULL) subject = "";
+ if (body == NULL) body = "";
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_outbox);
+ mapi_object_init(&obj_message);
+
+ /* session::OpenMsgStore() */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve the outbox folder id */
+ retval = GetDefaultFolder(&obj_store, &id_outbox, olFolderTopInformationStore);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* outbox = store->OpenFolder(id_outbox) */
+ retval = OpenFolder(&obj_store, id_outbox, &obj_outbox);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* message = outbox->CreateMessage() */
+ retval = CreateMessage(&obj_outbox, &obj_message);
+ mapi_errstr("CreateMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_7BIT_DISPLAY_NAME,
+ PR_DISPLAY_NAME,
+ PR_SMTP_ADDRESS,
+ PR_GIVEN_NAME);
+
+ usernames_to = get_cmdline_recipients(mem_ctx, "to");
+ usernames_cc = get_cmdline_recipients(mem_ctx, "cc");
+ usernames_bcc = get_cmdline_recipients(mem_ctx, "bcc");
+ usernames = collapse_recipients(mem_ctx, usernames_to, usernames_cc, usernames_bcc);
+
+ /* ResolveNames */
+ retval = ResolveNames(mapi_object_get_session(&obj_store), usernames,
+ SPropTagArray, &SRowSet, &flaglist, 0);
+ mapi_errstr("ResolveNames", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ if (!SRowSet) {
+ SRowSet = talloc_zero(mem_ctx, struct SRowSet);
+ }
+
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, usernames_to, flaglist, MAPI_TO);
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, usernames_cc, flaglist, MAPI_CC);
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, usernames_bcc, flaglist, MAPI_BCC);
+
+ SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
+ SPropValue.value.l = 0;
+ SRowSet_propcpy(mem_ctx, SRowSet, SPropValue);
+
+ /* ModifyRecipients */
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapi_errstr("ModifyRecipients", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = MAPIFreeBuffer(SRowSet);
+ mapi_errstr("MAPIFreeBuffer: SRowSet", GetLastError());
+
+ retval = MAPIFreeBuffer(flaglist);
+ mapi_errstr("MAPIFreeBuffer: flaglist", GetLastError());
+
+ /* message->SetProps() */
+ msgflag = MSGFLAG_UNSENT;
+ set_SPropValue_proptag(&props[0], PR_SUBJECT, (const void *)subject);
+ set_SPropValue_proptag(&props[1], PR_BODY, (const void *)body);
+ set_SPropValue_proptag(&props[2], PR_MESSAGE_FLAGS, (const void *)&msgflag);
+
+ retval = SetProps(&obj_message, props, CN_MSG_PROPS);
+ mapi_errstr("SetProps", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* message->SubmitMessage()
+ */
+ retval = SubmitMessage(&obj_message);
+ mapi_errstr("SubmitMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* objects->Release()
+ */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_outbox);
+ mapi_object_release(&obj_store);
+
+ /* uninitialize mapi
+ */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return ret;
+}
Added: trunk/openchange/torture/mapi_sendmail_html.c
===================================================================
--- trunk/openchange/torture/mapi_sendmail_html.c (rev 0)
+++ trunk/openchange/torture/mapi_sendmail_html.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,183 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Send attachments to an Exchange server
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+bool torture_rpc_mapi_sendmail_html(struct torture_context *torture)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ const char *subject = lp_parm_string(torture->lp_ctx, NULL, "mapi", "subject");
+ const char *body = lp_parm_string(torture->lp_ctx, NULL, "mapi", "body");
+ const char *filename = lp_parm_string(torture->lp_ctx, NULL, "mapi", "html");
+ const char **usernames;
+ const char **usernames_to;
+ const char **usernames_cc;
+ const char **usernames_bcc;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_outbox;
+ mapi_object_t obj_message;
+ uint64_t id_outbox;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ uint32_t index = 0;
+ struct SPropTagArray *SPropTagArray;
+ struct SBinary_short html;
+ struct SPropValue SPropValue;
+ struct SPropValue props[3];
+ uint32_t msgflag;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_sendmail");
+
+ /* get the attachment filename */
+ if (!filename) {
+ DEBUG(0, ("No filename specified with mapi:html\n"));
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_outbox);
+ mapi_object_init(&obj_message);
+
+ /* default if null */
+ if (subject == 0) subject = "";
+ if (body == 0) body = "";
+
+ /* session::OpenMsgStore() */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* id_outbox = store->GeOutboxFolder() */
+ retval = GetOutboxFolder(&obj_store, &id_outbox);
+ mapi_errstr("GetOutboxFodler", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* outbox = store->OpenFolder(id_outbox) */
+ retval = OpenFolder(&obj_store, id_outbox, &obj_outbox);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* message = outbox->CreateMessage() */
+ retval = CreateMessage(&obj_outbox, &obj_message);
+ mapi_errstr("CreateMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_7BIT_DISPLAY_NAME_UNICODE,
+ PR_DISPLAY_NAME_UNICODE,
+ PR_SMTP_ADDRESS_UNICODE,
+ PR_GIVEN_NAME_UNICODE);
+
+ usernames_to = get_cmdline_recipients(mem_ctx, "to");
+ usernames_cc = get_cmdline_recipients(mem_ctx, "cc");
+ usernames_bcc = get_cmdline_recipients(mem_ctx, "bcc");
+ usernames = collapse_recipients(mem_ctx, usernames_to, usernames_cc, usernames_bcc);
+
+ retval = ResolveNames(mapi_object_get_session(&obj_store), (const char **)usernames,
+ SPropTagArray, &SRowSet, &flaglist, MAPI_UNICODE);
+ mapi_errstr("ResolveNames", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ if (!SRowSet) {
+ SRowSet = talloc_zero(mem_ctx, struct SRowSet);
+ }
+
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, usernames_to, flaglist, MAPI_TO);
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, usernames_cc, flaglist, MAPI_CC);
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, usernames_bcc, flaglist, MAPI_BCC);
+
+
+ SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
+ SPropValue.value.l = 0;
+ SRowSet_propcpy(mem_ctx, &SRowSet[0], SPropValue);
+
+ /* message->ModifyRecipients() */
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapi_errstr("ModifyRecipients", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = MAPIFreeBuffer(SRowSet);
+ mapi_errstr("MAPIFreeBuffer: SRowSet", GetLastError());
+
+ retval = MAPIFreeBuffer(flaglist);
+ mapi_errstr("MAPIFreeBuffer: flaglist", GetLastError());
+
+ /* message->SetProps()
+ */
+
+ {
+ struct stat sb;
+ int fd;
+
+ if (stat(filename, &sb) != 0) return false;
+ if ((fd = open(filename, O_RDONLY)) == -1) {
+ DEBUG(0, ("Error while opening %s\n", filename));
+ return false;
+ }
+ html.lpb = talloc_size(mem_ctx, sb.st_size);
+ html.cb = read(fd, html.lpb, sb.st_size);
+ close(fd);
+ }
+
+ msgflag = MSGFLAG_UNSENT;
+ set_SPropValue_proptag(&props[0], PR_SUBJECT, (const void *)subject);
+ set_SPropValue_proptag(&props[1], PR_HTML, (const void *)&html);
+ set_SPropValue_proptag(&props[2], PR_MESSAGE_FLAGS, (const void *)&msgflag);
+ retval = SetProps(&obj_message, props, 3);
+ mapi_errstr("SetProps", GetLastError());
+
+ /* message->SubmitMessage() */
+ retval = SubmitMessage(&obj_message);
+ mapi_errstr("SubmitMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* objects->Release()
+ */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_outbox);
+ mapi_object_release(&obj_store);
+
+ /* session::Uninitialize()
+ */
+ MAPIUninitialize();
+
+ talloc_free(mem_ctx);
+ return ret;
+}
Added: trunk/openchange/torture/mapi_sendtasks.c
===================================================================
--- trunk/openchange/torture/mapi_sendtasks.c (rev 0)
+++ trunk/openchange/torture/mapi_sendtasks.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,128 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Create a task on Exchange server
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+#define CN_PROPS 5
+
+bool torture_rpc_mapi_sendtasks(struct torture_context *torture)
+{
+ NTSTATUS nt_status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ bool ret = true;
+ const char *task = lp_parm_string(torture->lp_ctx, NULL, "mapi", "task");
+ uint32_t priority = lp_parm_int(torture->lp_ctx, NULL, "mapi", "priority", 0);
+ uint32_t status = lp_parm_int(torture->lp_ctx, NULL, "mapi", "status", 0);
+ struct mapi_session *session;
+ uint64_t id_task;
+ mapi_object_t obj_store;
+ mapi_object_t obj_task;
+ mapi_object_t obj_table;
+ mapi_object_t obj_message;
+ struct SPropValue props[CN_PROPS];
+ struct mapi_nameid *nameid;
+ struct SPropTagArray *SPropTagArray;
+
+ if (!task) return false;
+
+ /* init torture */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_fetchmail");
+ nt_status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* init objects */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_task);
+ mapi_object_init(&obj_table);
+
+ /* session::OpenMsgStore */
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve the task Folder ID */
+ retval = GetDefaultFolder(&obj_store, &id_task, olFolderTasks);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* We now open the task folder */
+ retval = OpenFolder(&obj_store, id_task, &obj_task);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Operations on the task folder */
+ retval = CreateMessage(&obj_task, &obj_message);
+ mapi_errstr("CreateMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Build the list of named properties we want to set */
+ nameid = mapi_nameid_new(mem_ctx);
+ mapi_nameid_OOM_add(nameid, "TaskStatus", PSETID_Task);
+
+ /* GetIDsFromNames and map property types */
+ SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
+ retval = GetIDsFromNames(&obj_task, nameid->count,
+ nameid->nameid, 0, &SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+ mapi_nameid_SPropTagArray(nameid, SPropTagArray);
+ MAPIFreeBuffer(nameid);
+
+ set_SPropValue_proptag(&props[0], PR_CONVERSATION_TOPIC, (const void *) task);
+ set_SPropValue_proptag(&props[1], PR_NORMALIZED_SUBJECT, (const void *) task);
+ set_SPropValue_proptag(&props[2], PR_MESSAGE_CLASS, (const void *)"IPM.Task");
+ set_SPropValue_proptag(&props[3], PR_PRIORITY, (const void *)&priority);
+ set_SPropValue_proptag(&props[4], SPropTagArray->aulPropTag[0], (const void *)&status);
+ retval = SetProps(&obj_message, props, CN_PROPS);
+ mapi_errstr("SetProps", GetLastError());
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = SaveChangesMessage(&obj_task, &obj_message, KeepOpenReadOnly);
+ mapi_errstr("SaveChangesMessage", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_task);
+ mapi_object_release(&obj_store);
+
+ /* uninitialize mapi
+ */
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+
+ return (ret);
+}
Added: trunk/openchange/torture/mapi_sorttable.c
===================================================================
--- trunk/openchange/torture/mapi_sorttable.c (rev 0)
+++ trunk/openchange/torture/mapi_sorttable.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,121 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Tables related operations torture
+
+ Copyright (C) Julien Kerihuel 2008.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+bool torture_rpc_mapi_sorttable(struct torture_context *torture)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_ctable;
+ mapi_id_t id_folder;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ struct SSortOrderSet criteria;
+ struct mapi_session *session;
+ uint32_t count;
+ uint32_t i;
+
+ /* init torture test */
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_mapi_sorttable");
+ if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
+
+ /* Open Message Store*/
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ mapi_errstr("OpenMsgStore", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve Inbox folder ID */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Open Inbox Folder */
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapi_errstr("OpenFolder", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Retrieve the Contents Table */
+ mapi_object_init(&obj_ctable);
+ retval = GetContentsTable(&obj_folder, &obj_ctable, 0, &count);
+ mapi_errstr("GetContentsTable", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Customize the contents table view */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x2, PR_SUBJECT, PR_LAST_MODIFICATION_TIME);
+ retval = SetColumns(&obj_ctable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ mapi_errstr("SetColumns", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Browse and print table content */
+ printf("\nBefore SortTable ASCENDING:\n");
+ while (((retval = QueryRows(&obj_ctable, count, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND) &&
+ SRowSet.cRows) {
+ count -= SRowSet.cRows;
+
+ for (i = 0; i < SRowSet.cRows; i++) {
+ printf("\t[%d] %s\n", i, SRowSet.aRow[i].lpProps[0].value.lpszA);
+ }
+ }
+
+ /* SortTable */
+ memset(&criteria, 0x0, sizeof (struct SSortOrderSet));
+ criteria.cSorts = 1;
+ criteria.aSort = talloc_array(mem_ctx, struct SSortOrder, criteria.cSorts);
+ criteria.aSort[0].ulPropTag = PR_LAST_MODIFICATION_TIME;
+ criteria.aSort[0].ulOrder = TABLE_SORT_ASCEND;
+ retval = SortTable(&obj_ctable, &criteria);
+ mapi_errstr("SortTable", GetLastError());
+
+ /* SeekRow at beginning */
+ retval = SeekRow(&obj_ctable, BOOKMARK_BEGINNING, 0, &count);
+ mapi_errstr("SeekRow", GetLastError());
+
+ /* Browse and print table content */
+ printf("\nAfter SortTable ASCENDING:\n");
+ while (((retval = QueryRows(&obj_ctable, count, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND) &&
+ SRowSet.cRows) {
+ count -= SRowSet.cRows;
+
+ for (i = 0; i < SRowSet.cRows; i++) {
+ printf("\t[%d] %s\n", i, SRowSet.aRow[i].lpProps[0].value.lpszA);
+ }
+ }
+
+
+ mapi_object_release(&obj_ctable);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
Added: trunk/openchange/torture/mapi_torture.h
===================================================================
--- trunk/openchange/torture/mapi_torture.h (rev 0)
+++ trunk/openchange/torture/mapi_torture.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,65 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 __MAPI_TORTURE_H__
+#define __MAPI_TORTURE_H__
+
+#include <ldb.h>
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+#ifndef MAX
+#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
+#endif
+
+__BEGIN_DECLS
+
+int samdb_msg_add_string(struct ldb_context *, TALLOC_CTX *,
+ struct ldb_message *, const char *, const char *);
+int samdb_replace(struct ldb_context *, TALLOC_CTX *, struct ldb_message *);
+struct dom_sid *dom_sid_add_rid(TALLOC_CTX *, const struct dom_sid *, uint32_t);
+bool encode_pw_buffer(uint8_t buffer[516], const char *, int);
+void arcfour_crypt_blob(uint8_t *, int, const DATA_BLOB *);
+
+__END_DECLS
+
+#define DEFAULT_PROFDB_PATH "%s/.openchange/profiles.ldb"
+
+struct test_join {
+ struct dcerpc_pipe *p;
+ struct policy_handle user_handle;
+ struct libnet_JoinDomain *libnet_r;
+ struct dom_sid *dom_sid;
+ const char *dom_netbios_name;
+ const char *dom_dns_name;
+ struct dom_sid *user_sid;
+ struct GUID user_guid;
+ const char *netbios_name;
+};
+
+
+#endif /* __MAPI_TORTURE_H__ */
Added: trunk/openchange/torture/nspi_profile.c
===================================================================
--- trunk/openchange/torture/nspi_profile.c (rev 0)
+++ trunk/openchange/torture/nspi_profile.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,278 @@
+/*
+ OpenChange NSPI torture suite implementation.
+
+ Create a MAPI profile
+
+ Copyright (C) Julien Kerihuel 2005 - 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+bool set_profile_attribute(const char *profname, struct SRowSet rowset,
+ uint32_t property, const char *attr)
+{
+ struct SPropValue *lpProp;
+ enum MAPISTATUS ret;
+
+ lpProp = get_SPropValue_SRowSet(&rowset, property);
+
+ if (!lpProp) {
+ DEBUG(0, ("MAPI Property %s not set\n", attr));
+ return true;
+ }
+
+ ret = mapi_profile_add_string_attr(profname, attr, lpProp->value.lpszA);
+
+ if (ret != MAPI_E_SUCCESS) {
+ DEBUG(0, ("Problem adding attribute %s in profile %s\n", attr, profname));
+ return false;
+ }
+ return true;
+}
+
+bool set_profile_mvstr_attribute(const char *profname, struct SRowSet rowset,
+ uint32_t property, const char *attr)
+{
+ struct SPropValue *lpProp;
+ enum MAPISTATUS ret;
+ int i;
+
+ lpProp = get_SPropValue_SRowSet(&rowset, property);
+
+ if (!lpProp) {
+ DEBUG(0, ("MAPI Property %s not set\n", attr));
+ return true;
+ }
+
+ for (i = 0; i < lpProp->value.MVszA.cValues; i++) {
+ ret = mapi_profile_add_string_attr(profname, attr, lpProp->value.MVszA.lppszA[i]);
+ if (ret != MAPI_E_SUCCESS) {
+ DEBUG(0, ("Problem adding attriute %s in profile %s\n", attr, profname));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool torture_rpc_nspi_profile(struct torture_context *torture)
+{
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ struct nspi_context *nspi;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropTagArray *MIds = NULL;
+ struct SPropTagArray MIds2;
+ struct SPropTagArray *MId_server = NULL;
+ struct StringsArray_r pNames;
+ struct Restriction_r Filter;
+ struct SRowSet *rowset;
+ struct SPropValue *lpProp;
+ const char *profname = lp_parm_string(torture->lp_ctx, NULL, "mapi", "profile");
+ const char *profdb = lp_parm_string(torture->lp_ctx, NULL, "mapi", "profile_store");
+ uint32_t codepage = lp_parm_int(torture->lp_ctx, NULL, "mapi", "codepage", 0);
+ uint32_t language = lp_parm_int(torture->lp_ctx, NULL, "mapi", "language", 0);
+ uint32_t method = lp_parm_int(torture->lp_ctx, NULL, "mapi", "method", 0);
+ const char *username = NULL;
+ uint32_t instance_key = 0;
+
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_nspi_profile");
+
+ status = torture_rpc_connection(torture, &p, &ndr_table_exchange_nsp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(mem_ctx);
+
+ return false;
+ }
+
+ /* profiles */
+ retval = MAPIInitialize(profdb);
+ mapi_errstr("MAPIInitialize", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ nspi = nspi_bind(mem_ctx, p, cmdline_credentials, codepage, language, method);
+ if (!nspi) return false;
+
+ if (profname) {
+ const char *username = cli_credentials_get_username(cmdline_credentials);
+ const char *password = cli_credentials_get_password(cmdline_credentials);
+
+ retval = CreateProfile(profname, username, password, 0);
+ mapi_errstr("CreateProfile", GetLastError());
+ if (retval != MAPI_E_SUCCESS) {
+ DEBUG(0, ("Unable to create %s profile\n", profname));
+ return false;
+ }
+ {
+ const char *workstation = cli_credentials_get_workstation(cmdline_credentials);
+ const char *domain = cli_credentials_get_domain(cmdline_credentials);
+ const char *binding = lp_parm_string(torture->lp_ctx,
+ NULL, "torture", "binding");
+ struct dcerpc_binding *dcerpc_binding;
+ char *p_codepage = talloc_asprintf(mem_ctx, "0x%x", codepage);
+ char *p_language = talloc_asprintf(mem_ctx, "0x%x", language);
+ char *p_method = talloc_asprintf(mem_ctx, "0x%x", method);
+
+ dcerpc_parse_binding(mem_ctx, binding, &dcerpc_binding);
+
+ retval = mapi_profile_add_string_attr(profname, "workstation", workstation);
+ retval = mapi_profile_add_string_attr(profname, "domain", domain);
+ retval = mapi_profile_add_string_attr(profname, "binding", dcerpc_binding->host);
+ retval = mapi_profile_add_string_attr(profname, "codepage", p_codepage);
+ retval = mapi_profile_add_string_attr(profname, "language", p_language);
+ retval = mapi_profile_add_string_attr(profname, "method", p_method);
+ }
+ }
+
+ nspi->mem_ctx = mem_ctx;
+
+ retval = nspi_GetSpecialTable(nspi, 0, &rowset);
+ mapi_errstr("NspiGetSpecialTable", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(nspi->mem_ctx, 0xc,
+ PR_DISPLAY_NAME,
+ PR_OFFICE_TELEPHONE_NUMBER,
+ PR_OFFICE_LOCATION,
+ PR_TITLE,
+ PR_COMPANY_NAME,
+ PR_ACCOUNT,
+ PR_ADDRTYPE,
+ PR_ENTRYID,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_INSTANCE_KEY,
+ PR_EMAIL_ADDRESS
+ );
+
+ /* Set the username to match */
+ username = cli_credentials_get_username(nspi->cred);
+ if (!username) return false;
+
+ /* Build the restriction we want for NspiGetMatches */
+ lpProp = talloc_zero(nspi->mem_ctx, struct SPropValue);
+ lpProp->ulPropTag = PR_ANR_UNICODE;
+ lpProp->dwAlignPad = 0;
+ lpProp->value.lpszW = username;
+
+ Filter.rt = RES_PROPERTY;
+ Filter.res.resProperty.relop = RES_PROPERTY;
+ Filter.res.resProperty.ulPropTag = PR_ANR_UNICODE;
+ Filter.res.resProperty.lpProp = lpProp;
+
+ rowset = talloc_zero(nspi->mem_ctx, struct SRowSet);
+ MIds = talloc_zero(nspi->mem_ctx, struct SPropTagArray);
+ retval = nspi_GetMatches(nspi, SPropTagArray, &Filter, &rowset, &MIds);
+ MAPIFreeBuffer(lpProp);
+ mapi_errstr("NspiGetMatches", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ lpProp = get_SPropValue_SRowSet(rowset, PR_EMAIL_ADDRESS);
+ if (lpProp) {
+ DEBUG(3, ("PR_EMAIL_ADDRESS: %s\n", lpProp->value.lpszA));
+ nspi->org = x500_get_dn_element(nspi->mem_ctx, lpProp->value.lpszA, ORG);
+ nspi->org_unit = x500_get_dn_element(nspi->mem_ctx, lpProp->value.lpszA, ORG_UNIT);
+ MAPI_RETVAL_IF(!nspi->org_unit, MAPI_E_INVALID_PARAMETER, mem_ctx);
+ MAPI_RETVAL_IF(!nspi->org, MAPI_E_INVALID_PARAMETER, mem_ctx);
+ }
+
+ if (profname) {
+ set_profile_attribute(profname, *rowset, PR_EMAIL_ADDRESS, "EmailAddress");
+ set_profile_attribute(profname, *rowset, PR_DISPLAY_NAME, "DisplayName");
+ set_profile_attribute(profname, *rowset, PR_ACCOUNT, "Account");
+ set_profile_attribute(profname, *rowset, PR_ADDRTYPE, "AddrType");
+ retval = mapi_profile_add_string_attr(profname, "Organization", nspi->org);
+ retval = mapi_profile_add_string_attr(profname, "OrganizationUnit", nspi->org_unit);
+ }
+
+ SPropTagArray = set_SPropTagArray(nspi->mem_ctx, 0x7,
+ PR_DISPLAY_NAME,
+ PR_EMAIL_ADDRESS,
+ PR_DISPLAY_TYPE,
+ PR_EMS_AB_HOME_MDB,
+ PR_ATTACH_NUM,
+ PR_PROFILE_HOME_SERVER_ADDRS,
+ PR_EMS_AB_PROXY_ADDRESSES
+ );
+
+ nspi->pStat->CurrentRec = 0x0;
+ nspi->pStat->Delta = 0x0;
+ nspi->pStat->NumPos = 0x0;
+ nspi->pStat->TotalRecs = 0x1;
+
+ instance_key = MIds->aulPropTag[0];
+ MIds2.cValues = 0x1;
+ MIds2.aulPropTag = &instance_key;
+
+ retval = nspi_QueryRows(nspi, SPropTagArray, &MIds2, 1, &rowset);
+ mapi_errstr("NspiQueryRows", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ lpProp = get_SPropValue_SRowSet(rowset, PR_EMS_AB_HOME_MDB);
+ if (lpProp) {
+ nspi->servername = x500_get_servername(lpProp->value.lpszA);
+ if (profname) {
+ mapi_profile_add_string_attr(profname, "ServerName", nspi->servername);
+ set_profile_attribute(profname, *rowset, PR_EMS_AB_HOME_MDB, "HomeMDB");
+ set_profile_mvstr_attribute(profname, *rowset, PR_EMS_AB_PROXY_ADDRESSES, "ProxyAddress");
+ }
+ } else {
+ printf("Unable to find the server name\n");
+ return -1;
+ }
+
+
+ MId_server = talloc_zero(nspi->mem_ctx, struct SPropTagArray);
+ pNames.Count = 0x1;
+ pNames.Strings = (const char **) talloc_array(nspi->mem_ctx, char **, 1);
+ pNames.Strings[0] = (const char *) talloc_asprintf(nspi->mem_ctx, SERVER_DN,
+ nspi->org, nspi->org_unit,
+ nspi->servername);
+ retval = nspi_DNToMId(nspi, &pNames, &MId_server);
+ mapi_errstr("NspiDNToMId", GetLastError());
+ MAPIFreeBuffer((char *)pNames.Strings[0]);
+ MAPIFreeBuffer((char **)pNames.Strings);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(nspi->mem_ctx, 0x2,
+ PR_EMS_AB_NETWORK_ADDRESS);
+ retval = nspi_GetProps(nspi, SPropTagArray, MId_server, &rowset);
+ mapi_errstr("NspiGetProps", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ if (profname) {
+ set_profile_mvstr_attribute(profname, *rowset, PR_EMS_AB_NETWORK_ADDRESS, "NetworkAddress");
+ }
+
+ retval = nspi_unbind(nspi);
+ mapi_errstr("NspiUnbind", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ MAPIUninitialize();
+
+ talloc_free(mem_ctx);
+
+ return true;
+}
Added: trunk/openchange/torture/nspi_resolvenames.c
===================================================================
--- trunk/openchange/torture/nspi_resolvenames.c (rev 0)
+++ trunk/openchange/torture/nspi_resolvenames.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,139 @@
+/*
+ OpenChange MAPI torture suite implementation.
+
+ Query the WAB and attempts to resolve the given names
+
+ Copyright (C) Julien Kerihuel 2007.
+
+ 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 <gen_ndr/ndr_exchange.h>
+#include <param.h>
+#include <credentials.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <samba/popt.h>
+
+bool torture_rpc_nspi_resolvenames(struct torture_context *torture)
+{
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_session *session;
+ bool ret = true;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet *rowset = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ const char *profdb;
+ char *profname;
+ const char *username = lp_parm_string(torture->lp_ctx, NULL, "exchange", "resolvename");
+ const char *password = lp_parm_string(torture->lp_ctx, NULL, "mapi", "password");
+ uint32_t unicode = lp_parm_int(torture->lp_ctx, NULL, "mapi", "unicode", 0);
+ char *tmp;
+ char **usernames;
+ int j;
+
+ mem_ctx = talloc_named(NULL, 0, "torture_rpc_nspi_resolvenames");
+
+ if (!username) {
+ DEBUG(0,("Specify the usernames to resolve with exchange:resolvename\n"));
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ status = torture_rpc_connection(torture, &p, &ndr_table_exchange_nsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* init mapi */
+ profdb = lp_parm_string(torture->lp_ctx, NULL, "mapi", "profile_store");
+ if (!profdb) {
+ profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB_PATH, getenv("HOME"));
+ if (!profdb) {
+ DEBUG(0, ("Specify a valie MAPI profile store\n"));
+ return false;
+ }
+ }
+ retval = MAPIInitialize(profdb);
+ mapi_errstr("MAPIInitialize", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* profile name */
+ profname = talloc_strdup(mem_ctx, lp_parm_string(torture->lp_ctx, NULL, "mapi", "profile"));
+ if (!profname) {
+ retval = GetDefaultProfile(&profname);
+ if (retval != MAPI_E_SUCCESS) {
+ DEBUG(0, ("Please specify a valid profile name\n"));
+ return false;
+ }
+ }
+
+ retval = MapiLogonProvider(&session, profname, password, PROVIDER_ID_NSPI);
+ talloc_free(profname);
+ mapi_errstr("MapiLogonProvider", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0xd,
+ PR_ENTRYID,
+ PR_DISPLAY_NAME,
+ PR_ADDRTYPE,
+ PR_GIVEN_NAME,
+ PR_SMTP_ADDRESS,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_EMAIL_ADDRESS,
+ PR_SEND_INTERNET_ENCODING,
+ PR_SEND_RICH_INFO,
+ PR_SEARCH_KEY,
+ PR_TRANSMITTABLE_DISPLAY_NAME,
+ PR_7BIT_DISPLAY_NAME);
+
+ if ((tmp = strtok((char *)username, ",")) == NULL){
+ DEBUG(2, ("Invalid usernames string format\n"));
+ exit (1);
+ }
+
+ usernames = talloc_array(mem_ctx, char *, 2);
+ usernames[0] = strdup(tmp);
+
+ for (j = 1; (tmp = strtok(NULL, ",")) != NULL; j++) {
+ usernames = talloc_realloc(mem_ctx, usernames, char *, j+2);
+ usernames[j] = strdup(tmp);
+ }
+ usernames[j] = 0;
+
+ retval = ResolveNames(session, (const char **)usernames, SPropTagArray, &rowset, &flaglist, unicode?MAPI_UNICODE:0);
+ mapi_errstr("ResolveNames", GetLastError());
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapidump_Recipients((const char **)usernames, rowset, flaglist);
+
+ retval = MAPIFreeBuffer(rowset);
+ mapi_errstr("MAPIFreeBuffer: rowset", GetLastError());
+
+ retval = MAPIFreeBuffer(flaglist);
+ mapi_errstr("MAPIFreeBuffer: flaglist", GetLastError());
+
+ MAPIUninitialize();
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
Added: trunk/openchange/torture/openchange.c
===================================================================
--- trunk/openchange/torture/openchange.c (rev 0)
+++ trunk/openchange/torture/openchange.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,127 @@
+/*
+ Unix EMSMDB implementation
+
+ Test suite for OpenChange
+
+ 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 <samba/popt.h>
+#include <torture/mapi_torture.h>
+#include <torture.h>
+#include <torture/torture_proto.h>
+#include <smbtorture.h>
+
+NTSTATUS ndr_table_init(void);
+
+NTSTATUS samba_init_module(void)
+{
+ struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "OPENCHANGE");
+
+ ndr_table_init();
+
+ DEBUG(0, ("Loading openchange torture test\n"));
+
+ /* OpenChange torture tests */
+ /* Address Book name resolution */
+ torture_suite_add_simple_test(suite, "NSPI-PROFILE", torture_rpc_nspi_profile);
+ torture_suite_add_simple_test(suite, "NSPI-RESOLVENAMES", torture_rpc_nspi_resolvenames);
+ /* MAPI mail torture tests */
+ torture_suite_add_simple_test(suite, "MAPI-FETCHMAIL", torture_rpc_mapi_fetchmail);
+ torture_suite_add_simple_test(suite, "MAPI-FETCHATTACH", torture_rpc_mapi_fetchattach);
+ torture_suite_add_simple_test(suite, "MAPI-SENDMAIL", torture_rpc_mapi_sendmail);
+ torture_suite_add_simple_test(suite, "MAPI-SENDMAIL-HTML", torture_rpc_mapi_sendmail_html);
+ torture_suite_add_simple_test(suite, "MAPI-SENDATTACH", torture_rpc_mapi_sendattach);
+ torture_suite_add_simple_test(suite, "MAPI-DELETEMAIL", torture_rpc_mapi_deletemail);
+ torture_suite_add_simple_test(suite, "MAPI-NEWMAIL", torture_rpc_mapi_newmail);
+ torture_suite_add_simple_test(suite, "MAPI-COPYMAIL", torture_rpc_mapi_copymail);
+ /* MAPI calendar torture tests */
+ torture_suite_add_simple_test(suite, "MAPI-FETCHAPPOINTMENT", torture_rpc_mapi_fetchappointment);
+ torture_suite_add_simple_test(suite, "MAPI-SENDAPPOINTMENT", torture_rpc_mapi_sendappointment);
+ torture_suite_add_simple_test(suite, "MAPI-FETCHCONTACTS", torture_rpc_mapi_fetchcontacts);
+ torture_suite_add_simple_test(suite, "MAPI-SENDCONTACTS", torture_rpc_mapi_sendcontacts);
+ torture_suite_add_simple_test(suite, "MAPI-FETCHTASKS", torture_rpc_mapi_fetchtasks);
+ torture_suite_add_simple_test(suite, "MAPI-SENDTASKS", torture_rpc_mapi_sendtasks);
+ /* MAPI object torture tests */
+ torture_suite_add_simple_test(suite, "MAPI-ACLS", torture_rpc_mapi_permissions);
+ torture_suite_add_simple_test(suite, "MAPI-RESTRICTIONS", torture_rpc_mapi_restrictions);
+ torture_suite_add_simple_test(suite, "MAPI-CRITERIA", torture_rpc_mapi_criteria);
+ torture_suite_add_simple_test(suite, "MAPI-SORTTABLE", torture_rpc_mapi_sorttable);
+ torture_suite_add_simple_test(suite, "MAPI-BOOKMARK", torture_rpc_mapi_bookmark);
+ torture_suite_add_simple_test(suite, "MAPI-RECIPIENT", torture_rpc_mapi_recipient);
+ torture_suite_add_simple_test(suite, "MAPI-NAMEDPROPS", torture_rpc_mapi_namedprops);
+ /* Exchange Administration torture tests */
+ torture_suite_add_simple_test(suite, "EXCHANGE-CREATEUSER", torture_mapi_createuser);
+
+ suite->description = talloc_strdup(suite, "Exchange protocols tests (NSPI and EMSMDB)");
+
+ torture_register_suite(suite);
+ return NT_STATUS_OK;
+}
+
+/**
+ * Obtain the DCE/RPC binding context associated with a torture context.
+ *
+ * @param tctx Torture context
+ * @param binding Pointer to store DCE/RPC binding
+ */
+NTSTATUS torture_rpc_binding(struct torture_context *tctx,
+ struct dcerpc_binding **binding)
+{
+ NTSTATUS status;
+ const char *binding_string = torture_setting_string(tctx, "binding",
+ NULL);
+
+ if (binding_string == NULL) {
+ torture_comment(tctx,
+ "You must specify a DCE/RPC binding string\n");
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ status = dcerpc_parse_binding(tctx, binding_string, binding);
+ if (NT_STATUS_IS_ERR(status)) {
+ DEBUG(0,("Failed to parse dcerpc binding '%s'\n",
+ binding_string));
+ return status;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/**
+ * open a rpc connection to the chosen binding string
+ */
+_PUBLIC_ NTSTATUS torture_rpc_connection(struct torture_context *tctx,
+ struct dcerpc_pipe **p,
+ const struct ndr_interface_table *table)
+{
+ NTSTATUS status;
+ struct dcerpc_binding *binding;
+
+ status = torture_rpc_binding(tctx, &binding);
+ if (NT_STATUS_IS_ERR(status))
+ return status;
+
+ status = dcerpc_pipe_connect_b(tctx,
+ p, binding, table,
+ cmdline_credentials, NULL, tctx->lp_ctx);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ printf("Failed to connect to remote server: %s %s\n",
+ dcerpc_binding_string(tctx, binding), nt_errstr(status));
+ }
+
+ return status;
+}
Added: trunk/openchange/utils/backup/openchangebackup.c
===================================================================
--- trunk/openchange/utils/backup/openchangebackup.c (rev 0)
+++ trunk/openchange/utils/backup/openchangebackup.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,317 @@
+/*
+ MAPI Backup application suite
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2007
+
+ 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 "openchangebackup.h"
+#include <libmapi/defs_private.h>
+
+/**
+ * Initialize OCB (OpenChange Backup) subsystem
+ * and open a pointer on the LDB database
+ */
+struct ocb_context *ocb_init(TALLOC_CTX *mem_ctx, const char *dbpath)
+{
+ struct ocb_context *ocb_ctx = NULL;
+ char *url = NULL;
+ int ret;
+ struct tevent_context *ev;
+
+ /* sanity check */
+ OCB_RETVAL_IF_CODE(!mem_ctx, "invalid memory context", NULL, NULL);
+ OCB_RETVAL_IF_CODE(!dbpath, "dbpath not set", NULL, NULL);
+
+ ocb_ctx = talloc_zero(mem_ctx, struct ocb_context);
+
+ ev = tevent_context_init(ocb_ctx);
+ if (!ev) goto failed;
+
+ /* init ldb store */
+ ocb_ctx->ldb_ctx = ldb_init((TALLOC_CTX *)ocb_ctx, ev);
+ if (!ocb_ctx->ldb_ctx) goto failed;
+
+ url = talloc_asprintf(mem_ctx, "tdb://%s", dbpath);
+ ret = ldb_connect(ocb_ctx->ldb_ctx, url, 0, NULL);
+ talloc_free(url);
+ if (ret != LDB_SUCCESS) goto failed;
+
+ return ocb_ctx;
+failed:
+ ocb_release(ocb_ctx);
+ return NULL;
+}
+
+/**
+ * Release OCB subsystem
+ */
+uint32_t ocb_release(struct ocb_context *ocb_ctx)
+{
+ OCB_RETVAL_IF(!ocb_ctx, "subsystem not initialized\n", NULL);
+ talloc_free(ocb_ctx);
+
+ return 0;
+}
+
+/**
+ * init and prepare a record
+ */
+
+int ocb_record_init(struct ocb_context *ocb_ctx, const char *objclass, const char *dn,
+ const char *id, struct mapi_SPropValue_array *props)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_context *ldb_ctx;
+ struct ldb_result *res;
+ enum ldb_scope scope = LDB_SCOPE_SUBTREE;
+ struct ldb_dn *basedn;
+ int ret;
+ const char * const attrs[] = { "*", NULL };
+
+ /* sanity check */
+ OCB_RETVAL_IF(!ocb_ctx, "Subsystem not initialized", NULL);
+ OCB_RETVAL_IF(!dn, "Not a valid DN", NULL);
+ OCB_RETVAL_IF(!id, "Not a valid ID", NULL);
+
+ mem_ctx = (TALLOC_CTX *)ocb_ctx;
+ ldb_ctx = ocb_ctx->ldb_ctx;
+
+ /* Check if the record already exists */
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx), scope, attrs, dn);
+ OCB_RETVAL_IF(res->msgs, "Record already exists", NULL);
+
+ /* Retrieve the record basedn */
+ basedn = ldb_dn_new(ldb_ctx, ldb_ctx, dn);
+ OCB_RETVAL_IF(!ldb_dn_validate(basedn), "Invalid DN", NULL);
+
+ ocb_ctx->msg = ldb_msg_new(mem_ctx);
+ ocb_ctx->msg->dn = ldb_dn_copy(mem_ctx, basedn);
+
+ /* add records for cn */
+ ldb_msg_add_string(ocb_ctx->msg, "cn", id);
+
+ /* add filters attributes */
+ ldb_msg_add_string(ocb_ctx->msg, "objectClass", objclass);
+
+ talloc_free(basedn);
+
+ return 0;
+}
+
+
+/**
+ * Commit the record with all its attributes: single transaction
+ */
+uint32_t ocb_record_commit(struct ocb_context *ocb_ctx)
+{
+ int ret;
+
+ /* sanity checks */
+ OCB_RETVAL_IF(!ocb_ctx, "Subsystem not initialized", NULL);
+ OCB_RETVAL_IF(!ocb_ctx->ldb_ctx, "LDB context not initialized", NULL);
+ OCB_RETVAL_IF(!ocb_ctx->msg, "Message not initialized", NULL);
+
+ ret = ldb_add(ocb_ctx->ldb_ctx, ocb_ctx->msg);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(3, ("LDB operation failed: %s\n", ldb_errstring(ocb_ctx->ldb_ctx)));
+ return -1;
+ }
+
+ talloc_free(ocb_ctx->msg);
+
+ return 0;
+}
+
+
+/**
+ * Add a property (attr, value) couple to the current record
+ */
+uint32_t ocb_record_add_property(struct ocb_context *ocb_ctx,
+ struct mapi_SPropValue *lpProp)
+{
+ TALLOC_CTX *mem_ctx;
+ int i;
+ char *attr;
+ char *value = NULL;
+ const char *tag;
+
+ /* sanity checks */
+ OCB_RETVAL_IF(!ocb_ctx, "Subsystem not initialized", NULL);
+ OCB_RETVAL_IF(!ocb_ctx->ldb_ctx, "LDB context not initialized", NULL);
+ OCB_RETVAL_IF(!ocb_ctx->msg, "Message not initialized", NULL);
+
+ mem_ctx = (TALLOC_CTX *)ocb_ctx->msg;
+
+ tag = get_proptag_name(lpProp->ulPropTag);
+ if (tag) {
+ attr = talloc_asprintf(mem_ctx, "%s", tag);
+ } else {
+ attr = talloc_asprintf(mem_ctx, "PR-x%.8x", lpProp->ulPropTag);
+ }
+
+ for (i = 0; attr[i]; i++) {
+ if (attr[i] == '_') attr[i] = '-';
+ }
+
+ switch (lpProp->ulPropTag & 0xFFFF) {
+ case PT_SHORT:
+ ldb_msg_add_fmt(ocb_ctx->msg, attr, "%hd", lpProp->value.i);
+ break;
+ case PT_STRING8:
+ ldb_msg_add_string(ocb_ctx->msg, attr, lpProp->value.lpszA);
+ break;
+ case PT_UNICODE:
+ ldb_msg_add_string(ocb_ctx->msg, attr, lpProp->value.lpszW);
+ break;
+ case PT_ERROR: /* We shouldn't need to backup error properties */
+ return 0;
+ case PT_LONG:
+ ldb_msg_add_fmt(ocb_ctx->msg, attr, "%d", lpProp->value.l);
+ break;
+ case PT_BOOLEAN:
+ ldb_msg_add_fmt(ocb_ctx->msg, attr, "%s",
+ ((lpProp->value.b == true) ? "true" : "false"));
+ break;
+ case PT_I8:
+ ldb_msg_add_fmt(ocb_ctx->msg, attr, "%16"PRIx64, lpProp->value.d);
+ break;
+ case PT_SYSTIME:
+ value = ocb_ldb_timestring(mem_ctx, &lpProp->value.ft);
+ ldb_msg_add_string(ocb_ctx->msg, attr, value);
+ break;
+ case 0xFB:
+ case PT_BINARY:
+ if (lpProp->value.bin.cb) {
+ value = ldb_base64_encode(mem_ctx, (char *)lpProp->value.bin.lpb,
+ lpProp->value.bin.cb);
+ ldb_msg_add_string(ocb_ctx->msg, attr, value);
+ }
+ break;
+ case PT_MV_LONG:
+ for (i = 0; i < lpProp->value.MVl.cValues; i++) {
+ ldb_msg_add_fmt(ocb_ctx->msg, attr, "%d",
+ lpProp->value.MVl.lpl[i]);
+ }
+ break;
+ case PT_MV_BINARY:
+ for (i = 0; i < lpProp->value.MVbin.cValues; i++) {
+ struct SBinary_short bin;
+
+ bin = lpProp->value.MVbin.bin[i];
+ if (bin.cb) {
+ value = ldb_base64_encode(mem_ctx, (char *)bin.lpb, bin.cb);
+ ldb_msg_add_string(ocb_ctx->msg, attr, value);
+ }
+ }
+ break;
+ case PT_MV_STRING8:
+ for (i = 0; i < lpProp->value.MVszA.cValues; i++) {
+ ldb_msg_add_string(ocb_ctx->msg, attr,
+ lpProp->value.MVszA.strings[i].lppszA);
+ }
+ break;
+ default:
+ printf("%s case %d not supported\n", attr, lpProp->ulPropTag & 0xFFFF);
+ break;
+ }
+
+ talloc_free(attr);
+ return 0;
+}
+
+/**
+ * Retrieve UUID from Sbinary_short struct
+ * Generally used to map PR_STORE_KEY to a string
+ * Used for attachments
+ */
+char *get_record_uuid(TALLOC_CTX *mem_ctx, const struct SBinary_short *bin)
+{
+ uint32_t i;
+ char *lpb;
+
+ OCB_RETVAL_IF_CODE(!bin, "Invalid PR_RECORD_KEY val", NULL, NULL);
+ lpb = talloc_asprintf(mem_ctx, "%.2X", bin->lpb[0]);
+ for (i = 1; i < bin->cb; i++) {
+ lpb = talloc_asprintf_append(lpb, "%.2X", bin->lpb[i]);
+ }
+
+ return lpb;
+}
+
+
+/**
+ * Extract MAPI object unique ID from PR_SOURCE_KEY Sbinary_short data:
+ * PR_SOURCE_KEY = 22 bytes field
+ * - 16 first bytes = MAPI Store GUID
+ * - 6 last bytes = MAPI object unique ID
+ */
+char *get_MAPI_uuid(TALLOC_CTX *mem_ctx, const struct SBinary_short *bin)
+{
+ uint32_t i;
+ char *ab;
+
+ OCB_RETVAL_IF_CODE(!bin || bin->cb != 22, "Invalid SBinary", NULL, NULL);
+
+ ab = talloc_asprintf(mem_ctx, "%.2X", bin->lpb[16]);
+ for (i = 17; i < bin->cb; i++) {
+ ab = talloc_asprintf_append(ab, "%.2X", bin->lpb[i]);
+ }
+
+ return ab;
+}
+
+
+/**
+ * Retrieve the store GUID from a given record.
+ * This GUID should be unique for each store and identical for all
+ * objects belonging to this store
+ */
+char *get_MAPI_store_guid(TALLOC_CTX *mem_ctx, const struct SBinary_short *bin)
+{
+ int i;
+ char *ab;
+
+ OCB_RETVAL_IF_CODE(!bin || bin->cb != 22, "Invalid SBinary", NULL, NULL);
+
+ ab = talloc_asprintf(mem_ctx, "%.2X", bin->lpb[0]);
+ for (i = 1; i < 16; i++) {
+ ab = talloc_asprintf_append(ab, "%.2X", bin->lpb[i]);
+ }
+
+ return ab;
+}
+
+
+/**
+ * Convert date from MAPI property to ldb format
+ * Easier to manipulate
+ */
+char *ocb_ldb_timestring(TALLOC_CTX *mem_ctx, struct FILETIME *ft)
+{
+ NTTIME time;
+ time_t t;
+
+ OCB_RETVAL_IF_CODE(!ft, "Invalid FILTIME", NULL, NULL);
+
+ time = ft->dwHighDateTime;
+ time = time << 32;
+ time |= ft->dwLowDateTime;
+
+ t = nt_time_to_unix(time);
+ return ldb_timestring(mem_ctx, t);
+}
Added: trunk/openchange/utils/backup/openchangebackup.h
===================================================================
--- trunk/openchange/utils/backup/openchangebackup.h (rev 0)
+++ trunk/openchange/utils/backup/openchangebackup.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,97 @@
+/*
+ MAPI Backup application suite
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2007
+
+ 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 __OPENCHANGEBACKUP_H__
+#define __OPENCHANGEBACKUP_H__
+
+#include <libmapi/libmapi.h>
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/* Samba4 includes */
+#include <util.h>
+#include <talloc.h>
+#include <ldb_errors.h>
+#include <ldb.h>
+
+/* Data structures */
+
+struct ocb_context {
+ struct ldb_context *ldb_ctx; /* ldb database context */
+ struct ldb_message *msg; /* pointer on record msg */
+};
+
+/* Prototypes */
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+__BEGIN_DECLS
+struct ocb_context *ocb_init(TALLOC_CTX *, const char *);
+uint32_t ocb_release(struct ocb_context *);
+
+int ocb_record_init(struct ocb_context *, const char *,
+ const char *, const char *, struct mapi_SPropValue_array *);
+uint32_t ocb_record_commit(struct ocb_context *);
+uint32_t ocb_record_add_property(struct ocb_context *, struct mapi_SPropValue *);
+
+char *get_record_uuid(TALLOC_CTX *, const struct SBinary_short *);
+char *get_MAPI_uuid(TALLOC_CTX *, const struct SBinary_short *);
+char *get_MAPI_store_guid(TALLOC_CTX *, const struct SBinary_short *);
+char *ocb_ldb_timestring(TALLOC_CTX *, struct FILETIME *);
+__END_DECLS
+
+#define OCB_RETVAL_IF_CODE(x, m, c, r) \
+do { \
+ if (x) { \
+ DEBUG(3, ("[OCB] %s\n", m)); \
+ if (c) { \
+ talloc_free(c); \
+ } \
+ return r; \
+ } \
+} while (0);
+
+#define OCB_RETVAL_IF(x, m, c) OCB_RETVAL_IF_CODE(x, m, c, -1)
+
+
+#define DEFAULT_PROFDB "%s/.openchange/profiles.ldb"
+#define DEFAULT_OCBCONF "%s/.openchange/openchangebackup.conf"
+#define DEFAULT_OCBDB "%s/.openchange/openchangebackup_%s.ldb"
+
+/* objectClass */
+#define OCB_OBJCLASS_CONTAINER "container"
+#define OCB_OBJCLASS_MESSAGE "message"
+#define OCB_OBJCLASS_ATTACHMENT "attachment"
+
+#endif /* __OPENCHANGEBACKUP_H__ */
Added: trunk/openchange/utils/backup/openchangemapidump.c
===================================================================
--- trunk/openchange/utils/backup/openchangemapidump.c (rev 0)
+++ trunk/openchange/utils/backup/openchangemapidump.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,474 @@
+/*
+ MAPI Backup application suite
+ Dump a Mailbox store in a database
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2007
+
+ 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 <samba/popt.h>
+#include <param.h>
+
+#include "openchangebackup.h"
+#include <utils/openchange-tools.h>
+
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <time.h>
+
+/**
+ * write attachment to the database
+ */
+static enum MAPISTATUS mapidump_write_attachment(struct ocb_context *ocb_ctx,
+ struct mapi_SPropValue_array *props,
+ const char *contentdn,
+ const char *uuid)
+{
+ int ret;
+ uint32_t i;
+
+ ret = ocb_record_init(ocb_ctx, OCB_OBJCLASS_ATTACHMENT, contentdn, uuid, props);
+ if (ret == -1) return MAPI_E_SUCCESS;
+ for (i = 0; i < props->cValues; i++) {
+ ret = ocb_record_add_property(ocb_ctx, &props->lpProps[i]);
+ }
+ ret = ocb_record_commit(ocb_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * write message to the database (email, appointment, contact, task, note etc.)
+ */
+static enum MAPISTATUS mapidump_write_message(struct ocb_context *ocb_ctx,
+ struct mapi_SPropValue_array *props,
+ const char *contentdn,
+ const char *uuid)
+{
+ int ret;
+ uint32_t i;
+
+ ret = ocb_record_init(ocb_ctx, OCB_OBJCLASS_MESSAGE, contentdn, uuid, props);
+ if (ret == -1) return MAPI_E_SUCCESS;
+ for (i = 0; i < props->cValues; i++) {
+ ret = ocb_record_add_property(ocb_ctx, &props->lpProps[i]);
+ }
+ ret = ocb_record_commit(ocb_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * write containers to the database (folders)
+ */
+static enum MAPISTATUS mapidump_write_container(struct ocb_context *ocb_ctx,
+ struct mapi_SPropValue_array *props,
+ const char *containerdn,
+ const char *uuid)
+{
+ int ret;
+ uint32_t i;
+
+ ret = ocb_record_init(ocb_ctx, OCB_OBJCLASS_CONTAINER, containerdn, uuid, props);
+ if (ret == -1) return MAPI_E_SUCCESS;
+ for (i = 0; i < props->cValues; i++) {
+ ret = ocb_record_add_property(ocb_ctx, &props->lpProps[i]);
+ }
+ ret = ocb_record_commit(ocb_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * Retrieve all the attachments for a given message
+ */
+static enum MAPISTATUS mapidump_walk_attachment(TALLOC_CTX *mem_ctx,
+ struct ocb_context *ocb_ctx,
+ mapi_object_t *obj_message,
+ const char *messagedn)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet rowset;
+ struct mapi_SPropValue_array props;
+ mapi_object_t obj_atable;
+ mapi_object_t obj_attach;
+ uint32_t Numerator = 0;
+ uint32_t Denominator = 0;
+ uint32_t i;
+ const uint32_t *attach_num;
+ const struct SBinary_short *sbin;
+ char *uuid;
+ char *contentdn;
+
+ /* Get attachment table */
+ mapi_object_init(&obj_atable);
+ retval = GetAttachmentTable(obj_message, &obj_atable);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ /* Customize the table view */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_ATTACH_NUM);
+ retval = SetColumns(&obj_atable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ /* Walk through the table */
+ retval = QueryPosition(&obj_atable, &Numerator, &Denominator);
+
+ while ((retval = QueryRows(&obj_atable, Denominator, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND && rowset.cRows) {
+ for (i = 0; i < rowset.cRows; i++) {
+ attach_num = (const uint32_t *)find_SPropValue_data(&(rowset.aRow[i]), PR_ATTACH_NUM);
+ /* Open attachment */
+ mapi_object_init(&obj_attach);
+ retval = OpenAttach(obj_message, *attach_num, &obj_attach);
+ if (retval == MAPI_E_SUCCESS) {
+ retval = GetPropsAll(&obj_attach, &props);
+ if (retval == MAPI_E_SUCCESS) {
+ /* extract unique identifier from PR_RECORD_KEY */
+ sbin = (const struct SBinary_short *)find_mapi_SPropValue_data(&props, PR_RECORD_KEY);
+ uuid = get_record_uuid(mem_ctx, sbin);
+ contentdn = talloc_asprintf(mem_ctx, "cn=%s,%s", uuid, messagedn);
+ mapidump_write_attachment(ocb_ctx, &props, contentdn, uuid);
+
+ /* free allocated strings */
+ talloc_free(uuid);
+ talloc_free(contentdn);
+ }
+ }
+ mapi_object_release(&obj_attach);
+ }
+ }
+
+ mapi_object_release(&obj_atable);
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * Retrieve all the content within a folder
+ */
+static enum MAPISTATUS mapidump_walk_content(TALLOC_CTX *mem_ctx,
+ struct ocb_context *ocb_ctx,
+ mapi_object_t *obj_folder,
+ const char *containerdn)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray;
+ struct mapi_SPropValue_array props;
+ struct SRowSet rowset;
+ mapi_object_t obj_ctable;
+ mapi_object_t obj_message;
+ uint32_t count = 0;
+ uint32_t i;
+ const mapi_id_t *fid;
+ const mapi_id_t *mid;
+ char *uuid;
+ const struct SBinary_short *sbin;
+ const uint8_t *has_attach;
+ char *contentdn;
+
+ /* Get Contents Table */
+ mapi_object_init(&obj_ctable);
+ retval = GetContentsTable(obj_folder, &obj_ctable, 0, &count);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ /* Customize the table view */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT);
+ retval = SetColumns(&obj_ctable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ while ((retval = QueryRows(&obj_ctable, count, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND && rowset.cRows) {
+ for (i = 0; i < rowset.cRows; i++) {
+ mapi_object_init(&obj_message);
+ fid = (const uint64_t *) get_SPropValue_SRow_data(&rowset.aRow[i], PR_FID);
+ mid = (const uint64_t *) get_SPropValue_SRow_data(&rowset.aRow[i], PR_MID);
+ /* Open Message */
+ retval = OpenMessage(obj_folder, *fid, *mid, &obj_message, 0);
+ if (GetLastError() == MAPI_E_SUCCESS) {
+ retval = GetPropsAll(&obj_message, &props);
+ if (GetLastError() == MAPI_E_SUCCESS) {
+ /* extract unique identifier from PR_SOURCE_KEY */
+ sbin = (const struct SBinary_short *)find_mapi_SPropValue_data(&props, PR_SOURCE_KEY);
+ uuid = get_MAPI_uuid(mem_ctx, sbin);
+ contentdn = talloc_asprintf(mem_ctx, "cn=%s,%s", uuid, containerdn);
+ mapidump_write_message(ocb_ctx, &props, contentdn, uuid);
+
+ /* If Message has attachments then process them */
+ has_attach = (const uint8_t *)find_mapi_SPropValue_data(&props, PR_HASATTACH);
+ if (has_attach && *has_attach) {
+ mapidump_walk_attachment(mem_ctx, ocb_ctx, &obj_message, contentdn);
+ }
+
+ /* free allocated strings */
+ talloc_free(uuid);
+ talloc_free(contentdn);
+ }
+ }
+ mapi_object_release(&obj_message);
+ }
+ }
+
+ mapi_object_release(&obj_ctable);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ * Recursively retrieve folders
+ */
+static enum MAPISTATUS mapidump_walk_container(TALLOC_CTX *mem_ctx,
+ struct ocb_context *ocb_ctx,
+ mapi_object_t *obj_parent,
+ mapi_id_t folder_id,
+ char *parentdn,
+ int count)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet rowset;
+ struct mapi_SPropValue_array props;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_htable;
+ const uint32_t *child_content;
+ const uint32_t *child_folder;
+ char *containerdn;
+ char *uuid;
+ const mapi_id_t *fid;
+ uint32_t rcount;
+ uint32_t i;
+ const struct SBinary_short *sbin;
+
+ /* Open folder */
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(obj_parent, folder_id, &obj_folder);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ /* Retrieve all its properties */
+ retval = GetPropsAll(&obj_folder, &props);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+ child_content = (const uint32_t *)find_mapi_SPropValue_data(&props, PR_CONTENT_COUNT);
+ child_folder = (const uint32_t *)find_mapi_SPropValue_data(&props, PR_FOLDER_CHILD_COUNT);
+
+ /* extract unique identifier from PR_SOURCE_KEY */
+ sbin = (const struct SBinary_short *)find_mapi_SPropValue_data(&props, PR_SOURCE_KEY);
+ uuid = get_MAPI_uuid(mem_ctx, sbin);
+
+ if (parentdn == NULL && count == 0) {
+ parentdn = talloc_asprintf(mem_ctx, "cn=%s",
+ get_MAPI_store_guid(mem_ctx, sbin));
+ }
+
+ containerdn = talloc_asprintf(mem_ctx, "cn=%s,%s", uuid, parentdn);
+
+ /* Write entry for container */
+ mapidump_write_container(ocb_ctx, &props, containerdn, uuid);
+ talloc_free(uuid);
+
+ /* Get Contents Table if PR_CONTENT_COUNT >= 1 */
+ if (child_content && *child_content >= 1) {
+ retval = mapidump_walk_content(mem_ctx, ocb_ctx, &obj_folder, containerdn);
+ }
+
+ /* Get Container Table if PR_FOLDER_CHILD_COUNT >= 1 */
+
+ if (child_folder && *child_folder >= 1) {
+ mapi_object_init(&obj_htable);
+ retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, &rcount);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x3,
+ PR_FID,
+ PR_CONTENT_COUNT,
+ PR_FOLDER_CHILD_COUNT);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ while ((retval = QueryRows(&obj_htable, rcount, TBL_ADVANCE, &rowset) != MAPI_E_NOT_FOUND) && rowset.cRows) {
+ for (i = 0; i < rowset.cRows; i++) {
+ fid = (const uint64_t *)find_SPropValue_data(&rowset.aRow[i], PR_FID);
+ retval = mapidump_walk_container(mem_ctx, ocb_ctx, &obj_folder, *fid, containerdn, count + 1);
+ }
+ }
+ }
+
+ talloc_free(containerdn);
+ mapi_object_release(&obj_folder);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * Walk through known mapi folders
+ */
+
+static enum MAPISTATUS mapidump_walk(TALLOC_CTX *mem_ctx,
+ struct ocb_context *ocb_ctx,
+ mapi_object_t *obj_store)
+{
+ enum MAPISTATUS retval;
+ mapi_id_t id_mailbox;
+
+ retval = GetDefaultFolder(obj_store, &id_mailbox,
+ olFolderTopInformationStore);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ return mapidump_walk_container(mem_ctx, ocb_ctx, obj_store, id_mailbox, NULL, 0);
+}
+
+
+int main(int argc, const char *argv[])
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct ocb_context *ocb_ctx = NULL;
+ struct mapi_session *session = NULL;
+ mapi_object_t obj_store;
+ poptContext pc;
+ int opt;
+ /* command line options */
+ const char *opt_profdb = NULL;
+ char *opt_profname = NULL;
+ const char *opt_password = NULL;
+ const char *opt_config = NULL;
+ const char *opt_backupdb = NULL;
+ const char *opt_debug = NULL;
+ bool opt_dumpdata = false;
+
+ enum {OPT_PROFILE_DB=1000, OPT_PROFILE, OPT_PASSWORD,
+ OPT_MAILBOX, OPT_CONFIG, OPT_BACKUPDB, OPT_PF,
+ OPT_DEBUG, OPT_DUMPDATA};
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ {"database", 'f', POPT_ARG_STRING, NULL, OPT_PROFILE_DB, "set the profile database path", NULL},
+ {"profile", 'p', POPT_ARG_STRING, NULL, OPT_PROFILE, "set the profile name", NULL},
+ {"password", 'P', POPT_ARG_STRING, NULL, OPT_PASSWORD, "set the profile password", NULL},
+ {"config", 'c', POPT_ARG_STRING, NULL, OPT_CONFIG, "set openchangebackup configuration file path", NULL},
+ {"backup-db", 'b', POPT_ARG_STRING, NULL, OPT_BACKUPDB, "set the openchangebackup store path", NULL},
+ {"debuglevel", 0, POPT_ARG_STRING, NULL, OPT_DEBUG, "set the debug level", NULL},
+ {"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMPDATA, "dump the hex data", NULL},
+ POPT_OPENCHANGE_VERSION
+ { NULL, 0, 0, NULL, 0, NULL, NULL }
+ };
+
+ mem_ctx = talloc_named(NULL, 0, "openchangemapidump");
+
+ pc = poptGetContext("openchangemapidump", argc, argv, long_options, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_DEBUG:
+ opt_debug = poptGetOptArg(pc);
+ break;
+ case OPT_DUMPDATA:
+ opt_dumpdata = true;
+ break;
+ 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_CONFIG:
+ opt_config = poptGetOptArg(pc);
+ break;
+ case OPT_BACKUPDB:
+ opt_backupdb = poptGetOptArg(pc);
+ break;
+ }
+ }
+
+ /* Sanity check on options */
+ if (!opt_profdb) {
+ opt_profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, getenv("HOME"));
+ }
+
+ /* Initialize MAPI subsystem */
+ retval = MAPIInitialize(opt_profdb);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ /* debug options */
+ SetMAPIDumpData(opt_dumpdata);
+
+ if (opt_debug) {
+ SetMAPIDebugLevel(atoi(opt_debug));
+ }
+
+ /* If no profile is specified try to load the default one from
+ * the database
+ */
+ if (!opt_profname) {
+ retval = GetDefaultProfile(&opt_profname);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("GetDefaultProfile", GetLastError());
+ exit (1);
+ }
+ }
+
+ if (!opt_backupdb) {
+ opt_backupdb = talloc_asprintf(mem_ctx, DEFAULT_OCBDB,
+ getenv("HOME"),
+ opt_profname);
+ }
+
+ /* Initialize OpenChange Backup subsystem */
+ if (!(ocb_ctx = ocb_init(mem_ctx, opt_backupdb))) {
+ talloc_free(mem_ctx);
+ exit(-1);
+ }
+
+ /* We only need to log on EMSMDB to backup Mailbox store or Public Folders */
+ retval = MapiLogonProvider(&session, opt_profname, opt_password, PROVIDER_ID_EMSMDB);
+ talloc_free(opt_profname);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MapiLogonEx", GetLastError());
+ exit (1);
+ }
+
+ /* Open default message store */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("OpenMsgStore", GetLastError());
+ exit (1);
+ }
+
+ retval = mapidump_walk(mem_ctx, ocb_ctx, &obj_store);
+
+ /* Uninitialize MAPI and OCB subsystem */
+ mapi_object_release(&obj_store);
+ MAPIUninitialize();
+ ocb_release(ocb_ctx);
+ talloc_free(mem_ctx);
+
+ return 0;
+}
Added: trunk/openchange/utils/exchange2ical/exchange2ical.c
===================================================================
--- trunk/openchange/utils/exchange2ical/exchange2ical.c (rev 0)
+++ trunk/openchange/utils/exchange2ical/exchange2ical.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,391 @@
+/*
+ Convert Exchange appointments and meetings to ICAL files
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 <utils/exchange2ical/exchange2ical.h>
+#include <samba/popt.h>
+#include <param.h>
+#include <utils/openchange-tools.h>
+
+static void exchange2ical_init(TALLOC_CTX *mem_ctx, struct exchange2ical *exchange2ical)
+{
+ exchange2ical->mem_ctx = mem_ctx;
+
+ exchange2ical->method = ICAL_METHOD_NONE;
+ exchange2ical->partstat = ICAL_PARTSTAT_NONE;
+ exchange2ical->Recurring = NULL;
+ exchange2ical->RecurrencePattern = NULL;
+ exchange2ical->TimeZoneStruct = NULL;
+ exchange2ical->TimeZoneDesc = NULL;
+ exchange2ical->Keywords = NULL;
+ exchange2ical->Contacts = NULL;
+ exchange2ical->apptStateFlags = NULL;
+ exchange2ical->sensitivity = NULL;
+ exchange2ical->apptStartWhole = NULL;
+ exchange2ical->apptEndWhole = NULL;
+ exchange2ical->apptSubType = NULL;
+ exchange2ical->OwnerCriticalChange = NULL;
+ exchange2ical->body = NULL;
+ exchange2ical->LastModified = NULL;
+ exchange2ical->Location = NULL;
+ exchange2ical->Importance = NULL;
+ exchange2ical->ExceptionReplaceTime = NULL;
+ exchange2ical->ResponseRequested = NULL;
+ exchange2ical->NonSendableBcc = NULL;
+ exchange2ical->Sequence = NULL;
+ exchange2ical->Subject = NULL;
+ exchange2ical->MessageLocaleId = NULL;
+ exchange2ical->BusyStatus = NULL;
+ exchange2ical->IntendedBusyStatus = NULL;
+ exchange2ical->GlobalObjectId = NULL;
+ exchange2ical->AttendeeCriticalChange = NULL;
+ exchange2ical->OwnerApptId = NULL;
+ exchange2ical->apptReplyTime = NULL;
+ exchange2ical->NotAllowPropose = NULL;
+ exchange2ical->AllowExternCheck = NULL;
+ exchange2ical->apptLastSequence = NULL;
+ exchange2ical->apptSeqTime = NULL;
+ exchange2ical->AutoFillLocation = NULL;
+ exchange2ical->AutoStartCheck = NULL;
+ exchange2ical->CollaborateDoc = NULL;
+ exchange2ical->ConfCheck = NULL;
+ exchange2ical->ConfType = NULL;
+ exchange2ical->Directory = NULL;
+ exchange2ical->MWSURL = NULL;
+ exchange2ical->NetShowURL = NULL;
+ exchange2ical->OnlinePassword = NULL;
+ exchange2ical->OrgAlias = NULL;
+ exchange2ical->SenderName = NULL;
+ exchange2ical->SenderEmailAddress = NULL;
+ exchange2ical->ReminderSet = NULL;
+ exchange2ical->ReminderDelta = NULL;
+ exchange2ical->vcalendar = NULL;
+ exchange2ical->vevent = NULL;
+ exchange2ical->vtimezone = NULL;
+ exchange2ical->valarm = NULL;
+}
+
+static void exchange2ical_reset(struct exchange2ical *exchange2ical)
+{
+ if (exchange2ical->RecurrencePattern) {
+ talloc_free(exchange2ical->RecurrencePattern);
+ }
+
+ if (exchange2ical->TimeZoneStruct) {
+ talloc_free(exchange2ical->TimeZoneStruct);
+ }
+
+ if (exchange2ical->vcalendar) {
+ icalcomponent_free(exchange2ical->vcalendar);
+ }
+ exchange2ical_init(exchange2ical->mem_ctx, exchange2ical);
+}
+
+static int exchange2ical_get_properties(TALLOC_CTX *mem_ctx, struct SRow *aRow, struct exchange2ical *exchange2ical)
+{
+ struct Binary_r *apptrecur;
+ struct Binary_r *TimeZoneStruct;
+
+ exchange2ical->Keywords = (const struct StringArray_r *) octool_get_propval(aRow, PidNameKeywords);
+ exchange2ical->method = get_ical_method((const char *) octool_get_propval(aRow, PR_MESSAGE_CLASS_UNICODE));
+ if (!exchange2ical->method) return -1;
+
+ exchange2ical->Recurring = (uint8_t *) octool_get_propval(aRow, PidLidRecurring);
+ apptrecur = (struct Binary_r *) octool_get_propval(aRow, PidLidAppointmentRecur);
+ exchange2ical->RecurrencePattern = get_RecurrencePattern(mem_ctx, apptrecur);
+
+ exchange2ical->TimeZoneDesc = (const char *) octool_get_propval(aRow, PidLidTimeZoneDescription);
+ TimeZoneStruct = (struct Binary_r *) octool_get_propval(aRow, PidLidTimeZoneStruct);
+ exchange2ical->TimeZoneStruct = get_TimeZoneStruct(mem_ctx, TimeZoneStruct);
+
+ // TODO: should we use PidLidGlobalObjectId here instead of PidLidCleanGlobalObjectId?
+ exchange2ical->GlobalObjectId = (struct Binary_r *) octool_get_propval(aRow, PidLidCleanGlobalObjectId);
+ exchange2ical->apptStateFlags = (uint32_t *) octool_get_propval(aRow, PidLidAppointmentStateFlags);
+ exchange2ical->Contacts = (const struct StringArray_r *)octool_get_propval(aRow, PidLidContacts);
+ exchange2ical->apptStartWhole = (const struct FILETIME *)octool_get_propval(aRow, PidLidAppointmentStartWhole);
+ exchange2ical->apptEndWhole = (const struct FILETIME *)octool_get_propval(aRow, PidLidAppointmentEndWhole);
+ exchange2ical->apptSubType = (uint8_t *) octool_get_propval(aRow, PidLidAppointmentSubType);
+ exchange2ical->OwnerCriticalChange = (const struct FILETIME *)octool_get_propval(aRow, PidLidOwnerCriticalChange);
+ exchange2ical->Location = (const char *) octool_get_propval(aRow, PidLidLocation);
+ exchange2ical->ExceptionReplaceTime = (const struct FILETIME *)octool_get_propval(aRow, PidLidExceptionReplaceTime);
+ exchange2ical->NonSendableBcc = (const char *) octool_get_propval(aRow, PidLidNonSendableBcc);
+ exchange2ical->Sequence = (uint32_t *) octool_get_propval(aRow, PidLidAppointmentSequence);
+ exchange2ical->BusyStatus = (uint32_t *) octool_get_propval(aRow, PidLidBusyStatus);
+ exchange2ical->IntendedBusyStatus = (uint32_t *) octool_get_propval(aRow, PidLidIntendedBusyStatus);
+ exchange2ical->AttendeeCriticalChange = (const struct FILETIME *) octool_get_propval(aRow, PidLidAttendeeCriticalChange);
+ exchange2ical->apptReplyTime = (const struct FILETIME *)octool_get_propval(aRow, PidLidAppointmentReplyTime);
+ exchange2ical->NotAllowPropose = (uint8_t *) octool_get_propval(aRow, PidLidAppointmentNotAllowPropose);
+ exchange2ical->AllowExternCheck = (uint8_t *) octool_get_propval(aRow, PidLidAllowExternalCheck);
+ exchange2ical->apptLastSequence = (uint32_t *) octool_get_propval(aRow, PidLidAppointmentLastSequence);
+ exchange2ical->apptSeqTime = (const struct FILETIME *)octool_get_propval(aRow, PidLidAppointmentSequenceTime);
+ exchange2ical->AutoFillLocation = (uint8_t *) octool_get_propval(aRow, PidLidAutoFillLocation);
+ exchange2ical->AutoStartCheck = (uint8_t *) octool_get_propval(aRow, PidLidAutoStartCheck);
+ exchange2ical->CollaborateDoc = (const char *) octool_get_propval(aRow, PidLidCollaborateDoc);
+ exchange2ical->ConfCheck = (uint8_t *) octool_get_propval(aRow, PidLidConferencingCheck);
+ exchange2ical->ConfType = (uint32_t *) octool_get_propval(aRow, PidLidConferencingType);
+ exchange2ical->Directory = (const char *) octool_get_propval(aRow, PidLidDirectory);
+ exchange2ical->MWSURL = (const char *) octool_get_propval(aRow, PidLidMeetingWorkspaceUrl);
+ exchange2ical->NetShowURL = (const char *) octool_get_propval(aRow, PidLidNetShowUrl);
+ exchange2ical->OnlinePassword = (const char *) octool_get_propval(aRow, PidLidOnlinePassword);
+ exchange2ical->OrgAlias = (const char *) octool_get_propval(aRow, PidLidOrganizerAlias);
+ exchange2ical->ReminderSet = (uint8_t *) octool_get_propval(aRow, PidLidReminderSet);
+ exchange2ical->ReminderDelta = (uint32_t *) octool_get_propval(aRow, PidLidReminderDelta);
+
+ exchange2ical->sensitivity = (uint32_t *) octool_get_propval(aRow, PR_SENSITIVITY);
+ exchange2ical->partstat = get_ical_partstat((const char *) octool_get_propval(aRow, PR_MESSAGE_CLASS_UNICODE));
+ exchange2ical->created = (const struct FILETIME *)octool_get_propval(aRow, PR_CREATION_TIME);
+ exchange2ical->body = (const char *)octool_get_propval(aRow, PR_BODY_UNICODE);
+ exchange2ical->LastModified = (const struct FILETIME *)octool_get_propval(aRow, PR_LAST_MODIFICATION_TIME);
+ exchange2ical->Importance = (uint32_t *) octool_get_propval(aRow, PR_IMPORTANCE);
+ exchange2ical->ResponseRequested = (uint8_t *) octool_get_propval(aRow, PR_RESPONSE_REQUESTED);
+ exchange2ical->Subject = (const char *) octool_get_propval(aRow, PR_SUBJECT_UNICODE);
+ exchange2ical->MessageLocaleId = (uint32_t *) octool_get_propval(aRow, PR_MESSAGE_LOCALE_ID);
+ exchange2ical->OwnerApptId = (uint32_t *) octool_get_propval(aRow, PR_OWNER_APPT_ID);
+ exchange2ical->SenderName = (const char *) octool_get_propval(aRow, PR_SENDER_NAME);
+ exchange2ical->SenderEmailAddress = (const char *) octool_get_propval(aRow, PR_SENDER_EMAIL_ADDRESS);
+
+ return 0;
+}
+
+int main(int argc, const char *argv[])
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ int ret;
+ struct SRowSet SRowSet;
+ struct SRow aRow;
+ struct SPropValue *lpProps;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct exchange2ical exchange2ical;
+ struct mapi_session *session = NULL;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_table;
+ mapi_object_t obj_message;
+ mapi_id_t fid;
+ uint32_t count;
+ poptContext pc;
+ int opt;
+ uint32_t i;
+ const char *opt_profdb = NULL;
+ const char *opt_profname = NULL;
+ const char *opt_password = NULL;
+ const char *opt_debug = NULL;
+ bool opt_dumpdata = false;
+
+ enum { OPT_PROFILE_DB=1000, OPT_PROFILE, OPT_PASSWORD, OPT_DEBUG, OPT_DUMPDATA };
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "database", 'f', POPT_ARG_STRING, NULL, OPT_PROFILE_DB, "set the profile database path", NULL },
+ { "profile", 'p', POPT_ARG_STRING, NULL, OPT_PROFILE, "set the profile name", NULL },
+ { "password", 'P', POPT_ARG_STRING, NULL, OPT_PASSWORD, "set the profile password", NULL },
+ { "debuglevel", 'd', POPT_ARG_STRING, NULL, OPT_DEBUG, "set the debug level", NULL },
+ { "dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMPDATA, "dump the hex data", NULL },
+ POPT_OPENCHANGE_VERSION
+ { NULL, 0, 0, NULL, 0, NULL, NULL }
+ };
+
+ mem_ctx = talloc_named(NULL, 0, "exchange2ical");
+ exchange2ical_init(mem_ctx, &exchange2ical);
+
+ pc = poptGetContext("exchange2ical", 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 = poptGetOptArg(pc);
+ break;
+ case OPT_PASSWORD:
+ opt_password = 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(opt_profdb);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ /* debug options */
+ SetMAPIDumpData(opt_dumpdata);
+
+ if (opt_debug) {
+ SetMAPIDebugLevel(atoi(opt_debug));
+ }
+
+ session = octool_init_mapi(opt_profname, opt_password, 0);
+ MAPI_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, mem_ctx);
+
+ /* Open Mailbox */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("OpenMsgStore", GetLastError());
+ exit (1);
+ }
+
+ /* Open default calendar folder */
+/* retval = GetDefaultFolder(&obj_store, &fid, olFolderInbox); */
+ retval = GetDefaultFolder(&obj_store, &fid, olFolderCalendar);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("GetDefaultFolder", GetLastError());
+ exit (1);
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, fid, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("OpenFolder", GetLastError());
+ exit (1);
+ }
+
+ /* Open the contents table */
+ mapi_object_init(&obj_table);
+ retval = GetContentsTable(&obj_folder, &obj_table, 0, &count);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ DEBUG(0, ("MAILBOX (%d appointments)\n", count));
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x2,
+ PR_FID,
+ PR_MID);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("SetColumns", GetLastError());
+ }
+
+ while ((retval = QueryRows(&obj_table, count, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND && SRowSet.cRows) {
+ count -= SRowSet.cRows;
+ for (i = 0; i < SRowSet.cRows; i++) {
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(&obj_folder,
+ SRowSet.aRow[i].lpProps[0].value.d,
+ SRowSet.aRow[i].lpProps[1].value.d,
+ &obj_message, 0);
+ if (retval != MAPI_E_NOT_FOUND) {
+ retval = GetRecipientTable(&obj_message,
+ &exchange2ical.Recipients.SRowSet,
+ &exchange2ical.Recipients.SPropTagArray);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x2F,
+ PidNameKeywords,
+ PidLidRecurring,
+ PidLidAppointmentRecur,
+ PidLidAppointmentStateFlags,
+ PidLidTimeZoneDescription,
+ PidLidTimeZoneStruct,
+ PidLidContacts,
+ PidLidAppointmentStartWhole,
+ PidLidAppointmentEndWhole,
+ PidLidAppointmentSubType,
+ PidLidOwnerCriticalChange,
+ PidLidLocation,
+ PidLidExceptionReplaceTime,
+ PidLidNonSendableBcc,
+ PidLidAppointmentSequence,
+ PidLidBusyStatus,
+ PidLidIntendedBusyStatus,
+ PidLidCleanGlobalObjectId,
+ PidLidAttendeeCriticalChange,
+ PidLidAppointmentReplyTime,
+ PidLidAppointmentNotAllowPropose,
+ PidLidAllowExternalCheck,
+ PidLidAppointmentLastSequence,
+ PidLidAppointmentSequenceTime,
+ PidLidAutoFillLocation,
+ PidLidAutoStartCheck,
+ PidLidCollaborateDoc,
+ PidLidConferencingCheck,
+ PidLidConferencingType,
+ PidLidDirectory,
+ PidLidMeetingWorkspaceUrl,
+ PidLidNetShowUrl,
+ PidLidOnlinePassword,
+ PidLidOrganizerAlias,
+ PidLidReminderSet,
+ PidLidReminderDelta,
+ PR_MESSAGE_CLASS_UNICODE,
+ PR_SENSITIVITY,
+ PR_BODY_UNICODE,
+ PR_CREATION_TIME,
+ PR_LAST_MODIFICATION_TIME,
+ PR_IMPORTANCE,
+ PR_RESPONSE_REQUESTED,
+ PR_SUBJECT_UNICODE,
+ PR_OWNER_APPT_ID,
+ PR_SENDER_NAME,
+ PR_SENDER_EMAIL_ADDRESS);
+
+ retval = GetProps(&obj_message, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+
+ if (retval == MAPI_E_SUCCESS) {
+ aRow.ulAdrEntryPad = 0;
+ aRow.cValues = count;
+ aRow.lpProps = lpProps;
+
+ ret = exchange2ical_get_properties(mem_ctx, &aRow, &exchange2ical);
+ if (!ret) {
+ char filename[10];
+ snprintf(filename, 10, "test%i.vcf", i);
+ ical_component_VCALENDAR(&exchange2ical);
+ // Just for temporary debugging...
+ // writeVObjectToFile(filename, exchange2ical.vcalendar);
+ DEBUG(0, ("%u\n\n", i));
+ printf("ICAL file:\n%s\n", icalcomponent_as_ical_string(exchange2ical.vcalendar));
+ }
+ exchange2ical_reset(&exchange2ical);
+ MAPIFreeBuffer(lpProps);
+ }
+
+ mapi_object_release(&obj_message);
+ }
+ }
+ }
+
+ /* Uninitialize MAPI subsystem */
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ MAPIUninitialize();
+ poptFreeContext(pc);
+ talloc_free(mem_ctx);
+
+ return 0;
+}
Added: trunk/openchange/utils/exchange2ical/exchange2ical.h
===================================================================
--- trunk/openchange/utils/exchange2ical/exchange2ical.h (rev 0)
+++ trunk/openchange/utils/exchange2ical/exchange2ical.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,203 @@
+/*
+ Convert Exchange appointments to ICAL
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 __EXCHANGE2ICAL_H_
+#define __EXCHANGE2ICAL_H_
+
+#include <libmapi/libmapi.h>
+#include <gen_ndr/ndr_property.h>
+
+#include <libical/ical.h>
+
+#include <time.h>
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+struct message_recipients {
+ struct SRowSet SRowSet;
+ struct SPropTagArray SPropTagArray;
+};
+
+struct exchange2ical {
+ TALLOC_CTX *mem_ctx;
+ struct message_recipients Recipients;
+ enum icalproperty_method method;
+ enum icalparameter_partstat partstat;
+ uint8_t *Recurring;
+ struct RecurrencePattern *RecurrencePattern;
+ struct TimeZoneStruct *TimeZoneStruct;
+ const char *TimeZoneDesc;
+ const struct StringArray_r *Keywords;
+ const struct StringArray_r *Contacts;
+ uint32_t *apptStateFlags;
+ uint32_t *sensitivity;
+ uint32_t *Importance;
+ const struct FILETIME *created;
+ const char *body;
+ const struct FILETIME *apptStartWhole;
+ const struct FILETIME *apptEndWhole;
+ const struct FILETIME *OwnerCriticalChange;
+ const struct FILETIME *LastModified;
+ const struct FILETIME *ExceptionReplaceTime;
+ uint8_t *apptSubType;
+ const char *Location;
+ uint8_t *ResponseRequested;
+ const char *NonSendableBcc;
+ uint32_t *Sequence;
+ const char *Subject;
+ uint32_t *MessageLocaleId;
+ uint32_t *BusyStatus;
+ uint32_t *IntendedBusyStatus;
+ struct Binary_r *GlobalObjectId;
+ const struct FILETIME *AttendeeCriticalChange;
+ uint32_t *OwnerApptId;
+ const struct FILETIME *apptReplyTime;
+ uint8_t *NotAllowPropose;
+ uint8_t *AllowExternCheck;
+ uint32_t *apptLastSequence;
+ const struct FILETIME *apptSeqTime;
+ uint8_t *AutoFillLocation;
+ uint8_t *AutoStartCheck;
+ const char *CollaborateDoc;
+ uint8_t *ConfCheck;
+ uint32_t *ConfType;
+ const char *Directory;
+ const char *MWSURL;
+ const char *NetShowURL;
+ const char *OnlinePassword;
+ const char *OrgAlias;
+ const char *SenderName;
+ const char *SenderEmailAddress;
+ uint8_t *ReminderSet;
+ uint32_t *ReminderDelta;
+ icalcomponent *vcalendar;
+ icalcomponent *vevent;
+ icalcomponent *vtimezone;
+ icalcomponent *valarm;
+};
+
+struct ical_method {
+ enum icalproperty_method method;
+ enum icalparameter_partstat partstat;
+ const char *PidTagMessageClass;
+};
+
+struct ical_calendartype {
+ uint16_t type;
+ const char *calendar;
+};
+
+struct ical_class {
+ uint32_t sensivity;
+ enum icalproperty_class classtype;
+};
+
+#define OPENCHANGE_ICAL_PRODID "-//OpenChange Project/exchange2ical MIMEDIR//EN"
+#define OPENCHANGE_ICAL_VERSION "2.0"
+
+__BEGIN_DECLS
+
+/* definitions from exchange2ical_utils.c */
+struct icaltimetype get_icaltime_from_FILETIME(const struct FILETIME *);
+struct icaltimetype get_icaldate_from_FILETIME(const struct FILETIME *);
+struct tm *get_tm_from_FILETIME(const struct FILETIME *);
+struct icaltimetype get_icaltimetype_from_tm(struct tm *tm);
+struct icaldatetimeperiodtype get_icaldatetimeperiodtype_from_tm(struct tm *tm);
+
+bool has_component_DAYLIGHT(struct exchange2ical *);
+
+char *get_ical_date(TALLOC_CTX *, struct SYSTEMTIME *);
+enum icalproperty_method get_ical_method(const char *);
+enum icalparameter_partstat get_ical_partstat(const char *);
+const char *get_ical_calendartype(uint16_t);
+enum icalproperty_class get_ical_class(uint32_t);
+
+/* definitions from exchange2ical_component.c */
+void ical_component_VCALENDAR(struct exchange2ical *);
+void ical_component_VEVENT(struct exchange2ical *);
+void ical_component_VTIMEZONE(struct exchange2ical *);
+void ical_component_STANDARD(struct exchange2ical *);
+void ical_component_DAYLIGHT(struct exchange2ical *);
+void ical_component_VALARM(struct exchange2ical *);
+
+/* definitions from exchange2ical_property.c */
+void ical_property_ATTENDEE(struct exchange2ical *);
+void ical_property_CATEGORIES(struct exchange2ical *);
+void ical_property_CLASS(struct exchange2ical *);
+void ical_property_CONTACT(struct exchange2ical *);
+void ical_property_CREATED(struct exchange2ical *);
+void ical_property_DTEND(struct exchange2ical *);
+void ical_property_DTSTAMP(struct exchange2ical *);
+void ical_property_DTSTART(struct exchange2ical *);
+void ical_property_DESCRIPTION(struct exchange2ical *);
+void ical_property_EXDATE(struct exchange2ical *);
+void ical_property_LAST_MODIFIED(struct exchange2ical *);
+void ical_property_LOCATION(struct exchange2ical *);
+void ical_property_ORGANIZER(struct exchange2ical *);
+void ical_property_PRIORITY(struct exchange2ical *);
+void ical_property_RDATE(struct exchange2ical *);
+void ical_property_RRULE_Daily(struct exchange2ical *);
+void ical_property_RRULE_Weekly(struct exchange2ical *);
+void ical_property_RRULE_Monthly(struct exchange2ical *);
+void ical_property_RRULE_NthMonthly(struct exchange2ical *);
+void ical_property_RRULE_Yearly(struct exchange2ical *);
+void ical_property_RRULE_NthYearly(struct exchange2ical *);
+void ical_property_RRULE(struct exchange2ical *);
+void ical_property_RECURRENCE_ID(struct exchange2ical *);
+void ical_property_RESOURCES(struct exchange2ical *);
+void ical_property_SEQUENCE(struct exchange2ical *);
+void ical_property_SUMMARY(struct exchange2ical *);
+void ical_property_TRANSP(struct exchange2ical *);
+void ical_property_TRIGGER(struct exchange2ical *);
+void ical_property_UID(struct exchange2ical *);
+void ical_property_X_MICROSOFT_CDO_ATTENDEE_CRITICAL_CHANGE(struct exchange2ical *);
+void ical_property_X_MICROSOFT_CDO_BUSYSTATUS(struct exchange2ical *);
+void ical_property_X_MICROSOFT_CDO_INTENDEDSTATUS(struct exchange2ical *);
+void ical_property_X_MICROSOFT_CDO_OWNERAPPTID(struct exchange2ical *);
+void ical_property_X_MICROSOFT_CDO_OWNER_CRITICAL_CHANGE(struct exchange2ical *);
+void ical_property_X_MICROSOFT_CDO_REPLYTIME(struct exchange2ical *);
+void ical_property_X_MICROSOFT_DISALLOW_COUNTER(struct exchange2ical *);
+void ical_property_X_MS_OLK_ALLOWEXTERNCHECK(struct exchange2ical *);
+void ical_property_X_MS_OLK_APPTLASTSEQUENCE(struct exchange2ical *);
+void ical_property_X_MS_OLK_APPTSEQTIME(struct exchange2ical *);
+void ical_property_X_MS_OLK_AUTOFILLLOCATION(struct exchange2ical *);
+void ical_property_X_MS_OLK_AUTOSTARTCHECK(struct exchange2ical *);
+void ical_property_X_MS_OLK_COLLABORATEDOC(struct exchange2ical *);
+void ical_property_X_MS_OLK_CONFCHECK(struct exchange2ical *);
+void ical_property_X_MS_OLK_CONFTYPE(struct exchange2ical *);
+void ical_property_X_MS_OLK_DIRECTORY(struct exchange2ical *);
+void ical_property_X_MS_OLK_MWSURL(struct exchange2ical *);
+void ical_property_X_MS_OLK_NETSHOWURL(struct exchange2ical *);
+void ical_property_X_MS_OLK_ONLINEPASSWORD(struct exchange2ical *);
+void ical_property_X_MS_OLK_ORGALIAS(struct exchange2ical *);
+void ical_property_X_MS_OLK_SENDER(struct exchange2ical *);
+
+__END_DECLS
+
+#endif /* __EXCHANGE2ICAL_H_ */
Added: trunk/openchange/utils/exchange2ical/exchange2ical_component.c
===================================================================
--- trunk/openchange/utils/exchange2ical/exchange2ical_component.c (rev 0)
+++ trunk/openchange/utils/exchange2ical/exchange2ical_component.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,247 @@
+/*
+ Convert Exchange appointments and meetings to ICAL files
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 <utils/exchange2ical/exchange2ical.h>
+
+#include <libical/icalderivedproperty.h>
+
+void ical_component_VCALENDAR(struct exchange2ical *exchange2ical)
+{
+ icalproperty* prop;
+
+ exchange2ical->vcalendar = icalcomponent_new_vcalendar();
+ if (!(exchange2ical->vcalendar)) {
+ return;
+ }
+
+ prop = icalproperty_new_version(OPENCHANGE_ICAL_VERSION);
+ icalcomponent_add_property(exchange2ical->vcalendar, prop);
+
+ prop = icalproperty_new_prodid(OPENCHANGE_ICAL_PRODID);
+ icalcomponent_add_property(exchange2ical->vcalendar, prop);
+
+ prop = icalproperty_new_method(exchange2ical->method);
+ icalcomponent_add_property(exchange2ical->vcalendar, prop);
+
+ /* TODO: This appears wrong - should be a parameter of the VEVENT component, ATTENDEE property */
+ if (exchange2ical->partstat != ICAL_PARTSTAT_NONE) {
+ icalparameter *param = icalparameter_new_partstat(exchange2ical->partstat);
+ icalproperty_add_parameter(prop, param);
+ }
+
+ if (exchange2ical->RecurrencePattern && exchange2ical->RecurrencePattern->CalendarType) {
+ prop = icalproperty_new_x(get_ical_calendartype(exchange2ical->RecurrencePattern->CalendarType));
+ icalproperty_set_x_name(prop, "X-MICROSOFT-CALSCALE");
+ icalcomponent_add_property(exchange2ical->vcalendar, prop);
+ }
+
+ ical_component_VTIMEZONE(exchange2ical);
+
+ ical_component_VEVENT(exchange2ical);
+
+}
+
+void ical_component_VEVENT(struct exchange2ical *exchange2ical)
+{
+ exchange2ical->vevent = icalcomponent_new_vevent();
+ if ( ! (exchange2ical->vevent) ) {
+ return;
+ }
+ icalcomponent_add_component(exchange2ical->vcalendar, exchange2ical->vevent);
+ /* ATTACH property FIXME */
+ ical_property_ATTENDEE(exchange2ical);
+ ical_property_CATEGORIES(exchange2ical);
+ ical_property_CLASS(exchange2ical);
+ ical_property_CONTACT(exchange2ical);
+ ical_property_CREATED(exchange2ical);
+ ical_property_DTSTART(exchange2ical);
+ ical_property_DTEND(exchange2ical);
+ ical_property_DTSTAMP(exchange2ical);
+ ical_property_DESCRIPTION(exchange2ical);
+ ical_property_EXDATE(exchange2ical);
+ ical_property_LAST_MODIFIED(exchange2ical);
+ ical_property_LOCATION(exchange2ical);
+ ical_property_ORGANIZER(exchange2ical);
+ ical_property_PRIORITY(exchange2ical);
+ ical_property_RDATE(exchange2ical);
+ ical_property_RRULE(exchange2ical);
+ /* RECURRENCE-ID property:FIXME */
+ ical_property_RECURRENCE_ID(exchange2ical);
+ ical_property_RESOURCES(exchange2ical);
+ ical_property_SEQUENCE(exchange2ical);
+ ical_property_SUMMARY(exchange2ical);
+ ical_property_TRANSP(exchange2ical);
+ ical_property_UID(exchange2ical);
+
+ /* X-ALT-DESC FIXME */
+ ical_property_X_MICROSOFT_CDO_ATTENDEE_CRITICAL_CHANGE(exchange2ical);
+ ical_property_X_MICROSOFT_CDO_BUSYSTATUS(exchange2ical);
+ ical_property_X_MICROSOFT_CDO_INTENDEDSTATUS(exchange2ical);
+ ical_property_X_MICROSOFT_CDO_OWNERAPPTID(exchange2ical);
+ ical_property_X_MICROSOFT_CDO_OWNER_CRITICAL_CHANGE(exchange2ical);
+ ical_property_X_MICROSOFT_CDO_REPLYTIME(exchange2ical);
+ ical_property_X_MICROSOFT_DISALLOW_COUNTER(exchange2ical);
+ ical_property_X_MS_OLK_ALLOWEXTERNCHECK(exchange2ical);
+ ical_property_X_MS_OLK_APPTLASTSEQUENCE(exchange2ical);
+ ical_property_X_MS_OLK_APPTSEQTIME(exchange2ical);
+ ical_property_X_MS_OLK_AUTOFILLLOCATION(exchange2ical);
+ ical_property_X_MS_OLK_AUTOSTARTCHECK(exchange2ical);
+ ical_property_X_MS_OLK_COLLABORATEDOC(exchange2ical);
+ ical_property_X_MS_OLK_CONFCHECK(exchange2ical);
+ ical_property_X_MS_OLK_CONFTYPE(exchange2ical);
+ ical_property_X_MS_OLK_DIRECTORY(exchange2ical);
+ ical_property_X_MS_OLK_MWSURL(exchange2ical);
+ ical_property_X_MS_OLK_NETSHOWURL(exchange2ical);
+ ical_property_X_MS_OLK_ONLINEPASSWORD(exchange2ical);
+ ical_property_X_MS_OLK_ORGALIAS(exchange2ical);
+ ical_property_X_MS_OLK_SENDER(exchange2ical);
+ ical_component_VALARM(exchange2ical);
+}
+
+
+/**
+ VTIMEZONE component
+ */
+void ical_component_VTIMEZONE(struct exchange2ical *exchange2ical)
+{
+ exchange2ical->vtimezone = icalcomponent_new_vtimezone();
+ icalcomponent_add_component(exchange2ical->vcalendar, exchange2ical->vtimezone);
+
+ /* TZID property */
+ if (exchange2ical->TimeZoneDesc) {
+ icalproperty *tzid = icalproperty_new_tzid(exchange2ical->TimeZoneDesc);
+ icalcomponent_add_property(exchange2ical->vtimezone, tzid);
+ }
+
+ /* STANDARD sub-component */
+ ical_component_STANDARD(exchange2ical);
+
+ /* DAYLIGHT component */
+ ical_component_DAYLIGHT(exchange2ical);
+}
+
+
+/**
+ STANDARD sub-component
+ */
+void ical_component_STANDARD(struct exchange2ical *exchange2ical)
+{
+ char *dtstart = NULL;
+ int32_t tzoffsetfrom;
+ int32_t tzoffsetto;
+ icalcomponent *standard;
+ icalproperty *prop;
+
+ /* Sanity Check */
+ if (!exchange2ical->TimeZoneStruct) return;
+
+ standard = icalcomponent_new_xstandard();
+ icalcomponent_add_component(exchange2ical->vtimezone, standard);
+
+ /* DTSTART property */
+ dtstart = get_ical_date(exchange2ical->mem_ctx, &(exchange2ical->TimeZoneStruct->stStandardDate));
+ if (dtstart) {
+ prop = icalproperty_new_dtstart(icaltime_from_string(dtstart));
+ icalcomponent_add_property(standard, prop);
+ talloc_free(dtstart);
+ }
+
+ /* TODO: RRULE property */
+ // ical_property_RRULE(exchange2ical, exchange2ical->TimeZoneStruct->stStandardDate);
+
+ /* TZOFFSETFROM property */
+ tzoffsetfrom = -1 * (exchange2ical->TimeZoneStruct->lBias + exchange2ical->TimeZoneStruct->lDaylightBias);
+ prop = icalproperty_new_tzoffsetfrom(tzoffsetfrom);
+ icalcomponent_add_property(standard, prop);
+
+ /* TZOFFSETTO property */
+ tzoffsetto = -1 * (exchange2ical->TimeZoneStruct->lBias + exchange2ical->TimeZoneStruct->lStandardBias);
+ prop = icalproperty_new_tzoffsetto(tzoffsetto);
+ icalcomponent_add_property(standard, prop);
+}
+
+
+/**
+ DAYLIGHT sub-component
+ */
+void ical_component_DAYLIGHT(struct exchange2ical *exchange2ical)
+{
+ char *dtstart = NULL;
+ int32_t tzoffsetfrom;
+ int32_t tzoffsetto;
+ icalcomponent *daylight;
+ icalproperty *prop;
+
+ /* Sanity check */
+ if (has_component_DAYLIGHT(exchange2ical) == false) return;
+
+ daylight = icalcomponent_new_xdaylight();
+ icalcomponent_add_component(exchange2ical->vtimezone, daylight);
+
+ /* DTSTART property */
+ dtstart = get_ical_date(exchange2ical->mem_ctx, &exchange2ical->TimeZoneStruct->stDaylightDate);
+ if (dtstart) {
+ prop = icalproperty_new_dtstart(icaltime_from_string(dtstart));
+ icalcomponent_add_property(daylight, prop);
+ talloc_free(dtstart);
+ }
+ /* TODO: RRULE property */
+ // ical_property_RRULE(exchange2ical, exchange2ical->TimeZoneStruct->stDaylightDate);
+
+ /* TZOFFSETFROM property */
+ tzoffsetfrom = -1 * (exchange2ical->TimeZoneStruct->lBias + exchange2ical->TimeZoneStruct->lStandardBias);
+ prop = icalproperty_new_tzoffsetfrom(tzoffsetfrom);
+ icalcomponent_add_property(daylight, prop);
+
+ /* TZOFFSETTO property */
+ tzoffsetto = -1 * (exchange2ical->TimeZoneStruct->lBias + exchange2ical->TimeZoneStruct->lDaylightBias);
+ prop = icalproperty_new_tzoffsetto(tzoffsetto);
+ icalcomponent_add_property(daylight, prop);
+}
+
+
+/**
+ VALARM component
+
+ [MS-OXCICAL], Section 2.2.1.20.61
+ */
+void ical_component_VALARM(struct exchange2ical *exchange2ical)
+{
+ icalproperty *action;
+ icalproperty *description;
+
+ /* Sanity check */
+ if (!exchange2ical->vevent) return;
+ if (!exchange2ical->ReminderSet) return;
+ if (*exchange2ical->ReminderSet == false) return;
+
+ exchange2ical->valarm = icalcomponent_new_valarm();
+ if (!(exchange2ical->valarm)) {
+ printf("could not create new valarm\n");
+ return;
+ }
+ icalcomponent_add_component(exchange2ical->vevent, exchange2ical->valarm);
+ ical_property_TRIGGER(exchange2ical);
+ action = icalproperty_new_action(ICAL_ACTION_DISPLAY);
+ icalcomponent_add_property(exchange2ical->valarm, action);
+ description = icalproperty_new_description("Reminder");
+ icalcomponent_add_property(exchange2ical->valarm, description);
+}
Added: trunk/openchange/utils/exchange2ical/exchange2ical_property.c
===================================================================
--- trunk/openchange/utils/exchange2ical/exchange2ical_property.c (rev 0)
+++ trunk/openchange/utils/exchange2ical/exchange2ical_property.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1264 @@
+/*
+ Convert Exchange appointments and meetings to ICAL files
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 <utils/exchange2ical/exchange2ical.h>
+#include <utils/openchange-tools.h>
+
+
+struct RRULE_byday {
+ uint16_t DayOfWeek;
+ const char *DayName;
+};
+
+static const struct RRULE_byday RRULE_byday[] = {
+ { 0x0000, "SU" },
+ { 0x0001, "MO" },
+ { 0x0002, "TU" },
+ { 0x0003, "WE" },
+ { 0x0004, "TH" },
+ { 0x0005, "FR" },
+ { 0x0006, "SA" },
+ { 0x0007, NULL }
+};
+
+// TODO: check this - need an example
+void ical_property_ATTENDEE(struct exchange2ical *exchange2ical)
+{
+ uint32_t i;
+ const char *smtp;
+ const char *display_name;
+ uint32_t *RecipientFlags;
+ uint32_t *RecipientType;
+ struct SRowSet *SRowSet;
+
+ /* Sanity check */
+ if (!exchange2ical->apptStateFlags) return;
+ if (!(*exchange2ical->apptStateFlags & 0x1)) return;
+
+ SRowSet = &(exchange2ical->Recipients.SRowSet);
+
+ /* Loop over the recipient table */
+ for (i = 0; i < SRowSet->cRows; i++) {
+ smtp = (const char *) octool_get_propval(&(SRowSet->aRow[i]), PR_SMTP_ADDRESS);
+ display_name = (const char *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENT_DISPLAY_NAME);
+ RecipientFlags = (uint32_t *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENTS_FLAGS);
+ RecipientType = (uint32_t *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENT_TYPE);
+
+ if (RecipientFlags && !(*RecipientFlags & 0x20) && !(*RecipientFlags & 0x2) &&
+ (RecipientType && *RecipientType)) {
+ icalproperty *prop;
+ icalparameter *cn;
+ icalparameter *participantType;
+
+ if (smtp) {
+ char *mailtoURL;
+ mailtoURL = talloc_strdup(exchange2ical->mem_ctx, "mailto:");
+ mailtoURL = talloc_strdup_append(mailtoURL, smtp);
+ prop = icalproperty_new_attendee(mailtoURL);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ } else {
+ prop = icalproperty_new_attendee("invalid:nomail");
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ }
+
+ cn = icalparameter_new_cn(display_name);
+ icalproperty_add_parameter(prop, cn);
+
+ if (*RecipientType == 0x3) {
+ icalparameter *cutype = icalparameter_new_cutype(ICAL_CUTYPE_RESOURCE);
+ icalproperty_add_parameter(prop, cutype);
+ }
+
+ switch (*RecipientType) {
+ case 0x00000002:
+ participantType = icalparameter_new_role(ICAL_ROLE_OPTPARTICIPANT);
+ icalproperty_add_parameter(prop, participantType);
+ break;
+ case 0x00000003:
+ participantType = icalparameter_new_role(ICAL_ROLE_NONPARTICIPANT);
+ icalproperty_add_parameter(prop, participantType);
+ break;
+ }
+
+#if 0
+ // TODO: fix this
+ if (exchange2ical->partstat) {
+ icalparameter *partstat;
+ partstat = icalparameter_new_partstat(exchange2ical->partstat);
+ icalproperty_add_parameter(prop, partstat);
+ }
+#endif
+ if (exchange2ical->ResponseRequested) {
+ icalparameter *rsvp;
+ if (*(exchange2ical->ResponseRequested)) {
+ rsvp = icalparameter_new_rsvp(ICAL_RSVP_TRUE);
+ } else {
+ rsvp = icalparameter_new_rsvp(ICAL_RSVP_FALSE);
+ }
+ icalproperty_add_parameter(prop, rsvp);
+ }
+ }
+ }
+}
+
+
+void ical_property_CATEGORIES(struct exchange2ical *exchange2ical)
+{
+ uint32_t i;
+ char* categoryList;
+ icalproperty *prop;
+
+ /* Sanity check */
+ if (!exchange2ical->Keywords) return;
+ if (!exchange2ical->Keywords->cValues) return;
+
+ categoryList = talloc_strdup(exchange2ical->mem_ctx, exchange2ical->Keywords->lppszA[0]);
+ for (i = 1; i < exchange2ical->Keywords->cValues; ++i) {
+ categoryList = talloc_strdup_append(categoryList, ",");
+ categoryList = talloc_strdup_append(categoryList, exchange2ical->Keywords->lppszA[i]);
+ }
+ prop = icalproperty_new_categories(categoryList);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_CLASS(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+
+ /* Sanity check */
+ if (!exchange2ical->sensitivity) return;
+
+ prop = icalproperty_new_class(get_ical_class(*exchange2ical->sensitivity));
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_CONTACT(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+ uint32_t i;
+
+ /* Sanity check */
+ if (!exchange2ical->Contacts) return;
+ if (!exchange2ical->Contacts->cValues) return;
+
+ for (i = 0; i < exchange2ical->Contacts->cValues; i++) {
+ prop = icalproperty_new_contact(exchange2ical->Contacts->lppszA[i]);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ }
+}
+
+
+void ical_property_CREATED(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+ struct icaltimetype icaltime;
+
+ /* Sanity check */
+ if (!exchange2ical->created) return;
+
+ icaltime = get_icaltime_from_FILETIME(exchange2ical->created);
+
+ prop = icalproperty_new_created(icaltime);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+void ical_property_DTSTART(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+ icalparameter *tzid;
+ struct icaltimetype icaltime;
+
+ /* Sanity check */
+ if (!exchange2ical->apptStartWhole) return;
+
+ /* If this is an all-day appointment */
+ if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) {
+ icaltime = get_icaldate_from_FILETIME(exchange2ical->apptStartWhole);
+ prop = icalproperty_new_dtstart(icaltime);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ } else {
+ /* If this is a recurring non all-day event */
+ if (exchange2ical->Recurring && (*exchange2ical->Recurring == 0)) {
+ // TODO: we should handle recurrence here...
+ icaltime = get_icaltime_from_FILETIME(exchange2ical->apptStartWhole);
+ prop = icalproperty_new_dtstart(icaltime);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ if (exchange2ical->TimeZoneDesc) {
+ tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
+ icalproperty_add_parameter(prop, tzid);
+ }
+ } else {
+ /* If this is a non recurring non all-day event */
+ icaltime = get_icaltime_from_FILETIME(exchange2ical->apptStartWhole);
+ prop = icalproperty_new_dtstart(icaltime);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ if (exchange2ical->TimeZoneDesc) {
+ tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
+ icalproperty_add_parameter(prop, tzid);
+ }
+ }
+ }
+}
+
+
+void ical_property_DTEND(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+ icalparameter *tzid;
+ struct icaltimetype icaltime;
+
+ /* Sanity check */
+ if (!exchange2ical->apptEndWhole) return;
+
+ /* If this is an all-day appointment */
+ if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) {
+ icaltime = get_icaldate_from_FILETIME(exchange2ical->apptEndWhole);
+ prop = icalproperty_new_dtend(icaltime);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ } else {
+ /* If this is a recurring non all-day event */
+ if (exchange2ical->Recurring && (*exchange2ical->Recurring == 0)) {
+ // TODO: we should handle recurrence here...
+ icaltime = get_icaltime_from_FILETIME(exchange2ical->apptEndWhole);
+ prop = icalproperty_new_dtend(icaltime);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ if (exchange2ical->TimeZoneDesc) {
+ tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
+ icalproperty_add_parameter(prop, tzid);
+ }
+ } else {
+ /* If this is a non recurring non all-day event */
+ icaltime = get_icaltime_from_FILETIME(exchange2ical->apptEndWhole);
+ prop = icalproperty_new_dtend(icaltime);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ if (exchange2ical->TimeZoneDesc) {
+ tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
+ icalproperty_add_parameter(prop, tzid);
+ }
+ }
+ }
+}
+
+
+void ical_property_DTSTAMP(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+ struct icaltimetype icaltime;
+
+ /* Sanity check */
+ if (!exchange2ical->OwnerCriticalChange) return;
+
+ /* TODO: if the property doesn't exist, we should use system
+ * time instead
+ */
+
+ icaltime = get_icaltime_from_FILETIME(exchange2ical->OwnerCriticalChange);
+
+ prop = icalproperty_new_dtstamp(icaltime);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_DESCRIPTION(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+
+ if (exchange2ical->method == ICAL_METHOD_REPLY) return;
+ if (!exchange2ical->body) return;
+
+ prop = icalproperty_new_description(exchange2ical->body);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_EXDATE(struct exchange2ical *exchange2ical)
+{
+ uint32_t i;
+ NTTIME time;
+ struct timeval t;
+ struct tm *tm;
+ icalproperty *prop;
+
+ /* Sanity check */
+ if (exchange2ical->Recurring && (*exchange2ical->Recurring == 0x0)) return;
+ if (!exchange2ical->RecurrencePattern) return;
+ if (!exchange2ical->RecurrencePattern->DeletedInstanceCount) return;
+
+ for (i = 0; i < exchange2ical->RecurrencePattern->DeletedInstanceCount; i++) {
+ /* If this is an all-day appointment */
+ if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) {
+ /* There is a bug in MS-OXOCAL
+ * documentation. For all-day appointment,
+ * DeletedInstanceDates is set to a value
+ * which can't be the number of minutes since
+ * blabla */
+ } else {
+ /* number of minutes between midnight of the specified
+ * day and midnight, January 1, 1601 */
+ time = exchange2ical->RecurrencePattern->DeletedInstanceDates[i];
+ time *= 60;
+ time *= 10000000;
+ nttime_to_timeval(&t, time);
+ tm = localtime(&t.tv_sec);
+
+ prop = icalproperty_new_exdate(get_icaltimetype_from_tm(tm));
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ if (exchange2ical->TimeZoneDesc) {
+ icalparameter *tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
+ icalproperty_add_parameter(prop, tzid);
+ }
+ }
+ }
+}
+
+
+void ical_property_LAST_MODIFIED(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+ struct icaltimetype icaltime;
+
+ /* Sanity check */
+ if (!exchange2ical->LastModified) return;
+
+ /* TODO: if the property doesn't exist, we should use system
+ * time instead
+ */
+
+ icaltime = get_icaltime_from_FILETIME(exchange2ical->LastModified);
+
+ prop = icalproperty_new_lastmodified(icaltime);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_LOCATION(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+ /* Sanity check */
+ if (!exchange2ical->Location) return;
+
+ prop = icalproperty_new_location(exchange2ical->Location);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_ORGANIZER(struct exchange2ical *exchange2ical)
+{
+ const char *smtp;
+ const char *display_name;
+ uint32_t *RecipientFlags;
+ uint32_t *RecipientType;
+ uint32_t i;
+ struct SRowSet *SRowSet;
+
+ /* Sanity check */
+ if (!exchange2ical->apptStateFlags) return;
+ if (!(*exchange2ical->apptStateFlags & 0x1)) return;
+
+ SRowSet = &(exchange2ical->Recipients.SRowSet);
+
+ /* Loop over the recipient table */
+ for (i = 0; i < SRowSet->cRows; i++) {
+ smtp = (const char *) octool_get_propval(&(SRowSet->aRow[i]), PR_SMTP_ADDRESS);
+ display_name = (const char *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENT_DISPLAY_NAME);
+ RecipientFlags = (uint32_t *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENTS_FLAGS);
+ RecipientType = (uint32_t *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENT_TYPE);
+
+ if (RecipientFlags && !(*RecipientFlags & 0x20) &&
+ ((*RecipientFlags & 0x2) || (RecipientType && !*RecipientType))) {
+ icalproperty *prop;
+ icalparameter *cn;
+ if (smtp) {
+ char *mailtoURL;
+ mailtoURL = talloc_strdup(exchange2ical->mem_ctx, "mailto:");
+ mailtoURL = talloc_strdup_append(mailtoURL, smtp);
+ prop = icalproperty_new_organizer(mailtoURL);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ talloc_free(mailtoURL);
+ } else {
+ prop = icalproperty_new_organizer("invalid:nomail");
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ }
+ cn = icalparameter_new_cn(display_name);
+ icalproperty_add_parameter(prop, cn);
+ }
+ }
+}
+
+
+void ical_property_PRIORITY(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+ /* Sanity check */
+ if (!exchange2ical->Importance) return;
+
+ switch (*exchange2ical->Importance) {
+ case 0x00000000:
+ prop = icalproperty_new_priority(9);
+ break;
+ case 0x00000001:
+ prop = icalproperty_new_priority(5);
+ break;
+ case 0x00000002:
+ prop = icalproperty_new_priority(1);
+ break;
+ default:
+ prop = icalproperty_new_priority(5);
+ }
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_RDATE(struct exchange2ical *exchange2ical)
+{
+ uint32_t i;
+ NTTIME time;
+ struct timeval t;
+ struct tm *tm;
+ icalproperty *prop;
+
+ /* Sanity check */
+ if (exchange2ical->Recurring && (*exchange2ical->Recurring == 0x0)) return;
+ if (!exchange2ical->RecurrencePattern) return;
+ if (!exchange2ical->RecurrencePattern->ModifiedInstanceCount) return;
+
+ for (i = 0; i < exchange2ical->RecurrencePattern->ModifiedInstanceCount; i++) {
+ /* If this is an all-day appointment */
+ if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) {
+ /* There is a bug in MS-OXOCAL
+ * documentation. For all-day appointment,
+ * DeletedInstanceDates is set to a value
+ * which can't be the number of minutes since
+ * January 1st, 1601 */
+ } else {
+ /* number of minutes between midnight of the specified
+ * day and midnight, January 1st, 1601 */
+ time = exchange2ical->RecurrencePattern->ModifiedInstanceDates[i];
+ time *= 60;
+ time *= 10000000;
+ nttime_to_timeval(&t, time);
+ tm = localtime(&t.tv_sec);
+
+ prop = icalproperty_new_rdate(get_icaldatetimeperiodtype_from_tm(tm));
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ if (exchange2ical->TimeZoneDesc) {
+ icalparameter *tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
+ icalproperty_add_parameter(prop, tzid);
+ }
+ }
+ }
+}
+
+
+#if 0
+static const char *get_RRULE_byday(uint16_t DayOfWeek)
+{
+ uint16_t i;
+
+ for (i = 0; RRULE_byday[i].DayName; i++) {
+ if (DayOfWeek == RRULE_byday[i].DayOfWeek) {
+ return RRULE_byday[i].DayName;
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+
+void ical_property_RRULE_Daily(struct exchange2ical *exchange2ical)
+{
+ struct icalrecurrencetype recurrence;
+ icalproperty *prop;
+ struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
+
+ icalrecurrencetype_clear(&recurrence);
+ recurrence.freq = ICAL_DAILY_RECURRENCE;
+ recurrence.interval = (pat->Period / 1440);
+
+ // TODO: need answers from Microsoft on what is happening here
+ printf("endType:0x%x\n", pat->EndType);
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ if (pat->EndType == END_AFTER_N_OCCURRENCES) {
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ recurrence.count = pat->OccurrenceCount;
+ } else if (pat->EndType == END_AFTER_DATE) {
+ // TODO: set recurrence.until = pat->EndDate;
+ }
+
+ prop = icalproperty_new_rrule(recurrence);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_RRULE_Weekly(struct exchange2ical *exchange2ical)
+{
+ struct icalrecurrencetype recurrence;
+ icalproperty *prop;
+ struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
+ uint32_t rdfDaysBitmask = pat->PatternTypeSpecific.WeekRecurrencePattern;
+ short idx = 0;
+
+ icalrecurrencetype_clear(&recurrence);
+ recurrence.freq = ICAL_WEEKLY_RECURRENCE;
+
+ if (rdfDaysBitmask & Su) {
+ recurrence.by_day[idx] = ICAL_SUNDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & M) {
+ recurrence.by_day[idx] = ICAL_MONDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & Tu) {
+ recurrence.by_day[idx] = ICAL_TUESDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & W) {
+ recurrence.by_day[idx] = ICAL_WEDNESDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & Th) {
+ recurrence.by_day[idx] = ICAL_THURSDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & F) {
+ recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & Sa) {
+ recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
+ ++idx;
+ }
+ recurrence.by_day[idx] = ICAL_RECURRENCE_ARRAY_MAX;
+
+ recurrence.count = pat->OccurrenceCount;
+
+ // TODO: need answers from Microsoft on what is happening here
+ printf("endType:0x%x\n", pat->EndType);
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ if (pat->EndType == END_AFTER_N_OCCURRENCES) {
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ recurrence.count = pat->OccurrenceCount;
+ } else if (pat->EndType == END_AFTER_DATE) {
+ // TODO: set recurrence.until = pat->EndDate;
+ }
+
+ prop = icalproperty_new_rrule(recurrence);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_RRULE_Monthly(struct exchange2ical *exchange2ical)
+{
+ struct icalrecurrencetype recurrence;
+ icalproperty *prop;
+ struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
+ uint32_t day = pat->PatternTypeSpecific.Day;
+
+ icalrecurrencetype_clear(&recurrence);
+ recurrence.freq = ICAL_MONTHLY_RECURRENCE;
+ recurrence.interval = pat->Period;
+
+ if (day == 0x0000001F) {
+ recurrence.by_month_day[0] = -1;
+ } else {
+ recurrence.by_month_day[0] = day;
+ }
+ recurrence.by_month_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
+
+ recurrence.count = pat->OccurrenceCount;
+
+ // TODO: need answers from Microsoft on what is happening here
+ printf("endType:0x%x\n", pat->EndType);
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ if (pat->EndType == END_AFTER_N_OCCURRENCES) {
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ recurrence.count = pat->OccurrenceCount;
+ } else if (pat->EndType == END_AFTER_DATE) {
+ // TODO: set recurrence.until = pat->EndDate;
+ }
+
+ prop = icalproperty_new_rrule(recurrence);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_RRULE_NthMonthly(struct exchange2ical *exchange2ical)
+{
+ struct icalrecurrencetype recurrence;
+ icalproperty *prop;
+ struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
+ uint32_t rdfDaysBitmask = pat->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern;
+ short idx = 0;
+ enum RecurrenceN setpos = pat->PatternTypeSpecific.MonthRecurrencePattern.N;
+
+ icalrecurrencetype_clear(&recurrence);
+ recurrence.freq = ICAL_MONTHLY_RECURRENCE;
+ recurrence.interval = pat->Period;
+
+ if (rdfDaysBitmask & Su) {
+ recurrence.by_day[idx] = ICAL_SUNDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & M) {
+ recurrence.by_day[idx] = ICAL_MONDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & Tu) {
+ recurrence.by_day[idx] = ICAL_TUESDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & W) {
+ recurrence.by_day[idx] = ICAL_WEDNESDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & Th) {
+ recurrence.by_day[idx] = ICAL_THURSDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & F) {
+ recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & Sa) {
+ recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
+ ++idx;
+ }
+ recurrence.by_day[idx] = ICAL_RECURRENCE_ARRAY_MAX;
+
+ if (setpos == RecurrenceN_First) {
+ recurrence.by_set_pos[0] = 1;
+ recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ } else if (setpos == RecurrenceN_Second) {
+ recurrence.by_set_pos[0] = 2;
+ recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ } else if (setpos == RecurrenceN_Third) {
+ recurrence.by_set_pos[0] = 3;
+ recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ } else if (setpos == RecurrenceN_Fourth) {
+ recurrence.by_set_pos[0] = 4;
+ recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ } else if (setpos == RecurrenceN_Last) {
+ recurrence.by_set_pos[0] = -1;
+ recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ }
+
+ recurrence.count = pat->OccurrenceCount;
+
+ // TODO: need answers from Microsoft on what is happening here
+ printf("endType:0x%x\n", pat->EndType);
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ if (pat->EndType == END_AFTER_N_OCCURRENCES) {
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ recurrence.count = pat->OccurrenceCount;
+ } else if (pat->EndType == END_AFTER_DATE) {
+ // TODO: set recurrence.until = pat->EndDate;
+ }
+
+ prop = icalproperty_new_rrule(recurrence);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_RRULE_Yearly(struct exchange2ical *exchange2ical)
+{
+ struct icalrecurrencetype recurrence;
+ icalproperty *prop;
+ struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
+ uint32_t day = pat->PatternTypeSpecific.Day;
+ struct icaltimetype icaltime;
+
+ icalrecurrencetype_clear(&recurrence);
+ recurrence.freq = ICAL_YEARLY_RECURRENCE;
+ recurrence.interval = (pat->Period / 12);
+
+ if (day == 0x0000001F) {
+ recurrence.by_month_day[0] = -1;
+ } else {
+ recurrence.by_month_day[0] = day;
+ }
+ recurrence.by_month_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
+
+ icaltime = get_icaltime_from_FILETIME(exchange2ical->apptStartWhole);
+ recurrence.by_month[0] = icaltime.month;
+ recurrence.by_month[1] = ICAL_RECURRENCE_ARRAY_MAX;
+
+ recurrence.count = pat->OccurrenceCount;
+
+ // TODO: need answers from Microsoft on what is happening here
+ printf("endType:0x%x\n", pat->EndType);
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ if (pat->EndType == END_AFTER_N_OCCURRENCES) {
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ recurrence.count = pat->OccurrenceCount;
+ } else if (pat->EndType == END_AFTER_DATE) {
+ // TODO: set recurrence.until = pat->EndDate;
+ }
+
+ prop = icalproperty_new_rrule(recurrence);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+void ical_property_RRULE_NthYearly(struct exchange2ical *exchange2ical)
+{
+ struct icalrecurrencetype recurrence;
+ icalproperty *prop;
+ struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
+ uint32_t rdfDaysBitmask = pat->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern;
+ short idx = 0;
+ enum RecurrenceN setpos = pat->PatternTypeSpecific.MonthRecurrencePattern.N;
+
+ struct icaltimetype icaltime;
+
+ icalrecurrencetype_clear(&recurrence);
+ recurrence.freq = ICAL_YEARLY_RECURRENCE;
+ recurrence.interval = (pat->Period / 12);
+
+ if (rdfDaysBitmask & Su) {
+ recurrence.by_day[idx] = ICAL_SUNDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & M) {
+ recurrence.by_day[idx] = ICAL_MONDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & Tu) {
+ recurrence.by_day[idx] = ICAL_TUESDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & W) {
+ recurrence.by_day[idx] = ICAL_WEDNESDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & Th) {
+ recurrence.by_day[idx] = ICAL_THURSDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & F) {
+ recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
+ ++idx;
+ }
+ if (rdfDaysBitmask & Sa) {
+ recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
+ ++idx;
+ }
+ recurrence.by_day[idx] = ICAL_RECURRENCE_ARRAY_MAX;
+
+ if (setpos == RecurrenceN_First) {
+ recurrence.by_set_pos[0] = 1;
+ recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ } else if (setpos == RecurrenceN_Second) {
+ recurrence.by_set_pos[0] = 2;
+ recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ } else if (setpos == RecurrenceN_Third) {
+ recurrence.by_set_pos[0] = 3;
+ recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ } else if (setpos == RecurrenceN_Fourth) {
+ recurrence.by_set_pos[0] = 4;
+ recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ } else if (setpos == RecurrenceN_Last) {
+ recurrence.by_set_pos[0] = -1;
+ recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ }
+
+ icaltime = get_icaltime_from_FILETIME(exchange2ical->apptStartWhole);
+ recurrence.by_month[0] = icaltime.month;
+ recurrence.by_month[1] = ICAL_RECURRENCE_ARRAY_MAX;
+
+ // TODO: need answers from Microsoft on what is happening here
+ printf("endType:0x%x\n", pat->EndType);
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ if (pat->EndType == END_AFTER_N_OCCURRENCES) {
+ printf("seeing %i occurences\n", pat->OccurrenceCount);
+ recurrence.count = pat->OccurrenceCount;
+ } else if (pat->EndType == END_AFTER_DATE) {
+ // TODO: set recurrence.until = pat->EndDate;
+ }
+
+ prop = icalproperty_new_rrule(recurrence);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_RRULE(struct exchange2ical *exchange2ical)
+{
+ struct RecurrencePattern *pat;
+
+ /* Sanity check */
+ if (!(exchange2ical->RecurrencePattern)) return;
+
+ pat = exchange2ical->RecurrencePattern;
+
+ switch(pat->PatternType) {
+ case PatternType_Day:
+ ical_property_RRULE_Daily(exchange2ical);
+ break;
+ case PatternType_Week:
+ ical_property_RRULE_Weekly(exchange2ical);
+ break;
+ case PatternType_Month:
+ if ((pat->Period % 12 ) == 0) {
+ ical_property_RRULE_Yearly(exchange2ical);
+ } else {
+ ical_property_RRULE_Monthly(exchange2ical);
+ }
+ break;
+ case PatternType_MonthNth:
+ if ((pat->Period % 12 ) == 0) {
+ ical_property_RRULE_NthYearly(exchange2ical);
+ } else {
+ ical_property_RRULE_NthMonthly(exchange2ical);
+ }
+ break;
+ default:
+ printf("RRULE pattern type not implemented yet!:0x%x\n", pat->PatternType);
+ }
+}
+
+
+void ical_property_RECURRENCE_ID(struct exchange2ical *exchange2ical)
+{
+ /* Sanity check */
+ if (!exchange2ical->ExceptionReplaceTime) return;
+
+ /* TODO: I'm too lazy to implement this today */
+ DEBUG(0, ("RECURRENCE-ID:\n"));
+}
+
+
+void ical_property_RESOURCES(struct exchange2ical *exchange2ical)
+{
+ char *NonSendableBcc = NULL;
+ icalproperty *prop;
+
+ /* Sanity check */
+ if (!exchange2ical->NonSendableBcc) return;
+
+ NonSendableBcc = talloc_strdup(exchange2ical->mem_ctx, exchange2ical->NonSendableBcc);
+ all_string_sub(NonSendableBcc, ";", ",", 0);
+ prop = icalproperty_new_resources(NonSendableBcc);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ talloc_free(NonSendableBcc);
+}
+
+
+void ical_property_SEQUENCE(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+ if (!exchange2ical->Sequence) {
+ prop = icalproperty_new_sequence(0);
+ } else {
+ prop = icalproperty_new_sequence(*(exchange2ical->Sequence));
+ }
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+void ical_property_SUMMARY(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+ icalparameter *language;
+
+ if (exchange2ical->Subject) {
+ prop = icalproperty_new_summary(exchange2ical->Subject);
+ } else {
+ prop = icalproperty_new_summary("");
+ }
+
+ if (exchange2ical->MessageLocaleId) {
+ const char *langtag = lcid_langcode2langtag( *(exchange2ical->MessageLocaleId) );
+ language = icalparameter_new_language( langtag );
+ icalproperty_add_parameter(prop, language);
+ }
+
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_TRANSP(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+
+ /* Sanity check */
+ if (!exchange2ical->BusyStatus) return;
+
+ switch (*exchange2ical->BusyStatus) {
+ case 0x00000000:
+ prop = icalproperty_new_transp(ICAL_TRANSP_TRANSPARENT);
+ break;
+ case 0x00000001:
+ case 0x00000002:
+ case 0x00000003:
+ prop = icalproperty_new_transp(ICAL_TRANSP_OPAQUE);
+ break;
+ default:
+ prop = icalproperty_new_transp(ICAL_TRANSP_NONE);
+ }
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+}
+
+
+void ical_property_TRIGGER(struct exchange2ical *exchange2ical)
+{
+ struct icaltriggertype duration;
+ icalproperty *prop;
+ if (!exchange2ical->ReminderDelta) return;
+
+ if (*exchange2ical->ReminderDelta == 0x5AE980E1) {
+ duration = icaltriggertype_from_int(-15 * 60);
+ prop = icalproperty_new_trigger(duration);
+ icalcomponent_add_property(exchange2ical->valarm, prop);
+ } else {
+ duration = icaltriggertype_from_int(*(exchange2ical->ReminderDelta) * -1 * 60);
+ prop = icalproperty_new_trigger(duration);
+ icalcomponent_add_property(exchange2ical->valarm, prop);
+ }
+}
+
+
+#define GLOBAL_OBJECT_ID_DATA_START "\x76\x43\x61\x6c\x2d\x55\x69\x64\x01\x00\x00\x00"
+
+void ical_property_UID(struct exchange2ical *exchange2ical)
+{
+ uint32_t i;
+ const char *uid;
+ char* outstr;
+ struct GlobalObjectId *GlbObjId;
+ icalproperty *prop;
+
+ /* Sanity check */
+ if (!exchange2ical->GlobalObjectId) {
+ // printf("GlobalObjectId not found\n");
+ return;
+ }
+
+ GlbObjId = get_GlobalObjectId(exchange2ical->mem_ctx, exchange2ical->GlobalObjectId);
+ if (!GlbObjId) {
+ // printf("could not get GlbObjId\n");
+ return;
+ }
+
+ outstr=talloc_init("uid");
+ if (GlbObjId->Size >= 12 && (0 == memcmp(GlbObjId->Data, GLOBAL_OBJECT_ID_DATA_START, 12))) {
+ // TODO: could this code overrun GlobalObjectId->lpb?
+ // TODO: I think we should start at 12, not at zero...
+ for (i = 0; i < 52; i++) {
+ char objID[6];
+ snprintf(objID, 6, "%.2X", exchange2ical->GlobalObjectId->lpb[i]);
+ outstr = talloc_strdup_append(outstr, objID);
+ }
+
+ uid = (const char *)&(GlbObjId->Data[13]);
+ outstr = talloc_strdup_append(outstr, uid);
+
+ } else {
+ for (i = 0; i < 16; i++) {
+ char objID[6];
+ snprintf(objID, 6, "%.2X", exchange2ical->GlobalObjectId->lpb[i]);
+ outstr = talloc_strdup_append(outstr, objID);
+ }
+ /* YH, YL, Month and D must be set to 0 */
+ outstr = talloc_strdup_append(outstr, "00000000");
+
+ for (i = 20; i < exchange2ical->GlobalObjectId->cb; i++) {
+ char objID[6];
+ snprintf(objID, 6, "%.2X", exchange2ical->GlobalObjectId->lpb[i]);
+ outstr = talloc_strdup_append(outstr, objID);
+ }
+ }
+ prop = icalproperty_new_uid(outstr);
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+ talloc_free(outstr);
+ talloc_free(GlbObjId);
+}
+
+
+static void ical_property_add_x_property_value(icalcomponent *parent, const char* propname, const char* value)
+{
+ icalproperty *prop;
+
+ /* Sanity checks */
+ if (!parent) return;
+ if (!propname) return;
+ if (!value) return;
+
+ prop = icalproperty_new_x(value);
+ icalproperty_set_x_name(prop, propname);
+ icalcomponent_add_property(parent, prop);
+}
+
+
+void ical_property_X_MICROSOFT_CDO_ATTENDEE_CRITICAL_CHANGE(struct exchange2ical *exchange2ical)
+{
+ struct tm *tm;
+ char outstr[200];
+
+ /* Sanity check */
+ if (!exchange2ical->AttendeeCriticalChange) return;
+
+ tm = get_tm_from_FILETIME(exchange2ical->AttendeeCriticalChange);
+ strftime(outstr, sizeof(outstr), "%Y%m%dT%H%M%SZ", tm);
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-ATTENDEE-CRITICAL-CHANGE", outstr);
+}
+
+
+void ical_property_X_MICROSOFT_CDO_BUSYSTATUS(struct exchange2ical *exchange2ical)
+{
+ switch (*exchange2ical->BusyStatus) {
+ case 0x00000000:
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-BUSYSTATUS", "FREE");
+ break;
+ case 0x00000001:
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-BUSYSTATUS", "TENTATIVE");
+ break;
+ case 0x00000002:
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-BUSYSTATUS", "BUSY");
+ break;
+ case 0x00000003:
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-BUSYSTATUS", "OOF");
+ break;
+ }
+}
+
+
+void ical_property_X_MICROSOFT_CDO_INTENDEDSTATUS(struct exchange2ical *exchange2ical)
+{
+ if (!exchange2ical->IntendedBusyStatus) return;
+
+ switch (*exchange2ical->IntendedBusyStatus) {
+ case 0x00000000:
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-INTENDEDSTATUS", "FREE");
+ break;
+ case 0x00000001:
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-INTENDEDSTATUS", "TENTATIVE");
+ break;
+ case 0x00000002:
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-INTENDEDSTATUS", "BUSY");
+ break;
+ case 0x00000003:
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-INTENDEDSTATUS", "OOF");
+ break;
+ }
+}
+
+
+void ical_property_X_MICROSOFT_CDO_OWNERAPPTID(struct exchange2ical *exchange2ical)
+{
+ char outstr[200];
+ /* Sanity check */
+ if (!exchange2ical->OwnerApptId) return;
+ snprintf(outstr, 200, "%d", *(exchange2ical->OwnerApptId));
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-OWNERAPPTID", outstr);
+}
+
+
+void ical_property_X_MICROSOFT_CDO_OWNER_CRITICAL_CHANGE(struct exchange2ical *exchange2ical)
+{
+ struct tm *tm;
+ char outstr[200];
+
+ /* Sanity check */
+ if (!exchange2ical->OwnerCriticalChange) return;
+
+ /* FIXME: if the property doesn't exist, we should use system
+ * time instead
+ */
+
+ tm = get_tm_from_FILETIME(exchange2ical->OwnerCriticalChange);
+ strftime(outstr, sizeof(outstr), "%Y%m%dT%H%M%SZ", tm);
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-OWNER-CRITICAL-CHANGE", outstr);
+}
+
+
+void ical_property_X_MICROSOFT_CDO_REPLYTIME(struct exchange2ical *exchange2ical)
+{
+ struct tm *tm;
+ char outstr[200];
+
+ /* Sanity check */
+ if (!exchange2ical->apptReplyTime) return;
+
+ tm = get_tm_from_FILETIME(exchange2ical->apptReplyTime);
+ strftime(outstr, sizeof(outstr), "%Y%m%dT%H%M%SZ", tm);
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-REPLYTIME", outstr);
+}
+
+
+void ical_property_X_MICROSOFT_DISALLOW_COUNTER(struct exchange2ical *exchange2ical)
+{
+ /* Sanity check */
+ if (!exchange2ical->NotAllowPropose) return;
+
+ if (*(exchange2ical->NotAllowPropose) == true) {
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-DISALLOW-COUNTER", "TRUE");
+ } else {
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-DISALLOW-COUNTER", "FALSE");
+ }
+}
+
+
+void ical_property_X_MS_OLK_ALLOWEXTERNCHECK(struct exchange2ical *exchange2ical)
+{
+ /* Sanity check */
+ if (!exchange2ical->AllowExternCheck) return;
+
+ if (*(exchange2ical->AllowExternCheck) == true) {
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-ALLOWEXTERNCHECK", "TRUE");
+ } else {
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-ALLOWEXTERNCHECK", "FALSE");
+ }
+}
+
+
+void ical_property_X_MS_OLK_APPTLASTSEQUENCE(struct exchange2ical *exchange2ical)
+{
+ char outstr[20];
+ /* Sanity check */
+ if (!exchange2ical->apptLastSequence) return;
+
+ snprintf(outstr, 20, "%d", *exchange2ical->apptLastSequence);
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-APPTLASTSEQUENCE", outstr);
+}
+
+
+void ical_property_X_MS_OLK_APPTSEQTIME(struct exchange2ical *exchange2ical)
+{
+ struct tm *tm = NULL;
+ char outstr[200];
+
+ /* Sanity check */
+ if (!exchange2ical->apptSeqTime) return;
+
+ tm = get_tm_from_FILETIME(exchange2ical->apptSeqTime);
+ strftime(outstr, sizeof(outstr), "%Y%m%dT%H%M%SZ", tm);
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-APPTSEQTIME", outstr);
+}
+
+
+void ical_property_X_MS_OLK_AUTOFILLLOCATION(struct exchange2ical *exchange2ical)
+{
+ /* Sanity check */
+ if (!exchange2ical->AutoFillLocation) return;
+
+ if (*(exchange2ical->AutoFillLocation) == true) {
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-AUTOFILLLOCATION", "TRUE");
+ } else {
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-AUTOFILLLOCATION", "FALSE");
+ }
+}
+
+
+void ical_property_X_MS_OLK_AUTOSTARTCHECK(struct exchange2ical *exchange2ical)
+{
+ /* Sanity check */
+ if (!exchange2ical->AutoStartCheck) return;
+ if (*(exchange2ical->AutoStartCheck) == true) {
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-AUTOSTARTCHECK", "TRUE");
+ } else {
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-AUTOSTARTCHECK", "FALSE");
+ }
+}
+
+
+void ical_property_X_MS_OLK_COLLABORATEDOC(struct exchange2ical *exchange2ical)
+{
+ /* Sanity check */
+ if (!exchange2ical->CollaborateDoc) return;
+
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-COLLABORATEDOC", exchange2ical->CollaborateDoc);
+}
+
+
+void ical_property_X_MS_OLK_CONFCHECK(struct exchange2ical *exchange2ical)
+{
+ /* Sanity check */
+ if (!exchange2ical->ConfCheck) return;
+
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-CONFCHECK", (*exchange2ical->ConfCheck == true) ? "TRUE" : "FALSE");
+}
+
+
+void ical_property_X_MS_OLK_CONFTYPE(struct exchange2ical *exchange2ical)
+{
+ char outstr[20];
+ /* Sanity check */
+ if (!exchange2ical->ConfType) return;
+
+ snprintf(outstr, 20, "%d", *exchange2ical->ConfType);
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-CONFTYPE", outstr);
+}
+
+
+void ical_property_X_MS_OLK_DIRECTORY(struct exchange2ical *exchange2ical)
+{
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-DIRECTORY", exchange2ical->Directory);
+}
+
+
+void ical_property_X_MS_OLK_MWSURL(struct exchange2ical *exchange2ical)
+{
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-MWSURL", exchange2ical->MWSURL);
+}
+
+
+void ical_property_X_MS_OLK_NETSHOWURL(struct exchange2ical *exchange2ical)
+{
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-NETSHOWURL", exchange2ical->NetShowURL);
+}
+
+void ical_property_X_MS_OLK_ONLINEPASSWORD(struct exchange2ical *exchange2ical)
+{
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-ONLINEPASSWORD", exchange2ical->OnlinePassword);
+}
+
+void ical_property_X_MS_OLK_ORGALIAS(struct exchange2ical *exchange2ical)
+{
+ ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-ORGALIAS", exchange2ical->OrgAlias);
+}
+
+
+// TODO: double check this - need an example.
+void ical_property_X_MS_OLK_SENDER(struct exchange2ical *exchange2ical)
+{
+ icalproperty *prop;
+ icalparameter *param;
+ char outstr[200];
+
+ /* Sanity check */
+ if (!exchange2ical->apptStateFlags) return;
+ if (!(*exchange2ical->apptStateFlags & 0x1)) return;
+ if (!exchange2ical->SenderName) return;
+
+ if (exchange2ical->SenderEmailAddress) {
+ snprintf(outstr, 200, "mailto:%s",exchange2ical->SenderEmailAddress);
+ prop = icalproperty_new_x(outstr);
+ } else {
+ prop = icalproperty_new_x("invalid:nomail");
+ }
+
+ icalproperty_set_x_name(prop, "X-MS-OLK-SENDER");
+ icalcomponent_add_property(exchange2ical->vevent, prop);
+
+ param = icalparameter_new_cn(exchange2ical->SenderName);
+ icalproperty_add_parameter(prop, param);
+}
Added: trunk/openchange/utils/exchange2ical/exchange2ical_utils.c
===================================================================
--- trunk/openchange/utils/exchange2ical/exchange2ical_utils.c (rev 0)
+++ trunk/openchange/utils/exchange2ical/exchange2ical_utils.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,249 @@
+/*
+ Common conversion routines for exchange2ical
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 <utils/exchange2ical/exchange2ical.h>
+
+bool has_component_DAYLIGHT(struct exchange2ical *exchange2ical)
+{
+ if (!exchange2ical->TimeZoneStruct) return false;
+ if (!exchange2ical->TimeZoneStruct->stStandardDate.wYear &&
+ !exchange2ical->TimeZoneStruct->stStandardDate.wMonth &&
+ !exchange2ical->TimeZoneStruct->stStandardDate.wDayOfWeek &&
+ !exchange2ical->TimeZoneStruct->stStandardDate.wDay &&
+ !exchange2ical->TimeZoneStruct->stStandardDate.wHour &&
+ !exchange2ical->TimeZoneStruct->stStandardDate.wMinute &&
+ !exchange2ical->TimeZoneStruct->stStandardDate.wSecond &&
+ !exchange2ical->TimeZoneStruct->stStandardDate.wMilliseconds) return false;
+
+ return true;
+}
+
+char *get_ical_date(TALLOC_CTX *mem_ctx, struct SYSTEMTIME *time)
+{
+ char *date;
+
+ date = talloc_asprintf(mem_ctx, "%.4d%.2d%.2dT%.2d%.2d%.2d", time->wYear + 1601, time->wMonth,
+ time->wDay, time->wHour, time->wMinute, time->wSecond);
+ return date;
+}
+
+
+static struct ical_method ical_method[] = {
+ { ICAL_METHOD_PUBLISH, ICAL_PARTSTAT_NONE, "IPM.Appointment" },
+ { ICAL_METHOD_REQUEST, ICAL_PARTSTAT_NONE, "IPM.Schedule.Meeting.Request" },
+ { ICAL_METHOD_REPLY, ICAL_PARTSTAT_ACCEPTED, "IPM.Schedule.Meeting.Resp.Pos" },
+ { ICAL_METHOD_REPLY, ICAL_PARTSTAT_TENTATIVE,"IPM.Schedule.Meeting.Resp.Tent"},
+ { ICAL_METHOD_REPLY, ICAL_PARTSTAT_DECLINED, "IPM.Schedule.Meeting.Resp.Neg" },
+ { ICAL_METHOD_CANCEL, ICAL_PARTSTAT_NONE, "IPM.Schedule.Meeting.Canceled" },
+ { ICAL_METHOD_NONE, ICAL_PARTSTAT_NONE, NULL }
+};
+
+enum icalproperty_method get_ical_method(const char *msgclass)
+{
+ uint32_t i;
+
+ /* Sanity check */
+ if (!msgclass) return ICAL_METHOD_NONE;
+
+ for (i = 0; ical_method[i].PidTagMessageClass; i++) {
+ if (!strcmp(msgclass, ical_method[i].PidTagMessageClass)) {
+ return ical_method[i].method;
+ }
+ }
+
+ return ICAL_METHOD_NONE;
+}
+
+
+static struct ical_calendartype ical_calendartype[] = {
+ { 0x0001, "Gregorian" },
+ { 0x0002, "Gregorian_us" },
+ { 0x0003, "Japan" },
+ { 0x0004, "Taiwan" },
+ { 0x0005, "Korean" },
+ { 0x0006, "Hijri" },
+ { 0x0007, "Thai" },
+ { 0x0008, "Hebrew" },
+ { 0x0009, "GregorianMeFrench" },
+ { 0x000A, "GregorianArabic" },
+ { 0x000B, "GregorianXlitEnglish" },
+ { 0x000C, "GregorianXlitFrench" },
+ { 0x000E, "JapanLunar" },
+ { 0x000F, "ChineseLunar" },
+ { 0x0010, "Saka" },
+ { 0x0011, "LunarEtoChn" },
+ { 0x0012, "LunarEthoKor" },
+ { 0x0013, "LunarRockuyou" },
+ { 0x0014, "KoreanLunar" },
+ { 0x0017, "Umalqura" },
+ { 0x0000, NULL }
+};
+
+const char *get_ical_calendartype(uint16_t CalendarType)
+{
+ uint32_t i;
+
+ /* Sanity check */
+ if (!CalendarType) return NULL;
+
+ for (i = 0; ical_calendartype[i].type; i++) {
+ if (CalendarType == ical_calendartype[i].type) {
+ return ical_calendartype[i].calendar;
+ }
+ }
+
+ return NULL;
+}
+
+enum icalparameter_partstat get_ical_partstat(const char *msgclass)
+{
+ uint32_t i;
+
+ /* Sanity check */
+ if (!msgclass) return ICAL_PARTSTAT_NONE;
+
+ for (i = 0; ical_method[i].PidTagMessageClass; i++) {
+ if (!strcmp(msgclass, ical_method[i].PidTagMessageClass)) {
+ return ical_method[i].partstat;
+ }
+ }
+
+ return ICAL_PARTSTAT_NONE;
+}
+
+
+static struct ical_class ical_class[] = {
+ { 0x00000000, ICAL_CLASS_PUBLIC },
+ { 0x00000001, ICAL_CLASS_X },
+ { 0x00000002, ICAL_CLASS_PRIVATE },
+ { 0x00000003, ICAL_CLASS_CONFIDENTIAL },
+ { 0x00000000, ICAL_CLASS_NONE }
+};
+
+enum icalproperty_class get_ical_class(uint32_t sensivity)
+{
+ uint32_t i;
+
+ for (i = 0; ical_class[i].classtype != ICAL_CLASS_NONE; ++i) {
+ if (sensivity == ical_class[i].sensivity) {
+ return ical_class[i].classtype;
+ }
+ }
+
+ return ICAL_CLASS_NONE;
+}
+
+struct icaltimetype get_icaltimetype_from_tm(struct tm *tm)
+{
+ icaltimetype tt;
+
+ tt.year = tm->tm_year;
+ tt.month = tm->tm_mon;
+ tt.day = tm->tm_mday;
+ tt.hour = tm->tm_hour;
+ tt.minute = tm->tm_min;
+ tt.second = tm->tm_sec;
+
+ tt.is_utc = 0;
+ tt.is_date = 0;
+ tt.is_daylight = 0;
+ tt.zone = 0;
+
+ return tt;
+}
+
+struct icaldatetimeperiodtype get_icaldatetimeperiodtype_from_tm(struct tm *tm)
+{
+ struct icaldatetimeperiodtype tt;
+
+ // TODO: build tt here!
+
+ return tt;
+}
+
+struct tm *get_tm_from_FILETIME(const struct FILETIME *ft)
+{
+ NTTIME time;
+ struct timeval t;
+ struct tm *tm;
+
+ time = ft->dwHighDateTime;
+ time = time << 32;
+ time |= ft->dwLowDateTime;
+ nttime_to_timeval(&t, time);
+ tm = localtime(&t.tv_sec);
+
+ return tm;
+}
+
+struct icaltimetype get_icaltime_from_FILETIME(const struct FILETIME *ft)
+{
+ struct icaltimetype tt;
+ NTTIME nttime;
+ struct timeval temp_timeval;
+ struct tm *tm;
+
+ nttime = ft->dwHighDateTime;
+ nttime = nttime << 32;
+ nttime |= ft->dwLowDateTime;
+ nttime_to_timeval(&temp_timeval, nttime);
+ tm = gmtime(&temp_timeval.tv_sec);
+
+ tt.year = tm->tm_year + 1900;
+ tt.month = tm->tm_mon + 1;
+ tt.day = tm->tm_mday;
+ tt.hour = tm->tm_hour;
+ tt.minute = tm->tm_min;
+ tt.second = tm->tm_sec;
+ tt.is_date = 0;
+ tt.is_utc = 1;
+ tt.is_daylight = 0;
+ tt.zone = NULL;
+
+ return tt;
+}
+
+struct icaltimetype get_icaldate_from_FILETIME(const struct FILETIME *ft)
+{
+ struct icaltimetype tt;
+ NTTIME nttime;
+ struct timeval temp_timeval;
+ struct tm *tm;
+
+ nttime = ft->dwHighDateTime;
+ nttime = nttime << 32;
+ nttime |= ft->dwLowDateTime;
+ nttime_to_timeval(&temp_timeval, nttime);
+ tm = gmtime(&temp_timeval.tv_sec);
+
+ tt.year = tm->tm_year + 1900;
+ tt.month = tm->tm_mon + 1;
+ tt.day = tm->tm_mday;
+ tt.hour = 0;
+ tt.minute = 0;
+ tt.second = 0;
+ tt.is_date = 1;
+ tt.is_utc = 1;
+ tt.is_daylight = 0;
+ tt.zone = NULL;
+
+ return tt;
+}
\ No newline at end of file
Added: trunk/openchange/utils/exchange2mbox.c
===================================================================
--- trunk/openchange/utils/exchange2mbox.c (rev 0)
+++ trunk/openchange/utils/exchange2mbox.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,820 @@
+/*
+ Convert Exchange mails to mbox
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2007
+
+ 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 <samba/popt.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <param.h>
+#include <magic.h>
+
+#include "openchange-tools.h"
+
+/* Ugly and lazy but working ... */
+#define BOUNDARY "DocE+STaALJfprDB"
+#define MAX_READ_SIZE 0x4000
+#define MESSAGEID "Message-ID: "
+#define MESSAGEID_LEN 11
+
+/**
+ * delete a message on the exchange server
+ */
+static bool delete_message(TALLOC_CTX *mem_ctx, char *msgid,
+ const char *profname, const char *password)
+{
+ enum MAPISTATUS retval;
+ struct mapi_session *session;
+ mapi_object_t obj_store;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_table;
+ mapi_id_t id_inbox;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ uint32_t i;
+ uint64_t id_message;
+
+ if (!msgid) {
+ return false;
+ }
+
+ retval = MapiLogonEx(&session, profname, password);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Open the default message store */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Open Inbox */
+ retval = GetReceiveFolder(&obj_store, &id_inbox, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_init(&obj_inbox);
+ retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_init(&obj_table);
+ retval = GetContentsTable(&obj_inbox, &obj_table, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x3,
+ PR_FID,
+ PR_MID,
+ PR_INTERNET_MESSAGE_ID);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ while ((retval = QueryRows(&obj_table, 0xa, TBL_ADVANCE, &SRowSet)) == MAPI_E_SUCCESS) {
+ if (!SRowSet.cRows) break;
+ for (i = 0; i < SRowSet.cRows; i++) {
+ const char *message_id;
+
+ message_id = (const char *)find_SPropValue_data(&(SRowSet.aRow[i]), PR_INTERNET_MESSAGE_ID);
+
+ if (message_id && !strncmp(message_id, msgid, strlen(msgid))) {
+ id_message = SRowSet.aRow[i].lpProps[1].value.d;
+ retval = DeleteMessage(&obj_inbox, &id_message, 1);
+ if (retval != MAPI_E_SUCCESS) return false;
+ break;
+ }
+ }
+ }
+
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_inbox);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+/**
+ * Fetch message ids from the existing mbox
+ */
+static uint32_t update(TALLOC_CTX *mem_ctx, FILE *fp,
+ const char *profdb, char *profname,
+ const char *password)
+{
+ enum MAPISTATUS retval;
+ struct mapi_profile profile;
+ size_t read_size;
+ char *line = NULL;
+ ssize_t size;
+ const char *msgid;
+ char *id;
+ char **mbox_msgids;
+ char **prof_msgids;
+ unsigned int mbox_count = 0;
+ unsigned int count;
+ unsigned int i, j;
+ bool found = false;
+
+ retval = MAPIInitialize(profdb);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ if (!profname) {
+ retval = GetDefaultProfile(&profname);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+ }
+
+ retval = OpenProfile(&profile, profname, password);
+ MAPI_RETVAL_IF(retval, retval, profname);
+
+ mbox_msgids = talloc_zero(mem_ctx, char *);
+ /* Add Message-ID attribute to the profile if it is missing */
+#if defined(__FreeBSD__)
+ while ((line = fgetln(fp, &read_size)) != NULL) {
+#else
+ while ((size = getline(&line, &read_size, fp)) != -1) {
+#endif
+ if (line && !strncmp(line, MESSAGEID, strlen(MESSAGEID))) {
+ msgid = strstr(line, MESSAGEID);
+ id = talloc_strdup(mem_ctx, msgid + strlen(MESSAGEID));
+ id[strlen(id) - 1] = 0;
+
+ mbox_msgids = talloc_realloc(mem_ctx, mbox_msgids, char *, mbox_count + 2);
+ mbox_msgids[mbox_count] = talloc_strdup(mem_ctx, id);
+ mbox_count++;
+
+ retval = FindProfileAttr(&profile, "Message-ID", id);
+ if (GetLastError() == MAPI_E_NOT_FOUND) {
+ errno = 0;
+ printf("[+] Adding %s to %s\n", id, profname);
+ retval = mapi_profile_add_string_attr(profname, "Message-ID", id);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("mapi_profile_add_string_attr", GetLastError());
+ talloc_free(profname);
+ MAPIUninitialize();
+ return -1;
+ }
+ }
+ talloc_free(id);
+ }
+
+ }
+ if (line)
+ free(line);
+
+ /* Remove Message-ID and update Exchange mailbox if a
+ * Message-ID is missing in mbox
+ */
+ retval = GetProfileAttr(&profile, "Message-ID", &count, &prof_msgids);
+ MAPI_RETVAL_IF(retval, retval, profname);
+
+ if (count != mbox_count) {
+ printf("{+] Synchonizing mbox with Exchange mailbox\n");
+ for (i = 0; i < count; i++) {
+ found = false;
+ for (j = 0; j < mbox_count; j++) {
+ if (!strcmp(prof_msgids[i], mbox_msgids[j])) {
+ found = true;
+ }
+ }
+ if (found == false) {
+ if (delete_message(mem_ctx, prof_msgids[i], profname, password) == true) {
+ printf("%s deleted from the Exchange server\n", prof_msgids[i]);
+ mapi_profile_delete_string_attr(profname, "Message-ID", prof_msgids[i]);
+ }
+ }
+ }
+ } else {
+ printf("[+] mbox already synchronized with Exchange Mailbox\n");
+ }
+
+ talloc_free(prof_msgids);
+ talloc_free(mbox_msgids);
+ talloc_free(profname);
+ MAPIUninitialize();
+
+ return MAPI_E_SUCCESS;
+}
+
+static const char *get_filename(const char *filename)
+{
+ const char *substr;
+
+ if (!filename) return NULL;
+
+ substr = rindex(filename, '/');
+ if (substr) return substr;
+
+ return filename;
+}
+
+/*
+ encode as base64
+ Samba4 code
+ caller frees
+*/
+static char *ldb_base64_encode(void *mem_ctx, const char *buf, int len)
+{
+ const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ int bit_offset, byte_offset, idx, i;
+ const uint8_t *d = (const uint8_t *)buf;
+ int bytes = (len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
+ char *out;
+
+ out = talloc_array(mem_ctx, char, bytes+pad_bytes+1);
+ if (!out) return NULL;
+
+ for (i=0;i<bytes;i++) {
+ byte_offset = (i*6)/8;
+ bit_offset = (i*6)%8;
+ if (bit_offset < 3) {
+ idx = (d[byte_offset] >> (2-bit_offset)) & 0x3F;
+ } else {
+ idx = (d[byte_offset] << (bit_offset-2)) & 0x3F;
+ if (byte_offset+1 < len) {
+ idx |= (d[byte_offset+1] >> (8-(bit_offset-2)));
+ }
+ }
+ out[i] = b64[idx];
+ }
+
+ for (;i<bytes+pad_bytes;i++)
+ out[i] = '=';
+ out[i] = 0;
+
+ return out;
+}
+
+
+static char *get_base64_attachment(TALLOC_CTX *mem_ctx, mapi_object_t obj_attach, const uint32_t size, char **magic)
+{
+ enum MAPISTATUS retval;
+ const char *tmp;
+ mapi_object_t obj_stream;
+ uint32_t stream_size;
+ uint16_t read_size;
+ unsigned char buf[MAX_READ_SIZE];
+ uint32_t max_read_size = MAX_READ_SIZE;
+ DATA_BLOB data;
+ magic_t cookie = NULL;
+
+ data.length = 0;
+ data.data = talloc_size(mem_ctx, size);
+
+ retval = OpenStream(&obj_attach, PR_ATTACH_DATA_BIN, 0, &obj_stream);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ if (size < MAX_READ_SIZE) {
+ retval = ReadStream(&obj_stream, buf, size, &read_size);
+ if (retval != MAPI_E_SUCCESS) return NULL;
+ memcpy(data.data, buf, read_size);
+ }
+
+ for (stream_size = 0; stream_size < size; stream_size += 0x4000) {
+ retval = ReadStream(&obj_stream, buf, max_read_size, &read_size);
+ if (retval != MAPI_E_SUCCESS) return NULL;
+ memcpy(data.data + stream_size, buf, read_size);
+ }
+
+ data.length = size;
+
+ cookie = magic_open(MAGIC_MIME);
+ if (cookie == NULL) {
+ printf("%s\n", magic_error(cookie));
+ return NULL;
+ }
+ if (magic_load(cookie, NULL) == -1) {
+ printf("%s\n", magic_error(cookie));
+ return NULL;
+ }
+ tmp = magic_buffer(cookie, (void *)data.data, data.length);
+ *magic = talloc_strdup(mem_ctx, tmp);
+ magic_close(cookie);
+
+ /* convert attachment to base64 */
+ return (ldb_base64_encode(mem_ctx, (const char *)data.data, data.length));
+}
+
+/**
+ Sample mbox mail:
+
+ From Administrator Mon Apr 23 14:43:01 2007
+ Date: Mon Apr 23 14:43:01 2007
+ From: Administrator
+ To: Julien Kerihuel
+ Subject: This is the subject
+
+ This is a sample mail
+
+**/
+
+static bool message2mbox(TALLOC_CTX *mem_ctx, FILE *fp,
+ struct SRow *aRow, mapi_object_t *obj_message)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_tb_attach;
+ mapi_object_t obj_attach;
+ const uint64_t *delivery_date;
+ const char *date = NULL;
+ const char *from = NULL;
+ const char *to = NULL;
+ const char *cc = NULL;
+ const char *bcc = NULL;
+ const char *subject = NULL;
+ const char *msgid;
+ DATA_BLOB body;
+ const char *attach_filename;
+ const uint32_t *attach_size;
+ char *attachment_data;
+ const uint32_t *has_attach = NULL;
+ const uint32_t *attach_num = NULL;
+ char *magic;
+ char *line = NULL;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SPropValue *lpProps;
+ struct SRow aRow2;
+ struct SRowSet rowset_attach;
+ uint32_t count;
+ uint8_t format;
+ unsigned int i;
+ ssize_t len;
+
+ has_attach = (const uint32_t *) octool_get_propval(aRow, PR_HASATTACH);
+ from = (const char *) octool_get_propval(aRow, PR_SENT_REPRESENTING_NAME);
+ to = (const char *) octool_get_propval(aRow, PR_DISPLAY_TO);
+ cc = (const char *) octool_get_propval(aRow, PR_DISPLAY_CC);
+ bcc = (const char *) octool_get_propval(aRow, PR_DISPLAY_BCC);
+
+ if (!to && !cc && !bcc) {
+ return false;
+ }
+
+ delivery_date = (const uint64_t *)octool_get_propval(aRow, PR_MESSAGE_DELIVERY_TIME);
+ if (delivery_date) {
+ date = nt_time_string(mem_ctx, *delivery_date);
+ } else {
+ date = "None";
+ }
+
+ subject = (const char *) octool_get_propval(aRow, PR_CONVERSATION_TOPIC);
+ msgid = (const char *) octool_get_propval(aRow, PR_INTERNET_MESSAGE_ID);
+
+ retval = octool_get_body(mem_ctx, obj_message, aRow, &body);
+
+ /* First line From */
+ line = talloc_asprintf(mem_ctx, "From \"%s\" %s\n", from, date);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+
+ /* Second line: Date */
+ line = talloc_asprintf(mem_ctx, "Date: %s\n", date);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+
+ /* Third line From */
+ line = talloc_asprintf(mem_ctx, "From: %s\n", from);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+
+ /* To, Cc, Bcc */
+ if (to) {
+ line = talloc_asprintf(mem_ctx, "To: %s\n", to);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+ }
+
+ if (cc) {
+ line = talloc_asprintf(mem_ctx, "Cc: %s\n", cc);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+ }
+
+ if (bcc) {
+ line = talloc_asprintf(mem_ctx, "Bcc: %s\n", bcc);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+ }
+
+ /* Subject */
+ if (subject) {
+ line = talloc_asprintf(mem_ctx, "Subject: %s\n", subject);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+ }
+
+ if (msgid) {
+ line = talloc_asprintf(mem_ctx, "Message-ID: %s\n", msgid);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+ }
+
+ /* Set multi-type if we have attachment */
+ if (has_attach && *has_attach) {
+ line = talloc_asprintf(mem_ctx, "Content-Type: multipart/mixed; boundary=\"%s\"\n", BOUNDARY);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+ }
+
+ /* body */
+ if (body.length) {
+ if (has_attach && *has_attach) {
+ line = talloc_asprintf(mem_ctx, "--%s\n", BOUNDARY);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+ }
+ retval = GetBestBody(obj_message, &format);
+ switch (format) {
+ case olEditorText:
+ line = talloc_asprintf(mem_ctx, "Content-Type: text/plain; charset=us-ascii\n");
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+
+ /* Just display UTF8 content inline */
+ line = talloc_asprintf(mem_ctx, "Content-Disposition: inline\n");
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+ break;
+ case olEditorHTML:
+ line = talloc_asprintf(mem_ctx, "Content-Type: text/html\n");
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+ break;
+ case olEditorRTF:
+ line = talloc_asprintf(mem_ctx, "Content-Type: text/rtf\n");
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+
+ line = talloc_asprintf(mem_ctx, "--%s\n", BOUNDARY);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+ break;
+ }
+
+ len = fwrite(body.data, body.length, 1, fp);
+ talloc_free(body.data);
+ }
+
+ /* We are now fetching attachments */
+ if (has_attach && *has_attach) {
+ mapi_object_init(&obj_tb_attach);
+ retval = GetAttachmentTable(obj_message, &obj_tb_attach);
+ if (retval == MAPI_E_SUCCESS) {
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_ATTACH_NUM);
+ retval = SetColumns(&obj_tb_attach, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ retval = QueryRows(&obj_tb_attach, 0xa, TBL_ADVANCE, &rowset_attach);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ for (i = 0; i < rowset_attach.cRows; i++) {
+ attach_num = (const uint32_t *)find_SPropValue_data(&(rowset_attach.aRow[i]), PR_ATTACH_NUM);
+ retval = OpenAttach(obj_message, *attach_num, &obj_attach);
+ if (retval == MAPI_E_SUCCESS) {
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x3,
+ PR_ATTACH_FILENAME,
+ PR_ATTACH_LONG_FILENAME,
+ PR_ATTACH_SIZE);
+ lpProps = talloc_zero(mem_ctx, struct SPropValue);
+ retval = GetProps(&obj_attach, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval == MAPI_E_SUCCESS) {
+ aRow2.ulAdrEntryPad = 0;
+ aRow2.cValues = count;
+ aRow2.lpProps = lpProps;
+
+ attach_filename = get_filename(octool_get_propval(&aRow2, PR_ATTACH_LONG_FILENAME));
+ if (!attach_filename || (attach_filename && !strcmp(attach_filename, ""))) {
+ attach_filename = get_filename(octool_get_propval(&aRow2, PR_ATTACH_FILENAME));
+ }
+ attach_size = (const uint32_t *) octool_get_propval(&aRow2, PR_ATTACH_SIZE);
+ attachment_data = get_base64_attachment(mem_ctx, obj_attach, *attach_size, &magic);
+ if (attachment_data) {
+ line = talloc_asprintf(mem_ctx, "\n\n--%s\n", BOUNDARY);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+
+ line = talloc_asprintf(mem_ctx, "Content-Disposition: attachment; filename=\"%s\"\n", attach_filename);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+
+ line = talloc_asprintf(mem_ctx, "Content-Type: \"%s\"\n", magic);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+
+ line = talloc_asprintf(mem_ctx, "Content-Transfer-Encoding: base64\n\n");
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+
+ len = fwrite(attachment_data, strlen(attachment_data), 1, fp);
+ talloc_free(attachment_data);
+ }
+ }
+ MAPIFreeBuffer(lpProps);
+ }
+ }
+ if (has_attach && *has_attach) {
+ line = talloc_asprintf(mem_ctx, "\n\n--%s--\n\n\n", BOUNDARY);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
+ }
+ }
+
+ }
+
+ len = fwrite("\n\n\n", 3, 1, fp);
+
+ return true;
+}
+
+int main(int argc, const char *argv[])
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct mapi_session *session = NULL;
+ struct mapi_profile *profile;
+ mapi_object_t obj_store;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_table;
+ mapi_object_t obj_message;
+ mapi_id_t id_inbox;
+ uint32_t count;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SPropValue *lpProps;
+ struct SRow aRow;
+ struct SRowSet rowset;
+ poptContext pc;
+ int opt;
+ FILE *fp;
+ unsigned int i;
+ const char *opt_profdb = NULL;
+ char *opt_profname = NULL;
+ const char *opt_password = NULL;
+ const char *opt_mbox = NULL;
+ bool opt_update = false;
+ bool opt_dumpdata = false;
+ const char *opt_debug = NULL;
+ const char *msgid;
+
+ enum {OPT_PROFILE_DB=1000, OPT_PROFILE, OPT_PASSWORD, OPT_MBOX, OPT_UPDATE,
+ 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"},
+ {"mbox", 'm', POPT_ARG_STRING, NULL, OPT_MBOX, "set the mbox file", "FILENAME"},
+ {"update", 'u', POPT_ARG_NONE, 0, OPT_UPDATE, "mirror mbox changes back to the Exchange server", NULL},
+ {"debuglevel", 'd', POPT_ARG_STRING, NULL, OPT_DEBUG, "set the debug level", "LEVEL"},
+ {"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMPDATA, "dump the hex data", NULL},
+ POPT_OPENCHANGE_VERSION
+ { NULL, 0, POPT_ARG_NONE, NULL, 0, NULL, NULL }
+ };
+
+ mem_ctx = talloc_named(NULL, 0, "exchange2mbox");
+
+ pc = poptGetContext("exchange2mbox", 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_MBOX:
+ opt_mbox = poptGetOptArg(pc);
+ break;
+ case OPT_UPDATE:
+ opt_update = true;
+ 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"));
+ }
+
+ if (!opt_mbox) {
+ opt_mbox = talloc_asprintf(mem_ctx, DEFAULT_MBOX, getenv("HOME"));
+ }
+
+ /**
+ * Open the MBOX
+ */
+
+ if ((fp = fopen(opt_mbox, "a+")) == NULL) {
+ perror("fopen");
+ exit (1);
+ }
+
+ if (opt_update == true) {
+ retval = update(mem_ctx, fp, opt_profdb, opt_profname, opt_password);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ printf("Problem encountered during update\n");
+ exit (1);
+ }
+ }
+
+ /**
+ * Initialize MAPI subsystem
+ */
+
+ retval = MAPIInitialize(opt_profdb);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ /* debug options */
+ SetMAPIDumpData(opt_dumpdata);
+
+ if (opt_debug) {
+ SetMAPIDebugLevel(atoi(opt_debug));
+ }
+
+ /* if no profile is supplied use the default one */
+ if (!opt_profname) {
+ retval = GetDefaultProfile(&opt_profname);
+ if (retval != MAPI_E_SUCCESS) {
+ printf("No profile specified and no default profile found\n");
+ exit (1);
+ }
+ }
+
+ retval = MapiLogonEx(&session, opt_profname, opt_password);
+ talloc_free(opt_profname);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MapiLogonEx", GetLastError());
+ exit (1);
+ }
+ profile = session->profile;
+
+ /* Open the default message store */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("OpenMsgStore", GetLastError());
+ exit (1);
+ }
+
+ /* Open Inbox */
+ retval = GetReceiveFolder(&obj_store, &id_inbox, NULL);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ mapi_object_init(&obj_inbox);
+ retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ mapi_object_init(&obj_table);
+ retval = GetContentsTable(&obj_inbox, &obj_table, 0, &count);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_INTERNET_MESSAGE_ID);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ while ((retval = QueryRows(&obj_table, 0xa, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND && rowset.cRows) {
+ for (i = 0; i < rowset.cRows; i++) {
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(&obj_store,
+ rowset.aRow[i].lpProps[0].value.d,
+ rowset.aRow[i].lpProps[1].value.d,
+ &obj_message, 0);
+ if (GetLastError() == MAPI_E_SUCCESS) {
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x13,
+ PR_INTERNET_MESSAGE_ID,
+ PR_INTERNET_MESSAGE_ID_UNICODE,
+ PR_CONVERSATION_TOPIC,
+ PR_CONVERSATION_TOPIC_UNICODE,
+ PR_MESSAGE_DELIVERY_TIME,
+ PR_MSG_EDITOR_FORMAT,
+ PR_BODY,
+ PR_BODY_UNICODE,
+ PR_HTML,
+ PR_RTF_COMPRESSED,
+ PR_SENT_REPRESENTING_NAME,
+ PR_SENT_REPRESENTING_NAME_UNICODE,
+ PR_DISPLAY_TO,
+ PR_DISPLAY_TO_UNICODE,
+ PR_DISPLAY_CC,
+ PR_DISPLAY_CC_UNICODE,
+ PR_DISPLAY_BCC,
+ PR_DISPLAY_BCC_UNICODE,
+ PR_HASATTACH);
+ retval = GetProps(&obj_message, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Build a SRow structure */
+ aRow.ulAdrEntryPad = 0;
+ aRow.cValues = count;
+ aRow.lpProps = lpProps;
+
+ msgid = (const char *) octool_get_propval(&aRow, PR_INTERNET_MESSAGE_ID);
+ if (msgid) {
+ retval = FindProfileAttr(profile, "Message-ID", msgid);
+ if (GetLastError() == MAPI_E_NOT_FOUND) {
+ message2mbox(mem_ctx, fp, &aRow, &obj_message);
+ if (mapi_profile_add_string_attr(profile->profname, "Message-ID", msgid) != MAPI_E_SUCCESS) {
+ mapi_errstr("mapi_profile_add_string_attr", GetLastError());
+ } else {
+ printf("Message-ID: %s added to profile %s\n", msgid, profile->profname);
+ }
+ }
+ }
+ talloc_free(lpProps);
+ }
+ mapi_object_release(&obj_message);
+ errno = 0;
+ }
+ }
+
+ fclose(fp);
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_inbox);
+ mapi_object_release(&obj_store);
+ MAPIUninitialize();
+
+ talloc_free(mem_ctx);
+
+ return 0;
+}
Added: trunk/openchange/utils/mapiprofile.c
===================================================================
--- trunk/openchange/utils/mapiprofile.c (rev 0)
+++ trunk/openchange/utils/mapiprofile.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,739 @@
+/*
+ Wrapper over the MAPI Profile API
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2007-2009
+
+ 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 <samba/popt.h>
+#include <param.h>
+#include "openchange-tools.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <signal.h>
+
+#define DEFAULT_DIR "%s/.openchange"
+#define DEFAULT_PROFDB "%s/.openchange/profiles.ldb"
+#define DEFAULT_LCID "0x409" /* language code ID: en-US */
+
+static void mapiprofile_createdb(const char *profdb, const char *ldif_path)
+{
+ enum MAPISTATUS retval;
+
+ if (access(profdb, F_OK) == 0) {
+ fprintf(stderr, "[ERROR] mapiprofile: %s already exists\n", profdb);
+ exit (1);
+ }
+
+ retval = CreateProfileStore(profdb, ldif_path);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("CreateProfileStore", GetLastError());
+ exit (1);
+ }
+}
+
+static uint32_t callback(struct SRowSet *rowset, void *private)
+{
+ uint32_t i;
+ struct SPropValue *lpProp;
+ FILE *fd;
+ uint32_t index;
+ char entry[10];
+ const char *label = (const char *)private;
+ char *s;
+
+ printf("%s:\n", label);
+ for (i = 0; i < rowset->cRows; i++) {
+ lpProp = get_SPropValue_SRow(&(rowset->aRow[i]), PR_DISPLAY_NAME);
+ if (lpProp && lpProp->value.lpszA) {
+ printf("\t[%u] %s\n", i, lpProp->value.lpszA);
+ }
+ }
+ printf("\t[%u] cancel operation\n", i);
+ fd = fdopen(0, "r");
+getentry:
+ printf("Enter username id [0]: ");
+ s = fgets(entry, 10, fd);
+ index = atoi(entry);
+ if (index > i) {
+ printf("Invalid id - Must be a value between 0 and %u\n", i);
+ goto getentry;
+ }
+
+ fclose(fd);
+ return (index);
+}
+
+const char *g_profname;
+
+static void signal_delete_profile(void)
+{
+ enum MAPISTATUS retval;
+
+ fprintf(stderr, "CTRL-C caught ... Deleting profile\n");
+ if ((retval = DeleteProfile(g_profname)) != MAPI_E_SUCCESS) {
+ mapi_errstr("DeleteProfile", GetLastError());
+ }
+
+ (void) signal(SIGINT, SIG_DFL);
+ exit (1);
+}
+
+static void mapiprofile_create(const char *profdb, const char *profname,
+ const char *pattern, const char *username,
+ const char *password, const char *address,
+ const char *lcid, const char *workstation,
+ const char *domain, const char *realm,
+ uint32_t flags,
+ bool opt_dumpdata, const char *opt_debuglevel)
+{
+ enum MAPISTATUS retval;
+ struct mapi_session *session = NULL;
+ TALLOC_CTX *mem_ctx;
+ struct mapi_profile profile;
+
+ mem_ctx = talloc_named(NULL, 0, "mapiprofile_create");
+
+ /* catch CTRL-C */
+ g_profname = profname;
+
+#if defined (__FreeBSD__)
+ (void) signal(SIGINT, (sig_t) signal_delete_profile);
+#else
+ (void) signal(SIGINT, (sighandler_t) signal_delete_profile);
+#endif
+
+ retval = MAPIInitialize(profdb);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ /* debug options */
+ SetMAPIDumpData(opt_dumpdata);
+
+ if (opt_debuglevel) {
+ SetMAPIDebugLevel(atoi(opt_debuglevel));
+ }
+
+ /* Sanity check */
+ retval = OpenProfile(&profile, profname, NULL);
+ if (retval == MAPI_E_SUCCESS) {
+ fprintf(stderr, "[ERROR] mapiprofile: profile \"%s\" already exists\n", profname);
+ exit (1);
+ }
+
+ retval = CreateProfile(profname, username, password, flags);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("CreateProfile", GetLastError());
+ exit (1);
+ }
+
+ mapi_profile_add_string_attr(profname, "binding", address);
+ mapi_profile_add_string_attr(profname, "workstation", workstation);
+ mapi_profile_add_string_attr(profname, "domain", domain);
+
+ if (realm) {
+ mapi_profile_add_string_attr(profname, "realm", realm);
+ }
+
+ if (strncmp(lcid, "0x", 2) != 0) {
+ /* it doesn't look like a hex id, so try to convert it from
+ a string name (like "English_Australian" to a language code
+ ID string (like "0x0c09")
+ */
+ lcid = talloc_asprintf(mem_ctx, "0x%04x", lcid_lang2lcid(lcid));
+ }
+ if (!lcid_valid_locale(strtoul(lcid, 0, 16))) {
+ lcid = DEFAULT_LCID;
+ printf("Language code not recognised, using default (%s) instead\n", lcid);
+ }
+
+ /* This is only convenient here and should be replaced at some point */
+ mapi_profile_add_string_attr(profname, "codepage", "0x4e4");
+ mapi_profile_add_string_attr(profname, "language", lcid );
+ mapi_profile_add_string_attr(profname, "method", "0x409");
+
+ retval = MapiLogonProvider(&session, profname, password, PROVIDER_ID_NSPI);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MapiLogonProvider", GetLastError());
+ printf("Deleting profile\n");
+ if ((retval = DeleteProfile(profname)) != MAPI_E_SUCCESS) {
+ mapi_errstr("DeleteProfile", GetLastError());
+ }
+ talloc_free(mem_ctx);
+ exit (1);
+ }
+
+ if (pattern) {
+ username = pattern;
+ }
+
+ retval = ProcessNetworkProfile(session, username, (mapi_profile_callback_t) callback, "Select a user id");
+ if (retval != MAPI_E_SUCCESS && retval != 0x1) {
+ mapi_errstr("ProcessNetworkProfile", GetLastError());
+ printf("Deleting profile\n");
+ if ((retval = DeleteProfile(profname)) != MAPI_E_SUCCESS) {
+ mapi_errstr("DeleteProfile", GetLastError());
+ }
+ talloc_free(mem_ctx);
+ exit (1);
+ }
+
+ printf("Profile %s completed and added to database %s\n", profname, profdb);
+
+ talloc_free(mem_ctx);
+
+ MAPIUninitialize();
+}
+
+static void mapiprofile_delete(const char *profdb, const char *profname)
+{
+ enum MAPISTATUS retval;
+
+ if ((retval = MAPIInitialize(profdb)) != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ if ((retval = DeleteProfile(profname)) != MAPI_E_SUCCESS) {
+ mapi_errstr("DeleteProfile", GetLastError());
+ exit (1);
+ }
+
+ printf("Profile %s deleted from database %s\n", profname, profdb);
+
+ MAPIUninitialize();
+}
+
+
+static void mapiprofile_rename(const char *profdb, const char *old_profname, const char *new_profname)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ char *profname;
+
+ if ((retval = MAPIInitialize(profdb)) != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", retval);
+ exit (1);
+ }
+
+ mem_ctx = talloc_named(NULL, 0, "mapiprofile_rename");
+
+ if (!old_profname) {
+ if ((retval = GetDefaultProfile(&profname)) != MAPI_E_SUCCESS) {
+ mapi_errstr("GetDefaultProfile", retval);
+ talloc_free(mem_ctx);
+ exit (1);
+ }
+ } else {
+ profname = talloc_strdup(mem_ctx, old_profname);
+ }
+
+ if ((retval = RenameProfile(profname, new_profname)) != MAPI_E_SUCCESS) {
+ mapi_errstr("RenameProfile", retval);
+ talloc_free(profname);
+ talloc_free(mem_ctx);
+ exit (1);
+ }
+
+ talloc_free(profname);
+ talloc_free(mem_ctx);
+ MAPIUninitialize();
+}
+
+
+static void mapiprofile_set_default(const char *profdb, const char *profname)
+{
+ enum MAPISTATUS retval;
+
+ if ((retval = MAPIInitialize(profdb)) != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ if ((retval = SetDefaultProfile(profname)) != MAPI_E_SUCCESS) {
+ mapi_errstr("SetDefaultProfile", GetLastError());
+ exit (1);
+ }
+
+ printf("Profile %s is now set the default one\n", profname);
+
+ MAPIUninitialize();
+}
+
+static void mapiprofile_get_default(const char *profdb)
+{
+ enum MAPISTATUS retval;
+ char *profname;
+
+ if ((retval = MAPIInitialize(profdb)) != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ if ((retval = GetDefaultProfile(&profname)) != MAPI_E_SUCCESS) {
+ mapi_errstr("GetDefaultProfile", GetLastError());
+ exit (1);
+ }
+
+ printf("Default profile is set to %s\n", profname);
+
+ talloc_free(profname);
+ MAPIUninitialize();
+}
+
+static void mapiprofile_get_fqdn(const char *profdb,
+ const char *opt_profname,
+ const char *password,
+ bool opt_dumpdata)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct mapi_session *session = NULL;
+ const char *serverFQDN;
+ char *profname;
+
+ if ((retval = MAPIInitialize(profdb)) != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ SetMAPIDumpData(opt_dumpdata);
+
+ mem_ctx = talloc_named(NULL, 0, "mapiprofile_get_fqdn");
+
+ if (!opt_profname) {
+ if ((retval = GetDefaultProfile(&profname)) != MAPI_E_SUCCESS) {
+ mapi_errstr("GetDefaultProfile", GetLastError());
+ talloc_free(mem_ctx);
+ exit (1);
+ }
+ } else {
+ profname = talloc_strdup(mem_ctx, (char *)opt_profname);
+ }
+
+ retval = MapiLogonProvider(&session, profname, password, PROVIDER_ID_NSPI);
+ talloc_free(profname);
+ talloc_free(mem_ctx);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MapiLogonProvider", GetLastError());
+ exit (1);
+ }
+
+ retval = RfrGetFQDNFromLegacyDN(session, &serverFQDN);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("RfrGetFQDNFromLegacyDN", GetLastError());
+ exit (1);
+ }
+
+ printf("%s is at %s\n", global_mapi_ctx->session->profile->homemdb, serverFQDN);
+
+ MAPIUninitialize();
+}
+
+static void mapiprofile_list(const char *profdb)
+{
+ enum MAPISTATUS retval;
+ struct SRowSet proftable;
+ uint32_t count = 0;
+
+ if ((retval = MAPIInitialize(profdb)) != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ memset(&proftable, 0, sizeof (struct SRowSet));
+ if ((retval = GetProfileTable(&proftable)) != MAPI_E_SUCCESS) {
+ mapi_errstr("GetProfileTable", GetLastError());
+ exit (1);
+ }
+
+ printf("We have %u profiles in the database:\n", proftable.cRows);
+
+ for (count = 0; count != proftable.cRows; count++) {
+ const char *name = NULL;
+ uint32_t dflt = 0;
+
+ name = proftable.aRow[count].lpProps[0].value.lpszA;
+ dflt = proftable.aRow[count].lpProps[1].value.l;
+
+ if (dflt) {
+ printf("\tProfile = %s [default]\n", name);
+ } else {
+ printf("\tProfile = %s\n", name);
+ }
+
+ }
+
+ MAPIUninitialize();
+}
+
+static void mapiprofile_dump(const char *profdb, const char *opt_profname)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct mapi_profile profile;
+ char *profname;
+
+ if ((retval = MAPIInitialize(profdb)) != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ mem_ctx = talloc_named(NULL, 0, "mapiprofile_dump");
+
+ if (!opt_profname) {
+ if ((retval = GetDefaultProfile(&profname)) != MAPI_E_SUCCESS) {
+ mapi_errstr("GetDefaultProfile", GetLastError());
+ talloc_free(mem_ctx);
+ exit (1);
+ }
+ } else {
+ profname = talloc_strdup(mem_ctx, (const char *)opt_profname);
+ }
+
+ retval = OpenProfile(&profile, profname, NULL);
+ talloc_free(profname);
+ talloc_free(mem_ctx);
+ if (retval && (retval != MAPI_E_INVALID_PARAMETER)) {
+ mapi_errstr("OpenProfile", GetLastError());
+ exit (1);
+ }
+
+ printf("Profile: %s\n", profile.profname);
+ printf("\tusername == %s\n", profile.username);
+ printf("\tpassword == %s\n", profile.password);
+ printf("\tmailbox == %s\n", profile.mailbox);
+ printf("\tworkstation == %s\n", profile.workstation);
+ printf("\tdomain == %s\n", profile.domain);
+ printf("\tserver == %s\n", profile.server);
+
+ MAPIUninitialize();
+}
+
+static void mapiprofile_attribute(const char *profdb, const char *opt_profname,
+ const char *attribute)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct mapi_profile profile;
+ char *profname = NULL;
+ char **value = NULL;
+ unsigned int count = 0;
+ unsigned int i;
+
+ if ((retval = MAPIInitialize(profdb)) != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ mem_ctx = talloc_named(NULL, 0, "mapiprofile_attribute");
+
+ if (!opt_profname) {
+ if ((retval = GetDefaultProfile(&profname)) != MAPI_E_SUCCESS) {
+ mapi_errstr("GetDefaultProfile", GetLastError());
+ exit (1);
+ }
+ } else {
+ profname = talloc_strdup(mem_ctx, (const char *)opt_profname);
+ }
+
+ retval = OpenProfile(&profile, profname, NULL);
+ if (retval && (retval != MAPI_E_INVALID_PARAMETER)) {
+ mapi_errstr("OpenProfile", GetLastError());
+ talloc_free(profname);
+ talloc_free(mem_ctx);
+ exit (1);
+ }
+
+ if ((retval = GetProfileAttr(&profile, attribute, &count, &value))) {
+ mapi_errstr("ProfileGetAttr", GetLastError());
+ talloc_free(profname);
+ talloc_free(mem_ctx);
+ exit (1);
+ }
+
+ printf("Profile %s: results(%u)\n", profname, count);
+ for (i = 0; i < count; i++) {
+ printf("\t%s = %s\n", attribute, value[i]);
+ }
+ MAPIFreeBuffer(value);
+ talloc_free(profname);
+ talloc_free(mem_ctx);
+
+ MAPIUninitialize();
+}
+
+static void show_help(poptContext pc, const char *param)
+{
+ printf("%s argument missing\n", param);
+ poptPrintUsage(pc, stderr, 0);
+ exit (1);
+}
+
+int main(int argc, const char *argv[])
+{
+ TALLOC_CTX *mem_ctx;
+ int error;
+ poptContext pc;
+ int opt;
+ char *default_path;
+ bool create = false;
+ bool delete = false;
+ bool list = false;
+ bool listlangs = false;
+ bool dump = false;
+ bool newdb = false;
+ bool setdflt = false;
+ bool getdflt = false;
+ bool getfqdn = false;
+ bool opt_dumpdata = false;
+ const char *opt_debuglevel = NULL;
+ const char *ldif = NULL;
+ const char *address = NULL;
+ const char *workstation = NULL;
+ const char *domain = NULL;
+ const char *realm = NULL;
+ const char *username = NULL;
+ const char *lcid = NULL;
+ const char *pattern = NULL;
+ const char *password = NULL;
+ const char *profdb = NULL;
+ const char *profname = NULL;
+ const char *rename = NULL;
+ const char *attribute = NULL;
+ uint32_t nopass = 0;
+ char hostname[256];
+
+ enum {OPT_PROFILE_DB=1000, OPT_PROFILE, OPT_ADDRESS, OPT_WORKSTATION,
+ OPT_DOMAIN, OPT_REALM, OPT_USERNAME, OPT_LCID, OPT_PASSWORD,
+ OPT_CREATE_PROFILE, OPT_DELETE_PROFILE, OPT_LIST_PROFILE, OPT_DUMP_PROFILE,
+ OPT_DUMP_ATTR, OPT_PROFILE_NEWDB, OPT_PROFILE_LDIF, OPT_LIST_LANGS,
+ OPT_PROFILE_SET_DFLT, OPT_PROFILE_GET_DFLT, OPT_PATTERN, OPT_GETFQDN,
+ OPT_NOPASS, OPT_RENAME_PROFILE, OPT_DUMPDATA, OPT_DEBUGLEVEL};
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ {"ldif", 'L', POPT_ARG_STRING, NULL, OPT_PROFILE_LDIF, "set the ldif path", "PATH"},
+ {"getdefault", 'G', POPT_ARG_NONE, NULL, OPT_PROFILE_GET_DFLT, "get the default profile", NULL},
+ {"default", 'S', POPT_ARG_NONE, NULL, OPT_PROFILE_SET_DFLT, "set the default profile", NULL},
+ {"newdb", 'n', POPT_ARG_NONE, NULL, OPT_PROFILE_NEWDB, "create a new profile store", NULL},
+ {"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"},
+ {"address", 'I', POPT_ARG_STRING, NULL, OPT_ADDRESS, "set the exchange server IP address", "xxx.xxx.xxx.xxx"},
+ {"workstation", 'M', POPT_ARG_STRING, NULL, OPT_WORKSTATION, "set the workstation", "WORKSTATION_NAME"},
+ {"domain", 'D', POPT_ARG_STRING, NULL, OPT_DOMAIN, "set the domain/workgroup", "DOMAIN"},
+ {"realm", 'R', POPT_ARG_STRING, NULL, OPT_REALM, "set the realm", "REALM"},
+ {"username", 'u', POPT_ARG_STRING, NULL, OPT_USERNAME, "set the profile username", "USERNAME"},
+ {"langcode", 'C', POPT_ARG_STRING, NULL, OPT_LCID, "set the language code ID", "LANGCODE"},
+ {"pattern", 's', POPT_ARG_STRING, NULL, OPT_PATTERN, "username to search for", "USERNAME"},
+ {"password", 'p', POPT_ARG_STRING, NULL, OPT_PASSWORD, "set the profile password", "PASSWORD"},
+ {"nopass", 0, POPT_ARG_NONE, NULL, OPT_NOPASS, "do not save password in the profile", NULL},
+ {"create", 'c', POPT_ARG_NONE, NULL, OPT_CREATE_PROFILE, "create a profile in the database", NULL},
+ {"delete", 'r', POPT_ARG_NONE, NULL, OPT_DELETE_PROFILE, "delete a profile in the database", NULL},
+ {"rename", 'R', POPT_ARG_STRING, NULL, OPT_RENAME_PROFILE, "rename a profile in the database", NULL},
+ {"list", 'l', POPT_ARG_NONE, NULL, OPT_LIST_PROFILE, "list existing profiles in the database", NULL},
+ {"listlangs", 0, POPT_ARG_NONE, NULL, OPT_LIST_LANGS, "list all recognised languages", NULL},
+ {"dump", 0, POPT_ARG_NONE, NULL, OPT_DUMP_PROFILE, "dump a profile entry", NULL},
+ {"attr", 'a', POPT_ARG_STRING, NULL, OPT_DUMP_ATTR, "print an attribute value", "VALUE"},
+ {"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMPDATA, "dump the hex data", NULL},
+ {"debuglevel", 'd', POPT_ARG_STRING, NULL, OPT_DEBUGLEVEL, "set the debug level", "LEVEL"},
+ {"getfqdn", 0, POPT_ARG_NONE, NULL, OPT_GETFQDN, "returns the DNS FQDN of the NSPI server matching the legacyDN", NULL},
+ POPT_OPENCHANGE_VERSION
+ { NULL, 0, POPT_ARG_NONE, NULL, 0, NULL, NULL }
+ };
+
+ mem_ctx = talloc_named(NULL, 0, "mapiprofile");
+
+ pc = poptGetContext("mapiprofile", argc, argv, long_options, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch(opt) {
+ case OPT_DUMPDATA:
+ opt_dumpdata = true;
+ break;
+ case OPT_DEBUGLEVEL:
+ opt_debuglevel = poptGetOptArg(pc);
+ break;
+ case OPT_PROFILE_LDIF:
+ ldif = poptGetOptArg(pc);
+ break;
+ case OPT_PROFILE_NEWDB:
+ newdb = true;
+ break;
+ case OPT_PROFILE_SET_DFLT:
+ setdflt = true;
+ break;
+ case OPT_PROFILE_GET_DFLT:
+ getdflt = true;
+ break;
+ case OPT_PROFILE_DB:
+ profdb = poptGetOptArg(pc);
+ break;
+ case OPT_PROFILE:
+ profname = poptGetOptArg(pc);
+ break;
+ case OPT_ADDRESS:
+ address = poptGetOptArg(pc);
+ break;
+ case OPT_WORKSTATION:
+ workstation = poptGetOptArg(pc);
+ break;
+ case OPT_DOMAIN:
+ domain = poptGetOptArg(pc);
+ break;
+ case OPT_REALM:
+ realm = poptGetOptArg(pc);
+ break;
+ case OPT_USERNAME:
+ username = poptGetOptArg(pc);
+ break;
+ case OPT_LCID:
+ lcid = poptGetOptArg(pc);
+ break;
+ case OPT_PATTERN:
+ pattern = poptGetOptArg(pc);
+ break;
+ case OPT_PASSWORD:
+ password = poptGetOptArg(pc);
+ break;
+ case OPT_NOPASS:
+ nopass = 1;
+ break;
+ case OPT_CREATE_PROFILE:
+ create = true;
+ break;
+ case OPT_DELETE_PROFILE:
+ delete = true;
+ break;
+ case OPT_RENAME_PROFILE:
+ rename = poptGetOptArg(pc);
+ break;
+ case OPT_LIST_PROFILE:
+ list = true;
+ break;
+ case OPT_LIST_LANGS:
+ listlangs = true;
+ break;
+ case OPT_DUMP_PROFILE:
+ dump = true;
+ break;
+ case OPT_DUMP_ATTR:
+ attribute = poptGetOptArg(pc);
+ break;
+ case OPT_GETFQDN:
+ getfqdn = true;
+ break;
+ }
+ }
+
+ /* Sanity check on options */
+ if (!profdb) {
+ default_path = talloc_asprintf(mem_ctx, DEFAULT_DIR, getenv("HOME"));
+ error = mkdir(default_path, 0700);
+ talloc_free(default_path);
+ if ((error == -1) && (errno != EEXIST)) {
+ perror("mkdir");
+ talloc_free(mem_ctx);
+ exit (1);
+ }
+ profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB,
+ getenv("HOME"));
+ }
+
+ if ((list == false) && (getfqdn == false) && (newdb == false) && (listlangs == false)
+ && (getdflt == false) && (dump == false) && (rename == NULL) &&
+ (!attribute) && (!profname || !profdb)) {
+ poptPrintUsage(pc, stderr, 0);
+ exit (1);
+ }
+
+ if (newdb == true) {
+ if (!ldif) {
+ ldif = talloc_strdup(mem_ctx, mapi_profile_get_ldif_path());
+ }
+ if (!ldif) show_help(pc, "ldif");
+ mapiprofile_createdb(profdb, ldif);
+ }
+
+ /* Process the code here */
+
+ if (!workstation) {
+ gethostname(hostname, sizeof(hostname) - 1);
+ hostname[sizeof(hostname) - 1] = 0;
+ workstation = hostname;
+ }
+
+ if (create == true) {
+ if (!profname) show_help(pc, "profile");
+ if (!password) show_help(pc, "password");
+ if (!username) show_help(pc, "username");
+ if (!address) show_help(pc, "address");
+ if (!workstation) show_help(pc, "workstation");
+ if (!domain) show_help(pc, "domain");
+
+ if (!lcid) {
+ lcid = talloc_asprintf(mem_ctx, DEFAULT_LCID);
+ }
+ mapiprofile_create(profdb, profname, pattern, username, password, address,
+ lcid, workstation, domain, realm, nopass, opt_dumpdata, opt_debuglevel);
+ }
+
+ if (rename) {
+ mapiprofile_rename(profdb, profname, rename);
+ }
+
+ if (getfqdn == true) {
+ mapiprofile_get_fqdn(profdb, profname, password, opt_dumpdata);
+ }
+
+ if (listlangs == true) {
+ lcid_print_languages();
+ }
+
+ if (setdflt == true) {
+ mapiprofile_set_default(profdb, profname);
+ }
+
+ if (getdflt == true) {
+ mapiprofile_get_default(profdb);
+ }
+
+ if (delete == true) {
+ mapiprofile_delete(profdb, profname);
+ }
+
+ if (list == true) {
+ mapiprofile_list(profdb);
+ }
+
+ if (dump == true) {
+ mapiprofile_dump(profdb, profname);
+ }
+
+ if (attribute) {
+ mapiprofile_attribute(profdb, profname, attribute);
+ }
+
+ talloc_free(mem_ctx);
+
+ return (0);
+}
Added: trunk/openchange/utils/mapitest/Doxyfile.in
===================================================================
--- trunk/openchange/utils/mapitest/Doxyfile.in (rev 0)
+++ trunk/openchange/utils/mapitest/Doxyfile.in 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1270 @@
+# Doxyfile 1.5.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = MAPI Tests
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = apidocs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = utils/mapitest utils/mapitest/modules
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.h *.c *.doxy
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = *_private.h
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = *.yy.c *_private.h
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = doc/doxygen/pictures/
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER = "sed \
+ -e '20,40s/.*\<libmapi\/libmapi.h\>//' \
+ -e '20,40s/.*\<samba\/popt.h\>//' \
+ -e '20,40s/.*\<samba\/version.h\>//' \
+ -e '20,40s/.*\<utils\/openchange-tools.h\>//' \
+ -e '20,40s/.*\<utils\/mapitest\/mapitest.h\>//' \
+ -e '20,40s/.*\<utils\/mapitest\/proto.h\>//' \
+ -e '20,40s/.*\<errno.h\>//' \
+ -e '20,40s/.*\<err.h\>//' \
+ -e '20,40s/.*\<fcntl.h\>//' \
+ -e '20,40s/.*\<param.h\>//' \
+ -e '20,40s/.*\<time.h\>//' \
+ -e 's/_PUBLIC_//'"
+
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html/mapitest
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER = doc/doxygen/header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = doc/doxygen/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET = doc/doxygen/apidocs.css
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = _PUBLIC_
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen will always
+# show the root nodes and its direct children regardless of this setting.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
Added: trunk/openchange/utils/mapitest/mapitest.c
===================================================================
--- trunk/openchange/utils/mapitest/mapitest.c (rev 0)
+++ trunk/openchange/utils/mapitest/mapitest.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,333 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 <samba/popt.h>
+#include <param.h>
+
+#include <utils/openchange-tools.h>
+#include "utils/mapitest/mapitest.h"
+
+/**
+ \file
+ Core of %mapitest implementation
+*/
+
+/**
+ Initialize %mapitest structure
+ */
+static void mapitest_init(TALLOC_CTX *mem_ctx, struct mapitest *mt)
+{
+ mt->mem_ctx = mem_ctx;
+ mt->stream = NULL;
+ memset(&mt->info, 0, sizeof (mt->info));
+ mt->session = NULL;
+
+ mt->session = NULL;
+ mt->mapi_all = true;
+ mt->confidential = false;
+ mt->no_server = false;
+ mt->color = false;
+ mt->online = false;
+ mt->mapi_suite = false;
+ mt->cmdline_calls = NULL;
+ mt->cmdline_suite = NULL;
+}
+
+/**
+ Initialize %mapitest output stream
+
+ \param mt pointer to mapitest context
+ \param filename filename to write to (can be null, for output to stdout)
+*/
+static void mapitest_init_stream(struct mapitest *mt, const char *filename)
+{
+ if (filename == NULL) {
+ mt->stream = fdopen(STDOUT_FILENO, "a");
+ } else {
+ mt->stream = fopen(filename, "w+");
+ }
+
+ if (mt->stream == NULL) {
+ err(errno, "fdopen/fopen");
+ }
+}
+
+/**
+ Clean up %mapitest output stream
+
+ \param mt pointer to mapitest context
+*/
+static void mapitest_cleanup_stream(struct mapitest *mt)
+{
+ fclose(mt->stream);
+}
+
+
+static bool mapitest_get_testnames(TALLOC_CTX *mem_ctx, struct mapitest *mt,
+ const char *parameter)
+{
+ struct mapitest_unit *el = NULL;
+ char *tmp = NULL;
+
+ if ((tmp = strtok((char *)parameter, ";")) == NULL) {
+ fprintf(stderr, "Invalid testname list [;]\n");
+ return false;
+ }
+
+ el = talloc_zero(mem_ctx, struct mapitest_unit);
+ el->name = talloc_strdup(mem_ctx, tmp);
+ DLIST_ADD(mt->cmdline_calls, el);
+
+ while ((tmp = strtok(NULL, ";")) != NULL) {
+ el = talloc_zero(mem_ctx, struct mapitest_unit);
+ el->name = talloc_strdup(mem_ctx, tmp);
+ DLIST_ADD_END(mt->cmdline_calls, el, struct mapitest_unit *);
+ }
+
+ return true;
+}
+
+
+static void mapitest_list(struct mapitest *mt, const char *name)
+{
+ struct mapitest_suite *sel;
+ struct mapitest_test *el;
+
+ /* List all tests */
+ if (!name) {
+ for (sel = mt->mapi_suite; sel; sel = sel->next) {
+ printf("[*] Suite %s\n", sel->name);
+ printf("===================================\n");
+ printf(" * %-15s %s\n", "Name:", sel->name);
+ printf(" * %-15s %5s\n", "Description:", sel->description);
+ printf(" * Running Tests:\n");
+ for (el = sel->tests; el; el = el->next) {
+ printf("\t - %-35s: %-10s\n", el->name, el->description);
+ }
+ printf("\n\n");
+ }
+ }
+}
+
+
+/**
+ * Retrieve server specific information
+ */
+static bool mapitest_get_server_info(struct mapitest *mt,
+ char *opt_profname,
+ const char *password,
+ bool opt_dumpdata,
+ const char *opt_debug)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct emsmdb_info *info = NULL;
+ struct mapi_session *session = NULL;
+ char *profname = NULL;
+
+ if (mt->no_server == true) return 0;
+
+ mem_ctx = talloc_named(NULL, 0, "mapitest_get_server_info");
+
+ if (!profname) {
+ retval = GetDefaultProfile(&profname);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("GetDefaultProfile", retval);
+ talloc_free(mem_ctx);
+ return false;
+ }
+ } else {
+ profname = talloc_strdup(mem_ctx, opt_profname);
+ }
+
+ /* debug options */
+ SetMAPIDumpData(opt_dumpdata);
+
+ if (opt_debug) {
+ SetMAPIDebugLevel(atoi(opt_debug));
+ }
+
+ retval = MapiLogonEx(&session, profname, password);
+ MAPIFreeBuffer(profname);
+ talloc_free(mem_ctx);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MapiLogonEx", retval);
+ return false;
+ }
+ mt->session = session;
+
+ info = emsmdb_get_info(session);
+ memcpy(&mt->info, info, sizeof (struct emsmdb_info));
+
+ /* extract org and org_unit from info.mailbox */
+ mt->org = x500_get_dn_element(mt->mem_ctx, info->szDNPrefix, "/o=");
+ mt->org_unit = x500_get_dn_element(mt->mem_ctx, info->szDNPrefix, "/ou=");
+
+ return true;
+}
+
+
+
+/**
+ * main program
+ */
+int main(int argc, const char *argv[])
+{
+ enum MAPISTATUS retval;
+ int32_t num_tests_failed;
+ TALLOC_CTX *mem_ctx;
+ struct mapitest mt;
+ poptContext pc;
+ int opt;
+ bool ret;
+ bool opt_dumpdata = false;
+ const char *opt_debug = NULL;
+ const char *opt_profdb = NULL;
+ char *opt_profname = NULL;
+ const char *opt_username = NULL;
+ const char *opt_password = NULL;
+ const char *opt_outfile = NULL;
+
+ enum { OPT_PROFILE_DB=1000, OPT_PROFILE, OPT_USERNAME, OPT_PASSWORD,
+ OPT_CONFIDENTIAL, OPT_OUTFILE, OPT_MAPI_ALL, OPT_MAPI_CALLS,
+ OPT_MAPIADMIN_ALL, OPT_NO_SERVER, OPT_LIST_ALL, OPT_DUMP_DATA,
+ OPT_DEBUG, OPT_COLOR };
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ { "database", 'f', POPT_ARG_STRING, NULL, OPT_PROFILE_DB, "set the profile database", NULL },
+ { "profile", 'p', POPT_ARG_STRING, NULL, OPT_PROFILE, "set the profile name", NULL },
+ { "username", 'u', POPT_ARG_STRING, NULL, OPT_USERNAME, "set the account username", NULL },
+ { "password", 'p', POPT_ARG_STRING, NULL, OPT_PASSWORD, "set the profile or account password", NULL },
+ { "confidential", 0, POPT_ARG_NONE, NULL, OPT_CONFIDENTIAL, "remove any sensitive data from the report", NULL },
+ { "color", 0, POPT_ARG_NONE, NULL, OPT_COLOR, "color MAPI retval", NULL },
+ { "outfile", 'o', POPT_ARG_STRING, NULL, OPT_OUTFILE, "set the report output file", NULL },
+ { "mapi-calls", 0, POPT_ARG_STRING, NULL, OPT_MAPI_CALLS, "test custom ExchangeRPC tests", NULL },
+ { "list-all", 0, POPT_ARG_NONE, NULL, OPT_LIST_ALL, "list suite and tests - names and description", NULL },
+ { "no-server", 0, POPT_ARG_NONE, NULL, OPT_NO_SERVER, "only run tests that do not require server connection", NULL },
+ { "dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMP_DATA, "dump the hex data", NULL },
+ { "debuglevel", 'd', POPT_ARG_STRING, NULL, OPT_DEBUG, "set debug level", NULL },
+ POPT_OPENCHANGE_VERSION
+ { NULL, 0, 0, NULL, 0, NULL, NULL }
+ };
+
+ mem_ctx = talloc_named(NULL, 0, "mapitest");
+ mapitest_init(mem_ctx, &mt);
+ mapitest_register_modules(&mt);
+
+ pc = poptGetContext("mapitest", argc, argv, long_options, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_DUMP_DATA:
+ opt_dumpdata = true;
+ break;
+ case OPT_DEBUG:
+ opt_debug = poptGetOptArg(pc);
+ break;
+ case OPT_PROFILE_DB:
+ opt_profdb = poptGetOptArg(pc);
+ break;
+ case OPT_PROFILE:
+ opt_profname = talloc_strdup(mem_ctx, (char *)poptGetOptArg(pc));
+ break;
+ case OPT_USERNAME:
+ opt_username = poptGetOptArg(pc);
+ break;
+ case OPT_PASSWORD:
+ opt_password = poptGetOptArg(pc);
+ break;
+ case OPT_CONFIDENTIAL:
+ mt.confidential = true;
+ break;
+ case OPT_OUTFILE:
+ opt_outfile = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_CALLS:
+ ret = mapitest_get_testnames(mem_ctx, &mt, poptGetOptArg(pc));
+ if (ret == false) exit (-1);
+ mt.mapi_all = false;
+ break;
+ case OPT_NO_SERVER:
+ mt.no_server = true;
+ break;
+ case OPT_COLOR:
+ mt.color = true;
+ break;
+ case OPT_LIST_ALL:
+ mapitest_list(&mt, NULL);
+ talloc_free(mem_ctx);
+ poptFreeContext(pc);
+ return 0;
+ break;
+ }
+ }
+
+ poptFreeContext(pc);
+
+ /* Sanity check */
+ if (mt.cmdline_calls && (mt.mapi_all == true)) {
+ fprintf(stderr, "mapi-calls and mapi-all can't be set at the same time\n");
+ return -1;
+ }
+
+ /* Initialize MAPI subsystem */
+ if (!opt_profdb) {
+ opt_profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, getenv("HOME"));
+ }
+
+ retval = MAPIInitialize(opt_profdb);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", retval);
+ return -2;
+ }
+
+ mapitest_init_stream(&mt, opt_outfile);
+
+ mt.online = mapitest_get_server_info(&mt, opt_profname, opt_password,
+ opt_dumpdata, opt_debug);
+
+ mapitest_print_headers(&mt);
+
+ /* Run custom tests */
+ if (mt.cmdline_calls) {
+ struct mapitest_unit *el;
+ bool ret;
+
+ for (el = mt.cmdline_calls; el; el = el->next) {
+ printf("[*] %s\n", el->name);
+ ret = mapitest_run_test(&mt, el->name);
+ }
+ } else {
+ mapitest_run_all(&mt);
+ }
+
+ num_tests_failed = mapitest_stat_dump(&mt);
+
+ mapitest_cleanup_stream(&mt);
+
+ /* Uninitialize and free memory */
+ MAPIUninitialize();
+ talloc_free(mt.mem_ctx);
+
+ return num_tests_failed;
+}
Added: trunk/openchange/utils/mapitest/mapitest.h
===================================================================
--- trunk/openchange/utils/mapitest/mapitest.h (rev 0)
+++ trunk/openchange/utils/mapitest/mapitest.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,204 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 __MAPITEST_H__
+#define __MAPITEST_H__
+
+#include <libmapi/libmapi.h>
+
+#include <errno.h>
+#include <err.h>
+
+/* forward declaration */
+struct mapitest;
+struct mapitest_suite;
+
+#include "utils/mapitest/proto.h"
+
+/**
+ \file mapitest.h
+ Data structures for %mapitest
+ */
+
+/**
+ A list of %mapitest tests
+
+ %mapitest tests are grouped into test suites. This linked
+ list data structure represents the various tests as a
+ list of tests (i.e. the linked list is a suite of tests).
+
+ The function that executes the test is pointed to by the
+ fn element (i.e. fn is a function pointer).
+*/
+struct mapitest_test {
+ struct mapitest_test *prev; /*!< The previous test in the list */
+ struct mapitest_test *next; /*!< The next test in the list */
+ char *name; /*!< The name of this test */
+ char *description; /*!< The description of this test */
+ void *fn; /*!< pointer to the test function */
+};
+
+/**
+ List of test names
+
+ This linked list data structure has a list of names of tests. It is
+ used with mapitest_stat to record the failed tests.
+*/
+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 */
+};
+
+/**
+ %mapitest statistics
+
+ During a %mapitest run, %mapitest collects statistics on each test suite.
+
+ This data structure records the results for one run of a test suite.
+
+ 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 */
+ struct mapitest_unit *failure_info; /*!< List of names of the tests that failed */
+ bool enabled; /*!< Whether this statistics structure is valid */
+};
+
+/**
+ A list of test suites
+
+ %mapitest executes a set of tests. Those tests are grouped into
+ suites of related tests (e.g. all tests that do not require a
+ server are in one suite, the tests for NSPI are in another suite,
+ and so on). This linked list data structure represents the various
+ test suites to be executed.
+*/
+struct mapitest_suite {
+ struct mapitest_suite *prev; /*!< Pointer to the previous test suite */
+ struct mapitest_suite *next; /*!< Pointer to the next test suite */
+ char *name; /*!< The name of the test suite */
+ char *description; /*!< Description of the test suite */
+ bool online; /*!< Whether this suite requires a server */
+ struct mapitest_test *tests; /*!< The tests in this suite */
+ struct mapitest_stat *stat; /*!< Results of running this test */
+};
+
+/**
+ The context structure for a %mapitest run
+*/
+struct mapitest {
+ TALLOC_CTX *mem_ctx; /*!< talloc memory context for memory allocations */
+ struct mapi_session *session;
+ bool confidential; /*!< true if confidential information should be omitted */
+ bool no_server; /*!< true if only non-server tests should be run */
+ bool mapi_all; /*!< true if all tests should be run */
+ bool online; /*!< true if the server could be accessed */
+ bool color; /*!< true if the output should be colored */
+ struct emsmdb_info info;
+ struct mapitest_suite *mapi_suite; /*!< the various test suites */
+ struct mapitest_unit *cmdline_calls;
+ struct mapitest_unit *cmdline_suite;
+ const char *org;
+ const char *org_unit;
+ FILE *stream;
+ void *priv;
+};
+
+struct mapitest_module {
+ char *name;
+
+};
+
+/**
+ Context for %mapitest test folder
+*/
+struct mt_common_tf_ctx
+{
+ mapi_object_t obj_store;
+ mapi_object_t obj_top_folder;
+ mapi_object_t obj_test_folder;
+ mapi_object_t obj_test_msg[10];
+};
+
+
+/*
+ * Defines
+ */
+#define MAPITEST_SUCCESS 0
+#define MAPITEST_ERROR -1
+
+#define MT_STREAM_MAX_SIZE 0x3000
+
+#define MT_YES "[yes]"
+#define MT_NO "[no]"
+
+#define MT_CONFIDENTIAL "[Confidential]"
+
+#define MT_HDR_START "#############################[mapitest report]#################################\n"
+#define MT_HDR_END "###############################################################################\n"
+#define MT_HDR_FMT "[*] %-25s: %-20s\n"
+#define MT_HDR_FMT_DATE "[*] %-25s: %-20s"
+#define MT_HDR_FMT_SECTION "[*] %-25s:\n"
+#define MT_HDR_FMT_SUBSECTION "%-21s: %-10s\n"
+#define MT_HDR_FMT_STORE_VER "%-21s: %d.%d.%d\n"
+
+#define MT_DIRNAME_TOP "[MT] Top of Mailbox"
+#define MT_DIRNAME_APPOINTMENT "[MT] Calendar"
+#define MT_DIRNAME_CONTACT "[MT] Contact"
+#define MT_DIRNAME_JOURNAL "[MT] Journal"
+#define MT_DIRNAME_POST "[MT] Post"
+#define MT_DIRNAME_NOTE "[MT] Note"
+#define MT_DIRNAME_STICKYNOTE "[MT] Sticky Notes"
+#define MT_DIRNAME_TASK "[MT] Tasks"
+#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 MODULE_TITLE "[MODULE] %s\n"
+#define MODULE_TITLE_DELIM '#'
+#define MODULE_TITLE_NEWLINE 2
+#define MODULE_TITLE_LINELEN 80
+
+#define MODULE_TEST_TITLE "[TEST] %s\n"
+#define MODULE_TEST_RESULT "[RESULT] %s: %s\n"
+#define MODULE_TEST_DELIM '-'
+#define MODULE_TEST_DELIM2 '='
+#define MODULE_TEST_LINELEN 72
+#define MODULE_TEST_NEWLINE 1
+#define MODULE_TEST_SUCCESS "[SUCCESS]"
+#define MODULE_TEST_FAILURE "[FAILURE]"
+
+#define MT_ERROR "[ERROR]: %s\n"
+
+#define MT_STAT_TITLE "[STAT] FAILURE REPORT\n"
+#define MT_STAT_FAILURE "* %-35s: %s\n"
+
+#define MT_SUMMARY_TITLE "[STAT] TEST SUMMARY\n"
+
+#define MT_WHITE "\033[0;29m"
+#define MT_RED "\033[1;31m"
+#define MT_GREEN "\033[1;32m"
+
+#endif /* !__MAPITEST_H__ */
Added: trunk/openchange/utils/mapitest/mapitest_common.c
===================================================================
--- trunk/openchange/utils/mapitest/mapitest_common.c (rev 0)
+++ trunk/openchange/utils/mapitest/mapitest_common.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,534 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 <utils/openchange-tools.h>
+#include <utils/mapitest/mapitest.h>
+
+#include <fcntl.h>
+
+/**
+ \file
+ Support functions for %mapitest modules
+
+ These functions implement commonly needed functionality that
+ would otherwise be copied into each module implementation
+*/
+
+/**
+ Opens a default folder
+
+ This function opens one of the default (standard) folders,
+ returning the folder as obj_child. olNum may be one of:
+ - olFolderTopInformationStore
+ - olFolderDeletedItems
+ - olFolderOutbox
+ - olFolderSentMail
+ - olFolderInbox
+ - olFolderCalendar
+ - olFolderContacts
+ - olFolderJournal
+ - olFolderNotes
+ - olFolderTasks
+ - olFolderDrafts
+
+ \param mt pointer to the top level mapitest structure
+ \param obj_parent parent folder (usually the message store, must be opened)
+ \param obj_child the folder that has been opened
+ \param olNum the folder identifier (see list above)
+
+ \return true on success, false on failure
+ */
+_PUBLIC_ bool mapitest_common_folder_open(struct mapitest *mt,
+ mapi_object_t *obj_parent,
+ mapi_object_t *obj_child,
+ uint32_t olNum)
+{
+ enum MAPISTATUS retval;
+ mapi_id_t id_child;
+
+ retval = GetDefaultFolder(obj_parent, &id_child, olNum);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "GetDefaultFolder", GetLastError());
+ return false;
+ }
+
+ retval = OpenFolder(obj_parent, id_child, obj_child);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "OpenFolder", GetLastError());
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ This function deletes messages in a folder, based on matching the subject
+ name. This is meant to clean up a folder after a test has been run.
+
+ \param mt pointer to the top level mapitest structure
+ \param obj_folder the folder to search through
+ \param subject the message subject to match
+*/
+_PUBLIC_ bool mapitest_common_message_delete_by_subject(struct mapitest *mt,
+ mapi_object_t *obj_folder,
+ const char *subject)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_ctable;
+ mapi_id_t msgids[1];
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ uint32_t count;
+ const char *msubject = NULL;
+ uint32_t i;
+
+ /* Sanity checks */
+ if (subject == NULL) return false;
+
+ /* Retrieve the contents table */
+ mapi_object_init(&obj_ctable);
+ retval = GetContentsTable(obj_folder, &obj_ctable, 0, &count);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "GetContentsTable", GetLastError());
+ mapi_object_release(&obj_ctable);
+ return false;
+ }
+
+ /* Customize the content table view */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2,
+ PR_MID,
+ PR_SUBJECT);
+ retval = SetColumns(&obj_ctable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "SetColumns", GetLastError());
+ mapi_object_release(&obj_ctable);
+ return false;
+ }
+
+ while (((retval = QueryRows(&obj_ctable, count, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND) && SRowSet.cRows) {
+ for (i = 0; i < SRowSet.cRows; i++) {
+ if (retval == MAPI_E_SUCCESS) {
+ msgids[0] = SRowSet.aRow[i].lpProps[0].value.d;
+ msubject = (const char *)find_SPropValue_data(&SRowSet.aRow[i], PR_SUBJECT);
+ if (msubject && !strncmp(subject, msubject, strlen(subject))) {
+ DeleteMessage(obj_folder, msgids, 1);
+ }
+ }
+ }
+ }
+ mapi_object_release(&obj_ctable);
+ return false;
+}
+
+
+/**
+ Find a folder within a container
+ */
+_PUBLIC_ bool mapitest_common_find_folder(struct mapitest *mt,
+ mapi_object_t *obj_parent,
+ mapi_object_t *obj_child,
+ const char *name)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet rowset;
+ mapi_object_t obj_htable;
+ const char *tmp;
+ char *newname;
+ const uint64_t *fid;
+ uint32_t count;
+ uint32_t index;
+
+ mapi_object_init(&obj_htable);
+ retval = GetHierarchyTable(obj_parent, &obj_htable, 0, &count);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_htable);
+ return false;
+ }
+
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2,
+ PR_DISPLAY_NAME,
+ PR_FID);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_htable);
+ return false;
+ }
+
+ while (((retval = QueryRows(&obj_htable, count, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND) && rowset.cRows) {
+ for (index = 0; index < rowset.cRows; index++) {
+ fid = (const uint64_t *)find_SPropValue_data(&rowset.aRow[index], PR_FID);
+ tmp = (const char *)find_SPropValue_data(&rowset.aRow[index], PR_DISPLAY_NAME);
+
+ newname = windows_to_utf8(mt->mem_ctx, tmp);
+ if (newname && fid && !strcmp(newname, name)) {
+ retval = OpenFolder(obj_parent, *fid, obj_child);
+ mapi_object_release(&obj_htable);
+ MAPIFreeBuffer(newname);
+ return true;
+ }
+ MAPIFreeBuffer(newname);
+ }
+ }
+
+ mapi_object_release(&obj_htable);
+ return false;
+}
+
+
+/**
+ * Create a message ready to submit
+ */
+_PUBLIC_ bool mapitest_common_message_create(struct mapitest *mt,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_message,
+ const char *subject)
+{
+ enum MAPISTATUS retval;
+
+ /* Create the mesage */
+ retval = CreateMessage(obj_folder, obj_message);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "CreateMessage", GetLastError());
+ return false;
+ }
+
+ return mapitest_common_message_fill(mt, obj_message, subject);
+}
+
+/**
+ * Create a message ready to submit
+ */
+_PUBLIC_ bool mapitest_common_message_fill(struct mapitest *mt,
+ mapi_object_t *obj_message,
+ const char *subject)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ struct SPropValue SPropValue;
+ struct SPropValue lpProps[4];
+ const char *username[2];
+ const char *body;
+ uint32_t msgflag;
+ uint32_t format;
+
+ /* Sanity checks */
+ if (subject == NULL) return false;
+
+ /* Resolve recipients */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x6,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_7BIT_DISPLAY_NAME,
+ PR_DISPLAY_NAME,
+ PR_SMTP_ADDRESS,
+ PR_GIVEN_NAME);
+
+ username[0] = (const char *)mt->info.szDisplayName;
+ username[1] = NULL;
+
+ SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
+ flaglist = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+
+ retval = ResolveNames(mapi_object_get_session(obj_message), username, SPropTagArray,
+ &SRowSet, &flaglist, 0);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "ResolveNames", GetLastError());
+ talloc_free(SRowSet);
+ talloc_free(SPropTagArray);
+ talloc_free(flaglist);
+ return false;
+ }
+
+ SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
+ SPropValue.value.l = 0;
+ SRowSet_propcpy(mt->mem_ctx, SRowSet, SPropValue);
+
+ /* Set Recipients */
+ SetRecipientType(&(SRowSet->aRow[0]), MAPI_TO);
+ retval = ModifyRecipients(obj_message, SRowSet);
+ MAPIFreeBuffer(SRowSet);
+ MAPIFreeBuffer(flaglist);
+ if (retval != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "ModifyRecipients", retval);
+ return false;
+ }
+
+ /* Set message properties */
+ msgflag = MSGFLAG_SUBMIT;
+ set_SPropValue_proptag(&lpProps[0], PR_SUBJECT, (const void *) subject);
+ set_SPropValue_proptag(&lpProps[1], PR_MESSAGE_FLAGS, (const void *)&msgflag);
+ body = talloc_asprintf(mt->mem_ctx, "Body of message with subject: %s", subject);
+ set_SPropValue_proptag(&lpProps[2], PR_BODY, (const void *)body);
+ format = EDITOR_FORMAT_PLAINTEXT;
+ set_SPropValue_proptag(&lpProps[3], PR_MSG_EDITOR_FORMAT, (const void *)&format);
+
+ retval = SetProps(obj_message, lpProps, 4);
+ if (retval != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "SetProps", retval);
+ return false;
+ }
+
+ errno = 0;
+ return true;
+}
+
+
+/**
+ Generate a random blob of readable data
+
+ \param mem_ctx the talloc memory context to create the blob in
+ \param len the length of the blob to create
+
+ \return random blob of readable data, of length len bytes, with a
+ null terminator.
+
+ \note the data is from 0..len, and the null terminator is at position
+ len+1. So the returned array is actually len+1 bytes in total.
+
+ */
+_PUBLIC_ char *mapitest_common_genblob(TALLOC_CTX *mem_ctx, size_t len)
+{
+ int fd;
+ int ret;
+ unsigned int i;
+ char *retstr;
+ const char *list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,";
+ int list_len = strlen(list);
+
+ /* Sanity check */
+ if (!mem_ctx || (len == 0)) {
+ return NULL;
+ }
+
+ fd = open("/dev/urandom", O_RDONLY, 0);
+ if (fd == -1) {
+ return NULL;
+ }
+
+ retstr = talloc_array(mem_ctx, char, len + 1);
+ if ((ret = read(fd, retstr, len)) == -1) {
+ talloc_free(retstr);
+ return NULL;
+ }
+
+ for (i = 0; i < len; i++) {
+ retstr[i] = list[retstr[i] % list_len];
+ if (!retstr[i]) {
+ retstr[i] = 'X';
+ }
+ }
+ retstr[i] = '\0';
+
+ return retstr;
+}
+
+/**
+ Create a test folder, and fill with 10 sample messages
+
+ This function creates a test folder (name set by the MT_DIRNAME_TEST define),
+ and fills it with 5 messages with the same subject and 5 messages with the
+ same sender.
+
+ \param mt pointer to the mapitest context
+*/
+_PUBLIC_ bool mapitest_common_create_filled_test_folder(struct mapitest *mt)
+{
+ struct mt_common_tf_ctx *context;
+ enum MAPISTATUS retval;
+ const char *from = NULL;
+ const char *subject = NULL;
+ const char *body = NULL;
+ struct SPropValue lpProp[3];
+ int i;
+ uint32_t format;
+
+ context = mt->priv;
+
+ /* Create test folder */
+ mapi_object_init(&(context->obj_test_folder));
+ retval = CreateFolder(&(context->obj_top_folder), FOLDER_GENERIC,
+ MT_DIRNAME_TEST, NULL,
+ OPEN_IF_EXISTS, &(context->obj_test_folder));
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "Create the test folder", GetLastError());
+ return false;
+ }
+
+ /* Create 5 test messages in the test folder with the same subject */
+ for (i = 0; i < 5; ++i) {
+ mapi_object_init(&(context->obj_test_msg[i]));
+ retval = mapitest_common_message_create(mt, &(context->obj_test_folder),
+ &(context->obj_test_msg[i]), MT_MAIL_SUBJECT);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "Create test message", GetLastError());
+ mapi_object_release(&(context->obj_test_folder));
+ return false;
+ }
+
+ from = talloc_asprintf(mt->mem_ctx, "[MT] Dummy%i", i);
+ set_SPropValue_proptag(&lpProp[0], PR_SENDER_NAME, (const void *)from);
+ body = talloc_asprintf(mt->mem_ctx, "Body of message %i", i);
+ set_SPropValue_proptag(&lpProp[1], PR_BODY, (const void *)body);
+ format = EDITOR_FORMAT_PLAINTEXT;
+ set_SPropValue_proptag(&lpProp[2], PR_MSG_EDITOR_FORMAT, (const void *)&format);
+ retval = SetProps(&(context->obj_test_msg[i]), lpProp, 3);
+ MAPIFreeBuffer((void *)from);
+ MAPIFreeBuffer((void *)body);
+ if (retval != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "Set props on message", GetLastError());
+ mapi_object_release(&(context->obj_test_folder));
+ return false;
+ }
+ retval = SaveChangesMessage(&(context->obj_test_folder), &(context->obj_test_msg[i]), KeepOpenReadWrite);
+ if (retval != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "Save changes to message", GetLastError());
+ mapi_object_release(&(context->obj_test_folder));
+ return false;
+ }
+ }
+
+ /* Create 5 test messages in the test folder with the same sender */
+ for (i = 5; i < 10; ++i) {
+ mapi_object_init(&(context->obj_test_msg[i]));
+ subject = talloc_asprintf(mt->mem_ctx, "[MT] Subject%i", i);
+ retval = mapitest_common_message_create(mt, &(context->obj_test_folder),
+ &(context->obj_test_msg[i]), subject);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "Create test message", GetLastError());
+ return false;
+ }
+
+ from = talloc_asprintf(mt->mem_ctx, "[MT] Dummy From");
+ set_SPropValue_proptag(&lpProp[0], PR_SENDER_NAME, (const void *)from);
+ body = talloc_asprintf(mt->mem_ctx, "Body of message %i", i);
+ set_SPropValue_proptag(&lpProp[1], PR_BODY, (const void *)body);
+ format = EDITOR_FORMAT_PLAINTEXT;
+ set_SPropValue_proptag(&lpProp[2], PR_MSG_EDITOR_FORMAT, (const void *)&format);
+ retval = SetProps(&(context->obj_test_msg[i]), lpProp, 3);
+ MAPIFreeBuffer((void *)from);
+ MAPIFreeBuffer((void *)body);
+ if (retval != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "Set props on message", GetLastError());
+ return false;
+ }
+ retval = SaveChangesMessage(&(context->obj_test_folder), &(context->obj_test_msg[i]), KeepOpenReadWrite);
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ Convenience function to login to the server
+
+ This functions logs into the server, gets the top level store, and
+ gets the hierachy table for the top level store (which is returned as
+ obj_htable). It also creates a test folder with 10 test messages.
+
+ \param mt pointer to the top-level mapitest structure
+ \param obj_htable the hierachy table for the top level store
+ \param count the number of rows in the top level hierarchy table
+
+ \return true on success, otherwise false
+*/
+_PUBLIC_ bool mapitest_common_setup(struct mapitest *mt, mapi_object_t *obj_htable, uint32_t *count)
+{
+ bool ret = false;
+ struct mt_common_tf_ctx *context;
+
+ context = talloc(mt->mem_ctx, struct mt_common_tf_ctx);
+ mt->priv = context;
+
+ mapi_object_init(&(context->obj_store));
+ OpenMsgStore(mt->session, &(context->obj_store));
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&(context->obj_top_folder));
+ ret = mapitest_common_folder_open(mt, &(context->obj_store), &(context->obj_top_folder),
+ olFolderTopInformationStore);
+ if (ret == false) {
+ return false;
+ }
+
+ /* We do this before getting the hierachy table, because otherwise the new
+ test folder will be omitted, and the count will be wrong */
+ ret = mapitest_common_create_filled_test_folder(mt);
+ if (ret == false) {
+ return false;
+ }
+
+ mapi_object_init(obj_htable);
+ GetHierarchyTable(&(context->obj_top_folder), obj_htable, 0, count);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ Convenience function to clean up after logging into the server
+
+ This functions cleans up after a mapitest_common_setup() call
+
+ \param mt pointer to the top-level mapitest structure
+*/
+_PUBLIC_ void mapitest_common_cleanup(struct mapitest *mt)
+{
+ struct mt_common_tf_ctx *context;
+ int i;
+
+ context = mt->priv;
+
+ for (i = 0; i<10; ++i) {
+ mapi_object_release(&(context->obj_test_msg[i]));
+ }
+
+ EmptyFolder(&(context->obj_test_folder));
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "Empty test folder", GetLastError());
+ }
+
+ DeleteFolder(&(context->obj_top_folder), mapi_object_get_id(&(context->obj_test_folder)),
+ DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE, NULL);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "Delete test folder", GetLastError());
+ }
+
+ mapi_object_release(&(context->obj_test_folder));
+ mapi_object_release(&(context->obj_top_folder));
+ mapi_object_release(&(context->obj_store));
+
+ talloc_free(mt->priv);
+}
+
Added: trunk/openchange/utils/mapitest/mapitest_print.c
===================================================================
--- trunk/openchange/utils/mapitest/mapitest_print.c (rev 0)
+++ trunk/openchange/utils/mapitest/mapitest_print.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,476 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 <samba/version.h>
+#include <utils/mapitest/mapitest.h>
+
+#include <time.h>
+
+static int count = 0;
+
+#define CNT_INDENT() { count++; }
+#define CNT_DEINDENT() { count--; if (count < 0) count = 0; }
+#define CNT_PRINT(s) { int i; for (i = 0; i < count; i++) { fprintf(s, "\t"); } }
+
+/**
+ \file
+ Print / display functions for %mapitest output
+*/
+
+/**
+ \details Indent the mapitest_print tabulation counter
+ */
+_PUBLIC_ void mapitest_indent(void)
+{
+ CNT_INDENT();
+}
+
+
+/**
+ \details Deindent the mapitest_print tabulation counter
+ */
+_PUBLIC_ void mapitest_deindent(void)
+{
+ CNT_DEINDENT();
+}
+
+
+/**
+ \details Print tabulations given the internal counter
+
+ \param mt pointer to the top-level mapitest structure
+ */
+_PUBLIC_ void mapitest_print_tab(struct mapitest *mt)
+{
+ CNT_PRINT(mt->stream);
+}
+
+
+/**
+ \details Print a string in the stream
+
+ \param mt pointer to the top-level mapitest structure
+ \param format the format string
+ \param ... the format string parameters
+ */
+_PUBLIC_ void mapitest_print(struct mapitest *mt, const char *format, ...)
+{
+ va_list ap;
+ char *s = NULL;
+ int ret;
+
+ va_start(ap, format);
+ ret = vasprintf(&s, format, ap);
+ va_end(ap);
+
+ mapitest_print_tab(mt);
+ fprintf(mt->stream, s, strlen(s));
+ free(s);
+}
+
+/**
+ \details Print newline characters
+
+ \param mt pointer to the top-level mapitest structure
+ \param count number of newline characters to print
+ */
+_PUBLIC_ void mapitest_print_newline(struct mapitest *mt, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ fprintf(mt->stream, "\n");
+ }
+}
+
+/**
+ \details Print a line using a delimiter
+
+ \param mt pointer to the top-level mapitest structure
+ \param len the length of the line to print
+ \param delim the line delimiter
+ */
+_PUBLIC_ void mapitest_print_line(struct mapitest *mt, int len, char delim)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ fprintf(mt->stream, "%c", delim);
+ }
+ mapitest_print_newline(mt, 1);
+}
+
+
+/**
+ \details Underline a string
+
+ \param mt pointer to the top-level mapitest structure
+ \param str string to underline
+ \param delim the line delimiter
+ */
+_PUBLIC_ void mapitest_underline(struct mapitest *mt, const char *str, char delim)
+{
+ if (!str) return;
+
+ /* print str */
+ mapitest_print_tab(mt);
+ fprintf(mt->stream, "%s", str);
+
+ /* underline str using delim */
+ mapitest_print_tab(mt);
+ mapitest_print_line(mt, strlen(str), delim);
+}
+
+/**
+ \details Private general routine used to print a title
+
+ Avoid code redundancy over the API
+
+ \param mt pointer to the top-level mapitest structure
+ \param str the title
+ \param delim the underline delimiter
+ */
+_PUBLIC_ void mapitest_print_title(struct mapitest *mt, const char *str, char delim)
+{
+ mapitest_underline(mt, str, delim);
+ mapitest_indent();
+}
+
+
+/**
+ \details Print the module title
+
+ \param mt pointer to the top-level mapitest structure
+ \param str the module title string
+ */
+_PUBLIC_ void mapitest_print_module_title_start(struct mapitest *mt, const char *str)
+{
+ char *title = NULL;
+
+ if (!str) return;
+
+ title = talloc_asprintf(mt->mem_ctx, MODULE_TITLE, str);
+ mapitest_print(mt, "%s", title);
+ mapitest_print_tab(mt);
+ mapitest_print_line(mt, MODULE_TITLE_LINELEN, MODULE_TITLE_DELIM);
+ mapitest_indent();
+ talloc_free(title);
+}
+
+/**
+ \details Print the content at the end of the module
+
+ \param mt pointer to the top-level mapitest structure
+ */
+_PUBLIC_ void mapitest_print_module_title_end(struct mapitest *mt)
+{
+ mapitest_deindent();
+
+ mapitest_print_tab(mt);
+ mapitest_print_line(mt, MODULE_TITLE_LINELEN, MODULE_TITLE_DELIM);
+ mapitest_print_newline(mt, MODULE_TITLE_NEWLINE);
+}
+
+
+/**
+ \details print the test tile
+
+ \param mt pointer to the top-level mapitest structure
+ \param str the test title
+ */
+_PUBLIC_ void mapitest_print_test_title_start(struct mapitest *mt, const char *str)
+{
+ char *title = NULL;
+
+ if (!str) return;
+
+ title = talloc_asprintf(mt->mem_ctx, MODULE_TEST_TITLE, str);
+ mapitest_print(mt, "%s", title);
+ mapitest_print_tab(mt);
+ mapitest_print_line(mt, MODULE_TEST_LINELEN, MODULE_TEST_DELIM);
+ mapitest_indent();
+ talloc_free(title);
+}
+
+
+/**
+ \details Write the content at the end of a test
+
+ \param mt pointer to the top-level mapitest structure
+ */
+_PUBLIC_ void mapitest_print_test_title_end(struct mapitest *mt)
+{
+ mapitest_deindent();
+
+ mapitest_print_tab(mt);
+ mapitest_print_line(mt, MODULE_TEST_LINELEN, MODULE_TEST_DELIM);
+}
+
+
+/**
+ \details Starts the header output
+
+ \param mt pointer on the top-level mapitest structure
+ */
+static void mapitest_print_headers_start(struct mapitest *mt)
+{
+ mapitest_print(mt, MT_HDR_START);
+}
+
+
+/**
+ \details Ends the header output
+ */
+static void mapitest_print_headers_end(struct mapitest *mt)
+{
+ mapitest_print(mt, MT_HDR_END);
+}
+
+/**
+ \details Print mapitest report headers information
+
+ \param mt pointer to the top-level mapitest structure
+ */
+_PUBLIC_ void mapitest_print_headers_info(struct mapitest *mt)
+{
+ time_t t;
+ char *date;
+
+ time (&t);
+ date = ctime(&t);
+
+ mapitest_print(mt, MT_HDR_FMT_DATE, "Date", date);
+ mapitest_print(mt, MT_HDR_FMT, "Confidential mode",
+ (mt->confidential == true) ? MT_YES : MT_NO);
+ mapitest_print(mt, MT_HDR_FMT, "Samba Information", SAMBA_VERSION_STRING);
+ mapitest_print(mt, MT_HDR_FMT, "OpenChange Information", OPENCHANGE_VERSION_STRING);
+
+ mapitest_print_newline(mt, 1);
+ mapitest_print(mt, MT_HDR_FMT_SECTION, "System Information");
+ mapitest_indent();
+ mapitest_print(mt, MT_HDR_FMT_SUBSECTION, "Kernel name", OPENCHANGE_SYS_KERNEL_NAME);
+ mapitest_print(mt, MT_HDR_FMT_SUBSECTION, "Kernel release", OPENCHANGE_SYS_KERNEL_RELEASE);
+ mapitest_print(mt, MT_HDR_FMT_SUBSECTION, "Processor", OPENCHANGE_SYS_PROCESSOR);
+ mapitest_deindent();
+}
+
+
+/**
+ \details Print a report of the Exchange server and account information
+
+ \param mt pointer to the top-level mapitest structure
+ */
+_PUBLIC_ void mapitest_print_headers_server_info(struct mapitest *mt)
+{
+ if (mt->online == false) {
+ return;
+ }
+
+ mapitest_print_newline(mt, 1);
+ mapitest_print(mt, MT_HDR_FMT_SECTION, "Exchange Server");
+ mapitest_indent();
+ mapitest_print(mt, MT_HDR_FMT_STORE_VER, "Store version",
+ mt->info.rgwServerVersion[0],
+ mt->info.rgwServerVersion[1],
+ mt->info.rgwServerVersion[2]);
+ mapitest_print(mt, MT_HDR_FMT_SUBSECTION, "Username",
+ (mt->confidential == true) ? MT_CONFIDENTIAL : mt->info.szDisplayName);
+ mapitest_print(mt, MT_HDR_FMT_SUBSECTION, "Organization",
+ (mt->confidential == true) ? MT_CONFIDENTIAL : mt->org);
+ mapitest_print(mt, MT_HDR_FMT_SUBSECTION, "Organization Unit",
+ (mt->confidential == true) ? MT_CONFIDENTIAL : mt->org_unit);
+ mapitest_deindent();
+}
+
+
+/**
+ \details Print mapitest report headers
+
+ \param mt pointer to the top-level mapitest structure
+ */
+_PUBLIC_ void mapitest_print_headers(struct mapitest *mt)
+{
+ mapitest_print_headers_start(mt);
+ mapitest_indent();
+ mapitest_print_headers_info(mt);
+ if (mt->no_server == false) {
+ mapitest_print_headers_server_info(mt);
+ }
+ mapitest_deindent();
+ mapitest_print_headers_end(mt);
+ mapitest_print_newline(mt, 2);
+}
+
+
+/**
+ \details Print %mapitest test result
+
+ \param mt pointer to the top-level mapitest structure
+ \param name the test name
+ \param ret boolean value with the test result
+ */
+_PUBLIC_ void mapitest_print_test_result(struct mapitest *mt, char *name, bool ret)
+{
+ mapitest_print(mt, MODULE_TEST_RESULT, name, (ret == true) ?
+ MODULE_TEST_SUCCESS : MODULE_TEST_FAILURE);
+ mapitest_print_tab(mt);
+ mapitest_print_line(mt, MODULE_TEST_LINELEN, MODULE_TEST_DELIM2);
+ mapitest_print_newline(mt, MODULE_TEST_NEWLINE);
+}
+
+
+/**
+ \details Print %mapitest return value
+
+ \param mt pointer to the top-level mapitest structure
+ \param name the test name
+
+ \sa mapitest_print_retval_fmt for a version providing an additional format string
+ */
+_PUBLIC_ void mapitest_print_retval(struct mapitest *mt, char *name)
+{
+ const char *retstr = NULL;
+
+ retstr = mapi_get_errstr(GetLastError());
+
+ if (mt->color == true) {
+ if (retstr) {
+ mapitest_print(mt, "* %-35s: %s %s %s \n", name, (GetLastError() ? MT_RED : MT_GREEN), retstr, MT_WHITE);
+ } else {
+ mapitest_print(mt, "* %-35s: %s Unknown Error (0x%.8x) %s\n", name, MT_RED, GetLastError(), MT_WHITE);
+ }
+ } else {
+ if (retstr) {
+ mapitest_print(mt, "* %-35s: %s\n", name, retstr);
+ } else {
+ mapitest_print(mt, "* %-35s: Unknown Error (0x%.8x)\n", name, GetLastError());
+ }
+ }
+}
+
+
+/**
+ \details Print %mapitest return value with additional format string
+
+ \param mt pointer to the top-level mapitest structure
+ \param name the test name
+ \param format the format string
+ \param ... the format string parameters
+ */
+_PUBLIC_ void mapitest_print_retval_fmt(struct mapitest *mt, char *name, const char *format, ...)
+{
+ const char *retstr = NULL;
+ va_list ap;
+ char *s = NULL;
+ int ret;
+
+ va_start(ap, format);
+ ret = vasprintf(&s, format, ap);
+ va_end(ap);
+
+ retstr = mapi_get_errstr(GetLastError());
+
+ if (mt->color == true) {
+ if (retstr) {
+ mapitest_print(mt, "* %-35s: %s %s %s %s\n", name, (GetLastError() ? MT_RED: MT_GREEN), retstr, MT_WHITE, s);
+ } else {
+ mapitest_print(mt, "* %-35s: %s Unknown Error (0x%.8x) %s %s\n", name, MT_RED, GetLastError(), MT_WHITE, s);
+ }
+ } else {
+ if (retstr) {
+ mapitest_print(mt, "* %-35s: %s %s\n", name, retstr, s);
+ } else {
+ mapitest_print(mt, "* %-35s: Unknown Error (0x%.8x) %s\n", name, GetLastError(), s);
+ }
+ }
+ free(s);
+}
+
+
+/**
+ \details Print %mapitest return value for a given step
+
+ \param mt pointer tp the top-level mapitest structure
+ \param step the test step
+ \param name the test name
+
+ \sa mapitest_print_retval_step_fmt for a version providing an additional format string
+ */
+_PUBLIC_ void mapitest_print_retval_step(struct mapitest *mt, char *step, char *name)
+{
+ const char *retstr = NULL;
+
+ retstr = mapi_get_errstr(GetLastError());
+
+ if (mt->color == true) {
+ if (retstr) {
+ mapitest_print(mt, "* Step %-5s %-35s: %s %s %s\n", step, name, (GetLastError() ? MT_RED : MT_GREEN), retstr, MT_WHITE);
+ } else {
+ mapitest_print(mt, "* Step %-5s %-35s: %s Unknown Error (0x%.8x) %s\n", step, name, MT_RED, GetLastError(), MT_WHITE);
+ }
+ } else {
+ if (retstr) {
+ mapitest_print(mt, "* Step %-5s %-35s: %s\n", step, name, retstr);
+ } else {
+ mapitest_print(mt, "* Step %-5s %-35s: Unknown Error (0x%.8x)\n", step, name, GetLastError());
+ }
+ }
+}
+
+
+/**
+ \details Print %mapitest return value for a given step with additional format string
+
+ \param mt pointer to the top-level mapitest structure
+ \param step the test step
+ \param name the test name
+ \param format the format string
+ \param ... the format string parameters
+ */
+_PUBLIC_ void mapitest_print_retval_step_fmt(struct mapitest *mt, char *step, char *name, const char *format, ...)
+{
+ const char *retstr = NULL;
+ va_list ap;
+ char *s = NULL;
+ int ret;
+
+ va_start(ap, format);
+ ret = vasprintf(&s, format, ap);
+ va_end(ap);
+
+ retstr = mapi_get_errstr(GetLastError());
+
+ if (mt->color == true) {
+ if (retstr) {
+ mapitest_print(mt, "* Step %-5s %-35s: %s %s %s %s\n", step, name, (GetLastError() ? MT_RED : MT_GREEN), retstr, MT_WHITE, s);
+ } else {
+ mapitest_print(mt, "* Step %-5s %-35s: %s Unknown Error (0x%.8x) %s %s\n", step, name, MT_RED, GetLastError(), MT_WHITE, s);
+ }
+ } else {
+ if (retstr) {
+ mapitest_print(mt, "* Step %-5s %-35s: %s %s\n", step, name, retstr, s);
+ } else {
+ mapitest_print(mt, "* Step %-5s %-35s: Unknown Error (0x%.8x) %s\n", step, name, GetLastError(), s);
+ }
+ }
+ free(s);
+}
Added: trunk/openchange/utils/mapitest/mapitest_stat.c
===================================================================
--- trunk/openchange/utils/mapitest/mapitest_stat.c (rev 0)
+++ trunk/openchange/utils/mapitest/mapitest_stat.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,126 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "utils/mapitest/mapitest.h"
+
+/**
+ \file
+ mapitest statistics functions
+
+ mapitest records and prints the results of each test
+ using these functions
+*/
+
+/**
+ \details Initialize the mapitest statistic structure
+
+ \param mem_ctx memory allocation context
+
+ \return Allocated stat structure on success, otherwise NULL
+ */
+_PUBLIC_ struct mapitest_stat *mapitest_stat_init(TALLOC_CTX *mem_ctx)
+{
+ struct mapitest_stat *stat = NULL;
+
+ /* Sanity check */
+ if (!mem_ctx) return NULL;
+
+ stat = talloc_zero(mem_ctx, struct mapitest_stat);
+ stat->success = 0;
+ stat->failure = 0;
+ stat->failure_info = NULL;
+ stat->enabled = false;
+
+ return stat;
+}
+
+
+/**
+ \details Add test result to the suite statistic parameter
+
+ \param suite the suite container
+ \param name the test name
+ \param result the test result
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t mapitest_stat_add_result(struct mapitest_suite *suite,
+ const char *name,
+ bool result)
+{
+ struct mapitest_unit *el = NULL;
+
+ /* Sanity check */
+ if (!suite || !suite->stat || !name) return MAPITEST_ERROR;
+
+ if (result == true) {
+ 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);
+ DLIST_ADD_END(suite->stat->failure_info, el, struct mapitest_unit *);
+ }
+
+ suite->stat->enabled = true;
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details Dump mapitest statistics about test failures
+
+ \param mt the global mapitest structure
+
+ \return the number of test steps that failed (i.e. 0 for all success)
+ */
+_PUBLIC_ int32_t mapitest_stat_dump(struct mapitest *mt)
+{
+ struct mapitest_suite *suite;
+ struct mapitest_unit *el;
+ int32_t num_passed_tests = 0;
+ int32_t num_failed_tests = 0;
+
+ mapitest_print_title(mt, MT_STAT_TITLE, MODULE_TITLE_DELIM);
+
+ for (suite = mt->mapi_suite; suite; suite = suite->next) {
+ if (suite->stat->enabled == true) {
+ num_passed_tests += suite->stat->success;
+ num_failed_tests += suite->stat->failure;
+ if (suite->stat->failure) {
+ for (el = suite->stat->failure_info; el; el = el->next) {
+ mapitest_print(mt, MT_STAT_FAILURE, suite->name, el->name);
+ }
+ }
+ }
+ }
+
+ mapitest_print_test_title_end(mt);
+
+ mapitest_print_title(mt, MT_SUMMARY_TITLE, MODULE_TITLE_DELIM);
+ 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_test_title_end(mt);
+
+ return num_failed_tests;
+}
Added: trunk/openchange/utils/mapitest/mapitest_suite.c
===================================================================
--- trunk/openchange/utils/mapitest/mapitest_suite.c (rev 0)
+++ trunk/openchange/utils/mapitest/mapitest_suite.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,365 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "utils/mapitest/mapitest.h"
+
+/**
+ \file
+
+ mapitest test suite functions
+*/
+
+/**
+ \details Initialize a mapitest suite
+
+ \param mt the top-level mapitest structure
+ \param name the suite name
+ \param description the suite description
+ \param online whether this suite requires online (server) access
+
+ \return An allocated mapitest_suite pointer, otherwise NULL.
+ */
+_PUBLIC_ struct mapitest_suite *mapitest_suite_init(struct mapitest *mt,
+ const char *name,
+ const char *description,
+ bool online)
+{
+ struct mapitest_suite *suite = NULL;
+
+ /* Sanity check */
+ if (!mt || !mt->mem_ctx) return NULL;
+ if (!name) return NULL;
+
+ suite = talloc_zero(mt->mem_ctx, struct mapitest_suite);
+ suite->tests = NULL;
+ suite->stat = mapitest_stat_init((TALLOC_CTX *)suite);
+
+ suite->name = talloc_strdup((TALLOC_CTX *) suite, name);
+ if (!description) {
+ suite->description = NULL;
+ } else {
+ suite->description = talloc_strdup((TALLOC_CTX *)suite, description);
+ }
+
+ suite->online = online;
+
+ return suite;
+}
+
+
+/**
+ \details Register a mapitest suite
+
+ \param mt the top-level mapitest structure
+ \param suite the mapitest suite we want to add
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+
+ \sa mapitest_suite_init
+ */
+_PUBLIC_ uint32_t mapitest_suite_register(struct mapitest *mt,
+ struct mapitest_suite *suite)
+{
+ struct mapitest_suite *el = NULL;
+
+ /* Sanity check */
+ if (!mt || !mt->mem_ctx) return MAPITEST_ERROR;
+ if (!suite) return MAPITEST_ERROR;
+
+ /* Ensure the name is not yet registered */
+ for (el = mt->mapi_suite; el; el = el->next) {
+ if (el->name && !strcmp(el->name, suite->name)) {
+ fprintf(stderr, "Suite already registered\n");
+ return MAPITEST_ERROR;
+ }
+ }
+
+ DLIST_ADD_END(mt->mapi_suite, suite, struct mapitest_suite *);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details add a simple test to the mapitest suite
+
+ \param suite pointer on the parent suite
+ \param name the test name
+ \param run the test function
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+
+ \sa mapitest_suite_init, mapitest_suite_register
+ */
+_PUBLIC_ uint32_t mapitest_suite_add_simple_test(struct mapitest_suite *suite,
+ const char *name,
+ bool (*run) (struct mapitest *test))
+{
+ struct mapitest_test *el = NULL;
+
+ /* Sanity check */
+ if (!suite || !name || !run) return MAPITEST_ERROR;
+
+ /* Ensure the test is not yet registered */
+ for (el = suite->tests; el; el = el->next) {
+ if (el->name && !strcmp(el->name, name)) {
+ return MAPITEST_ERROR;
+ }
+ }
+
+ el = talloc_zero((TALLOC_CTX *) suite, struct mapitest_test);
+ el->name = talloc_asprintf((TALLOC_CTX *)suite, "%s-%s", suite->name, name);
+ el->description = NULL;
+ el->fn = run;
+
+ DLIST_ADD_END(suite->tests, el, struct mapitest_test *);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details add a test to the mapitest suite with description
+
+ \param suite pointer on the parent suite
+ \param name the test name
+ \param description the test description
+ \param run the test function
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+
+ \sa mapitest_suite_init, mapitest_suite_register
+*/
+_PUBLIC_ uint32_t mapitest_suite_add_test(struct mapitest_suite *suite,
+ const char *name, const char *description,
+ bool (*run) (struct mapitest *test))
+{
+ struct mapitest_test *el = NULL;
+
+ /* Sanity check */
+ if (!suite || !name || !run || !description) return MAPITEST_ERROR;
+
+ /* Ensure the test is not yet registered */
+ for (el = suite->tests; el; el = el->next) {
+ if (el->name && !strcmp(el->name, name)) {
+ return MAPITEST_ERROR;
+ }
+ }
+
+ el = talloc_zero((TALLOC_CTX *) suite, struct mapitest_test);
+ el->name = talloc_asprintf((TALLOC_CTX *)suite, "%s-%s", suite->name, name);
+ el->description = talloc_strdup((TALLOC_CTX *)suite, description);
+ el->fn = run;
+
+ DLIST_ADD_END(suite->tests, el, struct mapitest_test *);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details Find a suite given its name
+
+ \param mt top-level mapitest structure
+ \param name the suite name to be searched
+
+ \return Pointer on a suite on success, otherwise NULL
+ */
+_PUBLIC_ struct mapitest_suite *mapitest_suite_find(struct mapitest *mt,
+ const char *name)
+{
+ struct mapitest_suite *suite = NULL;
+
+ if (!name) return NULL;
+
+ for (suite = mt->mapi_suite; suite; suite = suite->next) {
+ if (!strcmp(name, suite->name)) {
+ return suite;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ \details run a test from a suite given its name
+
+ \param mt pointer on the top-level mapitest structure
+ \param suite pointer on the mapitest suite
+ \param name the name of the test to be run
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_suite_run_test(struct mapitest *mt,
+ struct mapitest_suite *suite,
+ const char *name)
+{
+ struct mapitest_test *el;
+ bool ret;
+ bool (*fn)(struct mapitest *);
+
+ if (!suite || !name) return false;
+
+ for (el = suite->tests; el; el = el->next) {
+ if (!strcmp(el->name, name)) {
+ 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);
+ return ret;
+ }
+ }
+
+ fprintf(stderr, "[ERROR] %s test doesn't exist\n", name);
+ return false;
+}
+
+
+/**
+ \details run the special SUITE-ALL test
+
+ \param mt the top-level mapitest structure
+ \param name the mapitest test name
+
+ \return true on success, otherwise -1
+ */
+static bool mapitest_run_test_all(struct mapitest *mt, const char *name)
+{
+ char *test_name;
+ char *sname;
+ char *tmp;
+ struct mapitest_test *el;
+ struct mapitest_suite *suite;
+ bool ret = false;
+
+ test_name = talloc_strdup(mt->mem_ctx, name);
+ if ((tmp = strtok(test_name, "-")) == NULL) {
+ talloc_free(test_name);
+ }
+
+ sname = talloc_strdup(mt->mem_ctx, tmp);
+ if ((tmp = strtok(NULL, "-")) == NULL) {
+ talloc_free(test_name);
+ talloc_free(sname);
+ return false;
+ }
+
+ if (!strcmp(tmp,"ALL")) {
+ suite = mapitest_suite_find(mt, sname);
+
+ if (suite) {
+ for (el = suite->tests; el; el = el->next) {
+ mapitest_suite_run_test(mt, suite, el->name);
+ ret = true;
+ }
+ }
+ }
+ talloc_free(sname);
+ talloc_free(test_name);
+ return ret;
+}
+
+
+/**
+ \details run a specific test from a particular suite
+
+ \param mt the top-level mapitest structure
+ \param name the mapitest test name
+
+ \return true on success, otherwise -1
+ */
+_PUBLIC_ bool mapitest_run_test(struct mapitest *mt, const char *name)
+{
+ struct mapitest_suite *suite;
+ struct mapitest_test *el;
+ bool ret;
+
+ /* sanity check */
+ if (!mt || !name) return false;
+
+ /* try to find the test */
+ for (suite = mt->mapi_suite; suite; suite = suite->next) {
+ for (el = suite->tests; el; el = el->next) {
+ if (!strcmp(name, el->name)) {
+ if ((mt->online == suite->online) || (suite->online == false)) {
+ errno = 0;
+ ret = mapitest_suite_run_test(mt, suite, name);
+ return ret;
+ } else {
+ fprintf(stderr, "Server is offline, skipping test: \"%s\"\n", name);
+ return true;
+ }
+ }
+ }
+ }
+
+ /* if no name matches, look it it matches ALL */
+ ret = mapitest_run_test_all(mt, name);
+
+ if (ret != true) {
+ fprintf(stderr, "[ERROR] Unknown test: \"%s\"\n", name);
+ }
+
+ return ret;
+}
+
+
+/**
+ \details all tests from all suites
+
+ \param mt the top-level mapitest structure
+
+ \return true on success, otherwise -1
+ */
+_PUBLIC_ bool 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) {
+ 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);
+ }
+
+ mapitest_print_module_title_end(mt);
+ }
+ }
+ return ret;
+}
Added: trunk/openchange/utils/mapitest/module.c
===================================================================
--- trunk/openchange/utils/mapitest/module.c (rev 0)
+++ trunk/openchange/utils/mapitest/module.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,363 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+_PUBLIC_ uint32_t mapitest_register_modules(struct mapitest *mt)
+{
+ uint32_t ret;
+
+ ret = module_oxcstor_init(mt);
+ ret += module_oxcfold_init(mt);
+ ret += module_oxctable_init(mt);
+ ret += module_oxomsg_init(mt);
+ ret += module_oxcmsg_init(mt);
+ ret += module_oxcprpt_init(mt);
+ ret += module_oxorule_init(mt);
+ ret += module_oxcfxics_init(mt);
+ ret += module_nspi_init(mt);
+ ret += module_noserver_init(mt);
+ ret += module_errorchecks_init(mt);
+ ret += module_lcid_init(mt);
+
+ return ret;
+}
+
+
+/**
+ \details Register the Store Object Protocol test suite
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_oxcstor_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "OXCSTOR", "Store Object Protocol", true);
+
+ mapitest_suite_add_test(suite, "LOGON", "Logon operation", mapitest_oxcstor_Logon);
+ mapitest_suite_add_test(suite, "GET-RECEIVE-FOLDER", "Retrieve the receive folder ID", mapitest_oxcstor_GetReceiveFolder);
+ mapitest_suite_add_test(suite, "SET-RECEIVE-FOLDER", "Set the receive folder", mapitest_oxcstor_SetReceiveFolder);
+ mapitest_suite_add_test(suite, "GET-RECEIVE-FOLDER-TABLE", "Retrieve the Receive Folder Table", mapitest_oxcstor_GetReceiveFolderTable);
+ mapitest_suite_add_test(suite, "PUBLICFOLDER-ISGHOSTED", "Determine if a public folder is ghosted", mapitest_oxcstor_PublicFolderIsGhosted);
+ mapitest_suite_add_test(suite, "GETOWNINGSERVERS", "Get the list of servers that host replicas of a given public folder", mapitest_oxcstor_GetOwningServers);
+ mapitest_suite_add_test(suite, "LONGTERMID", "Map to / from a Long Term ID", mapitest_oxcstor_LongTermId);
+ mapitest_suite_add_test(suite, "GETSTORESTATE", "Retrieve the store state", mapitest_oxcstor_GetStoreState);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details Register the Folder Object Protocol test suite
+
+ \param mt the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_oxcfold_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "OXCFOLD", "Folder Object Protocol", true);
+
+ mapitest_suite_add_test(suite, "OPEN", "Open a folder", mapitest_oxcfold_OpenFolder);
+ mapitest_suite_add_test(suite, "CREATE", "Create a folder", mapitest_oxcfold_CreateFolder);
+ mapitest_suite_add_test(suite, "GET-HIERARCHY-TABLE", "Retrieve the hierarchy table", mapitest_oxcfold_GetHierarchyTable);
+ mapitest_suite_add_test(suite, "GET-CONTENTS-TABLE", "Retrieve the contents table", mapitest_oxcfold_GetContentsTable);
+ mapitest_suite_add_test(suite, "SET-SEARCHCRITERIA", "Set a search criteria on a container", mapitest_oxcfold_SetSearchCriteria);
+ mapitest_suite_add_test(suite, "GET-SEARCHCRITERIA", "Retrieve a search criteria associated to a container", mapitest_oxcfold_GetSearchCriteria);
+ mapitest_suite_add_test(suite, "MOVECOPY-MESSAGES", "Move or copy messages from a source to destination folder", mapitest_oxcfold_MoveCopyMessages);
+ mapitest_suite_add_test(suite, "MOVEFOLDER", "Move folder from source to destination", mapitest_oxcfold_MoveFolder);
+ mapitest_suite_add_test(suite, "COPYFOLDER", "Copy folder from source to destination", mapitest_oxcfold_CopyFolder);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details Register the E-mail Object Protocol test suite
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_oxomsg_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "OXOMSG", "E-mail Object Protocol", true);
+
+ mapitest_suite_add_test(suite, "ADDRESS-TYPES", "Address Types", mapitest_oxomsg_AddressTypes);
+ mapitest_suite_add_test(suite, "SUBMIT-MESSAGE", "Submit message", mapitest_oxomsg_SubmitMessage);
+ mapitest_suite_add_test(suite, "ABORT-SUBMIT", "Abort submitted message", mapitest_oxomsg_AbortSubmit);
+ mapitest_suite_add_test(suite, "SET-SPOOLER", "Client intends to act as a mail spooler", mapitest_oxomsg_SetSpooler);
+ mapitest_suite_add_test(suite, "SPOOLER-LOCK-MESSAGE", "Lock the specified message for spooling", mapitest_oxomsg_SpoolerLockMessage);
+ mapitest_suite_add_test(suite, "TRANSPORT-SEND", "Sends the specified message object out for message delivery", mapitest_oxomsg_TransportSend);
+ mapitest_suite_add_test(suite, "GET-TRANSPORT-FOLDER", "Retrieve the temporary transport folder ID", mapitest_oxomsg_GetTransportFolder);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details Register the Message and Attachment Object Protocol test suite
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_oxcmsg_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "OXCMSG", "Message and Attachment Object Protocol", true);
+
+ mapitest_suite_add_test(suite, "CREATE-MESSAGE", "Create message", mapitest_oxcmsg_CreateMessage);
+ mapitest_suite_add_test(suite, "SET-MESSAGE-READ-FLAGS", "Set message read flag", mapitest_oxcmsg_SetMessageReadFlag);
+ mapitest_suite_add_test(suite, "SET-READ-FLAGS", "Set read flag on multiple messages", mapitest_oxcmsg_SetReadFlags);
+ mapitest_suite_add_test(suite, "MODIFY-RECIPIENTS", "Add new recipients", mapitest_oxcmsg_ModifyRecipients);
+ mapitest_suite_add_test(suite, "READ-RECIPIENTS", "Read recipients from a message", mapitest_oxcmsg_ReadRecipients);
+ mapitest_suite_add_test(suite, "REMOVE-ALL-RECIPIENTS", "Remove all recipients from a message", mapitest_oxcmsg_RemoveAllRecipients);
+ mapitest_suite_add_test(suite, "SAVE-CHANGES-MESSAGE", "Save changes on message", mapitest_oxcmsg_SaveChangesMessage);
+ mapitest_suite_add_test(suite, "GET-MESSAGE-STATUS", "Get message status", mapitest_oxcmsg_GetMessageStatus);
+ mapitest_suite_add_test(suite, "SET-MESSAGE-STATUS", "Set message status", mapitest_oxcmsg_SetMessageStatus);
+ mapitest_suite_add_test(suite, "OPEN-EMBEDDED-MESSAGE", "Open a message embedded in another message", mapitest_oxcmsg_OpenEmbeddedMessage);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details Register the Table Object Protocol test suite
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_oxctable_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "OXCTABLE", "Table Object Protocol", true);
+
+ mapitest_suite_add_test(suite, "SETCOLUMNS", "Set Table Columns", mapitest_oxctable_SetColumns);
+ mapitest_suite_add_test(suite, "QUERYCOLUMNS", "Query Table Columns", mapitest_oxctable_QueryColumns);
+ mapitest_suite_add_test(suite, "QUERYROWS", "Query Table Rows", mapitest_oxctable_QueryRows);
+ mapitest_suite_add_test(suite, "GETSTATUS", "Get Table Status", mapitest_oxctable_GetStatus);
+ mapitest_suite_add_test(suite, "SEEKROW", "Seek a row", mapitest_oxctable_SeekRow);
+ mapitest_suite_add_test(suite, "RESTRICT", "Apply filters to a table", mapitest_oxctable_Restrict);
+ mapitest_suite_add_test(suite, "SEEKROW-APPROX", "Seek an approximate row", mapitest_oxctable_SeekRowApprox);
+ mapitest_suite_add_test(suite, "CREATE-BOOKMARK", "Create a table bookmark", mapitest_oxctable_CreateBookmark);
+ mapitest_suite_add_test(suite, "SEEKROW-BOOKMARK", "Seek a row given a bookmark", mapitest_oxctable_SeekRowBookmark);
+ mapitest_suite_add_test(suite, "CATEGORY", "Expand/collapse category rows", mapitest_oxctable_Category);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details Register the Property and Stream Object Protocol test
+ suite
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_oxcprpt_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "OXCPRPT", "Property and Stream Object Protocol", true);
+
+ mapitest_suite_add_test(suite, "GET-PROPS", "Retrieve a specific set of properties", mapitest_oxcprpt_GetProps);
+ mapitest_suite_add_test(suite, "GET-PROPSALL", "Retrieve the whole property array", mapitest_oxcprpt_GetPropsAll);
+ mapitest_suite_add_test(suite, "GET-PROPLIST", "Retrieve the property list", mapitest_oxcprpt_GetPropList);
+ mapitest_suite_add_test(suite, "SET-PROPS", "Set a specific set of properties", mapitest_oxcprpt_SetProps);
+ mapitest_suite_add_test(suite, "DELETE-PROPS", "Delete a specific set of properties", mapitest_oxcprpt_DeleteProps);
+ mapitest_suite_add_test(suite, "DELETE-PROPS-NOREPL", "Delete a specific set of properties (no replicate)", mapitest_oxcprpt_DeletePropertiesNoReplicate);
+ mapitest_suite_add_test(suite, "COPY-PROPS", "Copy a specified set of properties", mapitest_oxcprpt_CopyProps);
+ mapitest_suite_add_test(suite, "STREAM", "Test stream operations", mapitest_oxcprpt_Stream);
+ mapitest_suite_add_test(suite, "COPYTO", "Copy or move properties", mapitest_oxcprpt_CopyTo);
+ mapitest_suite_add_test(suite, "COPYTO-STREAM", "Copy stream from source to desination stream", mapitest_oxcprpt_CopyToStream);
+ mapitest_suite_add_test(suite, "NAME-ID", "Convert between Names and IDs", mapitest_oxcprpt_NameId);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details Register the E-Mail Rules Protocol test suite
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_oxorule_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "OXORULE", "E-Mail Rules Protocol", true);
+
+ mapitest_suite_add_test(suite, "GET-RULES-TABLE", "Retrieve the rules table associated to a folder", mapitest_oxorule_GetRulesTable);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details Register the Bulk Data Transfer Protocol test suite
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_oxcfxics_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "OXCFXICS", "Bulk Data Transfer Protocol", true);
+
+ mapitest_suite_add_test(suite, "GET-LOCAL-REPLICA-IDS", "Reserve a range of IDs for local replica", mapitest_oxcfxics_GetLocalReplicaIds);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details Register the NSPI test suite
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_nspi_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "NSPI", "Name Service Provider Interface", true);
+
+ mapitest_suite_add_test(suite, "UPDATESTAT", "Update the STAT structure", mapitest_nspi_UpdateStat);
+ mapitest_suite_add_test(suite, "QUERYROWS", "Returns a number of rows from a specified table", mapitest_nspi_QueryRows);
+ mapitest_suite_add_test(suite, "SEEKENTRIES", "Searches for and sets the logical position in a specific table", mapitest_nspi_SeekEntries);
+ mapitest_suite_add_test(suite, "GETMATCHES", "Returns an explicit table", mapitest_nspi_GetMatches);
+ mapitest_suite_add_test(suite, "RESORTRESTRICTION", "Apply a sort order to the objects in a restricted address book container", mapitest_nspi_ResortRestriction);
+ mapitest_suite_add_test(suite, "DNTOMID", "Maps a set of DN to a set of MId", mapitest_nspi_DNToMId);
+ mapitest_suite_add_test(suite, "GETPROPLIST", "Retrieve the list of properties associated to an object", mapitest_nspi_GetPropList);
+ mapitest_suite_add_test(suite, "GETPROPS", "Returns a row containing a set of the properties and values", mapitest_nspi_GetProps);
+ mapitest_suite_add_test(suite, "COMPAREMIDS", "Compare the position in an AB container of two objects", mapitest_nspi_CompareMIds);
+ mapitest_suite_add_test(suite, "MODPROPS", "Modify an address book object", mapitest_nspi_ModProps);
+ mapitest_suite_add_test(suite, "GETSPECIALTABLE", "Returns the rows of a special table to the client", mapitest_nspi_GetSpecialTable);
+ mapitest_suite_add_test(suite, "GETTEMPLATEINFO", "Returns information about template objects", mapitest_nspi_GetTemplateInfo);
+ mapitest_suite_add_test(suite, "MODLINKATT", "Modifies the values of a specific property of a specific row", mapitest_nspi_ModLinkAtt);
+ mapitest_suite_add_test(suite, "QUERYCOLUMNS", "Returns a list of all the properties the NSPI server is aware of", mapitest_nspi_QueryColumns);
+ mapitest_suite_add_test(suite, "GETNAMESFROMIDS", "Returns a list of property names for a set of proptags", mapitest_nspi_GetNamesFromIDs);
+ mapitest_suite_add_test(suite, "GETIDSFROMNAMES", "Returns the property IDs associated with property names", mapitest_nspi_GetIDsFromNames);
+ mapitest_suite_add_test(suite, "RESOLVENAMES", "Resolve usernames", mapitest_nspi_ResolveNames);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
+
+
+/**
+ \details Return the no server test suite
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_noserver_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "NOSERVER", "No server operations", false);
+
+ mapitest_suite_add_test(suite, "LZFU", "Test Compressed RTF operations", mapitest_noserver_lzfu);
+ mapitest_suite_add_test(suite, "SROWSET", "Test SRowSet parsing", mapitest_noserver_srowset);
+ mapitest_suite_add_test(suite, "GETSETPROPS", "Test Property handling", mapitest_noserver_properties);
+ mapitest_suite_add_test(suite, "MAPIPROPS", "Test MAPI Property handling", mapitest_noserver_mapi_properties);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
+
+/**
+ \details Initialise the error / sanity-check test suite
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_errorchecks_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "ERRORCHECKS", "Error / sanity-check operations", false);
+
+ mapitest_suite_add_test(suite, "SIMPLEMAPI", "Test failure paths for simplemapi.c", mapitest_errorchecks_simplemapi_c);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
+
+/**
+ \details Initialise the language code / ID test suite
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_lcid_init(struct mapitest *mt)
+{
+ struct mapitest_suite *suite = NULL;
+
+ suite = mapitest_suite_init(mt, "LCID", "Language code / ID operations", false);
+
+ mapitest_suite_add_test(suite, "CODE2TAG", "Tests for lcid_langcode2langtag", mapitest_lcid_langcode2langtag);
+
+ mapitest_suite_register(mt, suite);
+
+ return MAPITEST_SUCCESS;
+}
Added: trunk/openchange/utils/mapitest/modules/mapitest.doxy
===================================================================
--- trunk/openchange/utils/mapitest/modules/mapitest.doxy (rev 0)
+++ trunk/openchange/utils/mapitest/modules/mapitest.doxy 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,14 @@
+/**
+\mainpage %mapitest documentation
+
+%mapitest acts as stand-alone torture test of a range of MAPI function
+calls. It is intended to validate the implementation of various
+functions, and to ensure that existing functionality does not suffer
+regression between releases.
+
+As a general principle, %mapitest calls should leave the system in the
+same state at the end as at the start - it is meant to clean up after
+itself.
+
+*/
+
Added: trunk/openchange/utils/mapitest/modules/module_errorchecks.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_errorchecks.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_errorchecks.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,312 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - Error / sanity-check path tests
+
+ Copyright (C) Brad Hards 2008
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_errorchecks.c
+
+ \brief Error / sanity-check path tests
+
+ \note These tests do not show how to use libmapi properly, and should
+ not be used as a programming reference.
+*/
+
+/**
+ \details Create a correctly initialized global context
+*/
+static void make_global_ctx_valid(char* mem_ctx)
+{
+ global_mapi_ctx = talloc_zero(mem_ctx, struct mapi_ctx);
+}
+
+/**
+ \details De-initialize the global context
+*/
+static void make_global_ctx_invalid(void)
+{
+ talloc_free(global_mapi_ctx);
+ global_mapi_ctx = 0;
+}
+
+/**
+ \details Verify simplemapi.c functions
+
+ This function:
+ -# Tests the sanity checks in GetDefaultPublicFolder
+ -# Tests the sanity checks in GetDefaultFolder
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+*/
+_PUBLIC_ bool mapitest_errorchecks_simplemapi_c(struct mapitest *mt)
+{
+ enum MAPISTATUS status;
+ mapi_object_t *obj_store = 0;
+ mapi_object_t *obj_folder = 0;
+ mapi_object_t *obj_message = 0;
+ mapi_object_t tmp;
+ uint64_t *folder = 0;
+ uint32_t id = 0x99;
+ uint32_t arg; // an all purpose argument...
+ TALLOC_CTX *mem_ctx;
+
+ make_global_ctx_invalid();
+
+ status = GetDefaultPublicFolder(obj_store, folder, id);
+ if ( (status != MAPI_E_NOT_INITIALIZED) || (GetLastError() != MAPI_E_NOT_INITIALIZED) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 1 - MAPI_E_NOT_INITIALIZED", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 1 - MAPI_E_NOT_INITIALIZED");
+ }
+
+ mem_ctx = talloc_autofree_context();
+ make_global_ctx_valid(mem_ctx);
+
+ status = GetDefaultPublicFolder(obj_store, folder, id);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 2 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 2 - MAPI_E_INVALID_PARAMETER");
+ }
+ obj_store = &tmp;
+ status = GetDefaultPublicFolder(obj_store, folder, id);
+ if ( ( status != MAPI_E_NOT_FOUND ) || (GetLastError() != MAPI_E_NOT_FOUND) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 3 - MAPI_E_NOT_FOUND", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 3 - MAPI_E_NOT_FOUND");
+ }
+
+ make_global_ctx_invalid();
+
+ obj_store = 0;
+
+ status = GetDefaultFolder(obj_store, folder, id);
+ if ( (status != MAPI_E_NOT_INITIALIZED) || (GetLastError() != MAPI_E_NOT_INITIALIZED) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 4 - MAPI_E_NOT_INITIALIZED", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 4 - MAPI_E_NOT_INITIALIZED");
+ }
+
+ make_global_ctx_valid(mem_ctx);
+
+ status = GetDefaultFolder(obj_store, folder, id);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 5 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 5 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ obj_store = &tmp;
+ obj_store->private_data = 0;
+ status = GetDefaultFolder(obj_store, folder, id);
+ if ( ( status != MAPI_E_NOT_INITIALIZED ) || (GetLastError() != MAPI_E_NOT_INITIALIZED) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 6 - MAPI_E_NOT_INITIALIZED", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 6 - MAPI_E_NOT_INITIALIZED");
+ }
+
+ make_global_ctx_invalid();
+
+ obj_store = 0;
+
+ status = GetFolderItemsCount(obj_folder, 0, 0);
+ if ( (status != MAPI_E_NOT_INITIALIZED) || (GetLastError() != MAPI_E_NOT_INITIALIZED) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 7 - MAPI_E_NOT_INITIALIZED", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 7 - MAPI_E_NOT_INITIALIZED");
+ }
+
+ make_global_ctx_valid(mem_ctx);
+
+ status = GetFolderItemsCount(obj_folder, 0, 0);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 8 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 8 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ obj_folder = &tmp;
+ status = GetFolderItemsCount(obj_folder, 0, 0);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 9 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 9 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ status = GetFolderItemsCount(obj_folder, &arg, 0);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 10 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 10 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ make_global_ctx_invalid();
+ obj_folder = 0;
+
+ /**************************************************************************************
+ Testing AddUserPermission(mapi_object_t *obj_folder, const char *username, enum ACLRIGHTS role)
+ */
+ status = AddUserPermission(obj_folder, 0, RightsNone);
+ if ( ( status != MAPI_E_NOT_INITIALIZED ) || (GetLastError() != MAPI_E_NOT_INITIALIZED) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 11 - MAPI_E_NOT_INITIALIZED", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 11 - MAPI_E_NOT_INITIALIZED");
+ }
+
+ make_global_ctx_valid(mem_ctx);
+
+ status = AddUserPermission(obj_folder, 0, RightsNone);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 12 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 12 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ obj_folder = &tmp;
+ status = AddUserPermission(obj_folder, 0, RightsNone);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 13 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 13 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ make_global_ctx_invalid();
+ obj_folder = 0;
+
+ /**************************************************************************************
+ Testing ModifyUserPermission(mapi_object_t *obj_folder, const char *username, enum ACLRIGHTS role)
+ */
+ status = ModifyUserPermission(obj_folder, 0, RightsNone);
+ if ( ( status != MAPI_E_NOT_INITIALIZED ) || (GetLastError() != MAPI_E_NOT_INITIALIZED) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 14 - MAPI_E_NOT_INITIALIZED", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 14 - MAPI_E_NOT_INITIALIZED");
+ }
+
+ make_global_ctx_valid(mem_ctx);
+
+ status = ModifyUserPermission(obj_folder, 0, RightsNone);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 15 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 15 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ obj_folder = &tmp;
+ status = ModifyUserPermission(obj_folder, 0, RightsNone);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 16 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 16 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ make_global_ctx_invalid();
+ obj_folder = 0;
+
+ /**************************************************************************************
+ Testing RemoveUserPermission(mapi_object_t *obj_folder, const char *username)
+ */
+ status = RemoveUserPermission(obj_folder, 0);
+ if ( ( status != MAPI_E_NOT_INITIALIZED ) || (GetLastError() != MAPI_E_NOT_INITIALIZED) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 17 - MAPI_E_NOT_INITIALIZED", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 17 - MAPI_E_NOT_INITIALIZED");
+ }
+
+ make_global_ctx_valid(mem_ctx);
+
+ status = RemoveUserPermission(obj_folder, 0);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 18 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 18 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ obj_folder = &tmp;
+ status = RemoveUserPermission(obj_folder, 0);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 19 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 19 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ make_global_ctx_invalid();
+ obj_folder = 0;
+
+ /**************************************************************************************
+ Testing GetBestBody(mapi_object_t *obj_message, uint8_t *format)
+ */
+ status = GetBestBody(obj_message, 0);
+ if ( ( status != MAPI_E_NOT_INITIALIZED ) || (GetLastError() != MAPI_E_NOT_INITIALIZED) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 20 - MAPI_E_NOT_INITIALIZED", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 20 - MAPI_E_NOT_INITIALIZED");
+ }
+
+ make_global_ctx_valid(mem_ctx);
+
+ status = GetBestBody(obj_message, 0);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 21 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 21 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ obj_message = &tmp;
+ status = GetBestBody(obj_message, 0);
+ if ( ( status != MAPI_E_INVALID_PARAMETER ) || (GetLastError() != MAPI_E_INVALID_PARAMETER) ) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - 0x%x\n", "Step 22 - MAPI_E_INVALID_PARAMETER", status);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 22 - MAPI_E_INVALID_PARAMETER");
+ }
+
+ make_global_ctx_invalid();
+ obj_message = 0;
+
+
+ return true;
+}
Added: trunk/openchange/utils/mapitest/modules/module_lcid.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_lcid.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_lcid.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,82 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - MS-LCID tests
+
+ Copyright (C) Brad Hards 2009
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_lcid.c
+
+ \brief Language Code checks (MS-LCID)
+
+ \note This is low level (internal) checking, and application programmers
+ do not normally need to deal with the functions checked in this test suite.
+*/
+
+/**
+ \details Verify libmapi/util/lcid.c functions
+
+ This function:
+ -# exercises lcid_langcode2langtag()
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+*/
+_PUBLIC_ bool mapitest_lcid_langcode2langtag(struct mapitest *mt)
+{
+ const char *tag;
+
+ tag = lcid_langcode2langtag( 0x0409 );
+ if (strcmp(tag, "en-US") != 0) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - %s\n", "Step 1 - mismatch", tag);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 1");
+ }
+
+ tag = lcid_langcode2langtag( 0x0439 );
+ if (strcmp(tag, "hi-IN") != 0) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - %s\n", "Step 2 - mismatch", tag);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 2");
+ }
+
+ tag = lcid_langcode2langtag( 0x1401 );
+ if (strcmp(tag, "ar-DZ") != 0) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - %s\n", "Step 3 - mismatch", tag);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 3");
+ }
+
+ tag = lcid_langcode2langtag( 0x0 );
+ if (tag != 0) {
+ mapitest_print(mt, "* %-35s: [FAILURE] - %s\n", "Step 4 - expected NULL", tag);
+ return false;
+ } else {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Step 4");
+ }
+ return true;
+}
+
Added: trunk/openchange/utils/mapitest/modules/module_noserver.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_noserver.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_noserver.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1055 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - Non connection oriented tests
+
+ Copyright (C) Brad Hards 2008-2009
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_noserver.c
+
+ \brief Non connection oriented tests
+*/
+
+/* From MS-OXRTFCP, Section 4.1.1 */
+#define RTF_COMPRESSED1_HEX "2d0000002b0000004c5a4675f1c5c7a703000a007263706731323542320af32068656c090020627705b06c647d0a800fa0"
+#define RTF_UNCOMPRESSED1 "{\\rtf1\\ansi\\ansicpg1252\\pard hello world}\r\n"
+
+/* From MS-OXRTFCP, Section 4.1.2 */
+#define RTF_COMPRESSED2_HEX "1a0000001c0000004c5a4675e2d44b51410004205758595a0d6e7d010eb0"
+#define RTF_UNCOMPRESSED2 "{\\rtf1 WXYZWXYZWXYZWXYZWXYZ}"
+
+
+/**
+ \details Test the Compressed RTF decompression routine.
+
+ This function:
+ -# Loads some test data and checks it
+ -# Decompresses the test data
+ -# Checks that the decompressed data matches the expected result
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+*/
+_PUBLIC_ bool mapitest_noserver_lzfu(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ DATA_BLOB uncompressed1;
+ DATA_BLOB uncompressed2;
+ uint8_t compressed_hex[1024];
+ uint8_t *compressed;
+ uint32_t compressed_length;
+
+ compressed = talloc_array(mt->mem_ctx, uint8_t, 1024);
+
+ memcpy(compressed_hex, RTF_COMPRESSED1_HEX, 98);
+ compressed_length = strhex_to_str((char*)compressed, 1024, (char*)compressed_hex, 98);
+ if (compressed_length != 49) {
+ mapitest_print(mt, "* %-40s: uncompress RTF - Bad length\n", "LZFU");
+ return false;
+ }
+
+ retval = uncompress_rtf(mt->mem_ctx, compressed, compressed_length, &uncompressed1);
+ if (retval != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "uncompress_rtf - step 1");
+ return false;
+ }
+
+ if (!strncmp((char*)uncompressed1.data, RTF_UNCOMPRESSED1, uncompressed1.length)) {
+ mapitest_print(mt, "* %-40s: PASSED\n", "uncompress_rtf - step 1");
+ } else {
+ mapitest_print(mt, "* %-40s: FAILED - %s\n", "uncompress_rtf - step 1", (char*)uncompressed1.data);
+ return false;
+ }
+
+ memcpy(compressed_hex, RTF_COMPRESSED2_HEX, 60);
+ compressed_length = strhex_to_str((char*)compressed, 1024, (char*)compressed_hex, 60);
+ if (compressed_length != 30) {
+ mapitest_print(mt, "* %-40s: uncompress RTF - Bad length\n", "LZFU");
+ return false;
+ }
+
+ retval = uncompress_rtf(mt->mem_ctx, compressed, compressed_length, &uncompressed2);
+ if (retval != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "uncompress_rtf - step 2");
+ return false;
+ }
+
+ if (!strncmp((char*)uncompressed2.data, RTF_UNCOMPRESSED2, uncompressed2.length)) {
+ mapitest_print(mt, "* %-40s: PASSED\n", "uncompress_rtf - step 2");
+ } else {
+ mapitest_print(mt, "* %-40s: FAILED - %s\n", "uncompress_rtf - step 2", (char*)uncompressed2.data);
+ return false;
+ }
+
+ /* TODO: add an uncompressed test here */
+
+ return true;
+}
+
+#define SROWSET_UNTAGGED "005b4d545d2044756d6d792046726f6d00426f6479206f66206d657373616765203800005b4d545d2044756d6d792046726f6d00426f6479206f66206d657373616765203900005b4d545d2044756d6d792046726f6d00426f6479206f66206d657373616765203700005b4d545d2044756d6d792046726f6d00426f6479206f66206d657373616765203600005b4d545d2044756d6d793400426f6479206f66206d657373616765203400005b4d545d2044756d6d792046726f6d00426f6479206f66206d657373616765203500005b4d545d2044756d6d793300426f6479206f66206d657373616765203300005b4d545d2044756d6d793100426f6479206f66206d657373616765203100005b4d545d2044756d6d793200426f6479206f66206d657373616765203200005b4d545d2044756d6d793000426f6479206f66206d657373616765203000"
+#define SROWSET_UNTAGGED_LEN 330
+
+static bool mapitest_noserver_srowset_untagged(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct loadparm_context *lp_ctx = NULL;
+ DATA_BLOB rawData;
+ uint8_t rawDataHex[1024];
+ struct SRowSet rowSet;
+ struct SRowSet referenceRowSet;
+ struct SPropTagArray *proptags;
+ uint32_t rowNum;
+ int i;
+
+ retval = GetLoadparmContext(&lp_ctx);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ rawData.data = talloc_array(mt->mem_ctx, uint8_t, 1024);
+ memcpy(rawDataHex, SROWSET_UNTAGGED, 2*SROWSET_UNTAGGED_LEN);
+ rawData.length = strhex_to_str((char*)rawData.data, 1024, (char*)rawDataHex, 2*SROWSET_UNTAGGED_LEN);
+ if (rawData.length != SROWSET_UNTAGGED_LEN) {
+ mapitest_print(mt, "* %-40s: untagged - Bad length\n", "SRowSet");
+ return false;
+ }
+
+ proptags = set_SPropTagArray(mt->mem_ctx, 2, PR_SENDER_NAME, PR_BODY);
+ rowSet.cRows = 10;
+ rowSet.aRow = talloc_array(mt->mem_ctx, struct SRow, 10);
+ emsmdb_get_SRowSet(mt->mem_ctx, lp_ctx, &rowSet, proptags, &rawData);
+
+ /* Check the resulting SRowSet */
+ if (rowSet.cRows != 10) {
+ mapitest_print(mt, "* %-40s: unexpected row count: %i\n", "SRowSet", rowSet.cRows);
+ return false;
+ }
+
+ /* Build reference RowSet */
+ referenceRowSet.cRows = rowSet.cRows;
+ referenceRowSet.aRow = talloc_array(mt->mem_ctx, struct SRow, rowSet.cRows);
+ for (rowNum = 0; rowNum < rowSet.cRows; ++rowNum) {
+ referenceRowSet.aRow[rowNum].ulAdrEntryPad = 0;
+ referenceRowSet.aRow[rowNum].cValues = 2;
+ referenceRowSet.aRow[rowNum].lpProps = talloc_array(mt->mem_ctx, struct SPropValue, 2);
+ referenceRowSet.aRow[rowNum].lpProps[0].ulPropTag = PR_SENDER_NAME;
+ referenceRowSet.aRow[rowNum].lpProps[0].dwAlignPad = 0;
+ referenceRowSet.aRow[rowNum].lpProps[1].ulPropTag = PR_BODY;
+ referenceRowSet.aRow[rowNum].lpProps[1].dwAlignPad = 0;
+ }
+ referenceRowSet.aRow[0].lpProps[0].value.lpszA = "[MT] Dummy From";
+ referenceRowSet.aRow[0].lpProps[1].value.lpszA = "Body of message 8";
+ referenceRowSet.aRow[1].lpProps[0].value.lpszA = "[MT] Dummy From";
+ referenceRowSet.aRow[1].lpProps[1].value.lpszA = "Body of message 9";
+ referenceRowSet.aRow[2].lpProps[0].value.lpszA = "[MT] Dummy From";
+ referenceRowSet.aRow[2].lpProps[1].value.lpszA = "Body of message 7";
+ referenceRowSet.aRow[3].lpProps[0].value.lpszA = "[MT] Dummy From";
+ referenceRowSet.aRow[3].lpProps[1].value.lpszA = "Body of message 6";
+ referenceRowSet.aRow[4].lpProps[0].value.lpszA = "[MT] Dummy4";
+ referenceRowSet.aRow[4].lpProps[1].value.lpszA = "Body of message 4";
+ referenceRowSet.aRow[5].lpProps[0].value.lpszA = "[MT] Dummy From";
+ referenceRowSet.aRow[5].lpProps[1].value.lpszA = "Body of message 5";
+ referenceRowSet.aRow[6].lpProps[0].value.lpszA = "[MT] Dummy3";
+ referenceRowSet.aRow[6].lpProps[1].value.lpszA = "Body of message 3";
+ referenceRowSet.aRow[7].lpProps[0].value.lpszA = "[MT] Dummy1";
+ referenceRowSet.aRow[7].lpProps[1].value.lpszA = "Body of message 1";
+ referenceRowSet.aRow[8].lpProps[0].value.lpszA = "[MT] Dummy2";
+ referenceRowSet.aRow[8].lpProps[1].value.lpszA = "Body of message 2";
+ referenceRowSet.aRow[9].lpProps[0].value.lpszA = "[MT] Dummy0";
+ referenceRowSet.aRow[9].lpProps[1].value.lpszA = "Body of message 0";
+
+
+ /* compare result with reference rowset */
+ for (rowNum = 0; rowNum < rowSet.cRows; ++rowNum) {
+ /* check each row has expected number of properties */
+ if (rowSet.aRow[rowNum].cValues != referenceRowSet.aRow[rowNum].cValues) {
+ mapitest_print(mt, "* %-40s: unexpected props count, row %i: %i\n", "SRowSet", rowSet.aRow[rowNum].cValues, rowNum);
+ return false;
+ }
+ for (i=0; i < rowSet.aRow[rowNum].cValues; ++i) {
+ /* check property tags are as expected */
+ if (rowSet.aRow[rowNum].lpProps[i].ulPropTag != referenceRowSet.aRow[rowNum].lpProps[i].ulPropTag) {
+ mapitest_print(mt, "* %-40s: unexpected proptag (%i/%i): 0x%08x\n", "SRowSet", rowNum, i, rowSet.aRow[rowNum].lpProps[i].ulPropTag);
+ return false;
+ }
+ /* check property values are as expected */
+ if (strcmp(rowSet.aRow[rowNum].lpProps[i].value.lpszA, referenceRowSet.aRow[rowNum].lpProps[i].value.lpszA) != 0) {
+ mapitest_print(mt, "* %-40s: unexpected property value (%i/%i): %s\n", "SRowSet", rowNum, i, rowSet.aRow[rowNum].lpProps[i].value.lpszA);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+#define SROWSET_TAGGED "01005b4d545d2044756d6d792046726f6d000a0f010480005b4d545d2044756d6d792046726f6d00426f6479206f66206d657373616765203500005b4d545d2044756d6d792046726f6d00426f6479206f66206d657373616765203600005b4d545d2044756d6d792046726f6d00426f6479206f66206d657373616765203700005b4d545d2044756d6d792046726f6d00426f6479206f66206d657373616765203800005b4d545d2044756d6d792046726f6d00426f6479206f66206d65737361676520390001005b4d545d2044756d6d7930000a0f010480005b4d545d2044756d6d793000426f6479206f66206d65737361676520300001005b4d545d2044756d6d7931000a0f010480005b4d545d2044756d6d793100426f6479206f66206d65737361676520310001005b4d545d2044756d6d7932000a0f010480005b4d545d2044756d6d793200426f6479206f66206d65737361676520320001005b4d545d2044756d6d7933000a0f010480005b4d545d2044756d6d793300426f6479206f66206d65737361676520330001005b4d545d2044756d6d7934000a0f010480005b4d545d2044756d6d793400426f6479206f66206d657373616765203400"
+#define SROWSET_TAGGED_LEN 448
+
+
+static bool mapitest_noserver_srowset_tagged(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct loadparm_context *lp_ctx = NULL;
+ DATA_BLOB rawData;
+ uint8_t rawDataHex[1024];
+ struct SRowSet rowSet;
+ struct SRowSet referenceRowSet;
+ struct SPropTagArray *proptags;
+ uint32_t rowNum;
+ int i;
+
+ retval = GetLoadparmContext(&lp_ctx);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ rawData.data = talloc_array(mt->mem_ctx, uint8_t, 1024);
+ memcpy(rawDataHex, SROWSET_TAGGED, 2*SROWSET_TAGGED_LEN);
+ rawData.length = strhex_to_str((char*)rawData.data, 1024, (char*)rawDataHex, 2*SROWSET_TAGGED_LEN);
+ if (rawData.length != SROWSET_TAGGED_LEN) {
+ mapitest_print(mt, "* %-40s: tagged - Bad length\n", "SRowSet");
+ return false;
+ }
+
+ proptags = set_SPropTagArray(mt->mem_ctx, 2, PR_SENDER_NAME, PR_BODY);
+ rowSet.cRows = 16;
+ rowSet.aRow = talloc_array(mt->mem_ctx, struct SRow, 16);
+ emsmdb_get_SRowSet(mt->mem_ctx, lp_ctx, &rowSet, proptags, &rawData);
+
+ /* Check the resulting SRowSet */
+ if (rowSet.cRows != 16) {
+ mapitest_print(mt, "* %-40s: unexpected row count: %i\n", "SRowSet", rowSet.cRows);
+ return false;
+ }
+
+ /* Build reference RowSet */
+ referenceRowSet.cRows = rowSet.cRows;
+ referenceRowSet.aRow = talloc_array(mt->mem_ctx, struct SRow, rowSet.cRows);
+ for (rowNum = 0; rowNum < rowSet.cRows; ++rowNum) {
+ referenceRowSet.aRow[rowNum].ulAdrEntryPad = 0;
+ referenceRowSet.aRow[rowNum].cValues = 2;
+ referenceRowSet.aRow[rowNum].lpProps = talloc_array(mt->mem_ctx, struct SPropValue, 2);
+ referenceRowSet.aRow[rowNum].lpProps[0].ulPropTag = PR_SENDER_NAME;
+ referenceRowSet.aRow[rowNum].lpProps[0].dwAlignPad = 0;
+ referenceRowSet.aRow[rowNum].lpProps[1].ulPropTag = PR_BODY;
+ referenceRowSet.aRow[rowNum].lpProps[1].dwAlignPad = 0;
+ }
+ referenceRowSet.aRow[0].lpProps[0].value.lpszA = "[MT] Dummy From";
+ referenceRowSet.aRow[0].lpProps[1].ulPropTag = PR_BODY_ERROR;
+ referenceRowSet.aRow[0].lpProps[1].value.err = MAPI_E_NOT_FOUND;
+ referenceRowSet.aRow[1].lpProps[0].value.lpszA = "[MT] Dummy From";
+ referenceRowSet.aRow[1].lpProps[1].value.lpszA = "Body of message 5";
+ referenceRowSet.aRow[2].lpProps[0].value.lpszA = "[MT] Dummy From";
+ referenceRowSet.aRow[2].lpProps[1].value.lpszA = "Body of message 6";
+ referenceRowSet.aRow[3].lpProps[0].value.lpszA = "[MT] Dummy From";
+ referenceRowSet.aRow[3].lpProps[1].value.lpszA = "Body of message 7";
+ referenceRowSet.aRow[4].lpProps[0].value.lpszA = "[MT] Dummy From";
+ referenceRowSet.aRow[4].lpProps[1].value.lpszA = "Body of message 8";
+ referenceRowSet.aRow[5].lpProps[0].value.lpszA = "[MT] Dummy From";
+ referenceRowSet.aRow[5].lpProps[1].value.lpszA = "Body of message 9";
+ referenceRowSet.aRow[6].lpProps[0].value.lpszA = "[MT] Dummy0";
+ referenceRowSet.aRow[6].lpProps[1].ulPropTag = PR_BODY_ERROR;
+ referenceRowSet.aRow[6].lpProps[1].value.err = MAPI_E_NOT_FOUND;
+ referenceRowSet.aRow[7].lpProps[0].value.lpszA = "[MT] Dummy0";
+ referenceRowSet.aRow[7].lpProps[1].value.lpszA = "Body of message 0";
+ referenceRowSet.aRow[8].lpProps[0].value.lpszA = "[MT] Dummy1";
+ referenceRowSet.aRow[8].lpProps[1].ulPropTag = PR_BODY_ERROR;
+ referenceRowSet.aRow[8].lpProps[1].value.err = MAPI_E_NOT_FOUND;
+ referenceRowSet.aRow[9].lpProps[0].value.lpszA = "[MT] Dummy1";
+ referenceRowSet.aRow[9].lpProps[1].value.lpszA = "Body of message 1";
+ referenceRowSet.aRow[10].lpProps[0].value.lpszA = "[MT] Dummy2";
+ referenceRowSet.aRow[10].lpProps[1].ulPropTag = PR_BODY_ERROR;
+ referenceRowSet.aRow[10].lpProps[1].value.err = MAPI_E_NOT_FOUND;
+ referenceRowSet.aRow[11].lpProps[0].value.lpszA = "[MT] Dummy2";
+ referenceRowSet.aRow[11].lpProps[1].value.lpszA = "Body of message 2";
+ referenceRowSet.aRow[12].lpProps[0].value.lpszA = "[MT] Dummy3";
+ referenceRowSet.aRow[12].lpProps[1].ulPropTag = PR_BODY_ERROR;
+ referenceRowSet.aRow[12].lpProps[1].value.err = MAPI_E_NOT_FOUND;
+ referenceRowSet.aRow[13].lpProps[0].value.lpszA = "[MT] Dummy3";
+ referenceRowSet.aRow[13].lpProps[1].value.lpszA = "Body of message 3";
+ referenceRowSet.aRow[14].lpProps[0].value.lpszA = "[MT] Dummy4";
+ referenceRowSet.aRow[14].lpProps[1].ulPropTag = PR_BODY_ERROR;
+ referenceRowSet.aRow[14].lpProps[1].value.err = MAPI_E_NOT_FOUND;
+ referenceRowSet.aRow[15].lpProps[0].value.lpszA = "[MT] Dummy4";
+ referenceRowSet.aRow[15].lpProps[1].value.lpszA = "Body of message 4";
+
+ /* compare result with reference rowset */
+ for (rowNum = 0; rowNum < rowSet.cRows; ++rowNum) {
+ /* check each row has expected number of properties */
+ if (rowSet.aRow[rowNum].cValues != referenceRowSet.aRow[rowNum].cValues) {
+ mapitest_print(mt, "* %-40s: unexpected props count, row %i: %i\n", "SRowSet", rowSet.aRow[rowNum].cValues, rowNum);
+ return false;
+ }
+ for (i=0; i < rowSet.aRow[rowNum].cValues; ++i) {
+ /* check property tags are as expected */
+ if (rowSet.aRow[rowNum].lpProps[i].ulPropTag != referenceRowSet.aRow[rowNum].lpProps[i].ulPropTag) {
+ mapitest_print(mt, "* %-40s: unexpected proptag (%i/%i): 0x%08x\n", "SRowSet", rowNum, i, rowSet.aRow[rowNum].lpProps[i].ulPropTag);
+ return false;
+ }
+ /* check property values are as expected */
+ if ((rowSet.aRow[rowNum].lpProps[i].ulPropTag & 0xFFFF) == PT_ERROR) {
+ if (rowSet.aRow[rowNum].lpProps[i].value.err != referenceRowSet.aRow[rowNum].lpProps[i].value.err) {
+ mapitest_print(mt, "* %-40s: unexpected property error value (%i/%i): 0x%04x\n", "SRowSet", rowNum, i, rowSet.aRow[rowNum].lpProps[i].value.err);
+ return false;
+ }
+ } else {
+ if (strcmp(rowSet.aRow[rowNum].lpProps[i].value.lpszA, referenceRowSet.aRow[rowNum].lpProps[i].value.lpszA) != 0) {
+ mapitest_print(mt, "* %-40s: unexpected property value (%i/%i): %s\n", "SRowSet", rowNum, i, rowSet.aRow[rowNum].lpProps[i].value.lpszA);
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+/**
+ \details Test the SRowSet parsing / assembly code
+
+ This function:
+ -# Loads some test data and checks it
+ -# Parses the test data
+ -# Checks that the parsed data matches the expected result
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+*/
+_PUBLIC_ bool mapitest_noserver_srowset(struct mapitest *mt)
+{
+ bool result;
+
+ result = mapitest_noserver_srowset_untagged(mt);
+ if (result == false) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SRowSet Untagged");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SRowSet Untagged");
+
+ result = mapitest_noserver_srowset_tagged(mt);
+ if (result == false) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SRowSet Tagged");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SRowSet Tagged");
+
+ return true;
+}
+
+static bool mapitest_no_server_props_i2(struct mapitest *mt)
+{
+ struct SPropValue propvalue;
+ uint16_t i2 = 0x5693; /* just a random, not zero value */
+ const uint16_t *i2get;
+
+ set_SPropValue_proptag(&propvalue, PT_SHORT, &i2);
+ i2get = (const uint16_t*)get_SPropValue_data(&propvalue);
+ if (!i2get || (*i2get != i2)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_SHORT");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_SHORT");
+ return true;
+}
+
+static bool mapitest_no_server_props_i4(struct mapitest *mt)
+{
+ struct SPropValue propvalue;
+ uint32_t i4 = 0x33870911;
+ const uint32_t *i4get;
+
+ set_SPropValue_proptag(&propvalue, PT_LONG, &i4);
+ i4get = (const uint32_t*)get_SPropValue_data(&propvalue);
+ if (!i4get || (*i4get != i4)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_LONG");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_LONG");
+
+ return true;
+}
+
+static bool mapitest_no_server_props_i8(struct mapitest *mt)
+{
+ struct SPropValue propvalue;
+ uint64_t i8 = 0x098763aa;
+ const uint64_t *i8get;
+
+ set_SPropValue_proptag(&propvalue, PT_I8, &i8);
+ i8get = (const uint64_t*)get_SPropValue_data(&propvalue);
+ if (!i8get || (*i8get != i8)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_I8");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_I8");
+
+ return true;
+}
+
+
+static bool mapitest_no_server_props_bool(struct mapitest *mt)
+{
+ struct SPropValue propvalue;
+ bool b = false;
+ const bool *boolget;
+
+ set_SPropValue_proptag(&propvalue, PT_BOOLEAN, &b);
+ boolget = (const bool*)get_SPropValue_data(&propvalue);
+ if (!boolget || (*boolget != b)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_BOOLEAN");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_BOOLEAN");
+
+ return true;
+}
+
+static bool mapitest_no_server_props_err(struct mapitest *mt)
+{
+ struct SPropValue propvalue;
+ enum MAPISTATUS err = MAPI_E_NOT_ME;
+ enum MAPISTATUS *errget;
+
+ set_SPropValue_proptag(&propvalue, PT_ERROR, &err);
+ errget = (enum MAPISTATUS*)get_SPropValue_data(&propvalue);
+ if (!errget || (*errget != err)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_ERROR");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_ERROR");
+
+ return true;
+}
+
+/* this seems strange... */
+static bool mapitest_no_server_props_null(struct mapitest *mt)
+{
+ struct SPropValue propvalue;
+ uint32_t nullval = 0;
+ const uint32_t *nullget;
+
+ set_SPropValue_proptag(&propvalue, PT_NULL, &nullval);
+ nullget = (const uint32_t*)get_SPropValue_data(&propvalue);
+ if (!nullget) {
+ printf("null nullget\n");
+ }
+ if (!nullget || (*nullget != nullval)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_NULL");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_NULL");
+
+ return true;
+}
+
+
+static bool mapitest_no_server_props_string8(struct mapitest *mt)
+{
+ struct SPropValue propvalue;
+ char *string = "OpenChange Project";
+ const char **stringget;
+
+ set_SPropValue_proptag(&propvalue, PT_STRING8, &string);
+ stringget = (const char**)get_SPropValue_data(&propvalue);
+ if (!stringget || (strncmp(*stringget, string, sizeof(*stringget)) != 0)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_STRING8");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_STRING8");
+
+ return true;
+}
+
+static bool mapitest_no_server_props_unicode(struct mapitest *mt)
+{
+ struct SPropValue propvalue;
+ char *string = "OpenChange Project"; /* OK, so it probably isn't valid UTF16.. */
+ const char **stringget;
+
+ set_SPropValue_proptag(&propvalue, PT_UNICODE, &string);
+ stringget = (const char**)get_SPropValue_data(&propvalue);
+ if (!stringget || (strncmp(*stringget, string, sizeof(*stringget)) != 0)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_UNICODE");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_UNICODE");
+
+ return true;
+}
+
+static bool mapitest_no_server_props_filetime(struct mapitest *mt)
+{
+ struct SPropValue propvalue;
+ struct FILETIME ft;
+ const struct FILETIME *ftget;
+
+ ft.dwLowDateTime = 0x12345678;
+ ft.dwHighDateTime = 0x87653491;
+ set_SPropValue_proptag(&propvalue, PT_SYSTIME, &ft);
+ ftget = (const struct FILETIME *)get_SPropValue_data(&propvalue);
+ if (!ftget || (ft.dwLowDateTime != ftget->dwLowDateTime) || (ft.dwHighDateTime != ftget->dwHighDateTime)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_SYSTIME");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_SYSTIME");
+
+ return true;
+}
+#if 0
+static bool mapitest_no_server_props_flatuid(struct mapitest *mt)
+{
+ bool res;
+ struct SPropValue propvalue;
+ struct FlatUID_r uid;
+ const struct FlatUID_r *uidget;
+ int i;
+
+ // initialise uid
+ for (i = 0; i < 16; ++i) {
+ uid.ab[i] = 0x40 + i;
+ }
+ printf("uid:");
+ for (i = 0; i < 16; ++i) {
+ printf("%c", uid.ab[i]);
+ }
+ printf("\n");
+
+ res = set_SPropValue_proptag(&propvalue, PT_CLSID, &uid);
+ if (res == false) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue set with PT_CLSID");
+ return false;
+ }
+ uidget = (const struct FlatUID_r*)get_SPropValue_data(&propvalue);
+ if (!uidget) {
+ printf("null uidget\n");
+ return false;
+ }
+ printf("uidget:");
+ for (i = 0; i < 16; ++i) {
+ printf("%c", uidget->ab[i]);
+ }
+ printf("\n");
+ if (!uidget || (memcmp(uid.ab, uidget->ab, 16))) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_CLSID");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_CLSID");
+
+ return true;
+}
+#endif
+
+static bool mapitest_no_server_props_bin(struct mapitest *mt)
+{
+ bool res;
+ struct SPropValue propvalue;
+
+ struct Binary_r bin;
+ const struct Binary_r *binget;
+ int i;
+
+ // initialise bin
+ bin.cb = 8;
+ bin.lpb = talloc_array(mt->mem_ctx, uint8_t, bin.cb);
+ for (i = 0; i < bin.cb; ++i) {
+ bin.lpb[i] = 0xF0 + i;
+ }
+
+ res = set_SPropValue_proptag(&propvalue, PT_BINARY, &bin);
+ if (res == false) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue set with PT_BINARY");
+ return false;
+ }
+ binget = (const struct Binary_r *)get_SPropValue_data(&propvalue);
+ if (!binget || (bin.cb != binget->cb) || (bin.lpb != binget->lpb)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_BINARY");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_BINARY");
+
+ talloc_free(bin.lpb);
+
+ return true;
+}
+
+
+static bool mapitest_no_server_props_mv_i2(struct mapitest *mt)
+{
+ bool res;
+ struct SPropValue propvalue;
+ struct ShortArray_r shortarray;
+ const struct ShortArray_r *shortarrayget;
+
+ // create and initialise shortarray
+ shortarray.cValues = 3;
+ shortarray.lpi = talloc_array(mt->mem_ctx, uint16_t, shortarray.cValues);
+ shortarray.lpi[0] = 0x1245;
+ shortarray.lpi[1] = 0x3498;
+ shortarray.lpi[2] = 0x5675;
+ res = set_SPropValue_proptag(&propvalue, PT_MV_SHORT, &shortarray);
+ if (res == false) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue set with PT_MV_SHORT");
+ return false;
+ }
+ shortarrayget = (const struct ShortArray_r *)get_SPropValue_data(&propvalue);
+ if (!shortarrayget || (shortarray.cValues != shortarrayget->cValues) || (shortarray.lpi != shortarrayget->lpi)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_MV_SHORT");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_MV_SHORT");
+
+ talloc_free(shortarray.lpi);
+
+ return true;
+}
+
+static bool mapitest_no_server_props_mv_i4(struct mapitest *mt)
+{
+ bool res;
+ struct SPropValue propvalue;
+ struct LongArray_r longarray;
+ const struct LongArray_r *longarrayget;
+
+ // create and initialise longarray
+ longarray.cValues = 2;
+ longarray.lpl = talloc_array(mt->mem_ctx, uint32_t, longarray.cValues);
+ longarray.lpl[0] = 0x34124543;
+ longarray.lpl[1] = 0x88567576;
+ res = set_SPropValue_proptag(&propvalue, PT_MV_LONG, &longarray);
+ if (res == false) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue set with PT_MV_LONG");
+ return false;
+ }
+ longarrayget = (const struct LongArray_r *)get_SPropValue_data(&propvalue);
+ if (!longarrayget || (longarray.cValues != longarrayget->cValues) || (longarray.lpl != longarrayget->lpl)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_MV_LONG");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_MV_LONG");
+
+ talloc_free(longarray.lpl);
+
+ return true;
+}
+
+static bool mapitest_no_server_props_mv_bin(struct mapitest *mt)
+{
+ bool res;
+ struct SPropValue propvalue;
+ struct BinaryArray_r binarray;
+ const struct BinaryArray_r *binarrayget;
+
+ // create and initialise binarray
+ struct Binary_r bin1, bin2;
+ int i;
+
+ // initialise bin
+ bin1.cb = 8;
+ bin1.lpb = talloc_array(mt->mem_ctx, uint8_t, bin1.cb);
+ for (i = 0; i < bin1.cb; ++i) {
+ bin1.lpb[i] = 0xC0 + i;
+ }
+ bin2.cb = 12;
+ bin2.lpb = talloc_array(mt->mem_ctx, uint8_t, bin2.cb);
+ for (i = 0; i < bin2.cb; ++i) {
+ bin2.lpb[i] = 0xA0 + i;
+ }
+
+ binarray.cValues = 2;
+ binarray.lpbin = talloc_array(mt->mem_ctx, struct Binary_r, binarray.cValues);
+ binarray.lpbin[0] = bin1;
+ binarray.lpbin[1] = bin2;
+
+ res = set_SPropValue_proptag(&propvalue, PT_MV_BINARY, &binarray);
+ if (res == false) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue set with PT_MV_BINARY");
+ return false;
+ }
+ binarrayget = (const struct BinaryArray_r *)get_SPropValue_data(&propvalue);
+ if (!binarrayget || (binarray.cValues != binarrayget->cValues) || (binarray.lpbin != binarrayget->lpbin)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_MV_BINARY");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_MV_BINARY");
+
+ talloc_free(binarray.lpbin);
+ talloc_free(bin1.lpb);
+ talloc_free(bin2.lpb);
+
+ return true;
+}
+
+static bool mapitest_no_server_props_mv_string8(struct mapitest *mt)
+{
+ bool res;
+ struct SPropValue propvalue;
+ struct StringArray_r stringarray;
+ const struct StringArray_r *stringarrayget;
+
+ // create and initialise stringarray
+ stringarray.cValues = 4;
+ stringarray.lppszA = talloc_array(mt->mem_ctx, const char*, stringarray.cValues);
+ stringarray.lppszA[0] = "Fedora";
+ stringarray.lppszA[1] = "FreeBSD";
+ stringarray.lppszA[2] = "OpenSolaris";
+ stringarray.lppszA[3] = "Debian";
+
+ res = set_SPropValue_proptag(&propvalue, PT_MV_STRING8, &stringarray);
+ if (res == false) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue set with PT_MV_STRING8");
+ return false;
+ }
+ stringarrayget = (const struct StringArray_r *)get_SPropValue_data(&propvalue);
+ if (!stringarrayget || (stringarray.cValues != stringarrayget->cValues) || (stringarray.lppszA != stringarrayget->lppszA)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_MV_STRING8");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_MV_STRING8");
+
+ talloc_free(stringarray.lppszA);
+
+ return true;
+}
+
+static bool mapitest_no_server_props_mv_unicode(struct mapitest *mt)
+{
+ bool res;
+ struct SPropValue propvalue;
+ struct WStringArray_r unicodearray;
+ const struct WStringArray_r *unicodearrayget;
+
+ // create and initialise unicodearray
+ unicodearray.cValues = 4;
+ unicodearray.lppszW = talloc_array(mt->mem_ctx, const char*, unicodearray.cValues);
+ unicodearray.lppszW[0] = "Fedora"; /* not valid UTF16, but should still be OK */
+ unicodearray.lppszW[1] = "FreeBSD";
+ unicodearray.lppszW[2] = "OpenSolaris";
+ unicodearray.lppszW[3] = "Debian";
+
+ res = set_SPropValue_proptag(&propvalue, PT_MV_UNICODE, &unicodearray);
+ if (res == false) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue set with PT_MV_UNICODE");
+ return false;
+ }
+ unicodearrayget = (const struct WStringArray_r *)get_SPropValue_data(&propvalue);
+ if (!unicodearrayget || (unicodearray.cValues != unicodearrayget->cValues) || (unicodearray.lppszW != unicodearrayget->lppszW)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_MV_UNICODE");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_MV_UNICODE");
+
+ talloc_free(unicodearray.lppszW);
+
+ return true;
+}
+
+
+static bool mapitest_no_server_props_mv_filetime(struct mapitest *mt)
+{
+ struct SPropValue propvalue;
+ struct FILETIME ft1, ft2, ft3;
+ struct DateTimeArray_r ftarray;
+ const struct DateTimeArray_r *ftarrayget;
+
+ ft1.dwLowDateTime = 0x12345678;
+ ft1.dwHighDateTime = 0x87653491;
+ ft2.dwLowDateTime = 0x10234324;
+ ft2.dwHighDateTime = 0x98748756;
+ ft3.dwLowDateTime = 0x53245324;
+ ft3.dwHighDateTime = 0x54324633;
+
+ ftarray.cValues = 3;
+ ftarray.lpft = talloc_array(mt->mem_ctx, struct FILETIME, ftarray.cValues);
+ ftarray.lpft[0] = ft1;
+ ftarray.lpft[1] = ft2;
+ ftarray.lpft[2] = ft3;
+
+ set_SPropValue_proptag(&propvalue, PT_MV_SYSTIME, &ftarray);
+ ftarrayget = (const struct DateTimeArray_r *)get_SPropValue_data(&propvalue);
+ if (!ftarrayget || (ftarray.cValues != ftarrayget->cValues) || (ftarray.lpft != ftarrayget->lpft)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "SPropValue get/set with PT_MV_SYSTIME");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "SPropValue get/set with PT_MV_SYSTIME");
+
+ talloc_free(ftarray.lpft);
+
+ return true;
+}
+
+/**
+ \details Test the property setter / getter code
+
+ This function:
+ -# Checks setting / getting on an SPropValue
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+*/
+_PUBLIC_ bool mapitest_noserver_properties(struct mapitest *mt)
+{
+ if (! mapitest_no_server_props_i2(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_i4(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_i8(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_bool(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_err(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_null(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_string8(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_unicode(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_filetime(mt)) {
+ return false;
+ }
+
+#if 0
+ if (! mapitest_no_server_props_flatuid(mt)) {
+ return false;
+ }
+#endif
+
+ if (! mapitest_no_server_props_bin(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_mv_i2(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_mv_i4(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_mv_string8(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_mv_unicode(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_mv_filetime(mt)) {
+ return false;
+ }
+
+ if (! mapitest_no_server_props_mv_bin(mt)) {
+ return false;
+ }
+
+ /*
+ Types we don't test yet:
+ */
+ // should this be a double_t?
+ // int64_t dbl;/* [case(0x0005)] */
+
+ // struct FlatUID_r *lpguid;/* [unique,case(0x0048)] */
+ // struct FlatUIDArray_r MVguid;/* [case(0x1048)] */
+ // uint32_t object;/* [case(0x000d)] */
+
+
+ return true;
+}
+
+/**
+ \details Test the mapi_SPropValue_array handling
+
+ This function:
+ -# Builds a mapi_SPropValue_array
+ -# Checks that appropriate values can be retrieved
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+*/
+_PUBLIC_ bool mapitest_noserver_mapi_properties(struct mapitest *mt)
+{
+ struct mapi_SPropValue_array valarray;
+ const uint16_t *i2get;
+ const uint32_t *i4get;
+ const uint32_t *i8get;
+ const uint8_t *boolget;
+ const char *stringget;
+ const struct FILETIME *ftget;
+ const struct SBinary_short *binget;
+ const struct mapi_MV_LONG_STRUCT *mvi4get;
+
+ valarray.cValues = 8;
+ valarray.lpProps = talloc_array(mt->mem_ctx, struct mapi_SPropValue, valarray.cValues);
+
+ valarray.lpProps[0].ulPropTag = PR_GENDER;
+ valarray.lpProps[0].value.i = 0x0001; /* Female */
+ valarray.lpProps[1].ulPropTag = PR_ORIGINAL_SENSITIVITY;
+ valarray.lpProps[1].value.l = 0x00000002; /* Private */
+ valarray.lpProps[2].ulPropTag = PR_ALTERNATE_RECIPIENT_ALLOWED;
+ valarray.lpProps[2].value.b = false;
+ valarray.lpProps[3].ulPropTag = PR_CONVERSATION_TOPIC;
+ valarray.lpProps[3].value.lpszA = "Elizabeth's Birthday";
+ valarray.lpProps[4].ulPropTag = PR_MESSAGE_SIZE_EXTENDED;
+ valarray.lpProps[4].value.d = 43857;
+ valarray.lpProps[5].ulPropTag = PR_RECORD_KEY;
+ valarray.lpProps[5].value.bin.cb = 4;
+ valarray.lpProps[5].value.bin.lpb = talloc_array(mt->mem_ctx, uint8_t, 4);
+ valarray.lpProps[5].value.bin.lpb[0] = 0x44;
+ valarray.lpProps[5].value.bin.lpb[1] = 0x00;
+ valarray.lpProps[5].value.bin.lpb[2] = 0x20;
+ valarray.lpProps[5].value.bin.lpb[3] = 0x00;
+ valarray.lpProps[6].ulPropTag = PR_FREEBUSY_BUSY_MONTHS;
+ valarray.lpProps[6].value.MVl.cValues = 2;
+ valarray.lpProps[6].value.MVl.lpl = talloc_array(mt->mem_ctx, uint32_t, 2);
+ valarray.lpProps[6].value.MVl.lpl[0] = 32130;
+ valarray.lpProps[6].value.MVl.lpl[1] = 32131;
+ valarray.lpProps[7].ulPropTag = PidLidAppointmentEndWhole;
+ valarray.lpProps[7].value.ft.dwLowDateTime = 0x12975909;
+ valarray.lpProps[7].value.ft.dwHighDateTime = 0x98989204;
+
+ /* now start pulling the values back out */
+ i2get = find_mapi_SPropValue_data(&valarray, PR_GENDER);
+ if (!i2get || (*i2get != 0x0001)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "mapi_SPropValue find with PT_SHORT");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "mapi_SPropValue find with PT_SHORT");
+
+
+ i4get = find_mapi_SPropValue_data(&valarray, PR_ORIGINAL_SENSITIVITY);
+ if (!i4get || (*i4get != 0x00000002)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "mapi_SPropValue find with PT_LONG");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "mapi_SPropValue find with PT_LONG");
+
+
+ i8get = find_mapi_SPropValue_data(&valarray, PR_MESSAGE_SIZE_EXTENDED);
+ if (!i8get || (*i8get != 43857)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "mapi_SPropValue find with PT_I8");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "mapi_SPropValue find with PT_I8");
+
+
+ boolget = find_mapi_SPropValue_data(&valarray, PR_ALTERNATE_RECIPIENT_ALLOWED);
+ if (!boolget || (*boolget != false)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "mapi_SPropValue find with PT_BOOLEAN");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "mapi_SPropValue find with PT_BOOLEAN");
+
+
+ stringget = find_mapi_SPropValue_data(&valarray, PR_CONVERSATION_TOPIC);
+ if (!stringget || (strcmp(stringget, "Elizabeth's Birthday") !=0 )) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "mapi_SPropValue find with PT_STRING");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "mapi_SPropValue find with PT_STRING");
+
+ ftget = find_mapi_SPropValue_data(&valarray, PidLidAppointmentEndWhole);
+ if (!ftget || (ftget->dwLowDateTime != 0x12975909) || (ftget->dwHighDateTime != 0x98989204)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "mapi_SPropValue find with PT_FILETIME");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "mapi_SPropValue find with PT_FILETIME");
+
+ binget = find_mapi_SPropValue_data(&valarray, PR_RECORD_KEY);
+ if (!binget || (binget->cb != 4 ) || (binget->lpb[0] != 0x44) || (binget->lpb[1] != 0x00)
+ || (binget->lpb[2] != 0x20) || (binget->lpb[3] != 0x00)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "mapi_SPropValue find with PT_BINARY");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "mapi_SPropValue find with PT_BINARY");
+
+
+ mvi4get = find_mapi_SPropValue_data(&valarray, PR_FREEBUSY_BUSY_MONTHS);
+ if (!mvi4get || (mvi4get->cValues != 2 ) || (mvi4get->lpl[0] != 32130) || (mvi4get->lpl[1] != 32131)) {
+ /* failure */
+ mapitest_print(mt, "* %-40s: [FAILURE]\n", "mapi_SPropValue find with PT_MV_LONG");
+ return false;
+ }
+ mapitest_print(mt, "* %-40s: [SUCCESS]\n", "mapi_SPropValue find with PT_MV_LONG");
+
+#if 0
+ // Types to still to test:
+ int64_t dbl;/* [case(0x0005)] */
+ uint32_t err;/* [case(0x000a)] */
+ const char * lpszW;/* [flag(LIBNDR_FLAG_STR_NULLTERM),case(0x001f)] */
+ struct GUID lpguid;/* [case(0x0048)] */
+ struct mapi_SRestriction_wrap Restrictions;/* [case(0x00fd)] */
+ struct RuleAction RuleAction;/* [case(0x00fe)] */
+ struct mapi_SLPSTRArray MVszA;/* [case(0x101e)] */
+ struct mapi_SPLSTRArrayW MVszW;/* [case(0x101f)] */
+ struct mapi_SGuidArray MVguid;/* [case(0x1048)] */
+ struct mapi_SBinaryArray MVbin;/* [case(0x1102)] */
+#endif
+ return true;
+}
Added: trunk/openchange/utils/mapitest/modules/module_nspi.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_nspi.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_nspi.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,855 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - NSPI tests
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_nspi.c
+
+ \brief NSPI tests
+ */
+
+
+/**
+ \details Test the NspiUpdateStat RPC operation (0x02)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_UpdateStat(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ uint32_t plDelta = 1;
+ struct SRowSet *SRowSet;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
+ retval = nspi_GetSpecialTable(nspi_ctx, 0x2, &SRowSet);
+ MAPIFreeBuffer(SRowSet);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ retval = nspi_UpdateStat(nspi_ctx, &plDelta);
+ mapitest_print_retval(mt, "NspiUpdateStat");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ mapitest_print(mt, "* %-35s: %d\n", "plDelta", plDelta);
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiQueryRows RPC operation (0x3)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_QueryRows(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct SPropTagArray *MIds;
+ struct SRowSet *SRowSet;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProp;
+ struct Restriction_r Filter;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ /* Build the array of columns we want to retrieve */
+ SPropTagArray = set_SPropTagArray(nspi_ctx->mem_ctx, 0x2, PR_DISPLAY_NAME,
+ PR_DISPLAY_TYPE);
+
+ /* Build the restriction we want for NspiGetMatches */
+ lpProp = talloc_zero(mt->mem_ctx, struct SPropValue);
+ lpProp->ulPropTag = PR_ACCOUNT;
+ lpProp->dwAlignPad = 0;
+ lpProp->value.lpszA = global_mapi_ctx->session->profile->username;
+
+ Filter.rt = RES_PROPERTY;
+ Filter.res.resProperty.relop = RES_PROPERTY;
+ Filter.res.resProperty.ulPropTag = PR_ACCOUNT;
+ Filter.res.resProperty.lpProp = lpProp;
+
+ SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
+ MIds = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ retval = nspi_GetMatches(nspi_ctx, SPropTagArray, &Filter, &SRowSet, &MIds);
+ MAPIFreeBuffer(lpProp);
+ MAPIFreeBuffer(SRowSet);
+ MAPIFreeBuffer(SPropTagArray);
+ mapitest_print_retval(mt, "NspiGetMatches");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ return false;
+ }
+
+ /* Query the rows */
+ SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
+ retval = nspi_QueryRows(nspi_ctx, NULL, MIds, 1, &SRowSet);
+ MAPIFreeBuffer(SRowSet);
+ mapitest_print_retval(mt, "NspiQueryRows");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiSeekEntries RPC operation (0x04)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_SeekEntries(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct SPropValue pTarget;
+ struct SPropTagArray *pPropTags;
+ struct SRowSet *SRowSet;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
+
+ pTarget.ulPropTag = PR_DISPLAY_NAME;
+ pTarget.dwAlignPad = 0x0;
+ pTarget.value.lpszA = global_mapi_ctx->session->profile->username;
+
+ pPropTags = set_SPropTagArray(mt->mem_ctx, 0x1,
+ PR_ACCOUNT);
+
+ retval = nspi_SeekEntries(nspi_ctx, SortTypeDisplayName, &pTarget, pPropTags, NULL, &SRowSet);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "NspiSeekEntries");
+ talloc_free(pPropTags);
+ talloc_free(SRowSet);
+ return false;
+ }
+
+ mapitest_print_retval(mt, "NspiSeekEntries");
+ MAPIFreeBuffer(SRowSet);
+ MAPIFreeBuffer(pPropTags);
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiGetMatches RPC operation (0x5)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_GetMatches(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct SPropTagArray *MIds;
+ struct SRowSet *SRowSet;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProp;
+ struct Restriction_r Filter;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ /* Build the array of columns we want to retrieve */
+ SPropTagArray = set_SPropTagArray(nspi_ctx->mem_ctx, 0x2, PR_DISPLAY_NAME,
+ PR_DISPLAY_TYPE);
+
+ /* Build the restriction we want for NspiGetMatches */
+ lpProp = talloc_zero(mt->mem_ctx, struct SPropValue);
+ lpProp->ulPropTag = PR_ACCOUNT;
+ lpProp->dwAlignPad = 0;
+ lpProp->value.lpszA = global_mapi_ctx->session->profile->username;
+
+ Filter.rt = RES_PROPERTY;
+ Filter.res.resProperty.relop = RES_PROPERTY;
+ Filter.res.resProperty.ulPropTag = PR_ACCOUNT;
+ Filter.res.resProperty.lpProp = lpProp;
+
+ SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
+ MIds = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ retval = nspi_GetMatches(nspi_ctx, SPropTagArray, &Filter, &SRowSet, &MIds);
+ MAPIFreeBuffer(lpProp);
+ MAPIFreeBuffer(SRowSet);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPIFreeBuffer(MIds);
+ mapitest_print_retval(mt, "NspiGetMatches");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiResortRestriction RPC operation (0x6)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_ResortRestriction(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct Restriction_r Filter;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SPropValue *lpProp = NULL;
+ struct SPropTagArray *MIds = NULL;
+ struct SPropTagArray *ppMIds = NULL;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ /* Build the array of columns we want to retrieve */
+ SPropTagArray = set_SPropTagArray(nspi_ctx->mem_ctx, 0xb,
+ PR_DISPLAY_NAME,
+ PR_OFFICE_TELEPHONE_NUMBER,
+ PR_OFFICE_LOCATION,
+ PR_TITLE,
+ PR_COMPANY_NAME,
+ PR_ACCOUNT,
+ PR_ADDRTYPE,
+ PR_ENTRYID,
+ PR_DISPLAY_TYPE,
+ PR_INSTANCE_KEY,
+ PR_EMAIL_ADDRESS
+ );
+
+ /* Build the restriction we want for NspiGetMatches */
+ lpProp = talloc_zero(mt->mem_ctx, struct SPropValue);
+ lpProp->ulPropTag = PR_OBJECT_TYPE;
+ lpProp->dwAlignPad = 0;
+ lpProp->value.l = 6;
+
+ Filter.rt = RES_PROPERTY;
+ Filter.res.resProperty.relop = RES_PROPERTY;
+ Filter.res.resProperty.ulPropTag = PR_OBJECT_TYPE;
+ Filter.res.resProperty.lpProp = lpProp;
+
+ SRowSet = talloc_zero(nspi_ctx->mem_ctx, struct SRowSet);
+ MIds = talloc_zero(nspi_ctx->mem_ctx, struct SPropTagArray);
+ retval = nspi_GetMatches(nspi_ctx, SPropTagArray, &Filter, &SRowSet, &MIds);
+ MAPIFreeBuffer(lpProp);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPIFreeBuffer(SRowSet);
+ mapitest_print_retval(mt, "NspiGetMatches");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ return false;
+ }
+
+ ppMIds = talloc_zero(nspi_ctx->mem_ctx, struct SPropTagArray);
+ retval = nspi_ResortRestriction(nspi_ctx, SortTypeDisplayName, MIds, &ppMIds);
+ mapitest_print_retval(mt, "NspiResortRestriction");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ MAPIFreeBuffer(ppMIds);
+ return false;
+ }
+
+ MAPIFreeBuffer(MIds);
+ MAPIFreeBuffer(ppMIds);
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiDNToMId RPC operation (0x7)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_DNToMId(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct StringsArray_r pNames;
+ struct SPropTagArray *MId;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ pNames.Count = 0x1;
+ pNames.Strings = (const char **) talloc_array(mt->mem_ctx, char **, 1);
+ pNames.Strings[0] = global_mapi_ctx->session->profile->homemdb;
+
+ MId = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+
+ retval = nspi_DNToMId(nspi_ctx, &pNames, &MId);
+ MAPIFreeBuffer((char **)pNames.Strings);
+ MAPIFreeBuffer(MId);
+
+ mapitest_print_retval(mt, "NspiDNToMId");
+
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiGetPropList RPC operation (0x08)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_GetPropList(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct SPropTagArray *pPropTags;
+ struct SPropTagArray *MIds;
+ struct SPropValue *lpProp;
+ struct Restriction_r Filter;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet *SRowSet;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ /* Step 1. Query for current profile username */
+ SPropTagArray = set_SPropTagArray(nspi_ctx->mem_ctx, 0x1, PR_DISPLAY_NAME);
+ lpProp = talloc_zero(nspi_ctx->mem_ctx, struct SPropValue);
+ lpProp->ulPropTag = PR_ANR_UNICODE;
+ lpProp->dwAlignPad = 0;
+ lpProp->value.lpszW = global_mapi_ctx->session->profile->username;
+
+ Filter.rt = RES_PROPERTY;
+ Filter.res.resProperty.relop = RES_PROPERTY;
+ Filter.res.resProperty.ulPropTag = PR_ANR_UNICODE;
+ Filter.res.resProperty.lpProp = lpProp;
+
+ SRowSet = talloc_zero(nspi_ctx->mem_ctx, struct SRowSet);
+ MIds = talloc_zero(nspi_ctx->mem_ctx, struct SPropTagArray);
+ retval = nspi_GetMatches(nspi_ctx, SPropTagArray, &Filter, &SRowSet, &MIds);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPIFreeBuffer(lpProp);
+ MAPIFreeBuffer(SRowSet);
+ if (retval != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ return retval;
+ }
+
+
+ /* Step 2. Call NspiGetPropList using the MId returned by NspiGetMatches */
+ pPropTags = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ retval = nspi_GetPropList(nspi_ctx, 0, MIds->aulPropTag[0], &pPropTags);
+ MAPIFreeBuffer(MIds);
+ mapitest_print_retval(mt, "NspiGetPropList");
+
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(pPropTags);
+ return false;
+ }
+
+ mapitest_print(mt, "* %-35s: %d\n", "Properties number", pPropTags->cValues);
+ MAPIFreeBuffer(pPropTags);
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiGetProps RPC operation (0x09)
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_GetProps(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct StringsArray_r pNames;
+ struct SPropTagArray *MId;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet *SRowSet;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ pNames.Count = 0x1;
+ pNames.Strings = (const char **) talloc_array(mt->mem_ctx, char **, 1);
+ pNames.Strings[0] = global_mapi_ctx->session->profile->homemdb;
+
+ MId = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+
+ retval = nspi_DNToMId(nspi_ctx, &pNames, &MId);
+ MAPIFreeBuffer((char **)pNames.Strings);
+ mapitest_print_retval(mt, "NspiDNToMId");
+
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MId);
+ return false;
+ }
+
+ SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_EMS_AB_NETWORK_ADDRESS);
+ retval = nspi_GetProps(nspi_ctx, SPropTagArray, MId, &SRowSet);
+ mapitest_print_retval(mt, "NspiGetProps");
+ MAPIFreeBuffer(SPropTagArray);
+ MAPIFreeBuffer(MId);
+ MAPIFreeBuffer(SRowSet);
+
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiCompareMIds RPC operation (0x0a)
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_CompareMIds(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ uint32_t plResult;
+ struct SPropTagArray *MIds;
+ struct SRowSet *SRowSet;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProp;
+ struct Restriction_r Filter;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ /* Build the array of columns we want to retrieve */
+ SPropTagArray = set_SPropTagArray(nspi_ctx->mem_ctx, 0x1, PR_DISPLAY_NAME);
+
+ /* Build the restriction we want for NspiGetMatches */
+ lpProp = talloc_zero(mt->mem_ctx, struct SPropValue);
+ lpProp->ulPropTag = PR_OBJECT_TYPE;
+ lpProp->dwAlignPad = 0;
+ lpProp->value.l = 6;
+
+ Filter.rt = RES_PROPERTY;
+ Filter.res.resProperty.relop = RES_PROPERTY;
+ Filter.res.resProperty.ulPropTag = PR_OBJECT_TYPE;
+ Filter.res.resProperty.lpProp = lpProp;
+
+ SRowSet = talloc_zero(nspi_ctx->mem_ctx, struct SRowSet);
+ MIds = talloc_zero(nspi_ctx->mem_ctx, struct SPropTagArray);
+ retval = nspi_GetMatches(nspi_ctx, SPropTagArray, &Filter, &SRowSet, &MIds);
+ MAPIFreeBuffer(lpProp);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPIFreeBuffer(SRowSet);
+ mapitest_print_retval(mt, "NspiGetMatches");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ return false;
+ }
+
+ /* Ensure we have at least two result to compare */
+ if (MIds->cValues < 2) {
+ mapitest_print(mt, "* Only one result found, can't compare\n");
+ MAPIFreeBuffer(MIds);
+ return false;
+ }
+
+ retval = nspi_CompareMIds(nspi_ctx, MIds->aulPropTag[0], MIds->aulPropTag[1], &plResult);
+ mapitest_print_retval(mt, "NspiCompareMIds");
+ MAPIFreeBuffer(MIds);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapitest_print(mt, "* %-35s: %d\n", "value of the comparison", plResult);
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiModProps RPC operation (0xb)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+*/
+_PUBLIC_ bool mapitest_nspi_ModProps(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct SRow *pRow;
+ struct SPropTagArray *pPropTags;
+ struct SPropValue modProp;
+ struct SPropTagArray *MIds;
+ struct SRowSet *SRowSet;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProp;
+ struct Restriction_r Filter;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ /* Build the array of columns we want to retrieve */
+ SPropTagArray = set_SPropTagArray(nspi_ctx->mem_ctx, 0x2, PR_DISPLAY_NAME,
+ PR_DISPLAY_TYPE);
+
+ /* Build the restriction we want for NspiGetMatches */
+ lpProp = talloc_zero(mt->mem_ctx, struct SPropValue);
+ lpProp->ulPropTag = PR_ACCOUNT;
+ lpProp->dwAlignPad = 0;
+ lpProp->value.lpszA = global_mapi_ctx->session->profile->username;
+
+ Filter.rt = RES_PROPERTY;
+ Filter.res.resProperty.relop = RES_PROPERTY;
+ Filter.res.resProperty.ulPropTag = PR_ACCOUNT;
+ Filter.res.resProperty.lpProp = lpProp;
+
+ SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
+ MIds = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ retval = nspi_GetMatches(nspi_ctx, SPropTagArray, &Filter, &SRowSet, &MIds);
+ MAPIFreeBuffer(lpProp);
+ MAPIFreeBuffer(SRowSet);
+ MAPIFreeBuffer(SPropTagArray);
+ mapitest_print_retval(mt, "NspiGetMatches");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ return false;
+ }
+
+ /* Query the rows */
+ SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
+ retval = nspi_QueryRows(nspi_ctx, NULL, MIds, 1, &SRowSet);
+ MAPIFreeBuffer(SRowSet);
+ mapitest_print_retval(mt, "NspiQueryRows");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ return false;
+ }
+
+ /* Build the SRow and SPropTagArray for NspiModProps */
+ pRow = talloc_zero(mt->mem_ctx, struct SRow);
+ modProp.ulPropTag = PR_DISPLAY_NAME_UNICODE;
+ modProp.value.lpszW = "mapitest ModProps";
+ SRow_addprop(pRow, modProp);
+
+ pPropTags = set_SPropTagArray(mt->mem_ctx, 0x1, PR_DISPLAY_NAME_UNICODE);
+
+ retval = nspi_ModProps(nspi_ctx, MIds->aulPropTag[0], pPropTags, pRow);
+ mapitest_print_retval(mt, "NspiModProps");
+ MAPIFreeBuffer(MIds);
+ MAPIFreeBuffer(pPropTags);
+ MAPIFreeBuffer(pRow);
+
+ /* Assuming true for the moment */
+ return true;
+}
+
+
+/**
+ \details Test the NspiGetSpecialTable RPC operation (0x0c)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_GetSpecialTable(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct SRowSet *SRowSet;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
+ retval = nspi_GetSpecialTable(nspi_ctx, 0x0, &SRowSet);
+ MAPIFreeBuffer(SRowSet);
+ mapitest_print_retval(mt, "NspiGetSpecialTable (Hierarchy Table)");
+
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
+ retval = nspi_GetSpecialTable(nspi_ctx, 0x2, &SRowSet);
+ MAPIFreeBuffer(SRowSet);
+ mapitest_print_retval(mt, "NspiGetSpecialTable (Address Creation Template)");
+
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiGetTemplateInfo RPC operation (0x0d)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_GetTemplateInfo(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct SRow *ppData = NULL;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ ppData = talloc_zero(mt->mem_ctx, struct SRow);
+ retval = nspi_GetTemplateInfo(nspi_ctx,
+ TI_TEMPLATE|TI_SCRIPT|TI_EMT|TI_HELPFILE_NAME|TI_HELPFILE_CONTENTS,
+ 0, NULL, &ppData);
+ mapitest_print_retval(mt, "NspiGetTemplateInfo");
+ MAPIFreeBuffer(ppData);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiModLinkAtt RPC operation (0x0e)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_ModLinkAtt(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+/* struct SPropTagArray *MIds; */
+ struct BinaryArray_r *lpEntryIds;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ lpEntryIds = talloc_zero(mt->mem_ctx, struct BinaryArray_r);
+ lpEntryIds->cValues = 0;
+ lpEntryIds->lpbin = NULL;
+
+ retval = nspi_ModLinkAtt(nspi_ctx, false, PR_EMS_AB_REPORTS, 0x0, lpEntryIds);
+ mapitest_print_retval(mt, "NspiModLinkAtt");
+ MAPIFreeBuffer(lpEntryIds);
+
+ /* Assuming true for the moment */
+ return true;
+}
+
+
+
+/**
+ \details Test the NspiQueryColumns RPC operation (0x10)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_QueryColumns(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct SPropTagArray *SPropTagArray = NULL;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ SPropTagArray = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+
+ retval = nspi_QueryColumns(nspi_ctx, true, &SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "NspiQueryColumns");
+ MAPIFreeBuffer(SPropTagArray);
+ return false;
+ }
+
+ mapitest_print(mt, "* %d columns returned\n", SPropTagArray->cValues);
+ mapitest_print_retval(mt, "NspiQueryColumns");
+ MAPIFreeBuffer(SPropTagArray);
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiGetNamesFromIDs RPC operation (0x11)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_GetNamesFromIDs(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct SPropTagArray *ppReturnedPropTags;
+ struct PropertyNameSet_r *ppNames;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+
+ ppReturnedPropTags = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ ppNames = talloc_zero(mt->mem_ctx, struct PropertyNameSet_r);
+ retval = nspi_GetNamesFromIDs(nspi_ctx, NULL, NULL, &ppReturnedPropTags, &ppNames);
+ mapitest_print_retval(mt, "NspiGetNamesFromIDs");
+ MAPIFreeBuffer(ppReturnedPropTags);
+ MAPIFreeBuffer(ppNames);
+
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiGetIDsFromNames RPC operation (0x12)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_GetIDsFromNames(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct SPropTagArray *ppReturnedPropTags;
+ struct PropertyNameSet_r *ppNames;
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+
+ ppReturnedPropTags = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ ppNames = talloc_zero(mt->mem_ctx, struct PropertyNameSet_r);
+ retval = nspi_GetNamesFromIDs(nspi_ctx, NULL, NULL, &ppReturnedPropTags, &ppNames);
+ mapitest_print_retval(mt, "NspiGetNamesFromIDs");
+ MAPIFreeBuffer(ppReturnedPropTags);
+
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(ppNames);
+ return false;
+ }
+
+ ppReturnedPropTags = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ retval = nspi_GetIDsFromNames(nspi_ctx, true, ppNames->cNames, ppNames->aNames, &ppReturnedPropTags);
+ mapitest_print_retval(mt, "NspiGetIDsFromNames");
+ MAPIFreeBuffer(ppReturnedPropTags);
+ MAPIFreeBuffer(ppNames);
+
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ \details Test the NspiResolveNames and NspiResolveNamesW RPC
+ operations (0x13 and 0x14)
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_nspi_ResolveNames(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct nspi_context *nspi_ctx;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ const char *username[2];
+
+ nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+
+ /* Build the username array */
+ username[0] = (const char *)mt->info.szDisplayName;
+ username[1] = NULL;
+
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0xd,
+ PR_ENTRYID,
+ PR_DISPLAY_NAME,
+ PR_ADDRTYPE,
+ PR_GIVEN_NAME,
+ PR_SMTP_ADDRESS,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_EMAIL_ADDRESS,
+ PR_SEND_INTERNET_ENCODING,
+ PR_SEND_RICH_INFO,
+ PR_SEARCH_KEY,
+ PR_TRANSMITTABLE_DISPLAY_NAME,
+ PR_7BIT_DISPLAY_NAME);
+
+ /* NspiResolveNames (0x13) */
+ flaglist = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ 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");
+ MAPIFreeBuffer(SPropTagArray);
+ talloc_free(flaglist);
+ talloc_free(SRowSet);
+ return false;
+ }
+ talloc_free(flaglist);
+ talloc_free(SRowSet);
+ mapitest_print_retval(mt, "NspiResolveNames");
+
+ /* 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");
+ talloc_free(flaglist);
+ talloc_free(SRowSet);
+ return false;
+ }
+ talloc_free(flaglist);
+ talloc_free(SRowSet);
+ mapitest_print_retval(mt, "NspiResolveNamesW");
+
+ return true;
+}
Added: trunk/openchange/utils/mapitest/modules/module_oxcfold.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxcfold.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_oxcfold.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,948 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - FOLDER OBJECT PROTOCOL operations
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_oxcfold.c
+
+ \brief Folder Object Protocol test suite
+*/
+
+struct folders {
+ uint32_t id;
+ uint64_t fid;
+ const char *name;
+};
+
+static struct folders top_folders[] = {
+ { 0x0, 0x0, "Mailbox Root Folder" },
+ { 0x1, 0x0, "Deferred Actions" },
+ { 0x2, 0x0, "Spooler Queue" },
+ { 0x3, 0x0, "Top of Information Store" },
+ { 0x4, 0x0, "Inbox" },
+ { 0x5, 0x0, "Outbox" },
+ { 0x6, 0x0, "Sent Items" },
+ { 0x7, 0x0, "Deleted Items" },
+ { 0x8, 0x0, "Common Views" },
+ { 0x9, 0x0, "Schedule" },
+ { 0xa, 0x0, "Search" },
+ { 0xb, 0x0, "Views" },
+ { 0xc, 0x0, "Shortcuts" },
+ { 0xd, 0x0, NULL }
+};
+
+static struct folders inbox_folders[] = {
+ { olFolderCalendar, 0x0, "Calendar" },
+ { olFolderContacts, 0x0, "Contacts" },
+ { olFolderJournal, 0x0, "Journal" },
+ { olFolderNotes, 0x0, "Notes" },
+ { olFolderTasks, 0x0, "Tasks" },
+ { olFolderDrafts, 0x0, "Drafts" },
+ { 0x0, 0x0, NULL }
+};
+
+struct test_folders {
+ const char *name;
+ const char *class;
+};
+
+
+static struct test_folders subfolders[] = {
+ { MT_DIRNAME_APPOINTMENT, IPF_APPOINTMENT },
+ { MT_DIRNAME_CONTACT, IPF_CONTACT },
+ { MT_DIRNAME_JOURNAL, IPF_JOURNAL },
+ { MT_DIRNAME_POST, IPF_POST },
+ { MT_DIRNAME_NOTE, IPF_NOTE },
+ { MT_DIRNAME_STICKYNOTE, IPF_STICKYNOTE },
+ { MT_DIRNAME_TASK, IPF_TASK },
+ { NULL, NULL }
+};
+
+
+/**
+ \details Test the OpenFolder (0x2) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open folders located within the top information store folder
+ -# Open folders located within the Inbox folder
+
+ \param mt the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcfold_OpenFolder(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_store_t *store;
+ mapi_id_t id_folder;
+ int i;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Prepare the top folder check */
+ store = (mapi_object_store_t *) obj_store.private_data;
+ top_folders[0].fid = store->fid_mailbox_root;
+ top_folders[1].fid = store->fid_deferred_actions;
+ top_folders[2].fid = store->fid_spooler_queue;
+ top_folders[3].fid = store->fid_top_information_store;
+ top_folders[4].fid = store->fid_inbox;
+ top_folders[5].fid = store->fid_outbox;
+ top_folders[6].fid = store->fid_sent_items;
+ top_folders[7].fid = store->fid_deleted_items;
+ top_folders[8].fid = store->fid_common_views;
+ top_folders[9].fid = store->fid_schedule;
+ top_folders[10].fid = store->fid_search;
+ top_folders[11].fid = store->fid_views;
+ top_folders[12].fid = store->fid_shortcuts;
+
+ /* Step2. Check top folders (Private mailbox) */
+ mapitest_print(mt, "* Private Mailbox - Message Store (Owner)\n");
+ mapitest_indent();
+ for (i = 0; top_folders[i].name; i++) {
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, top_folders[i].fid, &obj_folder);
+ mapitest_print_retval_fmt(mt, "OpenFolder", "(%s)", top_folders[i].name);
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+ mapi_object_release(&obj_folder);
+ }
+ mapitest_deindent();
+
+ /* Step3. Check for Inbox folders */
+ mapitest_print(mt, "* Private Mailbox - Mailbox (Owner)\n");
+ mapitest_indent();
+ for (i = 0; inbox_folders[i].name; i++) {
+ mapi_object_init(&obj_folder);
+ GetDefaultFolder(&obj_store, &id_folder, inbox_folders[i].id);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_print_retval_fmt(mt, "OpenFolder", "(%s)", inbox_folders[i].name);
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+ mapi_object_release(&obj_folder);
+ }
+ mapitest_deindent();
+
+ /* Release */
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the CreateFolder (0x1c) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the top information folder
+ -# Create a test directory
+ -# Create sub directories with different container classes
+ -# Empty the folder
+ -# Delete the folder
+
+ \param mt the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcfold_CreateFolder(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ struct SPropValue lpProp[1];
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_top;
+ mapi_object_t obj_child;
+ mapi_id_t id_folder;
+ int i;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Top Information Store folder */
+ mapi_object_init(&obj_folder);
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderTopInformationStore);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create the top test folder */
+ mapitest_print(mt, "* Create GENERIC \"%s\" folder\n", MT_DIRNAME_TOP);
+ mapi_object_init(&obj_top);
+ retval = CreateFolder(&obj_folder, FOLDER_GENERIC, MT_DIRNAME_TOP, NULL,
+ OPEN_IF_EXISTS, &obj_top);
+ mapitest_print_retval(mt, "CreateFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4. Create sub directories */
+ mapitest_print(mt, "* Creating sub directories\n");
+ mapitest_indent();
+ for (i = 0; subfolders[i].name; i++) {
+ /* Step 4.1. Create the sub folder */
+ mapi_object_init(&obj_child);
+ retval = CreateFolder(&obj_top, FOLDER_GENERIC, subfolders[i].name, NULL,
+ OPEN_IF_EXISTS, &obj_child);
+ mapitest_print_retval_fmt(mt, "CreateFolder", "(%s)", subfolders[i].name);
+
+ /* Step 4.2. Set its container class */
+ set_SPropValue_proptag(&lpProp[0], PR_CONTAINER_CLASS, (const void *) subfolders[i].class);
+ retval = SetProps(&obj_child, lpProp, 1);
+ mapitest_print_retval_fmt(mt, "SetProps", "(%s)", subfolders[i].name);
+
+ mapi_object_release(&obj_child);
+ }
+ mapitest_deindent();
+
+ /* Step 5. Empty Folder */
+ retval = EmptyFolder(&obj_top);
+ mapitest_print_retval(mt, "EmptyFolder");
+
+ /* Step 6. DeleteFolder */
+ retval = DeleteFolder(&obj_folder, mapi_object_get_id(&obj_top),
+ DEL_MESSAGES|DEL_FOLDERS|DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval(mt, "DeleteFolder");
+
+ /* Release */
+ mapi_object_release(&obj_top);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the GetHierarchyTable (0x4) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the top information folder
+ -# Call the GetHierarchyTable operation
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcfold_GetHierarchyTable(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_htable;
+ mapi_id_t id_folder;
+ uint32_t RowCount;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Top Information Store folder */
+ mapi_object_init(&obj_folder);
+
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderTopInformationStore);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Get the Hierarchy Table */
+ mapi_object_init(&obj_htable);
+ retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, &RowCount);
+ mapitest_print_retval_fmt(mt, "GetHierarchyTable", "(%d rows)", RowCount);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the GetContentsTable (0x5) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the top information folder
+ -# Call the GetContentsTable operation
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcfold_GetContentsTable(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_ctable;
+ mapi_id_t id_folder;
+ uint32_t RowCount;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Top Information Store folder */
+ mapi_object_init(&obj_folder);
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderTopInformationStore);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Get the Contents Table */
+ mapi_object_init(&obj_ctable);
+ retval = GetContentsTable(&obj_folder, &obj_ctable, 0, &RowCount);
+ mapitest_print_retval_fmt(mt, "GetContentsTable", "(%d rows)", RowCount);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_ctable);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the SetSearchCriteria (0x30) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Retrieve the inbox folder ID
+ -# Open the default search folder
+ -# Create a search folder within this folder
+ -# Set the message class property on this container
+ -# Set a restriction criteria
+ -# Call SetSearchCriteria
+ -# Delete the test search folder
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcfold_SetSearchCriteria(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_store;
+ mapi_object_t obj_search;
+ mapi_object_t obj_searchdir;
+ mapi_id_t id_inbox;
+ mapi_id_t id_search;
+ mapi_id_array_t id;
+ struct SPropValue lpProps[1];
+ struct mapi_SRestriction res;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Open Inbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_inbox, olFolderInbox);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Open Search folder */
+ retval = GetDefaultFolder(&obj_store, &id_search, olFolderFinder);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_search);
+ retval = OpenFolder(&obj_store, id_search, &obj_search);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4. Create a search folder */
+ mapi_object_init(&obj_searchdir);
+ retval = CreateFolder(&obj_search, FOLDER_SEARCH, "mapitest",
+ "mapitest search folder", OPEN_IF_EXISTS,
+ &obj_searchdir);
+ mapitest_print_retval(mt, "CreateFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 5. Set properties on this search folder */
+ lpProps[0].ulPropTag = PR_CONTAINER_CLASS;
+ lpProps[0].value.lpszA = IPF_NOTE;
+ retval = SetProps(&obj_searchdir, lpProps, 1);
+ mapitest_print_retval(mt, "SetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto error;
+ }
+
+ /* Step 6. Search criteria on this folder */
+ mapi_id_array_init(&id);
+ mapi_id_array_add_id(&id, id_inbox);
+
+ res.rt = RES_CONTENT;
+ res.res.resContent.fuzzy = FL_SUBSTRING;
+ res.res.resContent.ulPropTag = PR_SUBJECT;
+ res.res.resContent.lpProp.ulPropTag = PR_SUBJECT;
+ res.res.resContent.lpProp.value.lpszA = "[MT]";
+
+ retval = SetSearchCriteria(&obj_searchdir, &res,
+ BACKGROUND_SEARCH|RECURSIVE_SEARCH, &id);
+ mapitest_print_retval(mt, "SetSearchCriteria");
+ mapi_id_array_release(&id);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+error:
+ retval = DeleteFolder(&obj_search, mapi_object_get_id(&obj_searchdir),
+ DEL_MESSAGES|DEL_FOLDERS|DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval(mt, "DeleteFolder");
+ mapi_object_release(&obj_searchdir);
+ mapi_object_release(&obj_search);
+ mapi_object_release(&obj_store);
+ return ret;
+}
+
+
+/**
+ \details Test the GetSearchCriteria (0x31) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Retrieve the inbox folder ID
+ -# Open the default search folder
+ -# Create a search folder within this folder
+ -# Set the message class property on this container
+ -# Set a restriction criteria
+ -# Call SetSearchCriteria
+ -# Call GetSearchCriteria
+ -# Delete the test search folder
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcfold_GetSearchCriteria(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_store;
+ mapi_object_t obj_search;
+ mapi_object_t obj_searchdir;
+ mapi_id_t id_inbox;
+ mapi_id_t id_search;
+ mapi_id_array_t id;
+ struct SPropValue lpProps[1];
+ struct mapi_SRestriction res;
+ uint32_t ulSearchFlags;
+ uint16_t count;
+ mapi_id_t *fid;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Open Inbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_inbox, olFolderInbox);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Open Search folder */
+ retval = GetDefaultFolder(&obj_store, &id_search, olFolderFinder);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_search);
+ retval = OpenFolder(&obj_store, id_search, &obj_search);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4. Create a search folder */
+ mapi_object_init(&obj_searchdir);
+ retval = CreateFolder(&obj_search, FOLDER_SEARCH, "mapitest",
+ "mapitest search folder", OPEN_IF_EXISTS,
+ &obj_searchdir);
+ mapitest_print_retval(mt, "CreateFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 5. Set properties on this search folder */
+ lpProps[0].ulPropTag = PR_CONTAINER_CLASS;
+ lpProps[0].value.lpszA = IPF_NOTE;
+ retval = SetProps(&obj_searchdir, lpProps, 1);
+ mapitest_print_retval(mt, "SetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto error;
+ }
+
+ /* Step 6. Search criteria on this folder */
+ mapi_id_array_init(&id);
+ mapi_id_array_add_id(&id, id_inbox);
+
+ res.rt = RES_CONTENT;
+ res.res.resContent.fuzzy = FL_SUBSTRING;
+ res.res.resContent.ulPropTag = PR_SUBJECT;
+ res.res.resContent.lpProp.ulPropTag = PR_SUBJECT;
+ res.res.resContent.lpProp.value.lpszA = "[MT]";
+
+ retval = SetSearchCriteria(&obj_searchdir, &res,
+ BACKGROUND_SEARCH|RECURSIVE_SEARCH, &id);
+ mapitest_print_retval(mt, "SetSearchCriteria");
+ mapi_id_array_release(&id);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto error;
+ }
+
+ /* Step 7. Call GetSearchCriteria */
+ retval = GetSearchCriteria(&obj_searchdir, &res, &ulSearchFlags, &count, &fid);
+ mapitest_print_retval(mt, "GetSearchCriteria");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto error;
+ }
+
+
+error:
+ retval = DeleteFolder(&obj_search, mapi_object_get_id(&obj_searchdir),
+ DEL_MESSAGES|DEL_FOLDERS|DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval(mt, "DeleteFolder");
+ mapi_object_release(&obj_searchdir);
+ mapi_object_release(&obj_search);
+ mapi_object_release(&obj_store);
+ return ret;
+}
+
+
+/**
+ \details Test the MoveCopyMessages (0x33) opetation.
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the Inbox folder (source)
+ -# Open the Deleted Items folder (destination)
+ -# Creates 3 sample messages
+ -# Move messages from source to destination
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcfold_MoveCopyMessages(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder_src;
+ mapi_object_t obj_folder_dst;
+ mapi_object_t obj_message;
+ mapi_object_t dst_contents;
+ uint32_t dst_count;
+ struct mapi_SRestriction res;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ mapi_id_array_t msg_id_array;
+ mapi_id_t msgid[20];
+ mapi_id_t id_folder;
+ uint32_t i;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Source Inbox folder */
+ mapi_object_init(&obj_folder_src);
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder_src);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Open Destination Deleted Items folder */
+ mapi_object_init(&obj_folder_dst);
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderDeletedItems);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder_dst);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ mapi_object_init(&(dst_contents));
+ GetContentsTable(&(obj_folder_dst), &(dst_contents), 0, &dst_count);
+ mapitest_print_retval(mt, "GetContentsTable");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 4. Create sample messages */
+ mapi_id_array_init(&msg_id_array);
+ for (i = 0; i < 3; i++) {
+ mapi_object_init(&obj_message);
+ retval = mapitest_common_message_create(mt, &obj_folder_src, &obj_message, MT_MAIL_SUBJECT);
+ mapitest_print_retval(mt, "mapitest_common_message_create");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ retval = SaveChangesMessage(&obj_folder_src, &obj_message, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ mapi_id_array_add_obj(&msg_id_array, &obj_message);
+ mapi_object_release(&obj_message);
+ }
+
+ /* Step 5. Move messages from source to destination */
+ retval = MoveCopyMessages(&obj_folder_src, &obj_folder_dst, &msg_id_array, 0);
+ mapitest_print_retval(mt, "MoveCopyMessages");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ mapi_id_array_release(&msg_id_array);
+
+ /* Step 6. Apply a filter */
+ res.rt = RES_PROPERTY;
+ res.res.resProperty.relop = RES_PROPERTY;
+ res.res.resProperty.ulPropTag = PR_SUBJECT;
+ res.res.resProperty.lpProp.ulPropTag = PR_SUBJECT;
+ res.res.resProperty.lpProp.value.lpszA = MT_MAIL_SUBJECT;
+
+ retval = Restrict(&(dst_contents), &res, NULL);
+ mapitest_print_retval(mt, "Restrict");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 7. Get the filtered row */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_MID);
+ SetColumns(&(dst_contents), SPropTagArray);
+ mapitest_print_retval(mt, "SetColumns");
+ MAPIFreeBuffer(SPropTagArray);
+
+ QueryRows(&(dst_contents), 20, TBL_NOADVANCE, &SRowSet);
+ mapitest_print_retval(mt, "QueryRows");
+ if ( (retval == MAPI_E_SUCCESS) && (SRowSet.cRows > 0) ) {
+ for (i = 0; i < SRowSet.cRows; ++i) {
+ msgid[i] = SRowSet.aRow[i].lpProps[0].value.d;
+ }
+ }
+
+ /* Step 8. Delete Messages */
+ retval = DeleteMessage(&obj_folder_dst, msgid, i);
+ mapitest_print_retval(mt, "DeleteMessage");
+
+ /* Release */
+ mapi_object_release(&obj_folder_src);
+ mapi_object_release(&obj_folder_dst);
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
+
+
+/**
+ \details Test the MoveFolder (0x35) operation.
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the Inbox folder (source)
+ -# Create a temporary folder
+ -# Create 1 message in this new folder
+ -# Open the Deleted Items folder (destination)
+ -# Move the temporary folder from Inbox to DeletedItems
+ -# Empty and delete the moved temporary folder
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcfold_MoveFolder(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_src;
+ mapi_object_t obj_dst;
+ mapi_object_t obj_message;
+ bool ret = true;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open the inbox folder */
+ mapi_object_init(&obj_src);
+ ret = mapitest_common_folder_open(mt, &obj_store, &obj_src, olFolderInbox);
+ if (ret == false) return ret;
+
+ /* Step 3. Create temporary folder */
+ mapi_object_init(&obj_folder);
+ retval = CreateFolder(&obj_src, FOLDER_GENERIC, MT_DIRNAME_TOP, NULL,
+ OPEN_IF_EXISTS, &obj_folder);
+ mapitest_print_retval(mt, "CreateFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4. Create message within this temporary folder */
+ mapi_object_init(&obj_message);
+ ret = mapitest_common_message_create(mt, &obj_folder, &obj_message, MT_MAIL_SUBJECT);
+ mapitest_print_retval(mt, "mapitest_common_message_create");
+
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ mapi_object_release(&obj_message);
+
+ /* Step 5. Open the Deleted items folder */
+ mapi_object_init(&obj_dst);
+ ret = mapitest_common_folder_open(mt, &obj_store, &obj_dst, olFolderDeletedItems);
+
+ /* Step 6. MoveFolder */
+ retval = MoveFolder(&obj_folder, &obj_src, &obj_dst, MT_DIRNAME_TOP, false);
+ mapitest_print_retval(mt, "MoveFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ mapi_object_release(&obj_folder);
+
+ /* Step 7. Delete the moved folder */
+ mapi_object_init(&obj_folder);
+ ret = mapitest_common_find_folder(mt, &obj_dst, &obj_folder, MT_DIRNAME_TOP);
+ mapitest_print(mt, "* %-35s: %s\n", "mapitest_common_find_folder", (ret == true) ? "true" : "false");
+
+ if (ret == true) {
+ retval = EmptyFolder(&obj_folder);
+ mapitest_print_retval(mt, "EmptyFolder");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ retval = DeleteFolder(&obj_dst, mapi_object_get_id(&obj_folder),
+ DEL_MESSAGES|DEL_FOLDERS|DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval(mt, "DeleteFolder");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ }
+
+
+ /* Release */
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_src);
+ mapi_object_release(&obj_dst);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the CopyFolder (0x36) operation.
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the Inbox folder (source)
+ -# Create a temporary folder
+ -# Create a subdirectory
+ -# Open the Deleted Items folder (destination)
+ -# Copy the temporary folder from Inbox to DeletedItems
+ -# Empty and delete the original and copied folder
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcfold_CopyFolder(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_subfolder;
+ mapi_object_t obj_src;
+ mapi_object_t obj_dst;
+ bool ret = true;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open the inbox folder */
+ mapi_object_init(&obj_src);
+ ret = mapitest_common_folder_open(mt, &obj_store, &obj_src, olFolderInbox);
+ if (ret == false) return ret;
+
+ /* Step 3. Create temporary folder */
+ mapi_object_init(&obj_folder);
+ retval = CreateFolder(&obj_src, FOLDER_GENERIC, MT_DIRNAME_TOP, NULL,
+ OPEN_IF_EXISTS, &obj_folder);
+ mapitest_print_retval(mt, "CreateFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4. Create the sub folder */
+ mapi_object_init(&obj_subfolder);
+ retval = CreateFolder(&obj_folder, FOLDER_GENERIC, MT_DIRNAME_NOTE, NULL,
+ OPEN_IF_EXISTS, &obj_subfolder);
+ mapitest_print_retval(mt, "CreateFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ mapi_object_release(&obj_subfolder);
+
+ /* Step 5. Open the Deleted items folder */
+ mapi_object_init(&obj_dst);
+ ret = mapitest_common_folder_open(mt, &obj_store, &obj_dst, olFolderDeletedItems);
+
+ /* Step 6. CopyFolder */
+ retval = CopyFolder(&obj_folder, &obj_src, &obj_dst, MT_DIRNAME_TOP, false, false);
+ mapitest_print_retval(mt, "CopyFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 7. Delete the original and copied folder */
+ retval = EmptyFolder(&obj_folder);
+ mapitest_print_retval(mt, "EmptyFolder");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ retval = DeleteFolder(&obj_src, mapi_object_get_id(&obj_folder),
+ DEL_MESSAGES|DEL_FOLDERS|DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval(mt, "DeleteFolder");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ mapi_object_release(&obj_folder);
+
+ mapi_object_init(&obj_folder);
+ ret = mapitest_common_find_folder(mt, &obj_dst, &obj_folder, MT_DIRNAME_TOP);
+ mapitest_print(mt, "* %-35s: %s\n", "mapitest_common_find_folder", (ret == true) ? "true" : "false");
+
+ if (ret == true) {
+ retval = EmptyFolder(&obj_folder);
+ mapitest_print_retval(mt, "EmptyFolder");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ retval = DeleteFolder(&obj_dst, mapi_object_get_id(&obj_folder),
+ DEL_MESSAGES|DEL_FOLDERS|DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval(mt, "DeleteFolder");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ }
+
+ /* Release */
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_src);
+ mapi_object_release(&obj_dst);
+ mapi_object_release(&obj_store);
+
+
+ return ret;
+}
Added: trunk/openchange/utils/mapitest/modules/module_oxcfxics.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxcfxics.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_oxcfxics.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,69 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - BULK DATA TRANSFER PROTOCOL operations
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_oxcfxics.c
+
+ \brief Bulk Data Transfer Protocol test suite
+*/
+
+/**
+ \details Test the GetLocalReplicaIds (0x7f) operation
+
+ This function:
+ -# Log on private message store
+ -# Reserve a range of Ids
+ */
+_PUBLIC_ bool mapitest_oxcfxics_GetLocalReplicaIds(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ struct GUID ReplGuid;
+ uint8_t GlobalCount[6];
+ char *guid;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Reserve a range of IDs */
+ retval = GetLocalReplicaIds(&obj_store, 0x1000, &ReplGuid, GlobalCount);
+ mapitest_print_retval(mt, "GetLocalReplicaIds");
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+ guid = GUID_string(mt->mem_ctx, &ReplGuid);
+ mapitest_print(mt, "* %-35s: %s\n", "ReplGuid", guid);
+ mapitest_print(mt, "* %-35s: %x %x %x %x %x %x\n", "GlobalCount", GlobalCount[0],
+ GlobalCount[1], GlobalCount[2], GlobalCount[3], GlobalCount[4],
+ GlobalCount[5]);
+ talloc_free(guid);
+
+ return true;
+}
Added: trunk/openchange/utils/mapitest/modules/module_oxcmsg.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxcmsg.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_oxcmsg.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,1235 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - E-MAIL OBJECT PROTOCOL operations
+
+ Copyright (C) Julien Kerihuel 2008
+ Copyright (C) Brad Hards <bradh at openchange.org> 2009
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_oxcmsg.c
+
+ \brief Message and Attachment Object Protocol test suite
+*/
+
+
+/**
+ \details Test the CreateMessage (0x6) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the Outbox folder
+ -# Create the message
+ -# Delete the message
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcmsg_CreateMessage(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_id_t id_msgs[1];
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Outbox folder */
+ mapi_object_init(&obj_folder);
+ ret = mapitest_common_folder_open(mt, &obj_store, &obj_folder, olFolderOutbox);
+ if (ret == false) return ret;
+
+ /* Step 3. Create the message */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_folder, &obj_message);
+ mapitest_print_retval(mt, "CreateMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4. Delete the message */
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+#define OXCMSG_SETREADFLAGS "[OXCMSG] SetMessageReadFlag"
+
+/**
+ \details Test the SetMessageReadFlag (0x11) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the Inbox folder
+ -# Create a tmp message
+ -# Play with SetMessageReadFlag
+ -# Delete the message
+
+ Note: We can test either SetMessageReadFlag was effective by checking its
+ old/new value with GetProps on PR_MESSAGE_FLAGS property.
+
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcmsg_SetMessageReadFlag(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProps;
+ uint32_t cValues;
+ mapi_id_t id_msgs[1];
+ uint32_t status= 0;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Outbox folder */
+ mapi_object_init(&obj_folder);
+ ret = mapitest_common_folder_open(mt, &obj_store, &obj_folder, olFolderOutbox);
+ if (ret == false) return ret;
+
+ /* Step 3. Create the tmp message and save it */
+ mapi_object_init(&obj_message);
+ ret = mapitest_common_message_create(mt, &obj_folder, &obj_message, OXCMSG_SETREADFLAGS);
+ if (ret == false) return ret;
+
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadWrite);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4. Play with SetMessageReadFlag */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_MID, PR_MESSAGE_FLAGS);
+ ret = true;
+
+ /* 1. Retrieve and Save the original PR_MESSAGE_FLAGS value */
+ retval = GetProps(&obj_message, SPropTagArray, &lpProps, &cValues);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ if (cValues > 1) {
+ status = lpProps[1].value.l;
+ }
+ MAPIFreeBuffer(lpProps);
+
+ /* Set message flags as read */
+ retval = SetMessageReadFlag(&obj_folder, &obj_message, MSGFLAG_READ);
+ mapitest_print_retval_fmt(mt, "SetMessageReadFlag", "(%s)", "MSGFLAG_READ");
+
+ /* Check if the operation was successful */
+ retval = GetProps(&obj_message, SPropTagArray, &lpProps, &cValues);
+ mapitest_print_retval(mt, "GetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ if (cValues > 1 && status != lpProps[1].value.l) {
+ mapitest_print(mt, "* %-35s: PR_MESSAGE_FLAGS changed\n", "SetMessageReadFlag");
+ status = lpProps[1].value.l;
+ } else {
+ mapitest_print(mt, "* %-35s: PR_MESSAGE_FLAGS failed\n", "SetMessageReadFlag");
+ return false;
+ }
+ MAPIFreeBuffer(lpProps);
+
+ /* Set the message flags as submitted */
+ retval = SetMessageReadFlag(&obj_folder, &obj_message, MSGFLAG_SUBMIT);
+ mapitest_print_retval_fmt(mt, "SetMessageReadFlag", "(%s)", "MSGFLAG_SUBMIT");
+
+ /* Check if the operation was successful */
+ retval = GetProps(&obj_message, SPropTagArray, &lpProps, &cValues);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ if (cValues > 1 && status != lpProps[1].value.l) {
+ mapitest_print(mt, "* %-35s: PR_MESSAGE_FLAGS changed\n", "SetMessageReadFlag");
+ status = lpProps[1].value.l;
+ } else {
+ mapitest_print(mt, "* %-35s: PR_MESSAGE_FLAGS failed\n", "SetMessageReadFlag");
+ return false;
+ }
+
+ /* Step 5. Delete the message */
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ MAPIFreeBuffer(SPropTagArray);
+
+ return true;
+}
+
+/**
+ \details Test the ModifyRecipients (0xe) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the Outbox folder
+ -# Create the message
+ -# Resolve recipients names
+ -# Call ModifyRecipients operation for MAPI_TO, MAPI_CC, MAPI_BCC
+ -# Delete the message
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcmsg_ModifyRecipients(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_id_t id_folder;
+ char **username = NULL;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SPropValue SPropValue;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ mapi_id_t id_msgs[1];
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Outbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderOutbox);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create the message */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_folder, &obj_message);
+ mapitest_print_retval(mt, "CreateMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+
+ /* Step 4. Resolve the recipients and call ModifyRecipients */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x6,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_7BIT_DISPLAY_NAME,
+ PR_DISPLAY_NAME,
+ PR_SMTP_ADDRESS,
+ PR_GIVEN_NAME);
+
+ username = talloc_array(mt->mem_ctx, char *, 2);
+ username[0] = mt->info.szDisplayName;
+ username[1] = NULL;
+
+ retval = ResolveNames(mapi_object_get_session(&obj_message),
+ (const char **)username, SPropTagArray,
+ &SRowSet, &flaglist, 0);
+ mapitest_print_retval(mt, "ResolveNames");
+
+ SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
+ SPropValue.value.l = 0;
+ SRowSet_propcpy(mt->mem_ctx, SRowSet, SPropValue);
+
+ SetRecipientType(&(SRowSet->aRow[0]), MAPI_TO);
+ mapitest_print_retval(mt, "SetRecipientType");
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapitest_print_retval_fmt(mt, "ModifyRecipients", "(%s)", "MAPI_TO");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ SetRecipientType(&(SRowSet->aRow[0]), MAPI_CC);
+ mapitest_print_retval(mt, "SetRecipientType");
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapitest_print_retval_fmt(mt, "ModifyRecipients", "(%s)", "MAPI_CC");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+
+ SetRecipientType(&(SRowSet->aRow[0]), MAPI_BCC);
+ mapitest_print_retval(mt, "SetRecipientType");
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapitest_print_retval_fmt(mt, "ModifyRecipients", "(%s)", "MAPI_BCC");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 5. Delete the message */
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ /* Release */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the RemoveAllRecipients (0xd) operation
+
+ This function:
+ -# Log on the use private mailbox
+ -# Open the Outbox folder
+ -# Create the message, set recipients
+ -# Save the message
+ -# Remove all recipients
+ -# Delete the message
+
+ \param mt point on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcmsg_RemoveAllRecipients(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = false;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_id_t id_folder;
+ char **username = NULL;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SPropValue SPropValue;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ mapi_id_t id_msgs[1];
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Outbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create the message */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_folder, &obj_message);
+ mapitest_print_retval(mt, "CreateMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x6,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_7BIT_DISPLAY_NAME,
+ PR_DISPLAY_NAME,
+ PR_SMTP_ADDRESS,
+ PR_GIVEN_NAME);
+
+ username = talloc_array(mt->mem_ctx, char *, 2);
+ username[0] = mt->info.szDisplayName;
+ username[1] = NULL;
+
+ retval = ResolveNames(mapi_object_get_session(&obj_message),
+ (const char **)username, SPropTagArray,
+ &SRowSet, &flaglist, 0);
+ mapitest_print_retval(mt, "ResolveNames");
+
+ SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
+ SPropValue.value.l = 0;
+ SRowSet_propcpy(mt->mem_ctx, SRowSet, SPropValue);
+
+ SetRecipientType(&(SRowSet->aRow[0]), MAPI_TO);
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapitest_print_retval_fmt(mt, "ModifyRecipients", "(%s)", "MAPI_TO");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ SetRecipientType(&(SRowSet->aRow[0]), MAPI_CC);
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapitest_print_retval_fmt(mt, "ModifyRecipients", "(%s)", "MAPI_CC");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+
+ SetRecipientType(&(SRowSet->aRow[0]), MAPI_BCC);
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapitest_print_retval_fmt(mt, "ModifyRecipients", "(%s)", "MAPI_BCC");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ ret = true;
+
+ /* Step 5. Remove all recipients */
+ retval = RemoveAllRecipients(&obj_message);
+ mapitest_print_retval(mt, "RemoveAllRecipients");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 4. Save the message */
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 6. Delete the message */
+ errno = 0;
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
+
+
+/**
+ \details Test the ReadRecipients (0xf) operation
+
+ This function:
+ -# Log on the use private mailbox
+ -# Open the Outbox folder
+ -# Create the message, set recipients
+ -# Save the message
+ -# Read message recipients
+ -# Delete the message
+
+ \param mt point on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcmsg_ReadRecipients(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = false;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_id_t id_folder;
+ char **username = NULL;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SPropValue SPropValue;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ struct ReadRecipientRow *RecipientRows;
+ uint8_t count;
+ mapi_id_t id_msgs[1];
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Outbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create the message */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_folder, &obj_message);
+ mapitest_print_retval(mt, "CreateMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x6,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_7BIT_DISPLAY_NAME,
+ PR_DISPLAY_NAME,
+ PR_SMTP_ADDRESS,
+ PR_GIVEN_NAME);
+
+ username = talloc_array(mt->mem_ctx, char *, 2);
+ username[0] = mt->info.szDisplayName;
+ username[1] = NULL;
+
+ retval = ResolveNames(mapi_object_get_session(&obj_message),
+ (const char **)username, SPropTagArray,
+ &SRowSet, &flaglist, 0);
+ mapitest_print_retval(mt, "ResolveNames");
+
+ SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
+ SPropValue.value.l = 0;
+ SRowSet_propcpy(mt->mem_ctx, SRowSet, SPropValue);
+
+ retval = SetRecipientType(&(SRowSet->aRow[0]), MAPI_TO);
+ mapitest_print_retval(mt, "SetRecipientType");
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapitest_print_retval_fmt(mt, "ModifyRecipients", "(%s)", "MAPI_TO");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ SetRecipientType(&(SRowSet->aRow[0]), MAPI_CC);
+ mapitest_print_retval(mt, "SetRecipientType");
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapitest_print_retval_fmt(mt, "ModifyRecipients", "(%s)", "MAPI_CC");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+
+ SetRecipientType(&(SRowSet->aRow[0]), MAPI_BCC);
+ mapitest_print_retval(mt, "SetRecipientType");
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ mapitest_print_retval_fmt(mt, "ModifyRecipients", "(%s)", "MAPI_BCC");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ ret = true;
+
+ /* Step 4. Save the message */
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 5. Read recipients */
+ RecipientRows = talloc_zero(mt->mem_ctx, struct ReadRecipientRow);
+ retval = ReadRecipients(&obj_message, 0, &count, &RecipientRows);
+ mapitest_print_retval(mt, "ReadRecipients");
+ MAPIFreeBuffer(RecipientRows);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 6. Delete the message */
+ errno = 0;
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
+
+
+/**
+ \details Test the SaveChangesMessage (0xc) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the Outbox folder
+ -# Create the message
+ -# Save the message
+ -# Delete the message
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcmsg_SaveChangesMessage(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_id_t id_folder;
+ mapi_id_t id_msgs[1];
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Outbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderOutbox);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create the message */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_folder, &obj_message);
+ mapitest_print_retval(mt, "CreateMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4. Save the message */
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 5. Delete the saved message */
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the GetMessageStatus (0x1f) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the outbox folder
+ -# Create the message
+ -# Save the message
+ -# Get outbox contents table
+ -# Get messages status
+ -# Delete the message
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcmsg_GetMessageStatus(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_object_t obj_ctable;
+ mapi_id_t id_folder;
+ mapi_id_t id_msgs[1];
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ uint32_t count;
+ uint32_t status;
+ uint32_t i;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Outbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderOutbox);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create the message */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_folder, &obj_message);
+ mapitest_print_retval(mt, "CreateMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4. Save the message */
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 5. Get outbox contents table */
+ mapi_object_init(&obj_ctable);
+ retval = GetContentsTable(&obj_folder, &obj_ctable, 0, &count);
+ mapitest_print_retval(mt, "GetContentsTable");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2,
+ PR_MID, PR_MSG_STATUS);
+ retval = SetColumns(&obj_ctable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 6. Get Message Status */
+ while (((retval = QueryRows(&obj_ctable, count, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND) &&
+ SRowSet.cRows) {
+ count -= SRowSet.cRows;
+ for (i = 0; i < SRowSet.cRows; i++) {
+ retval = GetMessageStatus(&obj_folder, SRowSet.aRow[i].lpProps[0].value.d, &status);
+ mapitest_print_retval(mt, "GetMessageStatus");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ }
+ }
+
+ /* Step 7. Delete the saved message */
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_ctable);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+struct msgstatus {
+ uint32_t status;
+ const char *name;
+};
+
+static struct msgstatus msgstatus[] = {
+ {MSGSTATUS_HIDDEN, "MSGSTATUS_HIDDEN"},
+ {MSGSTATUS_HIGHLIGHTED, "MSGSTATUS_HIGHLIGHTED"},
+ {MSGSTATUS_TAGGED, "MSGSTATUS_TAGGED"},
+ {MSGSTATUS_REMOTE_DOWNLOAD, "MSGSTATUS_REMOTE_DOWNLOAD"},
+ {MSGSTATUS_REMOTE_DELETE, "MSGSTATUS_REMOTE_DELETE"},
+ {MSGSTATUS_DELMARKED, "MSGSTATUS_DELMARKED"},
+ {0, NULL}
+};
+
+/**
+ \details Test the GetMessageStatus (0x1f) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the outbox folder
+ -# Create the message
+ -# Save the message
+ -# Get outbox contents table
+ -# Set different messages status, then get them and compare values
+ -# Delete the message
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcmsg_SetMessageStatus(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_object_t obj_ctable;
+ mapi_id_t id_folder;
+ mapi_id_t id_msgs[1];
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ uint32_t count;
+ uint32_t i;
+ uint32_t ulOldStatus;
+ uint32_t ulOldStatus2;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Outbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderOutbox);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create the message */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_folder, &obj_message);
+ mapitest_print_retval(mt, "CreateMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4. Save the message */
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 5. Get outbox contents table */
+ mapi_object_init(&obj_ctable);
+ retval = GetContentsTable(&obj_folder, &obj_ctable, 0, &count);
+ mapitest_print_retval(mt, "GetContentsTable");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2,
+ PR_MID, PR_MSG_STATUS);
+ retval = SetColumns(&obj_ctable, SPropTagArray);
+ mapitest_print_retval(mt, "SetColumns");
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Fetch the first email */
+ retval = QueryRows(&obj_ctable, 1, TBL_NOADVANCE, &SRowSet);
+ mapitest_print_retval(mt, "QueryRows");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 6. SetMessageStatus + GetMessageStatus + Comparison */
+ for (i = 0; msgstatus[i].name; i++) {
+ retval = SetMessageStatus(&obj_folder, SRowSet.aRow[0].lpProps[0].value.d,
+ msgstatus[i].status, msgstatus[i].status, &ulOldStatus2);
+ mapitest_print_retval(mt, "SetMessageStatus");
+
+ retval = GetMessageStatus(&obj_folder, SRowSet.aRow[0].lpProps[0].value.d, &ulOldStatus);
+ mapitest_print_retval(mt, "GetMessageStatus");
+
+ if ((ulOldStatus != ulOldStatus2) && (ulOldStatus & msgstatus[i].status)) {
+ errno = 0;
+ mapitest_print(mt, "* %-35s: %s 0x%.8x\n", "Comparison", msgstatus[i].name, GetLastError());
+ }
+ }
+
+ /* Step 7. Delete the saved message */
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_ctable);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+/**
+ \details Test the SetReadFlags (0x66) operation
+
+ This function:
+ -# Opens the Inbox folder and creates some test content
+ -# Checks that the PR_MESSAGE_FLAGS property on each message is 0x0
+ -# Apply SetReadFlags() on every second messages
+ -# Check the results are as expected
+ -# Apply SetReadFlags() again
+ -# Check the results are as expected
+ -# Cleanup
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcmsg_SetReadFlags(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_htable;
+ mapi_object_t obj_test_folder;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ struct mt_common_tf_ctx *context;
+ int i;
+ uint64_t messageIds[5];
+
+ /* Step 1. Logon */
+ if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
+ return false;
+ }
+
+ /* Fetch the contents table for the test folder */
+ context = mt->priv;
+ mapi_object_init(&(obj_test_folder));
+ GetContentsTable(&(context->obj_test_folder), &(obj_test_folder), 0, NULL);
+ mapitest_print_retval(mt, "GetContentsTable");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_MID, PR_MESSAGE_FLAGS);
+ SetColumns(&obj_test_folder, SPropTagArray);
+ mapitest_print_retval(mt, "SetColumns");
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ QueryRows(&obj_test_folder, 10, TBL_NOADVANCE, &SRowSet);
+ mapitest_print_retval(mt, "QueryRows");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ for (i = 0; i < 10; ++i) {
+ if (*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1])) != 0x0) {
+ mapitest_print(mt, "* %-35s: unexpected flag 0x%x\n", "QueryRows",
+ (*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1]))));
+ ret = false;
+ goto cleanup;
+ }
+ }
+
+ for (i = 0; i < 5; ++i) {
+ messageIds[i] = (*(const uint64_t *)get_SPropValue_data(&(SRowSet.aRow[i*2].lpProps[0])));
+ }
+
+ SetReadFlags(&(context->obj_test_folder), 0x0, 5, messageIds);
+ mapitest_print_retval(mt, "SetReadFlags");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ retval = QueryRows(&obj_test_folder, 10, TBL_NOADVANCE, &SRowSet);
+ mapitest_print_retval(mt, "QueryRows");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ for (i = 0; i < 10; i+=2) {
+ if (*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1])) != MSGFLAG_READ) {
+ mapitest_print(mt, "* %-35s: unexpected flag (0) 0x%x\n", "QueryRows",
+ (*(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) {
+ mapitest_print(mt, "* %-35s: unexpected flag (1) 0x%x\n", "QueryRows",
+ (*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i+1].lpProps[1]))));
+ ret = false;
+ goto cleanup;
+ }
+ }
+
+ SetReadFlags(&(context->obj_test_folder), CLEAR_READ_FLAG, 5, messageIds);
+
+ retval = QueryRows(&obj_test_folder, 10, TBL_NOADVANCE, &SRowSet);
+ mapitest_print_retval(mt, "QueryRows");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ for (i = 0; i < 10; ++i) {
+ if (*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1])) != 0x0) {
+ mapitest_print(mt, "* %-35s: unexpected flag 0x%x\n", "QueryRows",
+ (*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1]))));
+ ret = false;
+ goto cleanup;
+ }
+ }
+
+ cleanup:
+ /* Cleanup and release */
+ mapi_object_release(&obj_htable);
+ mapitest_common_cleanup(mt);
+
+ return ret;
+}
+
+/**
+ \details Test the OpenEmbeddedMessage (0x46) and CreateAttach operations
+
+ This function:
+ -# Logs on the user private mailbox
+ -# Open the Inbox folder
+ -# Create a test message
+ -# Embed a message in the test message
+ -# Delete the test message
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcmsg_OpenEmbeddedMessage(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_object_t obj_attach;
+ mapi_object_t obj_embeddedmsg;
+ mapi_id_t id_msgs[1];
+ struct SPropValue attach[2];
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_store);
+ return false;
+ }
+
+ /* Step 2. Open Outbox folder */
+ mapi_object_init(&obj_folder);
+ ret = mapitest_common_folder_open(mt, &obj_store, &obj_folder, olFolderInbox);
+ if (ret == false) {
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ return false;
+ }
+
+ /* Step 3. Create the tmp message and save it */
+ mapi_object_init(&obj_message);
+ ret = mapitest_common_message_create(mt, &obj_folder, &obj_message, OXCMSG_SETREADFLAGS);
+ if (ret == false) return ret;
+
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadWrite);
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "SaveChangesMessage", retval);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ return false;
+ }
+
+ /* Step 4. Embed another message in the message */
+ mapi_object_init(&obj_attach);
+ retval = CreateAttach(&obj_message, &obj_attach);
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "CreateAttach", retval);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ return false;
+ }
+
+ /* use SetProps() to set the attachment up */
+ attach[0].ulPropTag = PR_ATTACH_METHOD;
+ attach[0].value.l = ATTACH_EMBEDDED_MSG;
+ attach[1].ulPropTag = PR_RENDERING_POSITION;
+ attach[1].value.l = 0;
+ retval = SetProps(&obj_attach, attach, 2);
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "SetProps", retval);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ return false;;
+ }
+
+ mapi_object_init(&obj_embeddedmsg);
+ retval = OpenEmbeddedMessage(&obj_attach, &obj_embeddedmsg, MAPI_CREATE);
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "OpenEmbeddedMessage", retval);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ return false;;
+ }
+
+ ret = mapitest_common_message_fill(mt, &obj_embeddedmsg, "[MT] EmbeddedMessage");
+ if (ret == false) {
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ return false;
+ }
+
+ // Save the changes to the embedded message
+ retval = SaveChangesMessage(&obj_message, &obj_embeddedmsg, KeepOpenReadOnly);
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "SaveChangesMessage", retval);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ return false;;
+ }
+ // Save the changes to the attachment and then the message
+ retval = SaveChangesAttachment(&obj_message, &obj_attach, KeepOpenReadOnly);
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "SaveChangesAttachment", retval);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ return false;;
+ }
+
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "SaveChangesMessage", retval);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ return false;;
+ }
+
+ /* Step 5. Delete the message */
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "DeleteMessage", GetLastError());
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
Added: trunk/openchange/utils/mapitest/modules/module_oxcprpt.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxcprpt.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_oxcprpt.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,2376 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - PROPERTY AND STREAM OBJECT PROTOCOL operations
+
+ Copyright (C) Julien Kerihuel 2008
+ Copyright (C) Brad Hards 2008
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_oxcprpt.c
+
+ \brief Property and Stream Object Protocol test suite
+*/
+
+/**
+ \details Test the GetProps (0x7) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Retrieve the properties list using GetPropList
+ -# Retrieve their associated values using the GetProps operation
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcprpt_GetProps(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProps;
+ uint32_t cValues;
+
+ /* Step 1. Logon Private Mailbox */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Retrieve the properties list using GetPropList */
+ SPropTagArray = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ retval = GetPropList(&obj_store, SPropTagArray);
+ mapitest_print_retval(mt, "GetPropList");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Call the GetProps operation */
+ retval = GetProps(&obj_store, SPropTagArray, &lpProps, &cValues);
+ mapitest_print_retval(mt, "GetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ MAPIFreeBuffer(SPropTagArray);
+
+ /* Release */
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the GetPropsAll (0x8) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Retrieve the whole set of properties and values associated to the store object
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcprpt_GetPropsAll(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ struct mapi_SPropValue_array properties_array;
+
+ /* Step 1. Logon Private Mailbox */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. GetPropsAll operation */
+ retval = GetPropsAll(&obj_store, &properties_array);
+ mapitest_print_retval(mt, "GetPropsAll");
+ MAPIFreeBuffer(properties_array.lpProps);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the GetPropList (0x9) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Retrieve the list of properties associated to the store object object
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcprpt_GetPropList(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ struct SPropTagArray *SPropTagArray;
+
+ /* Step 1. Logon Private Mailbox */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. GetPropList operation */
+ SPropTagArray = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ retval = GetPropList(&obj_store, SPropTagArray);
+ mapitest_print_retval(mt, "GetPropList");
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the SetProps (0xa) operation
+
+ This function:
+ -# Logon Private mailbox
+ -# Use GetProps to retrieve the mailbox name
+ -# Change it using SetProps
+ -# Reset the mailbox name to its original value
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcprpt_SetProps(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ struct SPropValue *lpProps;
+ struct SPropValue lpProp[1];
+ struct SPropTagArray *SPropTagArray;
+ const char *mailbox = NULL;
+ const char *new_mailbox = NULL;
+ uint32_t cValues;
+
+ /* Step 1. Logon Private Mailbox */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval_step_fmt(mt, "1.", "OpenMsgStore", "(%s)", "Logon Private Mailbox");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2: GetProps, retrieve mailbox name */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_DISPLAY_NAME);
+ retval = GetProps(&obj_store, SPropTagArray, &lpProps, &cValues);
+ mapitest_print_retval_step_fmt(mt, "2.", "GetProps", "(%s)", "Retrieve the mailbox name");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ MAPIFreeBuffer(SPropTagArray);
+
+ if (cValues && lpProps[0].value.lpszA) {
+ mailbox = lpProps[0].value.lpszA;
+ mapitest_print(mt, "* Step 2. Mailbox name = %s\n", mailbox);
+ } else {
+ mapitest_print(mt, MT_ERROR, "* Step 2 - GetProps: No mailbox name\n");
+ return false;
+ }
+
+ /* Step 2.1: SetProps with new value */
+ cValues = 1;
+ new_mailbox = talloc_asprintf(mt->mem_ctx, "%s [MAPITEST]", mailbox);
+ set_SPropValue_proptag(&lpProp[0], PR_DISPLAY_NAME,
+ (const void *) new_mailbox);
+ retval = SetProps(&obj_store, lpProp, cValues);
+ mapitest_print_retval_step_fmt(mt, "2.1.", "SetProps", "(%s)", "NEW mailbox name");
+
+ /* Step 2.2: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_DISPLAY_NAME);
+ retval = GetProps(&obj_store, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(new_mailbox, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 2.2 - Check: NEW mailbox name - [SUCCESS] (%s)\n", lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 2.2 - Check: NEW mailbox name [FAILURE]\n");
+ }
+ }
+ MAPIFreeBuffer((void *)new_mailbox);
+
+ /* Step 3.1: Reset mailbox to its original value */
+ cValues = 1;
+ set_SPropValue_proptag(&lpProp[0], PR_DISPLAY_NAME, (const void *)mailbox);
+ retval = SetProps(&obj_store, lpProp, cValues);
+ mapitest_print_retval_step_fmt(mt, "3.1.", "SetProps", "(%s)", "OLD mailbox name");
+
+ /* Step 3.2: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_DISPLAY_NAME);
+ retval = GetProps(&obj_store, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(mailbox, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 3.2 - Check: OLD mailbox name [SUCCESS]\n");
+ } else {
+ mapitest_print(mt, "* Step 3.2 - Check: OLD mailbox name, [FAILURE]\n");
+ }
+ }
+
+ /* Release */
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the DeleteProps (0xb) operation)
+
+ This function:
+ -# Opens the mailbox
+ -# Create a test folder
+ -# Creates a reference email, and sets some properties on it
+ -# Delete properties from this message
+ -# Checks that properties got deleted
+ -# Deletes both email and the test folder
+
+ \todo It would be useful to test the problem return values
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcprpt_DeleteProps(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_top_folder;
+ mapi_id_t id_top_folder;
+ mapi_object_t obj_ref_folder;
+ mapi_object_t obj_ref_message;
+ const char *name = NULL;
+ const char *subject = NULL;
+ struct SPropValue lpProp[3];
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProps;
+ uint32_t cValues;
+
+ /* Step 1. Logon Private Mailbox */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval_step_fmt(mt, "1.", "OpenMsgStore", "(%s)", "Logon Private Mailbox");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ mapi_object_init(&obj_top_folder);
+ retval = GetDefaultFolder(&obj_store, &id_top_folder, olFolderTopInformationStore);
+ retval = OpenFolder(&obj_store, id_top_folder, &obj_top_folder);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2: Create reference folder */
+ mapi_object_init(&obj_ref_folder);
+ retval = CreateFolder(&obj_top_folder, FOLDER_GENERIC, MT_DIRNAME_TOP, NULL,
+ OPEN_IF_EXISTS, &obj_ref_folder);
+ mapitest_print_retval_step_fmt(mt, "2.", "CreateFolder", "(%s)", "Create the test folder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3: Create reference message */
+ mapi_object_init(&obj_ref_message);
+ retval = mapitest_common_message_create(mt, &obj_ref_folder, &obj_ref_message, MT_MAIL_SUBJECT);
+ mapitest_print_retval_step_fmt(mt, "3.1.", "mapitest_common_message_create", "(%s)", "Create a reference email");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ retval = SaveChangesMessage(&obj_ref_folder, &obj_ref_message, KeepOpenReadWrite);
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ name = talloc_asprintf(mt->mem_ctx, "Reference: %s", "display name");
+ subject = talloc_asprintf(mt->mem_ctx, "Reference: %s", "subject");
+ set_SPropValue_proptag(&lpProp[0], PR_DISPLAY_NAME, (const void *)name);
+ set_SPropValue_proptag(&lpProp[1], PR_CONVERSATION_TOPIC, (const void *)subject);
+ retval = SetProps(&obj_ref_message, lpProp, 2);
+ mapitest_print_retval_step_fmt(mt, "3.2.", "SetProps", "(%s)", "Set email properties");
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 4.1. - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 4.1. - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 4.2. - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 4.2. - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ }
+ }
+ MAPIFreeBuffer(lpProps);
+
+ /* Step 5. Delete Properties */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_CONVERSATION_TOPIC);
+ retval = DeleteProps(&obj_ref_message, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ mapitest_print_retval_step_fmt(mt, "5.", "DeleteProps", "PR_CONVERSATION_TOPIC");
+
+ /* Step 6. Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_CONVERSATION_TOPIC);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (get_SPropValue(lpProps, PR_CONVERSATION_TOPIC) == NULL) {
+ mapitest_print(mt, "* Step 5.1. - GetProps verifier [SUCCESS]\n");
+ } else {
+ mapitest_print(mt, "* Step 5.1. - GetProps verifier [FAILURE]:\n");
+ }
+ MAPIFreeBuffer(lpProps);
+
+ /* Step 7: cleanup folders */
+ retval = DeleteFolder(&obj_top_folder, mapi_object_get_id(&obj_ref_folder),
+ DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval_step(mt, "6.", "DeleteFolder");
+
+ /* Release */
+ mapi_object_release(&obj_ref_message);
+ mapi_object_release(&obj_ref_folder);
+ mapi_object_release(&obj_top_folder);
+ mapi_object_release(&obj_store);
+
+
+ return true;
+}
+
+
+/**
+ \details Test the CopyProps (0x67) operation
+
+ This function:
+ -# Opens the mailbox
+ -# Creates a test folder
+ -# Creates a reference email, and sets some properties on it
+ -# Checks those properties are set correctly
+ -# Creates a second email, and sets some (different) properties on it
+ -# Checks those properties on the second folder are set correctly
+ -# Copies properties from the reference email to the second email (no overwrite)
+ -# Checks that properties on both emails are correct
+ -# Copies properties again, but with overwrite
+ -# Checks that properties on both emails are correct
+ -# Moves properties from the original email to the second email (no overwrite)
+ -# Checks that properties on both emails are correct
+ -# Deletes both emails and the test folder
+
+ \todo It would be useful to test the problem return values
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcprpt_CopyProps(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_top_folder;
+ mapi_id_t id_top_folder;
+ mapi_object_t obj_ref_folder;
+ mapi_object_t obj_ref_message;
+ const char *name = NULL;
+ const char *subject = NULL;
+ struct SPropValue lpProp[3];
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProps;
+ uint32_t cValues;
+ mapi_object_t obj_target_message;
+ const char *targ_name = NULL;
+ const char *targ_dept = NULL;
+ uint16_t problem_count = 999;
+ struct PropertyProblem *problems = NULL;
+
+ /* Step 1. Logon Private Mailbox */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval_step_fmt(mt, "1.", "OpenMsgStore", "(%s)", "Logon Private Mailbox");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ mapi_object_init(&obj_top_folder);
+ retval = GetDefaultFolder(&obj_store, &id_top_folder, olFolderTopInformationStore);
+ retval = OpenFolder(&obj_store, id_top_folder, &obj_top_folder);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2: Create reference folder */
+ mapi_object_init(&obj_ref_folder);
+ retval = CreateFolder(&obj_top_folder, FOLDER_GENERIC, MT_DIRNAME_TOP, NULL,
+ OPEN_IF_EXISTS, &obj_ref_folder);
+ mapitest_print_retval_step_fmt(mt, "2.", "CreateFolder", "(%s)", "Create the test folder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3: Create reference message */
+ mapi_object_init(&obj_ref_message);
+ retval = mapitest_common_message_create(mt, &obj_ref_folder, &obj_ref_message, MT_MAIL_SUBJECT);
+ mapitest_print_retval_step_fmt(mt, "3.1.", "mapitest_common_message_create", "(%s)", "Create a reference email");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ retval = SaveChangesMessage(&obj_ref_folder, &obj_ref_message, KeepOpenReadWrite);
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ name = talloc_asprintf(mt->mem_ctx, "Reference: %s", "display name");
+ subject = talloc_asprintf(mt->mem_ctx, "Reference: %s", "subject");
+ set_SPropValue_proptag(&lpProp[0], PR_DISPLAY_NAME, (const void *)name);
+ set_SPropValue_proptag(&lpProp[1], PR_CONVERSATION_TOPIC, (const void *)subject);
+ retval = SetProps(&obj_ref_message, lpProp, 2);
+ mapitest_print_retval_step_fmt(mt, "3.2.", "SetProps", "(%s)", "Set email properties");
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 4.1. - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 4.1. - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 4.2. - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 4.2. - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ }
+ }
+
+ /* Step 5: Create target message */
+ mapi_object_init(&obj_target_message);
+ retval = mapitest_common_message_create(mt, &obj_ref_folder, &obj_target_message, MT_MAIL_SUBJECT);
+ mapitest_print_retval_step_fmt(mt, "5.1.", "mapitest_common_message_create", "(%s)", "Create target email");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ retval = SaveChangesMessage(&obj_ref_folder, &obj_target_message, KeepOpenReadWrite);
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ 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);
+ set_SPropValue_proptag(&lpProp[1], PR_DEPARTMENT_NAME, (const void *)targ_dept);
+ retval = SetProps(&obj_target_message, lpProp, 2);
+ mapitest_print_retval_step_fmt(mt, "5.2.", "SetProps", "(%s)", "set properties on target email");
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 6: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_DEPARTMENT_NAME);
+ retval = GetProps(&obj_target_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(targ_name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 6A - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 6A - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(targ_dept, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 6B - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 6B - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ }
+ }
+
+
+
+ /* Step 7: Copy properties, no overwrite */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ retval = CopyProps(&obj_ref_message, &obj_target_message, SPropTagArray, CopyFlagsNoOverwrite,
+ &problem_count, &problems);
+ mapitest_print_retval_step_fmt(mt, "7.", "CopyProps", "(%s)", "no overwrite");
+ MAPIFreeBuffer(problems);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ MAPIFreeBuffer(SPropTagArray);
+
+ /* Step 8: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 8A - Check: Reference props still good - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 8A - Check: Reference props still good [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 8B - Check: Reference props still good - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 8B - Check: Reference props still good [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ }
+ }
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC, PR_DEPARTMENT_NAME);
+ retval = GetProps(&obj_target_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ /* this one shouldn't be overwritten */
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(targ_name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 8C - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 8C - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ }
+ }
+ /* this one should be copied */
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 8D - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 8D - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ }
+ }
+ /* this one should be unchanged */
+ if (lpProps[2].value.lpszA) {
+ if (!strncmp(targ_dept, lpProps[2].value.lpszA, strlen(lpProps[2].value.lpszA))) {
+ mapitest_print(mt, "* Step 8E - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[2].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 8E - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[2].value.lpszA);
+ }
+ }
+
+ /* Step 9: Copy properties, with overwrite */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ retval = CopyProps(&obj_ref_message, &obj_target_message, SPropTagArray, 0x0,
+ &problem_count, &problems);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPIFreeBuffer(problems);
+ mapitest_print_retval_step_fmt(mt, "9.", "CopyProps", "(%s)", "with overwrite");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 10: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 10A - Check: Reference props still good - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 10A - Check: Reference props still good [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 10B - Check: Reference props still good - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 10B - Check: Reference props still good [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ }
+ }
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC, PR_DEPARTMENT_NAME);
+ retval = GetProps(&obj_target_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ /* this one should now be overwritten */
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 10C - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 10C - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ }
+ }
+ /* this one should be copied */
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 10D - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 10D - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ }
+ }
+ /* this one should be unchanged */
+ if (lpProps[2].value.lpszA) {
+ if (!strncmp(targ_dept, lpProps[2].value.lpszA, strlen(lpProps[2].value.lpszA))) {
+ mapitest_print(mt, "* Step 10E - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[2].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 10E - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[2].value.lpszA);
+ }
+ }
+
+
+ /* Step 11: Move properties, no overwrite */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ retval = CopyProps(&obj_ref_message, &obj_target_message, SPropTagArray, CopyFlagsNoOverwrite|CopyFlagsMove,
+ &problem_count, &problems);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPIFreeBuffer(problems);
+ mapitest_print_retval_step_fmt(mt, "11.", "CopyProps", "(%s)", "move");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 12: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (cValues == 2) {
+ mapitest_print(mt, "* Step 12A - Properties removed [SUCCESS]\n");
+ } else {
+ mapitest_print(mt, "* Step 12A - Properties removed [FAILURE]\n");
+ }
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC, PR_DEPARTMENT_NAME);
+ retval = GetProps(&obj_target_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 12B - Check: Reference props move - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 12B - Check: Reference props move [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 12C - Check: Reference props move - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 12C - Check: Reference props move [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ }
+ }
+ if (lpProps[2].value.lpszA) {
+ if (!strncmp(targ_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 {
+ mapitest_print(mt, "* Step 12D - Check: Reference props move [FAILURE] (%s)\n",
+ lpProps[2].value.lpszA);
+ }
+ }
+
+
+ /* Cleanup reference strings */
+ MAPIFreeBuffer((void *)subject);
+ MAPIFreeBuffer((void *)name);
+ MAPIFreeBuffer((void *)targ_name);
+ MAPIFreeBuffer((void *)targ_dept);
+
+ /* Step 13: cleanup folders */
+ retval = DeleteFolder(&obj_top_folder, mapi_object_get_id(&obj_ref_folder),
+ DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval_step(mt, "13.1.", "DeleteFolder");
+
+ /* Release */
+ mapi_object_release(&obj_ref_message);
+ mapi_object_release(&obj_ref_folder);
+ mapi_object_release(&obj_top_folder);
+ mapi_object_release(&obj_store);
+
+
+ return true;
+}
+
+
+
+/**
+ \details Test Stream operations. This test uses all related stream
+ operations: OpenStream (0x2b), SetStreamSize (0x2f), WriteStream
+ (0x2d), CommitStream (0x5d), ReadStream (0x2c), SeekStream (0x2e)
+
+ This function:
+ -# Logon
+ -# Open Outbox folder
+ -# Create message
+ -# Create attachment and set properties
+ -# Open the stream
+ -# Set the stream size
+ -# Write into the stream
+ -# Commit the stream
+ -# Save the message
+ -# Get stream size and compare values
+ -# Open the stream again with different permissions
+ -# Read the stream and compare buffers
+ -# SeekStream at 0x1000 from the end of the stream
+ -# Read the 0x1000 last bytes and check if it matches
+ -# Delete the message;
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise -1
+ */
+_PUBLIC_ bool mapitest_oxcprpt_Stream(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_object_t obj_attach;
+ mapi_object_t obj_stream;
+ mapi_id_t id_folder;
+ DATA_BLOB data;
+ struct SPropValue attach[3];
+ char *stream = NULL;
+ char *out_stream = NULL;
+ uint32_t stream_len = 0x32146;
+ unsigned char buf[MT_STREAM_MAX_SIZE];
+ uint32_t StreamSize = 0;
+ uint16_t read_size = 0;
+ uint16_t write_len = 0;
+ uint32_t len = 0;
+ uint32_t offset = 0;
+ mapi_id_t id_msgs[1];
+ uint32_t i;
+ uint64_t NewPosition;
+
+ stream = mapitest_common_genblob(mt->mem_ctx, stream_len);
+ if (stream == NULL) {
+ return false;
+ }
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Inbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create the message */
+ mapi_object_init(&obj_message);
+ mapitest_common_message_create(mt, &obj_folder, &obj_message, MT_MAIL_SUBJECT);
+
+ /* Step 4. Create the attachment */
+ mapi_object_init(&obj_attach);
+ retval = CreateAttach(&obj_message, &obj_attach);
+ mapitest_print_retval(mt, "CreateAttach");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ attach[0].ulPropTag = PR_ATTACH_METHOD;
+ attach[0].value.l = ATTACH_BY_VALUE;
+ attach[1].ulPropTag = PR_RENDERING_POSITION;
+ attach[1].value.l = 0;
+ attach[2].ulPropTag = PR_ATTACH_FILENAME;
+ attach[2].value.lpszA = MT_MAIL_ATTACH;
+
+ retval = SetProps(&obj_attach, attach, 3);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 5. Open the stream */
+ mapi_object_init(&obj_stream);
+ retval = OpenStream(&obj_attach, PR_ATTACH_DATA_BIN, 2, &obj_stream);
+ mapitest_print_retval(mt, "OpenStream");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 6. Set the stream size */
+ retval = SetStreamSize(&obj_stream, (uint64_t) stream_len);
+ mapitest_print_retval(mt, "SetStreamSize");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 7. Write the stream */
+ write_len = 0;
+
+ if (stream_len < MT_STREAM_MAX_SIZE) {
+ data.length = stream_len;
+ data.data = (uint8_t *) stream;
+ retval = WriteStream(&obj_stream, &data, &write_len);
+ mapitest_print_retval_fmt(mt, "WriteStream", "(0x%x bytes written)", write_len);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ } else {
+ uint32_t StreamSize = stream_len;
+
+ for (offset = 0, len = MT_STREAM_MAX_SIZE, i = 0; StreamSize; i++) {
+ data.length = len;
+ data.data = (uint8_t *)stream + offset;
+ retval = WriteStream(&obj_stream, &data, &write_len);
+ mapitest_print_retval_fmt(mt, "WriteStream", "[%d] (0x%x bytes written)", i, write_len);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ break;
+ }
+
+ StreamSize -= write_len;
+ if (StreamSize > MT_STREAM_MAX_SIZE) {
+ offset += MT_STREAM_MAX_SIZE;
+ } else {
+ offset += write_len;
+ len = StreamSize;
+ }
+ }
+ }
+
+ /* Step 8. Commit the stream */
+ retval = CommitStream(&obj_stream);
+ mapitest_print_retval(mt, "CommitStream");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 9. Save the attachment */
+ retval = SaveChangesAttachment(&obj_message, &obj_attach, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesAttachment");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 10. Get stream size */
+ retval = GetStreamSize(&obj_stream, &StreamSize);
+ mapitest_print_retval(mt, "GetStreamSize");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ mapitest_print(mt, "* %-35s: %s\n", "StreamSize comparison",
+ (StreamSize == stream_len) ? "[PASSED]" : "[FAILURE]");
+
+ /* Step 11. Read the stream */
+ mapi_object_release(&obj_stream);
+ mapi_object_init(&obj_stream);
+
+ retval = OpenStream(&obj_attach, PR_ATTACH_DATA_BIN, 0, &obj_stream);
+ mapitest_print_retval(mt, "OpenStream");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ offset = 0;
+ out_stream = talloc_size(mt->mem_ctx, StreamSize + 1);
+ do {
+ retval = ReadStream(&obj_stream, buf, MT_STREAM_MAX_SIZE, &read_size);
+ mapitest_print_retval_fmt(mt, "ReadStream", "(0x%x bytes read)", read_size);
+ memcpy(out_stream + offset, buf, read_size);
+ offset += read_size;
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ break;
+ }
+ } while (read_size && (offset != StreamSize));
+ out_stream[offset] = '\0';
+
+ if (offset) {
+ if (!strcmp(stream, out_stream)) {
+ mapitest_print(mt, "* %-35s: [IN,OUT] stream [PASSED]\n", "Comparison");
+ } else {
+ mapitest_print(mt, "* %-35s: [IN,OUT] stream [FAILURE]\n", "Comparison");
+
+ }
+ }
+
+ /* Step 12. SeekStream from the end of the stream */
+ retval = SeekStream(&obj_stream, 0x2, (uint64_t) -0x1000, &NewPosition);
+ mapitest_print_retval(mt, "SeekStream");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+
+ talloc_free(out_stream);
+ out_stream = talloc_size(mt->mem_ctx, 0x1001);
+ retval = ReadStream(&obj_stream, (uint8_t *)out_stream, 0x1000, &read_size);
+ out_stream[read_size] = '\0';
+ mapitest_print_retval_fmt(mt, "ReadStream", "(0x%x bytes read)", read_size);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ if (read_size && !strcmp(out_stream, stream + StreamSize - read_size)) {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Comparison");
+ } else {
+ mapitest_print(mt, "* %-35s: [FAILURE]\n", "Comparison");
+ }
+
+ /* Step 14. Delete the message */
+ errno = 0;
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_stream);
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ talloc_free(stream);
+ talloc_free(out_stream);
+
+ return ret;
+}
+
+
+/**
+ \details Test the CopyToStream (0x3a) operation
+
+ This function:
+ -# Logon the mailbox
+ -# Open the inbox folder
+ -# Create a sample messages with an attachment
+ -# Create 2 streams
+ -# Fill the first stream with random data
+ -# Seek stream positions to the beginning
+ -# CopyToStream data from first stream to the second stream
+ -# Read dst stream and compare with src stream
+ -# Delete the message
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcprpt_CopyToStream(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_object_t obj_attach;
+ mapi_object_t obj_attach2;
+ mapi_object_t obj_stream;
+ mapi_object_t obj_stream2;
+ mapi_id_t id_folder;
+ mapi_id_t id_msgs[1];
+ struct SPropValue attach[3];
+ DATA_BLOB data;
+ char *stream = NULL;
+ char *dst_stream = NULL;
+ uint32_t stream_len = 0x32146;
+ unsigned char buf[MT_STREAM_MAX_SIZE];
+ uint32_t StreamSize = 0;
+ uint16_t write_len = 0;
+ uint16_t read_size = 0;
+ uint32_t len = 0;
+ uint32_t offset = 0;
+ uint32_t i;
+ uint64_t ReadByteCount = 0;
+ uint64_t WrittenByteCount = 0;
+ uint64_t NewPosition = 0;
+
+ stream = mapitest_common_genblob(mt->mem_ctx, stream_len);
+ if (stream == NULL) {
+ return false;
+ }
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Inbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create the message */
+ mapi_object_init(&obj_message);
+ mapitest_common_message_create(mt, &obj_folder, &obj_message, MT_MAIL_SUBJECT);
+
+ /* Step 4. Create the first attachment */
+ mapi_object_init(&obj_attach);
+ retval = CreateAttach(&obj_message, &obj_attach);
+ mapitest_print_retval(mt, "CreateAttach");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ attach[0].ulPropTag = PR_ATTACH_METHOD;
+ attach[0].value.l = ATTACH_BY_VALUE;
+ attach[1].ulPropTag = PR_RENDERING_POSITION;
+ attach[1].value.l = 0;
+ attach[2].ulPropTag = PR_ATTACH_FILENAME;
+ attach[2].value.lpszA = MT_MAIL_ATTACH;
+
+ retval = SetProps(&obj_attach, attach, 3);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 5. Open the stream */
+ mapi_object_init(&obj_stream);
+ retval = OpenStream(&obj_attach, PR_ATTACH_DATA_BIN, 2, &obj_stream);
+ mapitest_print_retval(mt, "OpenStream");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 6. Set the stream size */
+ retval = SetStreamSize(&obj_stream, (uint64_t) stream_len);
+ mapitest_print_retval(mt, "SetStreamSize");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 7. Write the stream */
+ write_len = 0;
+
+ if (stream_len < MT_STREAM_MAX_SIZE) {
+ data.length = stream_len;
+ data.data = (uint8_t *) stream;
+ retval = WriteStream(&obj_stream, &data, &write_len);
+ mapitest_print_retval_fmt(mt, "WriteStream", "(0x%x bytes written)", write_len);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ } else {
+ uint32_t StreamSize = stream_len;
+
+ for (offset = 0, len = MT_STREAM_MAX_SIZE, i = 0; StreamSize; i++) {
+ data.length = len;
+ data.data = (uint8_t *)stream + offset;
+ retval = WriteStream(&obj_stream, &data, &write_len);
+ mapitest_print_retval_fmt(mt, "WriteStream", "[%d] (0x%x bytes written)", i, write_len);
+
+ StreamSize -= write_len;
+ if (StreamSize > MT_STREAM_MAX_SIZE) {
+ offset += MT_STREAM_MAX_SIZE;
+ } else {
+ offset += write_len;
+ len = StreamSize;
+ }
+ }
+ }
+
+ /* Step 8. Commit the stream */
+ retval = CommitStream(&obj_stream);
+ mapitest_print_retval(mt, "CommitStream");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 9. Save the attachment */
+ retval = SaveChangesAttachment(&obj_message, &obj_attach, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesAttachment");
+
+ /* Step 10. Create the second attachment */
+ mapi_object_init(&obj_attach2);
+ retval = CreateAttach(&obj_message, &obj_attach2);
+ mapitest_print_retval(mt, "CreateAttach");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ attach[0].ulPropTag = PR_ATTACH_METHOD;
+ attach[0].value.l = ATTACH_BY_VALUE;
+ attach[1].ulPropTag = PR_RENDERING_POSITION;
+ attach[1].value.l = 0;
+ attach[2].ulPropTag = PR_ATTACH_FILENAME;
+ attach[2].value.lpszA = MT_MAIL_ATTACH2;
+
+ retval = SetProps(&obj_attach2, attach, 3);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 11. Open the dst stream */
+ mapi_object_init(&obj_stream2);
+ retval = OpenStream(&obj_attach2, PR_ATTACH_DATA_BIN, 2, &obj_stream2);
+ mapitest_print_retval(mt, "OpenStream");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 12. Get src stream size */
+ retval = GetStreamSize(&obj_stream, &StreamSize);
+ mapitest_print_retval_fmt(mt, "GetStreamSize", "(%s: 0x%x)", "Src", StreamSize);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 13. Reset streams positions to the beginning */
+ retval = SeekStream(&obj_stream, 0, 0, &NewPosition);
+ mapitest_print_retval_fmt(mt, "SeekStream", "(%s)", "Src");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ retval = SeekStream(&obj_stream2, 0, 0, &NewPosition);
+ mapitest_print_retval_fmt(mt, "SeekStream", "(%s)", "Dst");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 14. Copy src to dst stream */
+ retval = CopyToStream(&obj_stream, &obj_stream2, StreamSize, &ReadByteCount, &WrittenByteCount);
+ mapitest_print_retval(mt, "CopyToStream");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 14. Save the attachment */
+ retval = SaveChangesAttachment(&obj_message, &obj_attach2, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesAttachment");
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 15. Compare values */
+ mapitest_print(mt, "* %-35s: 0x%llx - 0x%llx %s\n", "Read/Write bytes comparison",
+ ReadByteCount, WrittenByteCount,
+ (ReadByteCount == WrittenByteCount) ? "[SUCCESS]" : "[FAILURE]");
+
+
+ /* Step 16. Get dst stream size */
+ retval = GetStreamSize(&obj_stream2, &StreamSize);
+ mapitest_print_retval_fmt(mt, "GetStreamSize", "(%s: 0x%x)", "Dst", StreamSize);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ retval = SeekStream(&obj_stream2, 0, 0, &NewPosition);
+ mapitest_print_retval_fmt(mt, "SeekStream", "(%s)", "Dst");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 17. Read the dst stream */
+ offset = 0;
+ dst_stream = talloc_size(mt->mem_ctx, StreamSize + 1);
+ do {
+ retval = ReadStream(&obj_stream2, buf, MT_STREAM_MAX_SIZE, &read_size);
+ mapitest_print_retval_fmt(mt, "ReadStream", "(0x%x bytes read)", read_size);
+ memcpy(dst_stream + offset, buf, read_size);
+ offset += read_size;
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ break;
+ }
+ } while (read_size || offset != StreamSize);
+ dst_stream[offset] = '\0';
+
+ /* Step 18. Compare streams */
+ if (!strcmp(stream, dst_stream)) {
+ mapitest_print(mt, "* %-35s: [SUCCESS]\n", "Comparison");
+ } else {
+ mapitest_print(mt, "* %-35s: [FAILURE]\n", "Comparison");
+ }
+
+
+ /* Step 19. Delete Message */
+ errno = 0;
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_stream2);
+ mapi_object_release(&obj_stream);
+ mapi_object_release(&obj_attach2);
+ mapi_object_release(&obj_attach);
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ talloc_free(stream);
+ talloc_free(dst_stream);
+
+ return ret;
+}
+
+
+/**
+ \details Test the CopyTo (0x39) operation
+
+ This function:
+ -# Opens the mailbox
+ -# Creates a test folder
+ -# Creates a reference email, and sets some properties on it
+ -# Checks those properties are set correctly
+ -# Creates a second email, and sets some (different) properties on it
+ -# Checks those properties on the second folder are set correctly
+ -# Copies properties from the reference email to the second email (no overwrite)
+ -# Checks that properties on both emails are correct
+ -# Copies properties again, but with overwrite
+ -# Checks that properties on both emails are correct
+ -# Moves properties from the original email to the second email (no overwrite)
+ -# Checks that properties on both emails are correct
+ -# Creates an attachment (with properties) on the reference email
+ -# Creates an attachment (with different properties) on the target email
+ -# Copies the properties on the reference email to the target
+ -# Checks the properties on both attachments are correct
+ -# Creates another folder
+ -# Copies properties from the test folder to the new folder
+ -# Checks that the properties on both folders are correct
+ -# Deletes both emails and the test folders
+
+ \todo It would be useful to test the problem return values
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_top_folder;
+ mapi_id_t id_top_folder;
+ mapi_object_t obj_ref_folder;
+ mapi_object_t obj_targ_folder;
+ mapi_object_t obj_ref_message;
+ mapi_object_t obj_target_message;
+ mapi_object_t obj_ref_attach;
+ mapi_object_t obj_targ_attach;
+ const char *name = NULL;
+ const char *subject = NULL;
+ const char *dept = NULL;
+ struct SPropValue lpProp[3];
+ struct SPropTagArray *exclude;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProps;
+ uint32_t cValues;
+ const char *targ_name = NULL;
+ const char *targ_dept = NULL;
+ uint16_t problem_count = 999;
+ struct PropertyProblem *problems = NULL;
+ bool ret = true;
+
+ /* Step 1. Logon Private Mailbox */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ mapi_object_init(&obj_top_folder);
+ retval = GetDefaultFolder(&obj_store, &id_top_folder, olFolderTopInformationStore);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+
+ retval = OpenFolder(&obj_store, id_top_folder, &obj_top_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 2: Create reference folder */
+ mapi_object_init(&obj_ref_folder);
+ retval = CreateFolder(&obj_top_folder, FOLDER_GENERIC, MT_DIRNAME_TOP, NULL,
+ OPEN_IF_EXISTS, &obj_ref_folder);
+ mapitest_print_retval_fmt(mt, "CreateFolder", "(Create test folder)");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ lpProp[0].ulPropTag = PR_CONTAINER_CLASS;
+ lpProp[0].value.lpszA = "IPF.Note";
+ SetProps(&obj_ref_folder, lpProp, 1);
+ mapitest_print_retval(mt, "SetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 3: Create reference message */
+ mapi_object_init(&obj_ref_message);
+ retval = mapitest_common_message_create(mt, &obj_ref_folder, &obj_ref_message, MT_MAIL_SUBJECT);
+ mapitest_print_retval(mt, "mapitest_common_message_create");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ retval = SaveChangesMessage(&obj_ref_folder, &obj_ref_message, KeepOpenReadWrite);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ name = talloc_asprintf(mt->mem_ctx, "Reference: %s", "display name");
+ 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[2], PR_DEPARTMENT_NAME, (const void *)dept);
+ retval = SetProps(&obj_ref_message, lpProp, 3);
+ mapitest_print_retval(mt, "SetProps");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 4: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC,
+ PR_DEPARTMENT_NAME);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 4A - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 4A - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 4B - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 4B - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ if (lpProps[2].value.lpszA) {
+ if (!strncmp(dept, lpProps[2].value.lpszA, strlen(lpProps[2].value.lpszA))) {
+ mapitest_print(mt, "* Step 4C - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[2].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 4C - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[2].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+
+ /* Step 5: Create target message */
+ mapi_object_init(&obj_target_message);
+ retval = mapitest_common_message_create(mt, &obj_ref_folder, &obj_target_message, MT_MAIL_SUBJECT);
+ mapitest_print_retval(mt, "mapitest_common_message_create");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ retval = SaveChangesMessage(&obj_ref_folder, &obj_target_message, KeepOpenReadWrite);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ 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);
+ set_SPropValue_proptag(&lpProp[1], PR_DEPARTMENT_NAME, (const void *)targ_dept);
+ retval = SetProps(&obj_target_message, lpProp, 2);
+ mapitest_print_retval(mt, "SetProps");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 6: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_DEPARTMENT_NAME);
+ retval = GetProps(&obj_target_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(targ_name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 6A - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 6A - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ ret = false;
+ goto cleanup;
+
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(targ_dept, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 6B - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 6B - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ ret = false;
+ goto cleanup;
+
+ }
+ }
+
+
+ /* Step 7: Copy properties, no overwrite */
+ exclude = set_SPropTagArray(mt->mem_ctx, 0x0);
+ retval = CopyTo(&obj_ref_message, &obj_target_message, exclude, CopyFlagsNoOverwrite,
+ &problem_count, &problems);
+ MAPIFreeBuffer(exclude);
+ MAPIFreeBuffer(problems);
+ mapitest_print_retval_fmt(mt, "CopyTo", "(no overwrite)");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 8: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 8A - Check: Reference props still good - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 8A - Check: Reference props still good [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 8B - Check: Reference props still good - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 8B - Check: Reference props still good [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC, PR_DEPARTMENT_NAME);
+ retval = GetProps(&obj_target_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ /* this one shouldn't be overwritten */
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(targ_name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 8C - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 8C - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ /* this one should be copied */
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 8D - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 8D - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ /* this one should be unchanged */
+ if (lpProps[2].value.lpszA) {
+ if (!strncmp(targ_dept, lpProps[2].value.lpszA, strlen(lpProps[2].value.lpszA))) {
+ mapitest_print(mt, "* Step 8E - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[2].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 8E - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[2].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+
+ /* Step 9: Copy properties, with overwrite */
+ exclude = set_SPropTagArray(mt->mem_ctx, 0x1, PR_DEPARTMENT_NAME);
+ retval = CopyTo(&obj_ref_message, &obj_target_message, exclude, 0x0,
+ &problem_count, &problems);
+ MAPIFreeBuffer(exclude);
+ MAPIFreeBuffer(problems);
+ mapitest_print_retval_fmt(mt, "CopyTo", "(with overwrite)");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 10: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 10A - Check: Reference props still good - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 10A - Check: Reference props still good [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 10B - Check: Reference props still good - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 10B - Check: Reference props still good [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC, PR_DEPARTMENT_NAME);
+ retval = GetProps(&obj_target_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ /* this one should now be overwritten */
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 10C - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 10C - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ /* this one should be copied */
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 10D - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 10D - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ /* this one should be unchanged */
+ if (lpProps[2].value.lpszA) {
+ if (!strncmp(targ_dept, lpProps[2].value.lpszA, strlen(lpProps[2].value.lpszA))) {
+ mapitest_print(mt, "* Step 10E - Check: Reference props copy - [SUCCESS] (%s)\n",
+ lpProps[2].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 10E - Check: Reference props copy [FAILURE] (%s)\n",
+ lpProps[2].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+
+ /* Step 11: Move properties, no overwrite */
+ exclude = set_SPropTagArray(mt->mem_ctx, 0x0);
+ retval = CopyTo(&obj_ref_message, &obj_target_message, exclude, CopyFlagsNoOverwrite|CopyFlagsMove,
+ &problem_count, &problems);
+ MAPIFreeBuffer(exclude);
+ MAPIFreeBuffer(problems);
+ mapitest_print(mt, "* %-35s: 0x%.8x\n", "Step 11 - CopyTo (move)", GetLastError());
+ if (GetLastError() != 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);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (cValues == 2) {
+ mapitest_print(mt, "* Step 12A - Properties removed [SUCCESS]\n");
+ } else {
+ mapitest_print(mt, "* Step 12A - Properties removed [FAILURE]\n");
+ ret = false;
+ goto cleanup;
+ }
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC, PR_DEPARTMENT_NAME);
+ retval = GetProps(&obj_target_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 12B - Check: Reference props move - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 12B - Check: Reference props move [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 12C - Check: Reference props move - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 12C - Check: Reference props move [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ if (lpProps[2].value.lpszA) {
+ if (!strncmp(targ_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 {
+ mapitest_print(mt, "* Step 12D - Check: Reference props move [FAILURE] (%s)\n",
+ lpProps[2].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+
+ /* Step 13: Create attachment on reference email, and set properties */
+ mapi_object_init(&obj_ref_attach);
+ CreateAttach(&obj_ref_message, &obj_ref_attach);
+ mapitest_print_retval(mt, "CreateAttach");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ lpProp[0].ulPropTag = PR_ATTACH_METHOD;
+ lpProp[0].value.l = ATTACH_BY_VALUE;
+ lpProp[1].ulPropTag = PR_RENDERING_POSITION;
+ lpProp[1].value.l = 0;
+ lpProp[2].ulPropTag = PR_ATTACH_FILENAME;
+ lpProp[2].value.lpszA = MT_MAIL_ATTACH;
+ SetProps(&obj_ref_attach, lpProp, 3);
+ mapitest_print_retval(mt, "SetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ SaveChangesAttachment(&obj_ref_message, &obj_ref_attach, KeepOpenReadWrite);
+ mapitest_print_retval(mt, "SaveChangesAttachment");
+
+ /* Step 14: Create attachment on target email */
+ mapi_object_init(&obj_targ_attach);
+ CreateAttach(&obj_target_message, &obj_targ_attach);
+ mapitest_print_retval(mt, "CreateAttach");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ lpProp[0].ulPropTag = PR_ATTACH_METHOD;
+ lpProp[0].value.l = ATTACH_BY_VALUE;
+ lpProp[1].ulPropTag = PR_RENDERING_POSITION;
+ lpProp[1].value.l = 0;
+ lpProp[2].ulPropTag = PR_ATTACH_FILENAME;
+ lpProp[2].value.lpszA = MT_MAIL_ATTACH2;
+ SetProps(&obj_targ_attach, lpProp, 3);
+ mapitest_print_retval(mt, "SetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ SaveChangesAttachment(&obj_target_message, &obj_targ_attach, KeepOpenReadWrite);
+ mapitest_print_retval(mt, "SaveChangesAttachment");
+
+ /* Step 15: Copy props from reference email attachment to target email attachment */
+ exclude = set_SPropTagArray(mt->mem_ctx, 0x0);
+ CopyTo(&obj_ref_attach, &obj_targ_attach, exclude, 0x0, &problem_count, &problems);
+ MAPIFreeBuffer(exclude);
+ MAPIFreeBuffer(problems);
+ mapitest_print_retval_fmt(mt, "CopyTo", "(attachments)");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 16: Check properties on both attachments are correct */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_ATTACH_FILENAME);
+ GetProps(&obj_ref_attach, SPropTagArray, &lpProps, &cValues);
+ mapitest_print_retval(mt, "GetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(MT_MAIL_ATTACH, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ 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);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_ATTACH_FILENAME);
+ GetProps(&obj_targ_attach, SPropTagArray, &lpProps, &cValues);
+ mapitest_print_retval(mt, "GetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(MT_MAIL_ATTACH, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 16D - Check: Target attachment props - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 16D - Check: Target attachment props [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+
+ /* Create another folder */
+ mapi_object_init(&obj_targ_folder);
+ retval = CreateFolder(&obj_top_folder, FOLDER_GENERIC, "[MT] Target Folder", NULL,
+ OPEN_IF_EXISTS, &obj_targ_folder);
+ mapitest_print_retval(mt, "CreateFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ lpProp[0].ulPropTag = PR_CONTAINER_CLASS;
+ lpProp[0].value.lpszA = "IPF.Journal";
+ SetProps(&obj_targ_folder, lpProp, 1);
+ mapitest_print_retval(mt, "SetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Copy properties from the test folder to the new folder */
+ exclude = set_SPropTagArray(mt->mem_ctx, 0x1, PR_DISPLAY_NAME);
+ CopyTo(&obj_ref_folder, &obj_targ_folder, exclude, 0x0, &problem_count, &problems);
+ MAPIFreeBuffer(exclude);
+ MAPIFreeBuffer(problems);
+ mapitest_print_retval_fmt(mt, "CopyTo", "(folder)");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Check that the properties on both folders are correct */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONTAINER_CLASS);
+ GetProps(&obj_ref_folder, SPropTagArray, &lpProps, &cValues);
+ mapitest_print_retval(mt, "GetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(MT_DIRNAME_TOP, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 19B - Check: Reference folder props - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 19B - Check: Reference folder props [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp("IPF.Note", lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 19C - Check: Reference folder props - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 19C - Check: Reference folder props [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONTAINER_CLASS);
+ GetProps(&obj_targ_folder, SPropTagArray, &lpProps, &cValues);
+ mapitest_print_retval(mt, "GetProps");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp("[MT] Target Folder", lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 19E - Check: Target folder props - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 19E - Check: Target folder props [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp("IPF.Note", lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 19F - Check: Target folder props - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 19F - Check: Target folder props [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ ret = false;
+ goto cleanup;
+ }
+ }
+
+
+ cleanup:
+ /* Cleanup reference strings */
+ MAPIFreeBuffer((void *)subject);
+ MAPIFreeBuffer((void *)name);
+ MAPIFreeBuffer((void *)targ_name);
+ MAPIFreeBuffer((void *)targ_dept);
+
+ /* Cleanup folders */
+ retval = DeleteFolder(&obj_top_folder, mapi_object_get_id(&obj_targ_folder),
+ DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval(mt, "DeleteFolder");
+ retval = DeleteFolder(&obj_top_folder, mapi_object_get_id(&obj_ref_folder),
+ DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval(mt, "DeleteFolder");
+
+ /* Release */
+ mapi_object_release(&obj_targ_attach);
+ mapi_object_release(&obj_ref_attach);
+ mapi_object_release(&obj_ref_message);
+ mapi_object_release(&obj_ref_folder);
+ mapi_object_release(&obj_top_folder);
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
+
+#define NAMEDPROP_NAME "mapitest_namedprop"
+#define NAMEDPROP_IDNUM 0xDB
+
+/**
+ \details Test the GetPropertyIdsFromNames (0x56),
+ GetNamesFromPropertyIds (0x55) and QueryNamesFromIDs (0x5f)
+ operations
+
+ This function:
+ -# Logs into the server
+ -# Create a test folder and test message
+ -# Creates one MNID_ID property
+ -# Creates one MNID_STRING property
+ -# Builds a table of Name, ID pairs using QueryNamesFromIDs()
+ -# Iterates over names, and calls GetIDsFromNames() on each name
+ -# Iterates over IDs, and calls GetNamesFromIDs() on each ID
+ -# Cleans up
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcprpt_NameId(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_top_folder;
+ mapi_id_t id_top_folder;
+ mapi_object_t obj_ref_folder;
+ mapi_object_t obj_ref_message;
+ struct mapi_nameid *nameid;
+ struct mapi_nameid *nameid2;
+ struct MAPINAMEID checknameid;
+ struct SPropTagArray *SPropTagArray;
+ uint32_t propID;
+ uint16_t *propIDs;
+ bool ret = true;
+ int i;
+
+ /* Log into the server */
+ mapi_object_init(&obj_store);
+ OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ mapi_object_init(&obj_top_folder);
+ GetDefaultFolder(&obj_store, &id_top_folder, olFolderTopInformationStore);
+ mapitest_print_retval(mt, "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ OpenFolder(&obj_store, id_top_folder, &obj_top_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 2: Create test folder */
+ mapi_object_init(&obj_ref_folder);
+ CreateFolder(&obj_top_folder, FOLDER_GENERIC, MT_DIRNAME_TOP, NULL,
+ OPEN_IF_EXISTS, &obj_ref_folder);
+ mapitest_print_retval(mt, "CreateFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ mapi_object_init(&obj_ref_message);
+ mapitest_common_message_create(mt, &obj_ref_folder, &obj_ref_message, MT_MAIL_SUBJECT);
+ mapitest_print_retval(mt, "mapitest_common_message_create");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ SaveChangesMessage(&obj_ref_folder, &obj_ref_message, KeepOpenReadWrite);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 3: Create and Retrieve one MNID_ID property */
+
+ /* Build the list of named properties we want to create */
+ nameid = mapi_nameid_new(mt->mem_ctx);
+ mapi_nameid_custom_lid_add(nameid, NAMEDPROP_IDNUM, PT_STRING8, PS_MAPI);
+
+ /* GetIDsFromNames and map property types */
+ SPropTagArray = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ retval = GetIDsFromNames(&obj_ref_folder, nameid->count,
+ nameid->nameid, MAPI_CREATE, &SPropTagArray);
+ mapitest_print_retval(mt, "GetIDsFromNames");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ MAPIFreeBuffer(nameid);
+ goto cleanup;
+ }
+
+ mapi_nameid_SPropTagArray(nameid, SPropTagArray);
+ MAPIFreeBuffer(nameid);
+
+ propID = (SPropTagArray->aulPropTag[0] & 0xFFFF0000) | PT_NULL;
+ MAPIFreeBuffer(SPropTagArray);
+
+ nameid = mapi_nameid_new(mt->mem_ctx);
+ GetNamesFromIDs(&obj_ref_message, propID, &nameid->count, &nameid->nameid);
+ mapitest_print_retval(mt, "GetNamesFromIDs");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(nameid);
+ ret = false;
+ goto cleanup;
+ }
+
+ if ((nameid->nameid[0].ulKind != MNID_ID) || (nameid->nameid[0].kind.lid != NAMEDPROP_IDNUM)) {
+ errno = MAPI_E_RESERVED;
+ mapitest_print_retval_fmt(mt, "GetNamesFromIDs",
+ "Unexpected result: ulKind: %x mapped to 0x%.4x",
+ nameid->nameid[0].ulKind, nameid->nameid[0].kind.lid);
+ ret = false;
+ goto cleanup;
+ }
+
+ MAPIFreeBuffer(nameid);
+
+ /* Step 4: Create one MNID_STRING property */
+ nameid = mapi_nameid_new(mt->mem_ctx);
+ SPropTagArray = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+
+ mapi_nameid_custom_string_add(nameid, NAMEDPROP_NAME, PT_STRING8, PS_MAPI);
+ GetIDsFromNames(&obj_ref_folder, nameid->count, nameid->nameid, MAPI_CREATE, &SPropTagArray);
+ mapitest_print_retval(mt, "GetIDsFromNames");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(nameid);
+ ret = false;
+ goto cleanup;
+ }
+
+ mapi_nameid_SPropTagArray(nameid, SPropTagArray);
+ MAPIFreeBuffer(nameid);
+
+ propID = SPropTagArray->aulPropTag[0];
+ MAPIFreeBuffer(SPropTagArray);
+
+ /* Builds an array of Name,ID pairs using QueryNamesFromIDs() */
+ nameid = mapi_nameid_new(mt->mem_ctx);
+ propIDs = talloc_zero(mt->mem_ctx, uint16_t);
+ QueryNamedProperties(&obj_ref_message, 0, NULL, &nameid->count, &propIDs, &nameid->nameid);
+ nameid->nameid = talloc_steal((TALLOC_CTX *)nameid, nameid->nameid);
+ mapitest_print_retval(mt, "QueryNamedProperties");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(nameid);
+ talloc_free(propIDs);
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Iterate over names and call GetIDsFromNames() on each name */
+ for (i = 0; i < nameid->count; i++) {
+ checknameid.lpguid = nameid->nameid[i].lpguid;
+ checknameid.ulKind = nameid->nameid[i].ulKind;
+
+ switch (nameid->nameid[i].ulKind) {
+ case MNID_ID:
+ checknameid.kind.lid = nameid->nameid[i].kind.lid;
+ break;
+ case MNID_STRING:
+ checknameid.kind.lpwstr.Name = nameid->nameid[i].kind.lpwstr.Name;
+ checknameid.kind.lpwstr.NameSize = nameid->nameid[i].kind.lpwstr.NameSize;
+ break;
+ }
+
+ SPropTagArray = talloc_zero(mt->mem_ctx, struct SPropTagArray);
+ GetIDsFromNames(&obj_ref_folder, 1, &checknameid, 0, &SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "GetIDsFromNames");
+ MAPIFreeBuffer(nameid);
+ MAPIFreeBuffer(SPropTagArray);
+ ret = false;
+ goto cleanup;
+ }
+
+ /* check we got the right number of IDs */
+ if (SPropTagArray->cValues != 1) {
+ errno = MAPI_E_RESERVED;
+ mapitest_print_retval_fmt(mt, "GetIDsFromNames", "Unexpected ID count (%i)", SPropTagArray->cValues);
+ MAPIFreeBuffer(nameid);
+ MAPIFreeBuffer(SPropTagArray);
+ ret = false;
+ goto cleanup;
+ }
+
+ /* check if the ID is the one we expected */
+ if (SPropTagArray->aulPropTag[0] != (propIDs[i] << 16)) {
+ errno = MAPI_E_RESERVED;
+ mapitest_print_retval_fmt(mt, "GetIDsFromNames", "Unexpected ID (0x%x, expected 0x%x)",
+ SPropTagArray->aulPropTag[0], (propIDs[i] << 16));
+ MAPIFreeBuffer(nameid);
+ MAPIFreeBuffer(SPropTagArray);
+ ret = false;
+ goto cleanup;
+ }
+ MAPIFreeBuffer(SPropTagArray);
+ }
+ mapitest_print(mt, "* Step 6: All IDs matched [SUCCESS]\n");
+
+ /* Iterates over IDs, and call GetNamesFromIDs() on each ID */
+ for (i = 0; i < nameid->count; i++) {
+ nameid2 = mapi_nameid_new(mt->mem_ctx);
+ GetNamesFromIDs(&obj_ref_folder, ((propIDs[i] << 16) & 0xFFFF0000) | PT_NULL, &nameid2->count, &nameid2->nameid);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "GetNamesFromIDs");
+ MAPIFreeBuffer(nameid2);
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Check we got the right number of names */
+ if (nameid2->count != 1) {
+ mapitest_print_retval_fmt(mt, "GetNamesFromIDs", "Unexpected name count (%i)", nameid2->count);
+ MAPIFreeBuffer(nameid);
+ MAPIFreeBuffer(nameid2);
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Check we got the right kind of name */
+ if (nameid2->nameid[0].ulKind != nameid->nameid[i].ulKind) {
+ mapitest_print_retval_fmt(mt, "GetIDsFromNames", "Unexpected kind (0x%x, expected 0x%x)",
+ nameid2->nameid[0].ulKind, nameid->nameid[i].ulKind);
+ MAPIFreeBuffer(nameid);
+ MAPIFreeBuffer(nameid2);
+ ret = false;
+ goto cleanup;
+ }
+
+ switch (nameid->nameid[i].ulKind) {
+ case MNID_ID:
+ if (nameid2->nameid[0].kind.lid != nameid->nameid[i].kind.lid) {
+ mapitest_print_retval_fmt(mt, "GetIDsFromNames", "Unexpected hex name (0x%x, expected 0x%x)",
+ nameid2->nameid[0].kind.lid, nameid->nameid[i].kind.lid);
+ MAPIFreeBuffer(nameid);
+ MAPIFreeBuffer(nameid2);
+ ret = false;
+ goto cleanup;
+ }
+ break;
+ case MNID_STRING:
+ if (nameid2->nameid[0].kind.lpwstr.NameSize != nameid->nameid[i].kind.lpwstr.NameSize) {
+ mapitest_print_retval_fmt(mt, "GetIDsFromNames", "Unexpected name length (0x%x, expected 0x%x)",
+ nameid2->nameid[0].kind.lpwstr.NameSize,
+ nameid->nameid[i].kind.lpwstr.NameSize);
+ MAPIFreeBuffer(nameid);
+ MAPIFreeBuffer(nameid2);
+ ret = false;
+ goto cleanup;
+ }
+ if (strncmp(nameid2->nameid[0].kind.lpwstr.Name, nameid->nameid[i].kind.lpwstr.Name, nameid->nameid[i].kind.lpwstr.NameSize) != 0) {
+ mapitest_print_retval_fmt(mt, "GetIDsFromNames", "Unexpected name (%s, expected %s)",
+ nameid2->nameid[0].kind.lpwstr.Name,
+ nameid->nameid[i].kind.lpwstr.Name);
+ MAPIFreeBuffer(nameid);
+ MAPIFreeBuffer(nameid2);
+ ret = false;
+ goto cleanup;
+ }
+ break;
+ }
+
+ MAPIFreeBuffer(nameid2);
+ }
+
+ MAPIFreeBuffer(nameid);
+ MAPIFreeBuffer(propIDs);
+
+ cleanup:
+ /* Clean up */
+ DeleteFolder(&obj_top_folder, mapi_object_get_id(&obj_ref_folder),
+ DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval(mt, "DeleteFolder");
+
+ /* Release */
+ mapi_object_release(&obj_ref_message);
+ mapi_object_release(&obj_ref_folder);
+ mapi_object_release(&obj_top_folder);
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
+
+
+/**
+ \details Test the DeletePropertiesNoReplicate (0x7a) operation
+
+ This function:
+ -# Opens the mailbox
+ -# Create a test folder
+ -# Creates a reference email, and sets some properties on it
+ -# Delete properties from this message
+ -# Checks that properties got deleted
+ -# Deletes both email and the test folder
+
+ \todo It would be useful to test the problem return values
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcprpt_DeletePropertiesNoReplicate(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_top_folder;
+ mapi_id_t id_top_folder;
+ mapi_object_t obj_ref_folder;
+ mapi_object_t obj_ref_message;
+ const char *name = NULL;
+ const char *subject = NULL;
+ struct SPropValue lpProp[3];
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProps;
+ uint32_t cValues;
+
+ /* Step 1. Logon Private Mailbox */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval_step_fmt(mt, "1.", "OpenMsgStore", "(%s)", "Logon Private Mailbox");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ mapi_object_init(&obj_top_folder);
+ retval = GetDefaultFolder(&obj_store, &id_top_folder, olFolderTopInformationStore);
+ retval = OpenFolder(&obj_store, id_top_folder, &obj_top_folder);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2: Create reference folder */
+ mapi_object_init(&obj_ref_folder);
+ retval = CreateFolder(&obj_top_folder, FOLDER_GENERIC, MT_DIRNAME_TOP, NULL,
+ OPEN_IF_EXISTS, &obj_ref_folder);
+ mapitest_print_retval_step_fmt(mt, "2.", "CreateFolder", "(%s)", "Create the test folder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3: Create reference message */
+ mapi_object_init(&obj_ref_message);
+ retval = mapitest_common_message_create(mt, &obj_ref_folder, &obj_ref_message, MT_MAIL_SUBJECT);
+ mapitest_print_retval_step_fmt(mt, "3.1.", "mapitest_common_message_create", "(%s)", "Create a reference email");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ retval = SaveChangesMessage(&obj_ref_folder, &obj_ref_message, KeepOpenReadWrite);
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ name = talloc_asprintf(mt->mem_ctx, "Reference: %s", "display name");
+ subject = talloc_asprintf(mt->mem_ctx, "Reference: %s", "subject");
+ set_SPropValue_proptag(&lpProp[0], PR_DISPLAY_NAME, (const void *)name);
+ set_SPropValue_proptag(&lpProp[1], PR_CONVERSATION_TOPIC, (const void *)subject);
+ retval = SetProps(&obj_ref_message, lpProp, 2);
+ mapitest_print_retval_step_fmt(mt, "3.2.", "SetProps", "(%s)", "Set email properties");
+ if (retval != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4: Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (lpProps[0].value.lpszA) {
+ if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
+ mapitest_print(mt, "* Step 4.1. - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[0].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 4.1. - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[0].value.lpszA);
+ }
+ }
+ if (lpProps[1].value.lpszA) {
+ if (!strncmp(subject, lpProps[1].value.lpszA, strlen(lpProps[1].value.lpszA))) {
+ mapitest_print(mt, "* Step 4.2. - Check: Reference props set - [SUCCESS] (%s)\n",
+ lpProps[1].value.lpszA);
+ } else {
+ mapitest_print(mt, "* Step 4.2. - Check: Reference props set [FAILURE] (%s)\n",
+ lpProps[1].value.lpszA);
+ }
+ }
+
+ /* Step 5. Delete Properties */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_CONVERSATION_TOPIC);
+ retval = DeletePropertiesNoReplicate(&obj_ref_message, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ mapitest_print_retval_step_fmt(mt, "5.", "DeletePropertiesNoReplicate", "PR_CONVERSATION_TOPIC");
+
+ /* Step 6. Double check with GetProps */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_CONVERSATION_TOPIC);
+ retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (get_SPropValue(lpProps, PR_CONVERSATION_TOPIC) == NULL) {
+ mapitest_print(mt, "* Step 5.1. - GetProps verifier [SUCCESS]\n");
+ } else {
+ mapitest_print(mt, "* Step 5.1. - GetProps verifier [FAILURE]:\n");
+ }
+
+ /* Step 7: cleanup folders */
+ retval = DeleteFolder(&obj_top_folder, mapi_object_get_id(&obj_ref_folder),
+ DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval_step(mt, "6.", "DeleteFolder");
+
+ /* Release */
+ mapi_object_release(&obj_ref_message);
+ mapi_object_release(&obj_ref_folder);
+ mapi_object_release(&obj_top_folder);
+ mapi_object_release(&obj_store);
+
+
+ return true;
+}
Added: trunk/openchange/utils/mapitest/modules/module_oxcstor.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxcstor.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_oxcstor.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,501 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - STORE OBJECT PROTOCOL operations
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_oxcstor.c
+
+ \brief Store Object Protocol test suite
+*/
+
+
+/**
+ \details Test the Logon (0xFE) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Log on the public folder store
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcstor_Logon(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+
+ /* Step 1. Logon Private Mailbox */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ mapi_object_release(&obj_store);
+
+ /* Step 2. Logon Public Folder store */
+ mapi_object_init(&obj_store);
+ retval = OpenPublicFolder(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenPublicFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the GetReceiveFolder (0x27) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Call the GetReceiveFolder operation
+
+ \param mt the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcstor_GetReceiveFolder(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_id_t id_inbox;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Call the GetReceiveFolder operation */
+ retval = GetReceiveFolder(&obj_store, &id_inbox, "IPF.Post");
+ mapitest_print_retval(mt, "GetReceiveFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the SetReceiveFolder (0x26) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Call the SetReceiveFolder operation
+
+ \param mt the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcstor_SetReceiveFolder(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_id_t id_inbox;
+ mapi_id_t id_tis;
+ mapi_object_t obj_tis;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_folder;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval_step(mt, "1.", "Logon");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Get the original ReceiveFolder */
+ retval = GetReceiveFolder(&obj_store, &id_inbox, NULL);
+ mapitest_print_retval_step(mt, "2.", "GetReceiveFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Open the ReceiveFolder */
+ mapi_object_init(&obj_inbox);
+ retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
+ mapitest_print_retval_step(mt, "3.", "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 4. Open the Top Information Store folder */
+ retval = GetDefaultFolder(&obj_store, &id_tis, olFolderTopInformationStore);
+ mapitest_print_retval_step(mt, "4.", "GetDefaultFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_tis);
+ retval = OpenFolder(&obj_store, id_tis, &obj_tis);
+ mapitest_print_retval_step(mt, "4.1.", "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Create the New Inbox folder under Top Information Store */
+ mapi_object_init(&obj_folder);
+ retval = CreateFolder(&obj_tis, FOLDER_GENERIC, "New Inbox", NULL,
+ OPEN_IF_EXISTS, &obj_folder);
+ mapitest_print_retval_step(mt, "5.", "CreateFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Set IPM.Note receive folder to New Inbox */
+ retval = SetReceiveFolder(&obj_store, &obj_folder, "IPM.Note");
+ mapitest_print_retval_step_fmt(mt, "6.", "SetReceiveFolder", "%s", "(New Inbox)");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Reset receive folder to Inbox */
+ retval = SetReceiveFolder(&obj_store, &obj_inbox, "IPM.Note");
+ mapitest_print_retval_step(mt, "6.1.", "SetReceiveFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ /* Delete New Inbox folder */
+ retval = EmptyFolder(&obj_folder);
+ mapitest_print_retval_step(mt, "7.", "EmptyFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ retval = DeleteFolder(&obj_tis, mapi_object_get_id(&obj_folder),
+ DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE, NULL);
+ mapitest_print_retval_step(mt, "8.", "DeleteFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_tis);
+ mapi_object_release(&obj_inbox);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the GetOwningServers (0x42) operation
+
+ This function:
+ -# Log on the public folders store
+ -# Open a public folder
+ -# Call the GetOwningServers operation
+
+ \param mt the top-level mapitest structure
+
+ \return true on success, otherwise false
+*/
+_PUBLIC_ bool mapitest_oxcstor_GetOwningServers(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ uint64_t folderId;
+ uint16_t OwningServersCount;
+ uint16_t CheapServersCount;
+ char *OwningServers;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenPublicFolder(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenPublicFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open IPM Subtree folder */
+ retval = GetDefaultPublicFolder(&obj_store, &folderId, olFolderPublicIPMSubtree);
+ mapitest_print_retval(mt, "GetDefaultPublicFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, folderId, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 3. Call GetOwningServers */
+ retval = GetOwningServers(&obj_store, &obj_folder, &OwningServersCount, &CheapServersCount, &OwningServers);
+ mapitest_print_retval(mt, "GetOwningServers");
+ if (GetLastError() != MAPI_E_SUCCESS && GetLastError() != ecNoReplicaAvailable) {
+ ret = false;
+ } else if (GetLastError() == ecNoReplicaAvailable) {
+ mapitest_print(mt, "* %-35s: No active replica for the folder\n", "GetOwningServers");
+ } else {
+ mapitest_print(mt, "* %-35s: OwningServersCount: %d\n", "PublicFolderIsGhosted", OwningServersCount);
+ if (OwningServersCount) {
+ uint16_t i;
+
+ for (i = 0; i < OwningServersCount; i++) {
+ mapitest_print(mt, "* %-35s: OwningServers: %s\n", "GetOwningServers", &OwningServers[i]);
+ }
+ talloc_free(&OwningServers);
+ }
+ }
+
+ /* cleanup objects */
+ mapi_object_release(&obj_folder);
+
+cleanup:
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
+
+/**
+ \details Test the PublicFolderIsGhosted (0x45) operation
+
+ This function:
+ -# Log on the public folders store
+ -# Open a public folder
+ -# Call the PublicFolderIsGhosted operation
+
+ \param mt the top-level mapitest structure
+
+ \return true on success, otherwise false
+*/
+_PUBLIC_ bool mapitest_oxcstor_PublicFolderIsGhosted(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ uint64_t folderId;
+ bool IsGhosted;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenPublicFolder(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenPublicFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open IPM Subtree folder */
+ retval = GetDefaultPublicFolder(&obj_store, &folderId, olFolderPublicIPMSubtree);
+ mapitest_print_retval(mt, "GetDefaultPublicFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, folderId, &obj_folder);
+ mapitest_print_retval(mt, "OpenFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 3. Call PublicFolderIsGhosted */
+ retval = PublicFolderIsGhosted(&obj_store, &obj_folder, &IsGhosted);
+ mapitest_print_retval(mt, "PublicFolderIsGhosted");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ mapitest_print(mt, "* %-35s: IsGhosted is set to %s\n", "PublicFolderIsGhosted", ((IsGhosted) ? "true" : "false"));
+
+ /* cleanup objects */
+ mapi_object_release(&obj_folder);
+
+cleanup:
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
+
+
+/**
+ \details Test the GetReceiveFolderTable (0x68) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Call the GetReceiveFolderTable operation
+
+ \param mt the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcstor_GetReceiveFolderTable(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ struct SRowSet SRowSet;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Call the GetReceiveFolderTable operation */
+ retval = GetReceiveFolderTable(&obj_store, &SRowSet);
+ mapitest_print_retval(mt, "GetReceiveFolderTable");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapidump_SRowSet(&SRowSet, "\t\t[*]");
+ MAPIFreeBuffer(SRowSet.aRow);
+
+ /* Release */
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+/**
+ \details Test the LongTermIdFromId (0x43) and IdFromLongTermId (0x44)
+ operations
+
+ This function:
+ -# Logs into the user private mailbox
+ -# Open the Receive Folder
+ -# Looks up the long term id for the receive folder FID
+ -# Looks up the short term id for the long term id
+ -# Checks the id matches the original FID
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcstor_LongTermId(struct mapitest *mt)
+{
+ mapi_object_t obj_store;
+ mapi_id_t id_inbox;
+ struct LongTermId long_term_id;
+ mapi_id_t id_check;
+ bool ret = true;
+
+ /* Step 1. Logon Private Mailbox */
+ mapi_object_init(&obj_store);
+ OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 2. Call the GetReceiveFolder operation */
+ GetReceiveFolder(&obj_store, &id_inbox, "IPF.Post");
+ mapitest_print_retval(mt, "GetReceiveFolder");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 3. Call GetLongTermIdFromId on Folder ID */
+ GetLongTermIdFromId(&obj_store, id_inbox, &long_term_id);
+ mapitest_print_retval(mt, "GetLongTermIdFromId");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 4. Call GetIdFromLongTermId on LongTermId from previous step*/
+ GetIdFromLongTermId(&obj_store, long_term_id, &id_check);
+ mapitest_print_retval(mt, "GetIdFromLongTermId");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 5. Check whether ids are the same */
+ if ( id_check == id_inbox ) {
+ mapitest_print(mt, "* Check: IDs match - [SUCCESS]\n" );
+ } else {
+ mapitest_print(mt, "* Check: IDs do not match - [SUCCESS] (0x%x, expected 0x%x)\n",
+ id_check, id_inbox);
+ ret=false;
+ goto cleanup;
+ }
+
+ cleanup:
+ /* Release */
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
+
+
+/**
+ \details Test the GetStoreState (0x7b) operation
+
+ This function:
+ -# Logs into the user private mailbox
+ -# Retrieve the store state
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcstor_GetStoreState(struct mapitest *mt)
+{
+ mapi_object_t obj_store;
+ uint32_t StoreState = 0;
+ bool ret = true;
+
+ /* Step 1. Logon Private Mailbox */
+ mapi_object_init(&obj_store);
+ OpenMsgStore(mt->session, &obj_store);
+ mapitest_print_retval(mt, "OpenMsgStore");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Get the store state */
+ GetStoreState(&obj_store, &StoreState);
+ mapitest_print_retval(mt, "GetStoreState");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ mapi_object_release(&obj_store);
+ return ret;
+}
Added: trunk/openchange/utils/mapitest/modules/module_oxctable.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxctable.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_oxctable.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,909 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - TABLE OBJECT PROTOCOL operations
+
+ Copyright (C) Julien Kerihuel 2008
+ Copyright (C) Brad Hards 2008
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_oxctable.c
+
+ \brief Table Object Protocol test suite
+*/
+
+/**
+ \details Test the SetColumns (0x12) operation
+
+ This function:
+ -# Opens the Inbox folder and gets the hierarchy table
+ -# Calls the SetColumns operation
+ -# Cleans up
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxctable_SetColumns(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_htable;
+ struct SPropTagArray *SPropTagArray;
+
+ /* Step 1. Logon */
+ if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
+ return false;
+ }
+
+ /* Step 2. SetColumns */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3,
+ PR_DISPLAY_NAME,
+ PR_FID,
+ PR_FOLDER_CHILD_COUNT);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ mapitest_print_retval(mt, "SetColumns");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Release */
+ mapi_object_release(&obj_htable);
+ mapitest_common_cleanup(mt);
+
+ return true;
+}
+
+
+/**
+ \details Test the QueryColumns (0x37) operation
+
+ This function:
+ -# Opens the Inbox folder and gets the hierarchy table
+ -# Calls the QueryColumn operation
+ -# Calls SetColumns on the test folder
+ -# Checks that QueryColumns on the test folder is correct
+ -# Cleans up
+
+ \param mt pointer to the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxctable_QueryColumns(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_htable;
+ mapi_object_t obj_test_folder;
+ struct SPropTagArray columns;
+ struct SPropTagArray *SPropTagArray;
+ struct mt_common_tf_ctx *context;
+ uint32_t count;
+
+ /* Step 1. Logon */
+ if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
+ return false;
+ }
+
+ /* Step 2. QueryColumns */
+ retval = QueryColumns(&obj_htable, &columns);
+ mapitest_print_retval(mt, "QueryColumns");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Get the test folder */
+ context = mt->priv;
+ mapi_object_init(&(obj_test_folder));
+ GetContentsTable(&(context->obj_test_folder), &(obj_test_folder), 0, &count);
+ mapitest_print_retval(mt, "GetContentsTable");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ if (count != 10) {
+ mapitest_print(mt, "* %-35s: unexpected count (%i)\n", "GetContentsTable", count);
+ /* This isn't a hard error for this test though, because it might be from a
+ previous test failure. Clean up and try again */
+ }
+
+
+ /* Step 4. SetColumns */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3,
+ PR_DISPLAY_NAME,
+ PR_FID,
+ PR_FOLDER_CHILD_COUNT);
+ retval = SetColumns(&(obj_test_folder), SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "SetColumns");
+ return false;
+ }
+
+ /* Step 5. QueryColumns on a contents folder */
+ retval = QueryColumns(&(obj_test_folder), &columns);
+ mapitest_print_retval(mt, "QueryColumns");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ /* TODO: check the return count against something */
+ mapitest_print(mt, "column count: %i\n", columns.cValues);
+
+ /* Step 6. Release */
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&(obj_test_folder));
+ mapitest_common_cleanup(mt);
+
+ return true;
+}
+
+/**
+ \details Test the Restrict (0x14) operation
+
+ This function:
+ -# Opens the Inbox folder and creates some test content
+ -# Checks that the content is OK
+ -# Applies a filter
+ -# Checks the results are as expected.
+ -# Resets the table
+ -# Checks the results are as expected.
+ -# Cleans up
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxctable_Restrict(struct mapitest *mt)
+{
+ mapi_object_t obj_htable;
+ mapi_object_t obj_test_folder;
+ struct mt_common_tf_ctx *context;
+ uint32_t count = 0;
+ uint32_t origcount = 0;
+ uint32_t Numerator = 0;
+ uint32_t Denominator = 0;
+ struct mapi_SRestriction res;
+ bool ret = true;
+
+ /* Step 1. Logon */
+ if (! mapitest_common_setup(mt, &obj_htable, &count)) {
+ return false;
+ }
+
+ /* Step 2. Get the test folder */
+ context = mt->priv;
+ mapi_object_init(&(obj_test_folder));
+ GetContentsTable(&(context->obj_test_folder), &(obj_test_folder), 0, &origcount);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "GetContentsTable");
+ ret = false;
+ goto cleanup;
+ }
+ if (origcount != 10) {
+ mapitest_print(mt, "* %-35s: unexpected count (%i)\n", "GetContentsTable", count);
+ /* This isn't a hard error for this test though, because it might be from a
+ previous test failure. Clean up and try again */
+ }
+
+ /* Apply a filter */
+ res.rt = RES_PROPERTY;
+ res.res.resProperty.relop = RES_PROPERTY;
+ res.res.resProperty.ulPropTag = PR_SUBJECT;
+ res.res.resProperty.lpProp.ulPropTag = PR_SUBJECT;
+ res.res.resProperty.lpProp.value.lpszA = MT_MAIL_SUBJECT;
+
+ Restrict(&(obj_test_folder), &res, NULL);
+ mapitest_print_retval(mt, "Restrict");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Checks the results are as expected */
+ context = mt->priv;
+ QueryPosition(&(obj_test_folder), &Numerator, &Denominator);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "QueryPosition");
+ ret = false;
+ goto cleanup;
+ }
+ if (Denominator != origcount/2) {
+ mapitest_print(mt, "* %-35s: unexpected filtered count (%i)\n", "QueryPosition", Denominator);
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Resets the table */
+ Reset(&(obj_test_folder));
+ mapitest_print_retval(mt, "Reset");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Checks the results are as expected */
+ context = mt->priv;
+ QueryPosition(&(obj_test_folder), &Numerator, &Denominator);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "QueryPosition");
+ ret = false;
+ goto cleanup;
+ }
+ if (Denominator != origcount) {
+ mapitest_print(mt, "* %-35s: unexpected reset count (%i)\n", "QueryPosition", Denominator);
+ ret = false;
+ goto cleanup;
+ }
+
+ cleanup:
+ /* Release */
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&(obj_test_folder));
+ mapitest_common_cleanup(mt);
+
+ return ret;
+}
+
+/**
+ \details Test the QueryRows (0x15) operation
+
+ This function:
+ -# Opens the Inbox folder and gets the hierarchy table
+ -# Set the required columns
+ -# Calls QueryRows until the end of the table
+ -# Open the test folder, and get its contents
+ -# Calls QueryRows until the end of the test folder
+ -# Checks the results are as expected.
+ -# Cleans up
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxctable_QueryRows(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_htable;
+ mapi_object_t obj_test_folder;
+ struct SRowSet SRowSet;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue lpProp;
+ struct mt_common_tf_ctx *context;
+ uint32_t idx = 0;
+ uint32_t count = 0;
+ const char* data;
+ int i;
+
+ /* Step 1. Logon */
+ if (! mapitest_common_setup(mt, &obj_htable, &count)) {
+ return false;
+ }
+
+ /* Step 2. Set Table Columns */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3,
+ PR_DISPLAY_NAME,
+ PR_FID,
+ PR_FOLDER_CHILD_COUNT);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "SetColumns");
+ return false;
+ }
+
+ /* Step 3. QueryRows */
+ do {
+ retval = QueryRows(&obj_htable, 0x2, TBL_ADVANCE, &SRowSet);
+ if (SRowSet.cRows > 0) {
+ idx += SRowSet.cRows;
+ if (retval == MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: %.2d/%.2d [PASSED]\n",
+ "QueryRows", idx, count);
+ } else {
+ mapitest_print(mt, "* %-35s: %.2d/%.2d [FAILED]\n",
+ "QueryRows", idx, count);
+ }
+ }
+ } while (retval == MAPI_E_SUCCESS && SRowSet.cRows > 0);
+
+
+ /* Step 4. Get the test folder */
+ context = mt->priv;
+ mapi_object_init(&(obj_test_folder));
+ GetContentsTable(&(context->obj_test_folder), &(obj_test_folder), 0, &count);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "GetContentsTable");
+ return false;
+ }
+ if (count != 10) {
+ mapitest_print(mt, "* %-35s: unexpected count (%i)\n", "GetContentsTable", count);
+ /* This isn't a hard error for this test though, because it might be from a
+ previous test failure. Clean up and try again */
+ }
+
+ /* Step 5. Set Table Columns on the test folder */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_BODY, PR_BODY_HTML);
+ retval = SetColumns(&obj_test_folder, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "SetColumns");
+ return false;
+ }
+
+ /* Step 6. QueryRows on test folder contents */
+ idx = 0;
+ do {
+ retval = QueryRows(&(obj_test_folder), 0x2, TBL_ADVANCE, &SRowSet);
+ if (SRowSet.cRows > 0) {
+ idx += SRowSet.cRows;
+ if (retval == MAPI_E_SUCCESS) {
+ mapitest_print(mt, "* %-35s: %.2d/%.2d [PASSED]\n",
+ "QueryRows", idx, count);
+ for (i = 0; i < SRowSet.cRows; ++i) {
+ lpProp = SRowSet.aRow[i].lpProps[0];
+ if (lpProp.ulPropTag != PR_BODY) {
+ mapitest_print(mt, "* %-35s: Bad proptag0 (0x%x)\n",
+ "QueryRows", lpProp.ulPropTag);
+ return false;
+ }
+ data = get_SPropValue_data(&lpProp);
+ if (0 != strncmp(data, "Body of message", 15)) {
+ mapitest_print(mt, "* %-35s: Bad propval0 (%s)\n",
+ "QueryRows", data);
+ return false;
+ }
+ lpProp = SRowSet.aRow[i].lpProps[1];
+ if (lpProp.ulPropTag != PR_BODY_HTML) {
+ mapitest_print(mt, "* %-35s: Bad proptag1 (0x%x)\n",
+ "QueryRows", lpProp.ulPropTag);
+ return false;
+ }
+ data = get_SPropValue_data(&lpProp);
+ if (0 != strncmp(data, "<!DOCTYPE HTML PUBLIC", 21)) {
+ mapitest_print(mt, "* %-35s: Bad propval1 (%s)\n",
+ "QueryRows", data);
+ return false;
+ }
+ }
+ } else {
+ mapitest_print(mt, "* %-35s: %.2d/%.2d [FAILED]\n",
+ "QueryRows", idx, count);
+ }
+ }
+ } while (retval == MAPI_E_SUCCESS && SRowSet.cRows > 0);
+
+ /* Release */
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&(obj_test_folder));
+ mapitest_common_cleanup(mt);
+
+ return true;
+}
+
+/**
+ \details Test the GetStatus (0x16) operation
+
+ This function:
+ -# Opens the Inbox folder and gets the hierarchy table
+ -# Call GetStatus
+ -# Cleans up
+ */
+_PUBLIC_ bool mapitest_oxctable_GetStatus(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_htable;
+ uint8_t TableStatus;
+
+ /* Step 1. Logon */
+ if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
+ return false;
+ }
+
+ /* Step 2. GetStatus */
+ retval = GetStatus(&obj_htable, &TableStatus);
+ mapitest_print_retval(mt, "GetStatus");
+ mapitest_print(mt, "* %-35s: TableStatus: %d\n", "GetStatus", TableStatus);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 3. Release */
+ mapi_object_release(&obj_htable);
+ mapitest_common_cleanup(mt);
+
+ return ret;
+}
+
+
+/**
+ \details Test the SeekRow (0x18) operation
+
+ This function:
+ -# Opens the Inbox folder and gets the hierarchy table
+ -# SeekRow with BOOKMARK_BEGINNING
+ -# SeekRow with BOOKMARK_END
+ -# SeekRow with BOOKMARK_CURRENT
+ -# Cleans up
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxctable_SeekRow(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_htable;
+ uint32_t count;
+
+ /* Step 1. Logon */
+ if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
+ return false;
+ }
+
+ /* Step 2. SeekRow */
+ retval = SeekRow(&obj_htable, BOOKMARK_BEGINNING, 0, &count);
+ mapitest_print_retval_fmt(mt, "SeekRow", "(BOOKMARK_BEGINNING)");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ retval = SeekRow(&obj_htable, BOOKMARK_END, 0, &count);
+ mapitest_print_retval_fmt(mt, "SeekRow", "(BOOKMARK_END)");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ retval = SeekRow(&obj_htable, BOOKMARK_CURRENT, 0, &count);
+ mapitest_print_retval_fmt(mt, "SeekRow", "(BOOKMARK_CURRENT)");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_htable);
+ mapitest_common_cleanup(mt);
+
+ return true;
+}
+
+
+/**
+ \details Test the SeekRowApprox (0x1a) operation
+
+ This function:
+ -# Opens the Inbox folder and gets the hierarchy table
+ -# SeekRowApprox with 0/1, 1/1 and 1/2 fractional values
+ -# Cleans up
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxctable_SeekRowApprox(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_htable;
+
+ /* Step 1. Logon */
+ if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
+ return false;
+ }
+
+ /* Step 2. SeekRowApprox */
+ retval = SeekRowApprox(&obj_htable, 0, 1);
+ mapitest_print_retval_fmt(mt, "SeekRowApprox", "0/1");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ retval = SeekRowApprox(&obj_htable, 1, 1);
+ mapitest_print_retval_fmt(mt, "SeekRowApprox", "1/1");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ retval = SeekRowApprox(&obj_htable, 1, 2);
+ mapitest_print_retval_fmt(mt, "SeekRowApprox", "1/2");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Release */
+ mapi_object_release(&obj_htable);
+ mapitest_common_cleanup(mt);
+
+ return true;
+}
+
+
+
+/**
+ \details Test the CreateBookmark (0x1b) operation
+
+ This function:
+ -# Opens the Inbox folder and gets the hierarchy table
+ -# Customize the MAPI table view
+ -# CreateBookmark for each table's row
+ -# Free Bookmark for each created bookmark
+ -# Cleans up
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxctable_CreateBookmark(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_htable;
+ uint32_t *bkPosition;
+ uint32_t count;
+ uint32_t i;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+
+
+ /* Step 1. Logon */
+ if (! mapitest_common_setup(mt, &obj_htable, &count)) {
+ return false;
+ }
+
+ /* Step 2. Customize the table view */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3,
+ PR_DISPLAY_NAME,
+ PR_FID,
+ PR_FOLDER_CHILD_COUNT);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create Bookmarks */
+ bkPosition = talloc_array(mt->mem_ctx, uint32_t, 1);
+ while (((retval = QueryRows(&obj_htable, count, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND) &&
+ SRowSet.cRows) {
+ count -= SRowSet.cRows;
+ for (i = 0; i < SRowSet.cRows; i++) {
+ bkPosition = talloc_realloc(mt->mem_ctx, bkPosition, uint32_t, i + 2);
+ retval = CreateBookmark(&obj_htable, &(bkPosition[i]));
+ mapitest_print_retval_fmt(mt, "CreateBookmark", "(%.2d)", i);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ }
+ }
+
+ retval = mapi_object_bookmark_get_count(&obj_htable, &count);
+
+ /* Step 4. Free Bookmarks */
+ for (i = 0; i < count; i++) {
+ retval = FreeBookmark(&obj_htable, bkPosition[i]);
+ mapitest_print_retval_fmt(mt, "FreeBookmark", "(%.2d)", i);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ }
+
+ /* Step 5. Release */
+ mapi_object_release(&obj_htable);
+ mapitest_common_cleanup(mt);
+ talloc_free(bkPosition);
+
+ return true;
+}
+
+
+
+/**
+ \details Test the SeekRowBookmark (0x19) operation
+
+ This function:
+ -# Open the Inbox folder and retrieve the hierarchy table
+ -# Customize the MAPI table view
+ -# SeekBookmark for each table's row
+ -# Free Bookmark for each created bookmark
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxctable_SeekRowBookmark(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_htable;
+ uint32_t *bkPosition;
+ uint32_t count;
+ uint32_t row;
+ uint32_t i;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+
+ /* Step 1. Logon */
+ if (! mapitest_common_setup(mt, &obj_htable, &count)) {
+ return false;
+ }
+
+ /* Step 2. Customize the table view */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3,
+ PR_DISPLAY_NAME,
+ PR_FID,
+ PR_FOLDER_CHILD_COUNT);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create Bookmarks */
+ bkPosition = talloc_array(mt->mem_ctx, uint32_t, 1);
+ while (((retval = QueryRows(&obj_htable, count, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND) &&
+ SRowSet.cRows) {
+ count -= SRowSet.cRows;
+ for (i = 0; i < SRowSet.cRows; i++) {
+ bkPosition = talloc_realloc(mt->mem_ctx, bkPosition, uint32_t, i + 2);
+ retval = CreateBookmark(&obj_htable, &(bkPosition[i]));
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ }
+ }
+ mapitest_print_retval(mt, "CreateBookmark");
+
+ retval = mapi_object_bookmark_get_count(&obj_htable, &count);
+
+ /* Step 4. SeekRowBookmark */
+ for (i = 0; i < count; i++) {
+ retval = SeekRowBookmark(&obj_htable, bkPosition[i], 0, &row);
+ mapitest_print_retval_fmt(mt, "SeekRowBookmark", "(%.2d)", i);
+ }
+
+
+ /* Step 5. Free Bookmarks */
+ for (i = 0; i < count; i++) {
+ retval = FreeBookmark(&obj_htable, bkPosition[i]);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+ }
+ mapitest_print_retval(mt, "FreeBookmark");
+
+ /* Step 6. Release */
+ mapi_object_release(&obj_htable);
+ mapitest_common_cleanup(mt);
+
+ talloc_free(bkPosition);
+
+ return true;
+}
+
+/**
+ \details Test the SortTable (0x13), ExpandRow (0x59), CollapseRow(0x5a),
+ GetCollapseState(0x6b) and SetCollapseState (0x6c) operations
+
+ This function:
+ -# Opens the Inbox folder and creates some test content
+ -# Checks that the content is OK
+ -# Applies a sort and categorisation
+ -# Checks the results are as expected.
+ -# Save away the Row ID and Insatnce Number for the first header
+ -# Collapse the first category
+ -# Checks the results are as expected.
+ -# Save the "collapse state"
+ -# Expand the first category again
+ -# Checks the results are as expected
+ -# Restore the saved "collapse state"
+ -# Checks the results are as expected
+ -# Cleans up
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxctable_Category(struct mapitest *mt)
+{
+ mapi_object_t obj_htable;
+ mapi_object_t obj_test_folder;
+ struct mt_common_tf_ctx *context;
+ uint32_t count = 0;
+ uint32_t origcount = 0;
+ bool ret = true;
+ struct SSortOrderSet criteria;
+ uint64_t inst_id = 0;
+ uint64_t inst_num = 0;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ uint32_t rowcount = 0;
+ uint32_t Numerator = 0;
+ uint32_t Denominator = 0;
+ struct SBinary_short collapseState;
+ uint32_t bookmark;
+
+
+ /* Step 1. Logon */
+ if (! mapitest_common_setup(mt, &obj_htable, &count)) {
+ return false;
+ }
+
+ /* Step 2. Get the test folder */
+ context = mt->priv;
+ mapi_object_init(&(obj_test_folder));
+ GetContentsTable(&(context->obj_test_folder), &(obj_test_folder), 0, &origcount);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval(mt, "GetContentsTable");
+ ret = false;
+ goto cleanup;
+ }
+ if (origcount != 10) {
+ mapitest_print(mt, "* %-35s: unexpected count (%i)\n", "GetContentsTable", count);
+ /* This isn't a hard error for this test though, because it might be from a
+ previous test failure. Clean up and try again */
+ }
+
+ /* We need the header row InstanceId to fold/unfold the headers */
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x6,
+ PR_SENDER_NAME,
+ PR_BODY,
+ PR_LAST_MODIFICATION_TIME,
+ PR_SUBJECT,
+ PR_INST_ID,
+ PR_INSTANCE_NUM);
+ SetColumns(&(obj_test_folder), SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ mapitest_print_retval(mt, "SetColumns");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Apply a categorised sort */
+ memset(&criteria, 0x0, sizeof (struct SSortOrderSet));
+ criteria.cSorts = 1;
+ criteria.cCategories = 1;
+ criteria.cExpanded = 1;
+ criteria.aSort = talloc_array(mt->mem_ctx, struct SSortOrder, criteria.cSorts);
+ criteria.aSort[0].ulPropTag = PR_SENDER_NAME;
+ criteria.aSort[0].ulOrder = TABLE_SORT_ASCEND;
+ SortTable(&(obj_test_folder), &criteria);
+ mapitest_print_retval(mt, "SortTable");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ rowcount = 2 * origcount;
+ QueryRows(&(obj_test_folder), rowcount, TBL_ADVANCE, &SRowSet);
+ mapitest_print_retval(mt, "QueryRows");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Checks the results are as expected */
+ QueryPosition(&(obj_test_folder), &Numerator, &Denominator);
+ mapitest_print_retval(mt, "QueryPosition");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ /* the categories are expanded, and there are six unique senders, so there are six
+ extra rows - one for each header row */
+ if (Denominator != origcount + 6) {
+ mapitest_print(mt, "* %-35s: unexpected count (%i)\n", "QueryPosition", Numerator);
+ ret = false;
+ goto cleanup;
+ }
+
+ /* save away ID/instance values for first row header */
+ inst_id = (*(const uint64_t *)get_SPropValue_data(&(SRowSet.aRow[0].lpProps[4])));
+ inst_num = (*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[0].lpProps[5])));
+
+ /* Collapse a row header */
+ CollapseRow(&(obj_test_folder), inst_id, &rowcount);
+ mapitest_print_retval(mt, "CollapseRow");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Checks the results are as expected */
+ QueryPosition(&(obj_test_folder), &Numerator, &Denominator);
+ mapitest_print_retval(mt, "QueryPosition");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ /* there are still six unique headers, but half of the real entries are under the first
+ header (usually 10, unless we have some other rubbish hanging around), and when we
+ collapse the first header row, that half disappear */
+ if (Denominator != origcount/2 + 6) {
+ mapitest_print(mt, "* %-35s: unexpected count (%i)\n", "QueryPosition", Denominator);
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Save the table collapse state */
+ GetCollapseState(&(obj_test_folder), inst_id, inst_num, &collapseState);
+ mapitest_print_retval(mt, "GetCollapseState");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+
+ /* Expand a category */
+ ExpandRow(&(obj_test_folder), inst_id, 20, &SRowSet, &rowcount);
+ mapitest_print_retval(mt, "ExpandRow");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Checks the results are as expected */
+ QueryPosition(&(obj_test_folder), &Numerator, &Denominator);
+ mapitest_print_retval(mt, "QueryPosition");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ /* we've expanded the first header row, so we now get all the entries plus the 6 headers */
+ if (Denominator != origcount + 6) {
+ mapitest_print(mt, "* %-35s: unexpected count (%i)\n", "QueryPosition", Denominator);
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Restore the collapse state */
+ SetCollapseState(&(obj_test_folder), &collapseState, &bookmark);
+ mapitest_print_retval(mt, "SetCollapseState");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Checks the results are as expected */
+ QueryPosition(&(obj_test_folder), &Numerator, &Denominator);
+ mapitest_print_retval(mt, "QueryPosition");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+ /* back to the situation with the first heading collapsed */
+ if (Denominator != origcount/2 + 6) {
+ mapitest_print(mt, "* %-35s: unexpected count (%i)\n", "QueryPosition", Denominator);
+ ret = false;
+ goto cleanup;
+ }
+
+ cleanup:
+ if (bookmark) {
+ FreeBookmark(&(obj_test_folder), bookmark);
+ mapitest_print_retval(mt, "FreeBookmark");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+ }
+
+ /* Release */
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&(obj_test_folder));
+ mapitest_common_cleanup(mt);
+
+ return ret;
+}
Added: trunk/openchange/utils/mapitest/modules/module_oxomsg.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxomsg.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_oxomsg.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,507 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - E-MAIL OBJECT PROTOCOL operations
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_oxomsg.c
+
+ \brief E-Mail Object Protocol test suite
+*/
+
+
+/**
+ \details Test the AddressTypes (0x49) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Call the AddressTypes operation
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxomsg_AddressTypes(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ uint16_t cValues;
+ struct mapi_LPSTR *transport = NULL;
+ uint32_t i;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step2. AddressTypes operation */
+ retval = AddressTypes(&obj_store, &cValues, &transport);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ for (i = 0; i < cValues; i++) {
+ mapitest_print(mt, "* Recipient Type: %s\n", transport[i].lppszA);
+ }
+
+ /* Release */
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the SubmitMessage (0x32) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the Outbox folder
+ -# Create a sample message
+ -# Submit the message
+ -# Delete the message
+ -# Clean up folders
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxomsg_SubmitMessage(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_id_t id_folder;
+ mapi_id_t id_msgs[1];
+ bool ret;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open Outbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderOutbox);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Create the sample message */
+ mapi_object_init(&obj_message);
+ ret = mapitest_common_message_create(mt, &obj_folder, &obj_message, MT_MAIL_SUBJECT);
+ if (ret == false) {
+ return ret;
+ }
+
+ /* Step 4. Submit Message */
+ retval = SubmitMessage(&obj_message);
+ mapitest_print_retval(mt, "SubmitMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 5. Delete Message */
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 6. Clean up anything else */
+ mapitest_common_message_delete_by_subject(mt, &obj_folder, MT_MAIL_SUBJECT);
+ GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+ OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_common_message_delete_by_subject(mt, &obj_folder, MT_MAIL_SUBJECT);
+
+ /* Release */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the AbortSubmit (0x34) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the Outbox folder
+ -# Create a sample message
+ -# Submit the message
+ -# Abort the submit operation
+ -# Delete the message
+ -# Clean up folders
+
+ Note: This operation may fail since it depends on how busy the
+ server is when we submit the message. It is possible the message
+ gets already processed before we have time to abort the message.
+
+ From preliminary tests, AbortSubmit returns MAPI_E_SUCCESS when we
+ call SubmitMessage with SubmitFlags set to 0x2.
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxomsg_AbortSubmit(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_id_t id_folder;
+ mapi_id_t id_msgs[1];
+ bool ret = true;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 2. Open Outbox folder */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderOutbox);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 3. Create the sample message */
+ mapi_object_init(&obj_message);
+ ret = mapitest_common_message_create(mt, &obj_folder, &obj_message, MT_MAIL_SUBJECT);
+ if (ret == false) {
+ goto cleanup;
+ }
+
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadWrite);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 4. Submit Message */
+ retval = SubmitMessage(&obj_message);
+ retval = AbortSubmit(&obj_store, &obj_folder, &obj_message);
+ mapitest_print_retval(mt, "AbortSubmit");
+ if ((GetLastError() != MAPI_E_SUCCESS) &&
+ (GetLastError() != MAPI_E_UNABLE_TO_ABORT) &&
+ (GetLastError() != MAPI_E_NOT_IN_QUEUE)) {
+ ret = false;
+ }
+
+ /* Step 5. Delete Message */
+cleanup:
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+ if ((retval != MAPI_E_SUCCESS) && (GetLastError() != ecNoDelSubmitMsg)) {
+ ret = false;
+ }
+ /* Step 6. Clean up anything else */
+ mapitest_common_message_delete_by_subject(mt, &obj_folder, MT_MAIL_SUBJECT);
+ GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+ OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_common_message_delete_by_subject(mt, &obj_folder, MT_MAIL_SUBJECT);
+
+ /* Release */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
+
+
+/**
+ \details Test the SetSpooler (0x47) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Informs the server it will acts as an email spooler
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxomsg_SetSpooler(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. SetSpooler */
+ retval = SetSpooler(&obj_store);
+ mapitest_print_retval(mt, "SetSpooler");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Release */
+ mapi_object_release(&obj_store);
+
+ return true;
+}
+
+
+/**
+ \details Test the SpoolerLockMessage (0x48) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Informs the server it will acts as an email spooler
+ -# Create a message in the outbox folder
+ -# Save message changes and Submit the message
+ -# Lock the message
+ -# Unlock-Finish the message
+ -# Deletes the message
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxomsg_SpoolerLockMessage(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_id_t id_msgs[1];
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. SetSpooler */
+ retval = SetSpooler(&obj_store);
+ mapitest_print_retval(mt, "SetSpooler");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 3. Open the outbox folder */
+ mapi_object_init(&obj_folder);
+ ret = mapitest_common_folder_open(mt, &obj_store, &obj_folder, olFolderOutbox);
+ if (ret == false) return ret;
+
+ /* Step 4. Create the message */
+ mapi_object_init(&obj_message);
+ ret = mapitest_common_message_create(mt, &obj_folder, &obj_message, MT_MAIL_SUBJECT);
+ mapitest_print(mt, "* %-35s: %s\n", "mapitest_common_message_create",
+ ret == true ? "TRUE" : "FALSE");
+ if (ret == false) return ret;
+
+ /* Step 5. Save changes on message */
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadWrite);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 6. Submit the message */
+ retval = SubmitMessage(&obj_message);
+ mapitest_print_retval(mt, "SubmitMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 7. Lock the message */
+ retval = SpoolerLockMessage(&obj_store, &obj_message, LockState_1stLock);
+ mapitest_print_retval_fmt(mt, "SpoolerLockMessage", "1stLock");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 8. finish locking the message */
+ retval = SpoolerLockMessage(&obj_store, &obj_message, LockState_1stFinished);
+ mapitest_print_retval_fmt(mt, "SpoolerLockMessage", "1stFinished");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 9. Delete Message */
+ id_msgs[0] = mapi_object_get_id(&obj_message);
+ retval = DeleteMessage(&obj_folder, id_msgs, 1);
+ mapitest_print_retval(mt, "DeleteMessage");
+
+ /* Release */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
+
+
+/**
+ \details Test the TransportSend (0x4a) operation
+
+ This function:
+ -# Logs on to the user private mailbox
+ -# Opens the outbox folder
+ -# Create the test message
+ -# Save changes to the message
+ -# Perform the TransportSend operation
+ -# Dump the properties
+ -# Clean up folders
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxomsg_TransportSend(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ struct mapi_SPropValue_array lpProps;
+ mapi_id_t id_folder;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ /* Step 2. Open the outbox folder */
+ mapi_object_init(&obj_folder);
+ ret = mapitest_common_folder_open(mt, &obj_store, &obj_folder, olFolderOutbox);
+ if (ret == false) return ret;
+
+ /* Step 3. Create the message */
+ mapi_object_init(&obj_message);
+ ret = mapitest_common_message_create(mt, &obj_folder, &obj_message, MT_MAIL_SUBJECT);
+ mapitest_print(mt, "* %-35s: %s\n", "mapitest_common_message_create",
+ ret == true ? "TRUE" : "FALSE");
+ if (ret == false) return ret;
+
+ /* Step 4. Save changes on message */
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadWrite);
+ mapitest_print_retval(mt, "SaveChangesMessage");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 5. TransportSend */
+ retval = TransportSend(&obj_message, &lpProps);
+ mapitest_print_retval(mt, "TransportSend");
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ /* Step 6. Dump the properties */
+ if (&lpProps != NULL) {
+ uint32_t i;
+ struct SPropValue lpProp;
+
+ for (i = 0; i < lpProps.cValues; i++) {
+ cast_SPropValue(&lpProps.lpProps[i], &lpProp);
+ mapidump_SPropValue(lpProp, "\t* ");
+ }
+ MAPIFreeBuffer(lpProps.lpProps);
+ }
+
+ /* Step 6. Clean up anything else */
+ mapitest_common_message_delete_by_subject(mt, &obj_folder, MT_MAIL_SUBJECT);
+ GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+ OpenFolder(&obj_store, id_folder, &obj_folder);
+ mapitest_common_message_delete_by_subject(mt, &obj_folder, MT_MAIL_SUBJECT);
+
+ /* Release */
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
+
+
+/**
+ \details Test the GetTransportFolder (0x6d) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Retrieves the folder ID of temporary transport folder
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxomsg_GetTransportFolder(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ mapi_id_t folder_id;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_store);
+ return false;
+ }
+
+ /* Step 2. Get the transport folder */
+ retval = GetTransportFolder(&obj_store, &folder_id);
+ mapitest_print_retval_fmt(mt, "GetTransportFolder", "(0x%llx)", folder_id);
+ if (GetLastError() != MAPI_E_SUCCESS) {
+ return false;
+ }
+
+ return true;
+}
Added: trunk/openchange/utils/mapitest/modules/module_oxorule.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxorule.c (rev 0)
+++ trunk/openchange/utils/mapitest/modules/module_oxorule.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,84 @@
+/*
+ Stand-alone MAPI testsuite
+
+ OpenChange Project - E-MAIL RULES PROTOCOL operations
+
+ Copyright (C) Julien Kerihuel 2008
+
+ 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+
+/**
+ \file module_oxorule.c
+
+ \brief E-Mail Rules Protocol test suite
+ */
+
+
+/**
+ \details Test the GetRulesTable (0x3f) operation
+
+ This function:
+ -# Log on the user private mailbox
+ -# Open the inbox folder
+ -# Retrieve the rules table
+
+ \param mt pointer on the top-level mapitest structure
+
+ \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxorule_GetRulesTable(struct mapitest *mt)
+{
+ enum MAPISTATUS retval;
+ bool ret = true;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_rtable;
+
+ /* Step 1. Logon */
+ mapi_object_init(&obj_store);
+ retval = OpenMsgStore(mt->session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ /* Step 2. Open the Inbox folder */
+ mapi_object_init(&obj_folder);
+ ret = mapitest_common_folder_open(mt, &obj_store, &obj_folder, olFolderInbox);
+ if (ret == false) {
+ goto cleanup;
+ }
+
+ /* Step 3. Retrieve the rules table */
+ mapi_object_init(&obj_rtable);
+ retval = GetRulesTable(&obj_folder, &obj_rtable, RulesTableFlags_Unicode);
+ mapitest_print_retval(mt, "GetRulesTable");
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ goto cleanup;
+ }
+
+ cleanup:
+ /* Release */
+ mapi_object_release(&obj_rtable);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+
+ return ret;
+}
Added: trunk/openchange/utils/mapitrace/Makefile.PL
===================================================================
--- trunk/openchange/utils/mapitrace/Makefile.PL (rev 0)
+++ trunk/openchange/utils/mapitrace/Makefile.PL 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,6 @@
+use ExtUtils::MakeMaker;
+WriteMakefile(
+ 'NAME' => 'MAPI::Mapitrace',
+ 'VERSION_FROM' => 'lib/MAPI/EcDoRpc.pm',
+ 'EXE_FILES' => [ 'mapitrace' ],
+ );
Added: trunk/openchange/utils/mapitrace/lib/MAPI/Dump_EcDoRpc.pm
===================================================================
--- trunk/openchange/utils/mapitrace/lib/MAPI/Dump_EcDoRpc.pm (rev 0)
+++ trunk/openchange/utils/mapitrace/lib/MAPI/Dump_EcDoRpc.pm 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,201 @@
+#############################################
+# EcDoRpc Dump utility for mapitrace tool
+# Copyright Julien Kerihuel 2007
+# <j.kerihuel at openchange.org>
+#
+# released under the GNU GPL v3 or later
+#
+package MAPI::Dump_EcDoRpc;
+
+require Exporter;
+ at ISA = qw(Exporter);
+ at EXPORT = qw();
+use vars qw($AUTOLOAD $VERSION);
+$VERSION = '0.01';
+
+use strict;
+use Data::Dumper;
+
+#######################################################
+# convenient sort functions #
+#######################################################
+sub pkt_number
+{
+ my ($aa) = $a =~ /(\d+)/;
+ my($bb) = $b =~ /(\d+)/;
+ ($aa) <=> ($bb);
+}
+
+sub asc_num {
+ hex($a) <=> hex($b);
+}
+#######################################################
+# BRACE DUMPING FUNCTIONS
+#######################################################
+
+sub dump_error_brace
+{
+ my $_self = shift;
+ my $self = shift;
+
+ foreach my $key (sort asc_num (keys(%{$self->{BRACES_ERROR}}))) {
+ my $inout = $self->{BRACES_ERROR}->{$key}->{error};
+ if ($inout) {
+ print "[mapitrace] error in [$inout]: ";
+ print $self->{BRACES_ERROR}->{$key}->{$inout}->{filename} . "\n";
+ }
+ }
+}
+
+sub dump_brace_start
+{
+ my $_self = shift;
+ my $in = shift;
+ my $out = shift;
+
+ print MAPI::EcDoRpc->get_filename($in->{filename});
+ print " / ";
+ print MAPI::EcDoRpc->get_filename($out->{filename});
+ print "\n";
+ print "----------------------------------------------\n";
+}
+
+sub dump_brace_end
+{
+ print "\n\n";
+}
+
+#######################################################
+# DUMP FUNCTIONS FOR THE ANALYZE PART
+#######################################################
+
+#
+# Dump the handles array from a request or response
+#
+sub dump_handles
+{
+ my $_self = shift;
+ my $self = shift;
+ my @handles = @_;
+
+ print $self->{filename} . " :\n";
+ print "handles array (" . ($#handles + 1) . "):\n";
+ print "\t$_\n" foreach (@handles);
+ print "\n";
+}
+
+#
+# Provides a dual dump view for the handle array
+# both in request and response
+#
+# MAPI Semantic tells that request and response have the same
+# number of handles elements
+#
+sub dump_brace_handles
+{
+ my $_self = shift;
+ my $mapi_call = shift;
+
+ my @handles_in = @{$mapi_call->{handles_in}};
+ my @handles_out = @{$mapi_call->{handles_out}};
+
+ print "handles array (" . ($#handles_in + 1) . "):\n";
+ for (my $i = 0; $handles_in[$i]; $i++) {
+ printf "\t[%.2x] %s -> %s\n", $i, $handles_in[$i], $handles_out[$i];
+ }
+}
+
+#
+# Print a call
+#
+#
+sub dump_call
+{
+ my $mapi_call = shift;
+ my $key = shift;
+ my $call_idx = shift;
+ my $space = shift;
+
+ my $in = $mapi_call->{calls}->{REQ};
+ my $out = $mapi_call->{calls}->{REPL};
+
+ my $new_idx;
+
+ if ($call_idx) {
+ $new_idx = MAPI::EcDoRpc->get_call_index($mapi_call, $call_idx);
+ printf "\t%s+-- [0x%.2x] [%s] (opnum = %s) %15s (handle_idx = %s) (child of %s)\n",
+ $space, hex($call_idx),
+ (exists $out->{$new_idx}->{retval}) ? $out->{$new_idx}->{retval}:'',
+ $in->{$call_idx}->{opnum}, $in->{$call_idx}->{opname},
+ $in->{$call_idx}->{handle_idx}, $in->{$key}->{opname};
+ } else {
+ $new_idx = MAPI::EcDoRpc->get_call_index($mapi_call, $key);
+ printf "\t[0x%.2x] [%s] (opnum = %s) %25s (handle_idx = %s) (self_handle_idx = %s)\n",
+ hex($key),
+ (exists $out->{$new_idx}->{retval}) ? $out->{$new_idx}->{retval} : '',
+ $in->{$key}->{opnum}, $in->{$key}->{opname},
+ $in->{$key}->{handle_idx},
+ $in->{$key}->{self_handle_idx};
+ }
+}
+
+#
+# Dump mapi calls
+#
+# Since calls with self_handles have a smaller index than other calls relying on them
+# When a parent value is > than the current idx, we can skip display the call.
+# It should have normally been printing earlier when checking for call children
+# Return -1 if we have an error
+#
+
+sub dump_mapi_calls
+{
+ my $_self = shift;
+ my $mapi_call = shift;
+
+ my $in = $mapi_call->{calls}->{REQ};
+ my $out = $mapi_call->{calls}->{REPL};
+
+ my $in_call_count = MAPI::EcDoRpc->get_mapi_calls_request_count($in);
+
+ if ($in_call_count != keys(%{$out})) {
+ print "[mapitrace] error: Oops seems like we have some trouble ...\n";
+ print "[mapitrace] error: Mismatch call count between request ($in_call_count) and response (". keys(%{$out}) .")\n";
+ return -1;
+ }
+
+ printf "serialized mapi calls (count = %.2d):\n", $in_call_count;
+ foreach my $key (sort asc_num (keys(%{$in}))) {
+ if ($in->{$key}->{self_handle_idx}) {
+ # If this self_handle call has a child ;p
+ my $space = " ";
+ if (exists $in->{$key}->{parent}) {
+ $space .= " ";
+ } else {
+ dump_call($mapi_call, $key, 0, 0);
+ }
+ # Check if the call with self_handle_idx has children
+ # The dump will fail if we have Release call.
+ # In order to avoid this problem we use out instead
+
+ if ($in->{$key}->{children}) {
+ foreach my $call_idx (sort asc_num @{$in->{$key}->{children}}) {
+ dump_call($mapi_call, $key, $call_idx, $space);
+ }
+ }
+ }
+ else {
+ if (exists $in->{$key}->{parent} && hex($in->{$key}->{parent}) < hex($key)) {
+ } else {
+ printf "\t[0x%.2x] [%s] (opnum = %s) %25s (handle_idx = %s)\n",
+ hex($key),
+ (exists $out->{$key}->{retval}) ? $out->{$key}->{retval}: '',
+ $in->{$key}->{opnum}, $in->{$key}->{opname}, $in->{$key}->{handle_idx};
+ }
+ }
+ }
+ print "\n";
+ return 0;
+}
+
+1;
Added: trunk/openchange/utils/mapitrace/lib/MAPI/EcDoRpc.pm
===================================================================
--- trunk/openchange/utils/mapitrace/lib/MAPI/EcDoRpc.pm (rev 0)
+++ trunk/openchange/utils/mapitrace/lib/MAPI/EcDoRpc.pm 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,797 @@
+#############################################
+# EcDoRpc package for mapitrace tool
+# Copyright Julien Kerihuel 2007
+# <j.kerihuel at openchange.org>
+#
+# released under the GNU GPL v3 or later
+#
+package MAPI::EcDoRpc;
+
+require Exporter;
+ at ISA = qw(Exporter);
+ at EXPORT = qw();
+use vars qw($AUTOLOAD $VERSION);
+$VERSION = '0.03';
+
+use strict;
+use File::Basename;
+use MAPI::Dump_EcDoRpc;
+use MAPI::Graph;
+use MAPI::Regression;
+use MAPI::Statistic;
+
+use Data::Dumper;
+
+#######################################################
+# CONVENIENT SORT FUNCTIONS
+#######################################################
+sub pkt_number
+{
+ my ($aa) = $a =~ /(\d+)/;
+ my($bb) = $b =~ /(\d+)/;
+ ($aa) <=> ($bb);
+}
+
+sub asc_num {
+ hex($a) <=> hex($b);
+}
+
+sub sort_packets
+{
+ my $garbage = 0;
+
+ my @file1 = split(/\_/, get_filename($garbage, $a));
+ my @file2 = split(/\_/, get_filename($garbage, $b));
+
+ hex($file1[0]) <=> hex($file2[0]);
+}
+
+#######################################################
+# CONVENIENT GET FUNCTIONS
+#######################################################
+
+#
+# Dump the filename from a pathname
+#
+sub get_filename
+{
+ my $_self = shift;
+ my $pathname = shift;
+
+ my @parts = split(/\//, $pathname);
+ return $parts[$#parts];
+}
+
+
+
+#######################################################
+# INIT PART
+#######################################################
+
+#
+# index packets by ascending numeric order
+# brace packets {in,out}
+# ndrdump files in the output field
+#
+
+sub new
+{
+ my $_self = shift;
+ my $path = shift;
+ my $outputdir = shift;
+ my $verbose = shift;
+ my $counter = -1;
+
+ my $self = {};
+ $self->{CONF} = {};
+ $self->{CONF}->{stdout} = 1;
+ $self->{CONF}->{outputdir} = $outputdir;
+ $self->{CONF}->{path} = $path;
+ $self->{CONF}->{verbose} = $verbose;
+ $self->{CONF}->{name} = $_self->get_filename($path);
+
+ $self->{ECDORPC} = {};
+ $self->{ECDORPC}->{braces_count} = 0;
+ $self->{ECDORPC}->{braces} = {};
+
+ $self->{ECDORPC_ERROR} = {};
+ $self->{ECDORPC_ERROR}->{in} = {};
+ $self->{ECDORPC_ERROR}->{out} = {};
+
+ ############# Should disappear ################
+ $self->{BRACES_ERROR} = {};
+ $self->{SKIPPED_FILES} = {};
+
+ $self->{SKIPPED_FILES}->{REQ} = {};
+ $self->{SKIPPED_FILES}->{REQ}->{count} = 0;
+ $self->{SKIPPED_FILES}->{REQ}->{files} = {};
+
+ $self->{SKIPPED_FILES}->{REPL} = {};
+ $self->{SKIPPED_FILES}->{REPL}->{count} = 0;
+ $self->{SKIPPED_FILES}->{REPL}->{files} = {};
+ ############# /Should disappear ################
+
+ my @files = <$path/*_Mapi_EcDoRpc>;
+ my @ndrdump_files = sort sort_packets @files;
+
+ $self->{STATISTIC} = MAPI::Statistic->new($_self->get_filename($path), @ndrdump_files);
+
+ my $in_filename = 0;
+ my $out_filename = 0;
+ foreach(@ndrdump_files) {
+ chomp($_);
+ if ($_ =~ /in/) {
+ if ($in_filename) {
+ print "[1] Skipping $in_filename\n" if $self->{CONF}->{verbose};
+ $in_filename = $_;
+ add_skipped_file($self, $in_filename, "REQ");
+ } else {
+ $in_filename = $_ if (!$in_filename);
+ }
+ }
+ if ($_ =~ /out/) {
+ if (!$in_filename) {
+ print "[2] Skipping $_\n" if $self->{CONF}->{verbose};
+ add_skipped_file($self, $_, "REPL");
+ } else {
+ $out_filename = $_;
+ $counter++;
+ add_brace($self, $counter, $in_filename, $out_filename);
+ $out_filename = $in_filename = 0;
+ }
+ }
+ $self->{ECDORPC}->{braces_count} = $counter;
+ }
+
+ bless($self);
+
+ return $self;
+}
+
+#######################################################
+# ERROR RELATED FUNCTIONS
+#######################################################
+sub add_bad_packet
+{
+ my $self = shift;
+ my $inout = shift;
+ my $filename = shift;
+ my $output = shift;
+
+ $self->{STATISTIC}->failure_request_counter() if ($inout eq "in");
+ $self->{STATISTIC}->failure_response_counter() if ($inout eq "out");
+
+ $self->{ECDORPC_ERROR}->{$inout}->{$filename} = {};
+ my $packet = $self->{ECDORPC_ERROR}->{$inout}->{$filename};
+
+ $packet->{output} = $output;
+}
+
+sub error_report
+{
+ my $self = shift;
+ my $inout = shift;
+
+ if ($inout ne "in" && $inout ne "out") {
+ print "[mapitrace]: Wrong parameter, must be in or out\n";
+ return -1;
+ }
+
+
+ print "\n[$inout" . "put error_report]:\n\n";
+ foreach my $key (sort sort_packets keys (%{$self->{ECDORPC_ERROR}->{$inout}})) {
+ print $key . "\n";
+ }
+}
+
+#######################################################
+# NDRDUMP + BRACES + STORAGE OPERATIONS
+#######################################################
+
+#
+# Initialize and add a brace to the hash
+#
+sub add_brace
+{
+ my $self = shift;
+ my $idx = shift;
+ my $in_filename = shift;
+ my $out_filename = shift;
+
+ $self->{ECDORPC}->{braces}->{$idx} = {};
+ $self->{ECDORPC}->{braces}->{$idx}->{in} = {};
+ $self->{ECDORPC}->{braces}->{$idx}->{out} = {};
+
+ $self->{ECDORPC}->{braces}->{$idx}->{in}->{filename} = $in_filename;
+ $self->{ECDORPC}->{braces}->{$idx}->{in}->{output} = '';
+
+ $self->{ECDORPC}->{braces}->{$idx}->{out}->{filename} = $out_filename;
+ $self->{ECDORPC}->{braces}->{$idx}->{out}->{output} = '';
+
+ $self->{STATISTIC}->increment_brace_counter();
+}
+
+#
+# Store the error brace in the BRACES_ERROR hash and
+# Delete the brace from the ECDORPC hash
+#
+sub delete_brace
+{
+ my $self = shift;
+ my $idx = shift;
+
+ $self->{BRACES_ERROR}->{$idx} = {};
+ $self->{BRACES_ERROR}->{$idx} = $self->{ECDORPC}->{braces}->{$idx};
+
+ $self->{ECDORPC}->{braces_count}--;
+ delete($self->{ECDORPC}->{braces}->{$idx});
+
+ $self->{STATISTIC}->increment_brace_error_counter();
+}
+
+#
+# ndrdump a brace and check in the output
+# if we have an error (segfault)
+#
+sub ndrdump_brace
+{
+ my $self = shift;
+ my $idx = shift;
+ my $inout = shift;
+
+ my $filename = $self->{ECDORPC}->{braces}->{$idx}->{$inout}->{filename};
+ my $output = `ndrdump -l libmapi.so exchange_emsmdb 0x2 $inout $filename`;
+
+ $self->{ECDORPC}->{braces}->{$idx}->{$inout}->{output} = $output;
+ if ($output =~ /INTERNAL ERROR:/) {
+ $self->add_bad_packet($inout, $filename, $output);
+ $self->{ECDORPC}->{braces}->{$idx}->{error} = $inout;
+ return $idx;
+ }
+
+ $self->{STATISTIC}->success_request_counter() if ($inout eq "in");
+ $self->{STATISTIC}->success_response_counter() if ($inout eq "out");
+
+ return 0;
+}
+
+#
+# ndrdump the files in the list and clean the hash
+# if incorrect braces are found
+#
+sub ndrdump
+{
+ my $self = shift;
+ my @invalid_braces = ();
+ my $idx;
+
+ foreach my $key (sort asc_num (keys(%{$self->{ECDORPC}->{braces}}))) {
+ push(@invalid_braces, $idx) if ($idx = ndrdump_brace($self, $key, "in"));
+ push(@invalid_braces, $idx) if ($idx = ndrdump_brace($self, $key, "out"));
+ }
+
+# $self->{STATISTIC}->{}
+
+ foreach(@invalid_braces) {
+ delete_brace($self, $_);
+ }
+
+# MAPI::Dump_EcDoRpc->dump_error_brace($self);
+}
+
+############################################################
+# ANALYZE PART
+############################################################
+
+#
+# Retrieve the handles array (in,out) from a given packet
+#
+sub get_pkt_handles
+{
+ my $self = shift;
+ my $mapi_call = shift;
+ my $inout = shift;
+ my $output = shift;
+ my @lines = split(/\n/, $output);
+ my $count_marker = 0;
+
+ foreach(@lines) {
+ if ($count_marker) {
+ $_ =~ /: (\w+) \(/i;
+ push(@{$mapi_call->{handles_in}}, $1) if ($inout eq "REQ");
+ push(@{$mapi_call->{handles_out}}, $1) if ($inout eq "REPL");
+ $count_marker--;
+ }
+
+ if (!$count_marker && $_ =~ /\(handles\)/) {
+ $_ =~/number=(\d+)/i;
+ $count_marker = $1;
+ }
+ }
+}
+
+#
+# Reset mapi_call markers
+#
+sub mapi_call_reset_markers
+{
+ my $mapi_call = shift;
+
+ $mapi_call->{marker}->{opnum} = 0;
+ $mapi_call->{marker}->{opname} = 0;
+ $mapi_call->{marker}->{handle_idx} = 0;
+ $mapi_call->{marker}->{sub_handles} = 0;
+ $mapi_call->{marker}->{store} = 0;
+}
+
+#
+# Initialize the mapi call parsing structure
+#
+
+sub init_mapi_call
+{
+ my $mapi_call = {};
+
+ # Initialize markers
+ $mapi_call->{marker} = {};
+ mapi_call_reset_markers($mapi_call);
+ $mapi_call->{marker}->{call_idx} = -1;
+
+ # Initialize the call serialization hash
+ $mapi_call->{calls} = {};
+
+ # Initialize handles
+ $mapi_call->{handles_in} = ();
+ $mapi_call->{handles_out} = ();
+
+ bless($mapi_call);
+ return ($mapi_call);
+}
+
+#
+# Get the start of a mapi call
+#
+
+sub get_mapi_call_start
+{
+ my $mapi_call = shift;
+ my $line = shift;
+ my $inout = shift;
+
+ if ($line =~ /EcDoRpc_MAPI_$inout$/) {
+ mapi_call_reset_markers($mapi_call);
+ $mapi_call->{marker}->{opnum} = 1;
+ $mapi_call->{marker}->{call_idx}++;
+ }
+}
+
+#
+# Get mapi call opnum
+#
+sub get_mapi_call_opnum
+{
+ my $mapi_call = shift;
+ my $line = shift;
+ my $inout = shift;
+
+ if ($mapi_call->{marker}->{opnum} && $line =~ /opnum\s+:/) {
+ $line =~ /(0x\w{2})/i;
+
+ my $idx = $mapi_call->{marker}->{call_idx};
+ $mapi_call->{calls}->{$inout}->{$idx}->{opnum} = $1;
+
+ $mapi_call->{marker}->{opnum} = 0;
+ $mapi_call->{marker}->{handle_idx} = 1;
+ $mapi_call->{marker}->{retval} = 1;
+ }
+}
+
+#
+# Get mapi call opname
+#
+sub get_mapi_call_opname
+{
+ my $mapi_call = shift;
+ my $line = shift;
+ my $inout = shift;
+
+ if ($mapi_call->{marker}->{opname} && $line =~ /mapi_\w+: struct/) {
+ $line =~ /mapi_(\w+):/i;
+
+ my $idx = $mapi_call->{marker}->{call_idx};
+ $mapi_call->{calls}->{$inout}->{$idx}->{opname} = $1;
+
+ $mapi_call->{marker}->{opname} = 0;
+ $mapi_call->{marker}->{sub_handles} = 1;
+ }
+}
+
+#
+# Get mapi call error code
+#
+sub get_mapi_call_retval
+{
+ my $mapi_call = shift;
+ my $line = shift;
+ my $inout = shift;
+
+ if ($mapi_call->{marker}->{retval} && $line =~ /error_code/) {
+ $line =~ /error_code\s+:\s+(\w+)/i;
+ my $idx = $mapi_call->{marker}->{call_idx};
+ $mapi_call->{calls}->{$inout}->{$idx}->{retval} = $1;
+ $mapi_call->{marker}->{retval} = 0;
+ }
+}
+
+#
+# Get mapi call handle idx
+#
+sub get_mapi_call_handle_idx
+{
+ my $mapi_call = shift;
+ my $line = shift;
+ my $inout = shift;
+
+ if ($mapi_call->{marker}->{handle_idx} && $line =~ /handle_idx\s+:/) {
+ $line =~ /(0x\w{2})/i;
+
+ my $idx = $mapi_call->{marker}->{call_idx};
+ $mapi_call->{calls}->{$inout}->{$idx}->{handle_idx} = $1;
+
+ $mapi_call->{marker}->{handle_idx} = 0;
+ $mapi_call->{marker}->{opname} = 1;
+ }
+}
+
+#
+# Get sub handles idx within mapi_call specific dump
+#
+sub get_mapi_call_sub_handle_idx
+{
+ my $mapi_call = shift;
+ my $line = shift;
+ my $inout = shift;
+
+ if ($mapi_call->{marker}->{sub_handles} && $line =~ /handle_idx/) {
+ $line =~ /(0x\w{2})/i;
+
+ my $idx = $mapi_call->{marker}->{call_idx};
+ $mapi_call->{calls}->{$inout}->{$idx}->{self_handle_idx} = $1;
+ }
+}
+
+#
+# Retrieve MAPI calls for a given packet:
+# - opnum
+# - handle_idx
+# - opname
+# - sub handles
+#
+sub get_mapi_calls
+{
+ my $self = shift;
+ my $mapi_call = shift;
+ my $inout = shift;
+
+ # Reset the mapi call counter
+ $mapi_call->{marker}->{call_idx} = -1;
+
+ my @lines = split(/\n/, $self->{output});
+ foreach my $line (@lines) {
+ chomp($line);
+
+ get_mapi_call_start($mapi_call, $line, $inout);
+ get_mapi_call_opnum($mapi_call, $line, $inout);
+ get_mapi_call_handle_idx($mapi_call, $line, $inout);
+ get_mapi_call_retval($mapi_call, $line, $inout);
+ get_mapi_call_opname($mapi_call, $line, $inout);
+ get_mapi_call_sub_handle_idx($mapi_call, $line, $inout);
+ }
+
+ # We do not need anymore the markers
+ delete($mapi_call->{marker});
+}
+
+#
+# When checking mapi calls number consistency between in and out,
+# we have to remove Release calls count from request cause Release
+# doesn't produce any call in out (until now).
+#
+sub get_mapi_calls_request_count
+{
+ my $_self = shift;
+ my $in = shift;
+
+ my $counter = keys(%{$in});
+
+ foreach my $key (keys(%{$in})) {
+ if (hex($in->{$key}->{opnum}) == 0x1) {
+ $counter--;
+ }
+ }
+ return $counter;
+}
+
+#
+# Get the call index for a given call in the response
+# This hack fixes the Release issue
+# Note: MAPI serialize calls in such way we can predict
+# the response call index with reasonable confidence
+#
+sub get_call_index
+{
+ my $self = shift;
+ my $mapi_call = shift;
+ my $call_idx = shift;
+
+ my $in = $mapi_call->{calls}->{REQ};
+
+ return $call_idx if (keys(%{$in}) == $self->get_mapi_calls_request_count($in));
+
+ # If count mismatches case
+
+ return $call_idx if ($call_idx == 0);
+
+ for (my $idx = 0; $idx <= $call_idx; $idx++) {
+ $call_idx-- if (hex($in->{$idx}->{opnum}) == 0x1);
+ }
+ return $call_idx;
+}
+
+#
+# Analyze EcDoRpc braces output and extract the information
+# we need to create the object hierarchy
+#
+
+sub analyze
+{
+ my $self = shift;
+ my $trace_opt = shift;
+
+ foreach my $key (sort asc_num (keys(%{$self->{ECDORPC}->{braces}}))) {
+ my $in = $self->{ECDORPC}->{braces}->{$key}->{in};
+ my $out = $self->{ECDORPC}->{braces}->{$key}->{out};
+
+ MAPI::Dump_EcDoRpc->dump_brace_start($in, $out) if ($trace_opt);
+
+ $self->{ECDORPC}->{braces}->{$key}->{mapi_calls} = init_mapi_call();
+ my $mapi_call = $self->{ECDORPC}->{braces}->{$key}->{mapi_calls};
+
+ get_mapi_calls($in, $mapi_call, "REQ");
+ get_mapi_calls($out, $mapi_call, "REPL");
+
+ # Add the request/response handle array in the element hash
+ $self->get_pkt_handles($mapi_call, "REQ", $in->{output});
+ $self->get_pkt_handles($mapi_call, "REPL", $out->{output});
+
+ $self->get_mapi_call_hierarchy($in, $out, $mapi_call, $key);
+ if ($trace_opt) {
+ if (MAPI::Dump_EcDoRpc->dump_mapi_calls($mapi_call)) {
+ $self->delete_brace($key);
+ } else {
+ MAPI::Dump_EcDoRpc->dump_brace_handles($mapi_call);
+ MAPI::Dump_EcDoRpc->dump_brace_end();
+ }
+ }
+ }
+}
+
+############################################################
+# ANALYZE PART FOR HANDLES
+############################################################
+
+#
+# Get mapi_call hierarchy within a serialized request
+#
+# Explanations:
+# * If the call has a handle_idx set to 0xffffffff but this handle_idx is
+# already referenced by a previous call in its self_handle_idx field, then
+# the call is a child of the one with the set_handle_idx
+#
+# * In MAPI Semantic, a self handle is unique and can't be set twice
+#
+sub get_mapi_call_hierarchy
+{
+ my $self = shift;
+ my $request = shift;
+ my $response = shift;
+ my $mapi_call = shift;
+ my $key = shift;
+
+ ## WARNING: This is the nasty hack that should be removed
+ if (!defined $mapi_call->{handles_in} || !defined $mapi_call->{handles_out}) {
+ $self->delete_brace($key);
+ return ;
+ }
+
+ my @handles_in = @{$mapi_call->{handles_in}};
+ my @handles_out = @{$mapi_call->{handles_out}};
+
+ my $self_handles = {};
+ my $in = $mapi_call->{calls}->{REQ};
+
+ # If we don't have multi calls, no need to go further
+ return if (keys(%{$in}) == 1);
+
+ # Retrieve calls with self_handle
+ foreach my $key (sort pkt_number keys(%{$in})) {
+ if ($in->{$key}->{self_handle_idx}) {
+ my $self_handle_idx = $in->{$key}->{self_handle_idx};
+ $self_handles->{$self_handle_idx} = $key;
+ $in->{$key}->{children} = ();
+ }
+ }
+
+ # If we don't have any self handles, no need to go further
+ return if (keys(%{$in}) == 0);
+
+ # We now retrieve calls again
+ # check for handle_idx referring handles value 0xffffffff
+ # and check if their handle idx is already indexed in %self_handles
+ # which means it is a child of this call
+ foreach my $key (sort pkt_number keys(%{$in})) {
+ if ($handles_in[hex($in->{$key}->{handle_idx})] &&
+ $handles_in[hex($in->{$key}->{handle_idx})] eq "0xffffffff") {
+ my $call_handle_idx = $in->{$key}->{handle_idx};
+ if (exists $self_handles->{$call_handle_idx}) {
+ my $parent_call_idx = $self_handles->{$call_handle_idx};
+ $in->{$key}->{parent} = $self_handles->{$call_handle_idx};
+ push(@{$in->{$parent_call_idx}->{children}}, $key);
+ }
+ }
+ }
+}
+
+############################################################
+# WRAPPER FUNCTIONS ON THE GRAPHVIZ MODULE
+############################################################
+
+#
+# process the call hierarchy and prepare the nodes for graph output
+#
+sub graph_calls
+{
+ my $self = shift;
+ my $g = shift;
+ my $brace_key = shift;
+
+ my $brace = $self->{ECDORPC}->{braces}->{$brace_key};
+ my $mapi_call = $brace->{mapi_calls};
+
+ return if (!exists $mapi_call->{handles_out});
+
+ # Get the request and response handles
+ my @handles_out = @{$mapi_call->{handles_out}};
+
+ # Get the request mapi_call serialization hash
+ my $in = $mapi_call->{calls}->{REQ};
+
+ # Check if we are in a serialized call
+ # if (@handles_out == 1) {
+ # $g->add_node($mapi_call, 0);
+ # return ;
+ # }
+
+
+ # Process the serialized
+ # We first check for self_handle packets only
+ # Next we process self_handle packets with children
+ # Finally we check normal calls
+ foreach my $key (sort asc_num (keys(%{$in}))) {
+ if ($in->{$key}->{self_handle_idx}) {
+ $g->add_node($mapi_call, $key);
+ if (exists $in->{$key}->{children}) {
+ foreach my $call_idx (@{$in->{$key}->{children}}) {
+ $g->add_node($mapi_call, $call_idx);
+ }
+ }
+ } else {
+ $g->add_node($mapi_call, $key);
+ }
+ }
+}
+
+sub graph
+{
+ my $self = shift;
+ my $dir = shift;
+ my $highlight = shift;
+ my $png = $dir . "/" . $self->get_filename($self->{CONF}->{path}) . ".png";
+
+ # mkdir output directory if it doesn't exist
+ mkdir $dir;
+
+# my $g = MAPI::Graph_EcDoRpc->new($png);
+ my $g = MAPI::Graph->new($png, $highlight);
+
+ # Dump the hierarchy
+ $self->graph_calls($g, $_) foreach (sort asc_num
+ (keys(%{$self->{ECDORPC}->{braces}})));
+
+ $g->render();
+}
+
+############################################################
+# WRAPPER FUNCTIONS ON THE STATS MODULE
+############################################################
+
+#
+# Add skipped files
+#
+sub add_skipped_file
+{
+ my $self = shift;
+ my $filename = shift;
+ my $inout = shift;
+
+ my $count = $self->{SKIPPED_FILES}->{$inout}->{count};
+ my $files = $self->{SKIPPED_FILES}->{$inout}->{files};
+
+ # Initiate and add the new entry
+ $files->{$count} = {};
+ $files->{$count}->{filename} = $filename;
+
+ # Increment the counter
+ $self->{SKIPPED_FILES}->{$inout}->{count}++;
+}
+
+#
+#
+#
+sub stats
+{
+ my $self = shift;
+
+ $self->{STATISTIC}->scenario();
+
+# print Dumper($self->{SKIPPED_FILES});
+}
+
+############################################################
+# SEARCH FUNCTIONS PART
+############################################################
+
+#
+# Trace a call through the scenario
+#
+sub search_call
+{
+ my $self = shift;
+ my $callname = shift;
+ my $dump_opt = shift;
+ my $inout = shift;
+
+ my $search = {};
+ my $count = 0;
+ my @results = ();
+
+ my $find_marker = 0;
+
+ # We loop through mapi calls REQ calls and search for the given call
+ foreach my $brace_key (sort pkt_number keys(%{$self->{ECDORPC}->{braces}})) {
+ my $brace = $self->{ECDORPC}->{braces}->{$brace_key};
+
+ foreach my $call_key (sort pkt_number keys(%{$brace->{mapi_calls}->{calls}->{REQ}})) {
+ my $call = $brace->{mapi_calls}->{calls}->{REQ}->{$call_key};
+
+ if ($call->{opname} && $call->{opname} eq $callname) {
+ $find_marker = 1;
+ $search->{$count}->{brace_key} = $brace_key;
+ $count++;
+ print $brace->{$inout}->{output} if ($dump_opt && $inout);
+ push(@results, $call->{opname} . ": " . $self->get_filename($brace->{in}->{filename}) . " / " . $self->get_filename($brace->{out}->{filename}) . "\n");
+ }
+ }
+ }
+
+ if ($#results >= 0) {
+ print "[X] Call found in [ " . $self->{CONF}->{name} . " ]:\n";
+ print "\t$_" foreach (@results);
+ } else {
+ print "[O] No call found in [ " . $self->{CONF}->{name} . " ]\n";
+ }
+ # We are now looking for the call in problematic packets
+
+}
+
+1;
Added: trunk/openchange/utils/mapitrace/lib/MAPI/Graph.pm
===================================================================
--- trunk/openchange/utils/mapitrace/lib/MAPI/Graph.pm (rev 0)
+++ trunk/openchange/utils/mapitrace/lib/MAPI/Graph.pm 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,313 @@
+##################################################
+# EcDoRpc GraphViz Dump package for mapitrace tool
+# Copyright Julien Kerihuel 2007
+# <j.kerihuel at openchange.org>
+#
+# released under the GNU GPL
+#
+
+package MAPI::Graph;
+
+require Exporter;
+ at ISA = qw(Exporter);
+ at EXPORT = qw();
+use vars qw($AUTOLOAD $VERSION);
+$VERSION = '0.01';
+
+use strict;
+use GraphViz;
+use Data::Dumper;
+
+#
+# Init the MAPI::Graph object
+#
+sub new
+{
+ my $_self = shift;
+ my $output_file = shift;
+ my $highlight = shift;
+
+ my $self = {};
+
+ $self->{graph} = GraphViz->new(node => {shape => 'box'});
+ $self->{nodelist} = {};
+ $self->{output_file} = $output_file;
+ $self->{highlight} = $highlight;
+
+ bless($self);
+ return $self;
+}
+
+#
+# Render the graph
+#
+sub render
+{
+ my $self = shift;
+
+ print "Dumping graph in ." . $self->{output_file} . "\n";
+ $self->{graph}->as_png($self->{output_file});
+}
+
+#
+# Init a new node in the general nodelist hash
+# A node is a set of queue each of them composed of children
+#
+sub node_init
+{
+ my $self = shift;
+ my $node_id = shift;
+
+ my $nodelist = $self->{nodelist};
+
+ print "[node_init]: Adding node: $node_id\n";
+ $nodelist->{$node_id} = {};
+ $nodelist->{$node_id}->{children} = {};
+ $nodelist->{$node_id}->{count} = 1;
+ @{$nodelist->{$node_id}->{children}->{1}} = ();
+}
+
+#
+# If a release occur on a node we need to increment
+# the depth so we can start a new hierarchy
+#
+sub add_depth
+{
+ my $self = shift;
+ my $node_id = shift;
+
+ my $node = $self->{nodelist}->{$node_id};
+
+ $node->{count} += 1;
+ my $count = $node->{count};
+
+ $node->{children}->{$count} = ();
+
+}
+
+#
+# Get the last child id for the given node_id
+#
+sub get_last_nodelist_child
+{
+ my $self = shift;
+ my $node_id = shift;
+
+ my $node = $self->{nodelist}->{$node_id};
+
+ return 0 if (!$node);
+
+ my $count = $node->{count};
+ my $child_id = @{$node->{children}->{$count}};
+
+ # If the node doesn't have children return the parent one
+ return $node_id if (!$child_id);
+
+ # Otherwise return the last child
+ my @hierarchy = @{$node->{children}->{$count}};
+ $child_id -= 1;
+ my $last_child = $hierarchy[$child_id];
+ return $last_child;
+}
+
+#
+# add a child to an existing node in the nodelist hash
+#
+sub nodelist_add_child
+{
+ my $self = shift;
+ my $node_id = shift;
+
+ # get the node in the hash
+ my $node = $self->{nodelist}->{$node_id};
+ # get the number of hierarchy array
+ my $count = $node->{count};
+ # get the number of children for the given hierarchy
+ my $child_count = @{$node->{children}->{$count}};
+ # we increment the child counter
+ $child_count += 1;
+ my $child_name = "$node_id:$count:$child_count";
+
+ print "Adding node: $child_name\n";
+ push(@{$node->{children}->{$count}}, $child_name);
+
+ return $child_name;
+}
+
+#
+# add a node in the general nodelist hash
+# it can be a node or the child of an existing node
+#
+sub nodelist_add
+{
+ my $self = shift;
+ my $node_id = shift;
+
+ my $nodelist = $self->{nodelist};
+
+ # Add the node directly if not referenced in the nodelist hash
+ if (!exists $nodelist->{$node_id}) {
+ $self->node_init($node_id);
+ return $node_id;
+ }
+
+ # If the node already exists, add a child for the correct one
+ my $last_child = $self->nodelist_add_child($node_id);
+ return $last_child;
+}
+
+#
+# Add edge between two nodes
+#
+sub add_edge
+{
+ my $self = shift;
+ my $parent_handle = shift;
+ my $self_handle = shift;
+
+ my $g = $self->{graph};
+
+ # If self_handle exists add an edge between
+ # the last parent's child and the self_handle
+ my $last_child = $self->get_last_nodelist_child($parent_handle);
+
+ if ($self_handle) {
+ print "[add_edge] $last_child -> $self_handle\n";
+ $g->add_edge($last_child, $self_handle);
+ } else {
+ # if this is a root element we shouldn't add edge
+ if ($parent_handle ne $last_child) {
+ print "[add_edge] $parent_handle -> $last_child\n";
+ $g->add_edge($parent_handle, $last_child);
+ } else {
+ print "[add_edge]: no edge for $parent_handle\n";
+ }
+ }
+}
+
+#
+# Add a node to the graph
+#
+
+sub add_node
+{
+ my $self = shift;
+ my $mapi_call = shift;
+ my $key = shift;
+
+ my $g = $self->{graph};
+
+ my $parent_handle = $self->get_parent_handle($mapi_call, $key);
+ my $self_handle = $self->get_self_handle($mapi_call, $key);
+
+ # If we do not have a self handle
+ if (!$self_handle) {
+ my $last_child = $self->get_last_nodelist_child($parent_handle);
+ my $node_id = $self->nodelist_add($parent_handle);
+ my $label = $self->get_node_label($mapi_call, $key);
+
+ if ($self->{highlight} && !$self->node_highlight($label)) {
+ print "############ HERE ##############\n";
+ $g->add_node($node_id, label => $label,
+ style => "filled",
+ color => "green");
+ } else {
+ $g->add_node($node_id, label => $label);
+ }
+
+ # If there is already a child, link against it
+ if ($last_child && $last_child ne $parent_handle) {
+ $g->add_edge($last_child => $node_id);
+
+ } else {
+ # Otherwise, just link it to the parent node
+ $self->add_edge($parent_handle);
+ }
+
+ }
+
+ # If we do have a self handle
+ if ($self_handle) {
+ my $node_id = $self->nodelist_add($self_handle);
+ my $label = $self->get_node_label($mapi_call, $key);
+
+ if ($self->{highlight} && !$self->node_highlight($label)) {
+ print "############ HERE ##############\n";
+ $g->add_node($node_id, label => $label,
+ style => "filled",
+ color => "green");
+ } else {
+ $g->add_node($node_id, label => $label);
+ }
+ $self->add_edge($parent_handle, $node_id);
+ }
+}
+
+sub get_node_label
+{
+ my $self = shift;
+ my $mapi_call = shift;
+ my $key = shift;
+
+ my $in = $mapi_call->{calls}->{REQ}->{$key};
+ my $label = '';
+
+ $label = sprintf "%s (%s)", $in->{opname}, $in->{opnum};
+
+ return $label;
+}
+
+sub node_highlight
+{
+ my $self = shift;
+ my $label = shift;
+
+ return -1 if !$self->{highlight};
+
+ my $label2 = substr($label, 0, length($self->{highlight}));
+
+ if ($self->{highlight} eq $label2) {
+ print "WE CAN HIGHLIGHT THE CALL\n";
+ return 0;
+ }
+ return -1;
+}
+
+#########################################
+# HANDLE CONVENIENT FUNCTIONS
+#########################################
+
+#
+# get the parent handle (handle_idx field)
+#
+sub get_parent_handle
+{
+ my $self = shift;
+ my $mapi_call = shift;
+ my $key = shift;
+
+ my $in = $mapi_call->{calls}->{REQ}->{$key};
+ my @handles = @{$mapi_call->{handles_out}};
+
+ my $parent_handle = $in->{handle_idx};
+ return $handles[hex($parent_handle)];
+}
+
+#
+# get the self handle (self_handle_idx field)
+#
+sub get_self_handle
+{
+ my $self = shift;
+ my $mapi_call = shift;
+ my $key = shift;
+
+ my $in = $mapi_call->{calls}->{REQ}->{$key};
+ my @handles = @{$mapi_call->{handles_out}};
+
+ return 0 if (!exists $in->{self_handle_idx});
+
+ my $self_handle = $in->{self_handle_idx};
+
+ return $handles[hex($self_handle)];
+}
Added: trunk/openchange/utils/mapitrace/lib/MAPI/Regression.pm
===================================================================
--- trunk/openchange/utils/mapitrace/lib/MAPI/Regression.pm (rev 0)
+++ trunk/openchange/utils/mapitrace/lib/MAPI/Regression.pm 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,18 @@
+#############################################
+# EcDoRpc package for mapitrace tool
+# Copyright Julien Kerihuel 2007
+# <j.kerihuel at openchange.org>
+#
+# released under the GNU GPL v3 or later
+#
+package MAPI::Regression;
+
+require Exporter;
+ at ISA = qw(Exporter);
+ at EXPORT = qw();
+use vars qw($AUTOLOAD $VERSION);
+$VERSION = '0.01';
+
+use strict;
+
+1;
Added: trunk/openchange/utils/mapitrace/lib/MAPI/Statistic.pm
===================================================================
--- trunk/openchange/utils/mapitrace/lib/MAPI/Statistic.pm (rev 0)
+++ trunk/openchange/utils/mapitrace/lib/MAPI/Statistic.pm 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,191 @@
+##############################################
+# EcDoRpc Statistic package for mapitrace tool
+# Copyright Julien Kerihuel 2007
+# <j.kerihuel at openchange.org>
+#
+# released under the GNU GPL v3 or later
+#
+package MAPI::Statistic;
+
+require Exporter;
+ at ISA = qw(Exporter);
+ at EXPORT = qw();
+use vars qw($AUTOLOAD $VERSION);
+$VERSION = '0.01';
+
+use strict;
+use Data::Dumper;
+
+#######################################################
+# INIT PART
+#######################################################
+
+#
+# Initiate the statistic object
+#
+sub new
+{
+ my $_self = shift;
+ my ($scenario) = shift;
+ my (@files) = @_;
+
+ my $self = {};
+
+ $self->{SCENARIO} = {};
+ $self->{SCENARIO}->{name} = $scenario;
+ $self->{SCENARIO}->{total} = $#files + 1;
+
+ $self->{SCENARIO}->{BRACES}->{total} = 0;
+ $self->{SCENARIO}->{BRACES}->{failure} = 0;
+
+ $self->{SCENARIO}->{REQUEST}->{total} = 0;
+ $self->{SCENARIO}->{REQUEST}->{success} = 0;
+ $self->{SCENARIO}->{REQUEST}->{failure} = 0;
+
+ $self->{SCENARIO}->{RESPONSE}->{total} = 0;
+ $self->{SCENARIO}->{RESPONSE}->{success} = 0;
+ $self->{SCENARIO}->{RESPONSE}->{failure} = 0;
+
+ count_total_packets_type($self, @files);
+
+ $self->{SCENARIO}->{CALLS} = {};
+
+ bless($self);
+
+ return $self;
+}
+
+#######################################################
+# COUNT FUNCTION PART
+#######################################################
+
+#
+# Count the full number of requests and replies
+#
+sub count_total_packets_type
+{
+ my $self = shift;
+ my (@files) = @_;
+
+ foreach (@files) {
+ $self->{SCENARIO}->{REQUEST}->{total}++ if ($_ =~ /in/);
+ $self->{SCENARIO}->{RESPONSE}->{total}++ if ($_ =~ /out/);
+ }
+}
+
+#
+#
+#
+sub increment_brace_counter
+{
+ my $self = shift;
+
+ $self->{SCENARIO}->{BRACES}->{total}++;
+}
+
+sub increment_brace_error_counter
+{
+ my $self = shift;
+
+ $self->{SCENARIO}->{BRACES}->{failure}++;
+}
+
+#
+#
+#
+sub count_packet_inc
+{
+ my $self = shift;
+ my $inout = shift;
+ my $state = shift;
+
+ return -1 if (!$state || !$inout);
+ $self->{SCENARIO}->{REQUEST}->{$state}++ if ($inout eq "in");
+ $self->{SCENARIO}->{RESPONSE}->{$state}++ if ($inout eq "out");
+}
+
+#
+# Accessors
+#
+sub success_request_counter
+{
+ my $self = shift;
+ $self->increment_counter("REQUEST", "success");
+}
+
+sub failure_request_counter
+{
+ my $self = shift;
+ $self->increment_counter("REQUEST", "failure");
+}
+
+sub success_response_counter
+{
+ my $self = shift;
+ $self->increment_counter("RESPONSE", "success");
+}
+
+sub failure_response_counter
+{
+ my $self = shift;
+ $self->increment_counter("RESPONSE", "failure");
+}
+
+sub increment_counter
+{
+ my $self = shift;
+ my $type = shift;
+ my $case = shift;
+
+ $self->{SCENARIO}->{$type}->{$case}++;
+}
+
+#######################################################
+# DUMP PART
+#######################################################
+
+sub percent
+{
+ my $obj = shift;
+ my $type = shift;
+
+ return ($obj->{$type}->{total} / $obj->{total}) * 100;
+}
+
+sub scenario
+{
+ my $self = shift;
+
+ my $request_percent = percent($self->{SCENARIO}, "REQUEST");
+ my $response_percent = percent($self->{SCENARIO}, "RESPONSE");
+
+ print "+-----[ Scenario: " . $self->{SCENARIO}->{name} . " ]-----+\n";
+ print "[statistic]: We have " . $self->{SCENARIO}->{total} . " packets ";
+ print "(request: " . $request_percent . "%, ";
+ print "response: " . $response_percent . "%)\n";
+
+ my $success_req_rate = ($self->{SCENARIO}->{REQUEST}->{success} / $self->{SCENARIO}->{REQUEST}->{total}) * 100;
+ my $success_repl_rate = ($self->{SCENARIO}->{RESPONSE}->{success} / $self->{SCENARIO}->{RESPONSE}->{total}) * 100;
+ print "[statistic]: request success rate: " . $success_req_rate . "\n";
+ print "[statistic]: response success rate: " . $success_repl_rate . "\n";
+
+ my $braces_count = $self->{SCENARIO}->{BRACES}->{total};
+ my $braces_failure = $self->{SCENARIO}->{BRACES}->{failure};
+ if ($braces_failure) {
+ print "[statistic]: success brace analysis rate: " . ((1 - ($braces_failure/$braces_count)) * 100) . "\n";
+ print "[statistic]: braces skipped: " . $braces_failure . "/" . $braces_count . "\n";
+ } else {
+ print "[statistic]: success brace analysis rate: 100%\n";
+ print "[statistic]: no braces skipped\n";
+ }
+ print "+--------------------------------------------------------------+\n";
+
+}
+
+sub dump
+{
+ my $self = shift;
+}
+
+
+1;
Added: trunk/openchange/utils/mapitrace/mapitrace
===================================================================
--- trunk/openchange/utils/mapitrace/mapitrace (rev 0)
+++ trunk/openchange/utils/mapitrace/mapitrace 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,118 @@
+#!/usr/bin/perl -w
+
+##############################################
+# package to dump the mapi call hierarchy and
+# add IDL regression support
+#
+# Copyright Julien Kerihuel 2007.
+# <j.kerihuel at openchange.org>
+#
+# released under GNU GPL v3 or later
+
+use strict;
+
+use FindBin qw($RealBin $Script);
+use lib "$RealBin";
+use lib "$RealBin/lib";
+#use lib "lib";
+use MAPI::EcDoRpc;
+use Getopt::Long;
+
+my ($opt_help) = 0;
+my ($opt_outputdir) = '.';
+my ($opt_graph) = 0;
+my ($opt_highlight) = 0;
+my ($opt_trace) = 0;
+my ($opt_search_call) = 0;
+my ($opt_dump_call) = 0;
+my ($opt_inout) = 0;
+my ($opt_error) = 0;
+my ($opt_stats) = 0;
+my ($opt_verbose) = 0;
+############################################
+# display help text
+sub ShowHelp()
+{
+ print "mapi call hierarchy tracing tool and IDL regression support
+Copyright (C) Julien Kerihuel <j.kerihuel\@openchange.org>
+
+Usage: $Script [options]
+
+Generic Options:
+--help this help page
+--outputdir=OUTDIR put output in OUTDIR/ []
+--graph create a png graph
+--trace dump the mapi call hierarchy on command line
+--verbose verbose output
+
+Tracing Options:
+--search-call=CALL trace a single call through a scenario
+--dump-call dump all the packets containing the call specified
+--highlight=CALL highlight a call in the generated graph
+--inout=INOUT filter either requests (in) or response (out)
+
+Regression Options:
+--error_report=in,out Investigate invalid packets
+--stats Display statistics for a given scenario
+
+\n";
+ exit (0);
+}
+
+# main program
+my $result = GetOptions (
+ 'help|h|?' => \$opt_help,
+ 'outputdir=s' => \$opt_outputdir,
+ 'graph|g' => \$opt_graph,
+ 'highlight=s'=> \$opt_highlight,
+ 'trace|t' => \$opt_trace,
+ 'search-call=s' => \$opt_search_call,
+ 'dump-call|d' => \$opt_dump_call,
+ 'inout=s' => \$opt_inout,
+ 'error_report=s' => \$opt_error,
+ 'stats|s' => \$opt_stats,
+ 'verbose|v' => \$opt_verbose
+ );
+
+if (not $result) {
+ exit (1);
+}
+
+if ($opt_help) {
+ ShowHelp();
+ exit (0);
+}
+
+sub process_tracing($)
+{
+ my $directory = shift;
+ my $outputdir = $opt_outputdir;
+
+
+ opendir(DIR,$directory) or die "Unable to process $directory";
+ closedir(DIR);
+
+ my $EcDoRpc = MAPI::EcDoRpc->new($directory, $outputdir, $opt_verbose);
+
+ $EcDoRpc->ndrdump();
+ $EcDoRpc->analyze($opt_trace);
+
+ if ($opt_error) {
+ my @inout = split(/,/, $opt_error);
+
+ foreach (sort @inout) {
+ $EcDoRpc->error_report($_);
+ }
+ }
+
+ $EcDoRpc->stats() if ($opt_stats);
+ $EcDoRpc->search_call($opt_search_call, $opt_dump_call, $opt_inout) if ($opt_search_call);
+ $EcDoRpc->graph($outputdir, $opt_highlight) if ($opt_graph);
+}
+
+if (scalar(@ARGV) == 0) {
+ print "$Script: no input directory\n";
+ exit (1);
+}
+
+process_tracing($_) foreach (@ARGV);
Property changes on: trunk/openchange/utils/mapitrace/mapitrace
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/openchange/utils/openchange-tools.c
===================================================================
--- trunk/openchange/utils/openchange-tools.c (rev 0)
+++ trunk/openchange/utils/openchange-tools.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,334 @@
+/*
+ Convenient functions for openchange tools
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2007
+
+ 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 "openchange-tools.h"
+
+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 },
+ { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version " },
+ { NULL }
+};
+
+
+/*
+ * Retrieve the property value for a given SRow and property tag.
+ *
+ * If the property type is a string: fetch PT_STRING8 then PT_UNICODE
+ * in case the desired property is not available in first choice.
+ *
+ * Fetch property normally for any others properties
+ */
+_PUBLIC_ void *octool_get_propval(struct SRow *aRow, uint32_t proptag)
+{
+ const char *str;
+
+ if (((proptag & 0xFFFF) == PT_STRING8) ||
+ ((proptag & 0xFFFF) == PT_UNICODE)) {
+ proptag = (proptag & 0xFFFF0000) | PT_STRING8;
+ str = (const char *) find_SPropValue_data(aRow, proptag);
+ if (str) return (void *)str;
+
+ proptag = (proptag & 0xFFFF0000) | PT_UNICODE;
+ str = (const char *) find_SPropValue_data(aRow, proptag);
+ return (void *)str;
+ }
+
+ return (void *)find_SPropValue_data(aRow, proptag);
+}
+
+
+/*
+ * Read a stream and store it in a DATA_BLOB
+ */
+static enum MAPISTATUS octool_get_stream(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_stream,
+ DATA_BLOB *body)
+{
+ enum MAPISTATUS retval;
+ uint16_t read_size;
+ uint8_t buf[0x1000];
+
+ body->length = 0;
+ body->data = talloc_zero(mem_ctx, uint8_t);
+
+ do {
+ retval = ReadStream(obj_stream, buf, 0x1000, &read_size);
+ MAPI_RETVAL_IF(retval, GetLastError(), body->data);
+ if (read_size) {
+ body->data = talloc_realloc(mem_ctx, body->data, uint8_t,
+ body->length + read_size);
+ memcpy(&(body->data[body->length]), buf, read_size);
+ body->length += read_size;
+ }
+ } while (read_size);
+
+ errno = 0;
+ return MAPI_E_SUCCESS;
+}
+
+
+/*
+ * Fetch the body given PR_MSG_EDITOR_FORMAT property value
+ */
+_PUBLIC_ enum MAPISTATUS octool_get_body(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_message,
+ struct SRow *aRow,
+ DATA_BLOB *body)
+{
+ enum MAPISTATUS retval;
+ const struct SBinary_short *bin;
+ mapi_object_t obj_stream;
+ char *data;
+ uint8_t format;
+
+ /* Sanity checks */
+ MAPI_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
+
+ /* initialize body DATA_BLOB */
+ body->data = NULL;
+ body->length = 0;
+
+ retval = GetBestBody(obj_message, &format);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ switch (format) {
+ case olEditorText:
+ data = octool_get_propval(aRow, PR_BODY);
+ if (data) {
+ body->data = talloc_memdup(mem_ctx, data, strlen(data));
+ body->length = strlen(data);
+ } else {
+ mapi_object_init(&obj_stream);
+ retval = OpenStream(obj_message, PR_BODY, 0, &obj_stream);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ retval = octool_get_stream(mem_ctx, &obj_stream, body);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ mapi_object_release(&obj_stream);
+ }
+ break;
+ case olEditorHTML:
+ bin = (const struct SBinary_short *) octool_get_propval(aRow, PR_HTML);
+ if (bin) {
+ body->data = talloc_memdup(mem_ctx, bin->lpb, bin->cb);
+ body->length = bin->cb;
+ } else {
+ mapi_object_init(&obj_stream);
+ retval = OpenStream(obj_message, PR_HTML, 0, &obj_stream);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ retval = octool_get_stream(mem_ctx, &obj_stream, body);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ mapi_object_release(&obj_stream);
+ }
+ break;
+ case olEditorRTF:
+ mapi_object_init(&obj_stream);
+
+ retval = OpenStream(obj_message, PR_RTF_COMPRESSED, 0, &obj_stream);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ retval = WrapCompressedRTFStream(&obj_stream, body);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ mapi_object_release(&obj_stream);
+ break;
+ default:
+ DEBUG(0, ("Undefined Body\n"));
+ break;
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/*
+ * Optimized dump message routine (use GetProps rather than GetPropsAll)
+ */
+_PUBLIC_ enum MAPISTATUS octool_message(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_message)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProps;
+ struct SRow aRow;
+ uint32_t count;
+ ssize_t len;
+ /* common email fields */
+ const char *msgid;
+ const char *from, *to, *cc, *bcc;
+ const char *subject;
+ DATA_BLOB body;
+ const uint8_t *has_attach;
+ const uint32_t *cp;
+ const char *codepage;
+
+ /* Build the array of properties we want to fetch */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x13,
+ PR_INTERNET_MESSAGE_ID,
+ PR_INTERNET_MESSAGE_ID_UNICODE,
+ PR_CONVERSATION_TOPIC,
+ PR_CONVERSATION_TOPIC_UNICODE,
+ PR_MSG_EDITOR_FORMAT,
+ PR_BODY,
+ PR_BODY_UNICODE,
+ PR_HTML,
+ PR_RTF_COMPRESSED,
+ PR_SENT_REPRESENTING_NAME,
+ PR_SENT_REPRESENTING_NAME_UNICODE,
+ PR_DISPLAY_TO,
+ PR_DISPLAY_TO_UNICODE,
+ PR_DISPLAY_CC,
+ PR_DISPLAY_CC_UNICODE,
+ PR_DISPLAY_BCC,
+ PR_DISPLAY_BCC_UNICODE,
+ PR_HASATTACH,
+ PR_MESSAGE_CODEPAGE);
+ lpProps = talloc_zero(mem_ctx, struct SPropValue);
+ retval = GetProps(obj_message, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ /* Build a SRow structure */
+ aRow.ulAdrEntryPad = 0;
+ aRow.cValues = count;
+ aRow.lpProps = lpProps;
+
+ msgid = (const char *) octool_get_propval(&aRow, PR_INTERNET_MESSAGE_ID);
+ subject = (const char *) octool_get_propval(&aRow, PR_CONVERSATION_TOPIC);
+
+ retval = octool_get_body(mem_ctx, obj_message, &aRow, &body);
+
+ if (retval != MAPI_E_SUCCESS) {
+ printf("Invalid Message: %s\n", msgid ? msgid : "");
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+ }
+
+ from = (const char *) octool_get_propval(&aRow, PR_SENT_REPRESENTING_NAME);
+ to = (const char *) octool_get_propval(&aRow, PR_DISPLAY_TO);
+ cc = (const char *) octool_get_propval(&aRow, PR_DISPLAY_CC);
+ bcc = (const char *) octool_get_propval(&aRow, PR_DISPLAY_BCC);
+
+ has_attach = (const uint8_t *) octool_get_propval(&aRow, PR_HASATTACH);
+ cp = (const uint32_t *) octool_get_propval(&aRow, PR_MESSAGE_CODEPAGE);
+ switch (cp ? *cp : 0) {
+ case CP_USASCII:
+ codepage = "CP_USASCII";
+ break;
+ case CP_UNICODE:
+ codepage = "CP_UNICODE";
+ break;
+ case CP_JAUTODETECT:
+ codepage = "CP_JAUTODETECT";
+ break;
+ case CP_KAUTODETECT:
+ codepage = "CP_KAUTODETECT";
+ break;
+ case CP_ISO2022JPESC:
+ codepage = "CP_ISO2022JPESC";
+ break;
+ case CP_ISO2022JPSIO:
+ codepage = "CP_ISO2022JPSIO";
+ break;
+ default:
+ codepage = "";
+ break;
+ }
+
+ printf("+-------------------------------------+\n");
+ printf("message id: %s\n", msgid ? msgid : "");
+ printf("subject: %s\n", subject ? subject : "");
+ printf("From: %s\n", from ? from : "");
+ printf("To: %s\n", to ? to : "");
+ printf("Cc: %s\n", cc ? cc : "");
+ printf("Bcc: %s\n", bcc ? bcc : "");
+ if (has_attach) {
+ printf("Attachment: %s\n", *has_attach ? "True" : "False");
+ }
+ printf("Codepage: %s\n", codepage);
+ printf("Body:\n");
+ fflush(0);
+ if (body.length) {
+ len = write(1, body.data, body.length);
+ len = write(1, "\n", 1);
+ fflush(0);
+ talloc_free(body.data);
+ }
+ return MAPI_E_SUCCESS;
+}
+
+
+/*
+ * OpenChange MAPI programs initialization routine
+ */
+_PUBLIC_ struct mapi_session *octool_init_mapi(const char *opt_profname,
+ const char *opt_password,
+ uint32_t provider)
+{
+ enum MAPISTATUS retval;
+ char *profname = NULL;
+ struct mapi_session *session = NULL;
+ TALLOC_CTX *mem_ctx = NULL;
+
+ mem_ctx = talloc_named(NULL, 0, "octool_init_mapi");
+ if (opt_profname) {
+ profname = talloc_strdup(mem_ctx, (char *)opt_profname);
+ } else {
+ retval = GetDefaultProfile(&profname);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("GetDefaultProfile", GetLastError());
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+ }
+
+ if (!provider) {
+ retval = MapiLogonEx(&session, profname, opt_password);
+ } else {
+ retval = MapiLogonProvider(&session, profname, opt_password, provider);
+ }
+ MAPIFreeBuffer((char *)profname);
+
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MapiLogonEx", GetLastError());
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ talloc_free(mem_ctx);
+ return session;
+}
Added: trunk/openchange/utils/openchange-tools.h
===================================================================
--- trunk/openchange/utils/openchange-tools.h (rev 0)
+++ trunk/openchange/utils/openchange-tools.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,61 @@
+/*
+ OpenChange Tools includes
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2007
+
+ 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 __OPENCHANGETOOLS_H__
+#define __OPENCHANGETOOLS_H__
+
+#include <popt.h>
+
+#define DEFAULT_PROFDB "%s/.openchange/profiles.ldb"
+#define DEFAULT_TDB "%s/.openchange/index.tdb"
+#define DEFAULT_MBOX "%s/.openchange/mbox"
+#define DEFAULT_ICAL "%s/.openchange/ical"
+#define DEFAULT_VCF "%s/.openchange/vcf"
+#define DEFAULT_DIR "%s/.openchange"
+
+#ifndef __BEGIN_DECLS
+#ifdef __cplusplus
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif
+
+/* Common popt structures for tool */
+extern struct poptOption popt_openchange_version[];
+
+#define POPT_OPENCHANGE_VERSION { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_openchange_version, 0, "Common openchange options:", NULL },
+
+#ifndef _PUBLIC_
+#define _PUBLIC_
+#endif
+
+__BEGIN_DECLS
+_PUBLIC_ enum MAPISTATUS octool_message(TALLOC_CTX *, mapi_object_t *);
+_PUBLIC_ void *octool_get_propval(struct SRow *, uint32_t);
+_PUBLIC_ enum MAPISTATUS octool_get_body(TALLOC_CTX *, mapi_object_t *,
+ struct SRow *, DATA_BLOB *);
+_PUBLIC_ struct mapi_session *octool_init_mapi(const char *, const char *, uint32_t);
+__END_DECLS
+
+#endif /*!__OPENCHANGETOOLS_H__ */
Added: trunk/openchange/utils/openchangeclient.c
===================================================================
--- trunk/openchange/utils/openchangeclient.c (rev 0)
+++ trunk/openchange/utils/openchangeclient.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,3366 @@
+/*
+ Stand-alone MAPI application
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2007-2008
+
+ 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/defs_private.h>
+#include <libocpf/ocpf.h>
+#include <samba/popt.h>
+#include <param.h>
+
+#include "openchangeclient.h"
+#include "openchange-tools.h"
+
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <time.h>
+#include <ctype.h>
+
+/**
+ * init sendmail struct
+ */
+
+static void init_oclient(struct oclient *oclient)
+{
+ /* update and delete parameter */
+ oclient->update = NULL;
+ oclient->delete = NULL;
+
+ /* properties list */
+ oclient->props = NULL;
+
+ /* email related parameter */
+ oclient->subject = NULL;
+ oclient->pr_body = NULL;
+ oclient->pr_html_inline = NULL;
+ oclient->attach = NULL;
+ oclient->attach_num = 0;
+ oclient->store_folder = NULL;
+
+ /* appointment related parameters */
+ oclient->location = NULL;
+ oclient->dtstart = NULL;
+ oclient->dtend = NULL;
+ oclient->busystatus = -1;
+ oclient->label = -1;
+ oclient->private = false;
+ oclient->freebusy = NULL;
+ oclient->force = false;
+
+ /* contact related parameters */
+ oclient->email = NULL;
+ oclient->full_name = NULL;
+ oclient->card_name = NULL;
+
+ /* task related parameters */
+ oclient->importance = -1;
+ oclient->taskstatus = -1;
+
+ /* note related parameters */
+ oclient->color = -1;
+ oclient->width = -1;
+ oclient->height = -1;
+
+ /* pf related parameters */
+ oclient->pf = false;
+
+ /* folder related parameters */
+ oclient->folder = NULL;
+ oclient->folder_name = NULL;
+ oclient->folder_comment = NULL;
+
+ /* ocpf related parameters */
+ oclient->ocpf_files = NULL;
+ oclient->ocpf_dump = NULL;
+}
+
+static char *utf8tolinux(TALLOC_CTX *mem_ctx, const char *wstring)
+{
+ char *newstr;
+
+ newstr = windows_to_utf8(mem_ctx, wstring);
+ return newstr;
+}
+
+static enum MAPISTATUS openchangeclient_getdir(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_container,
+ mapi_object_t *obj_child,
+ const char *path)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray = NULL;
+ struct SRowSet SRowSet;
+ mapi_object_t obj_htable;
+ mapi_object_t obj_folder;
+ char *newname;
+ char **folder = NULL;
+ const char *name;
+ const uint64_t *fid;
+ const uint32_t *child;
+ bool found = false;
+ uint32_t index;
+ uint32_t i;
+
+ /* Step 1. Extract the folder list from full path */
+ folder = str_list_make(mem_ctx, path, "/");
+ mapi_object_copy(&obj_folder, obj_container);
+
+ for (i = 0; folder[i]; i++) {
+ found = false;
+
+ mapi_object_init(&obj_htable);
+ retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, NULL);
+ MAPI_RETVAL_IF(retval, GetLastError(), folder);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x3,
+ PR_DISPLAY_NAME,
+ PR_FID,
+ PR_FOLDER_CHILD_COUNT);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, retval, folder);
+
+ while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND) && SRowSet.cRows) {
+ for (index = 0; (index < SRowSet.cRows) && (found == false); index++) {
+ fid = (const uint64_t *)find_SPropValue_data(&SRowSet.aRow[index], PR_FID);
+ name = (const char *)find_SPropValue_data(&SRowSet.aRow[index], PR_DISPLAY_NAME);
+ child = (const uint32_t *)find_SPropValue_data(&SRowSet.aRow[index], PR_FOLDER_CHILD_COUNT);
+
+ newname = utf8tolinux(mem_ctx, name);
+ if (newname && fid && !strcmp(newname, folder[i])) {
+ retval = OpenFolder(&obj_folder, *fid, obj_child);
+ MAPI_RETVAL_IF(retval, retval, folder);
+
+ found = true;
+ mapi_object_copy(&obj_folder, obj_child);
+ }
+ MAPIFreeBuffer(newname);
+ }
+ }
+
+ mapi_object_release(&obj_htable);
+ }
+
+ talloc_free(folder);
+ MAPI_RETVAL_IF(found == false, MAPI_E_NOT_FOUND, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+static enum MAPISTATUS openchangeclient_getpfdir(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_store,
+ mapi_object_t *obj_child,
+ const char *name)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_pf;
+ mapi_id_t id_pf;
+
+ retval = GetDefaultPublicFolder(obj_store, &id_pf, olFolderPublicIPMSubtree);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ mapi_object_init(&obj_pf);
+ retval = OpenFolder(obj_store, id_pf, &obj_pf);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ retval = openchangeclient_getdir(mem_ctx, &obj_pf, obj_child, name);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * read a file and store it in the appropriate structure element
+ */
+
+static bool oclient_read_file(TALLOC_CTX *mem_ctx, const char *filename,
+ struct oclient *oclient, uint32_t mapitag)
+{
+ struct stat sb;
+ int fd;
+
+ /* stat the file */
+ if (stat(filename, &sb) != 0) return false;
+ if ((fd = open(filename, O_RDONLY)) == -1) {
+ printf("Error while opening %s\n", filename);
+ return false;
+ }
+
+ switch (mapitag) {
+ case PR_HTML:
+ oclient->pr_html.lpb = talloc_size(mem_ctx, sb.st_size);
+ oclient->pr_html.cb = read(fd, oclient->pr_html.lpb, sb.st_size);
+ close(fd);
+ break;
+ case PR_ATTACH_DATA_BIN:
+ oclient->attach[oclient->attach_num].filename = talloc_strdup(mem_ctx, filename);
+ oclient->attach[oclient->attach_num].bin.lpb = talloc_size(mem_ctx, sb.st_size);
+ oclient->attach[oclient->attach_num].bin.cb = sb.st_size;
+ if ((oclient->attach[oclient->attach_num].bin.lpb = mmap(NULL, sb.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0)) == (void *) -1) {
+ perror("mmap");
+ close(fd);
+ return false;
+ }
+ oclient->attach[oclient->attach_num].fd = fd;
+ printf("filename = %s (size = %u / %u)\n", filename, oclient->attach[oclient->attach_num].bin.cb, (uint32_t)sb.st_size);
+ close(fd);
+ break;
+ default:
+ printf("unsupported MAPITAG: %s\n", get_proptag_name(mapitag));
+ close(fd);
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+/**
+ * Parse attachments and load their content
+ */
+static bool oclient_parse_attachments(TALLOC_CTX *mem_ctx, const char *filename,
+ struct oclient *oclient)
+{
+ char **filenames;
+ char *tmp = NULL;
+ uint32_t j;
+
+ if ((tmp = strtok((char *)filename, ";")) == NULL) {
+ printf("Invalid string format [;]\n");
+ return false;
+ }
+
+ filenames = talloc_array(mem_ctx, char *, 2);
+ filenames[0] = strdup(tmp);
+
+ for (j = 1; (tmp = strtok(NULL, ";")) != NULL; j++) {
+ filenames = talloc_realloc(mem_ctx, filenames, char *, j+2);
+ filenames[j] = strdup(tmp);
+ }
+ filenames[j] = 0;
+ oclient->attach = talloc_array(mem_ctx, struct attach, j);
+
+ for (j = 0; filenames[j]; j++) {
+ oclient->attach_num = j;
+ if (oclient_read_file(mem_ctx, filenames[j], oclient, PR_ATTACH_DATA_BIN) == false) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+static const char *get_filename(const char *filename)
+{
+ const char *substr;
+
+ if (!filename) return NULL;
+
+ substr = rindex(filename, '/');
+ if (substr) return substr;
+
+ return filename;
+}
+
+
+/**
+ * build unique ID from folder and message
+ */
+static char *build_uniqueID(TALLOC_CTX *mem_ctx, mapi_object_t *obj_folder,
+ mapi_object_t *obj_message)
+{
+ enum MAPISTATUS retval;
+ char *id;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProps;
+ uint32_t count;
+ const uint64_t *mid;
+ const uint64_t *fid;
+
+ /* retrieve the folder ID */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_FID);
+ retval = GetProps(obj_folder, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) return NULL;
+ fid = (const uint64_t *)get_SPropValue_data(lpProps);
+
+ /* retrieve the message ID */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_MID);
+ retval = GetProps(obj_message, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+ if (GetLastError() != MAPI_E_SUCCESS) return NULL;
+ mid = (const uint64_t *)get_SPropValue_data(lpProps);
+
+ if (!fid || !mid) return NULL;
+
+ id = talloc_asprintf(mem_ctx, "%"PRIX64"/%"PRIX64, *fid, *mid);
+ return id;
+}
+
+
+/**
+ * fetch the user INBOX
+ */
+
+#define MAX_READ_SIZE 0x1000
+
+static bool store_attachment(mapi_object_t obj_attach, const char *filename, uint32_t size, struct oclient *oclient)
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ ssize_t len;
+ char *path;
+ mapi_object_t obj_stream;
+ uint16_t read_size;
+ int fd;
+ DIR *dir;
+ unsigned char buf[MAX_READ_SIZE];
+
+ if (!filename || !size) return false;
+
+ mem_ctx = talloc_named(NULL, 0, "store_attachment");
+ mapi_object_init(&obj_stream);
+
+ if (!(dir = opendir(oclient->store_folder))) {
+ if (mkdir(oclient->store_folder, 0700) == -1) return false;
+ } else {
+ closedir(dir);
+ }
+
+ path = talloc_asprintf(mem_ctx, "%s/%s", oclient->store_folder, filename);
+ if ((fd = open(path, O_CREAT|O_WRONLY, S_IWUSR|S_IRUSR)) == -1) return false;
+ talloc_free(path);
+
+ retval = OpenStream(&obj_attach, PR_ATTACH_DATA_BIN, 0, &obj_stream);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ read_size = 0;
+ do {
+ retval = ReadStream(&obj_stream, buf, MAX_READ_SIZE, &read_size);
+ if (retval != MAPI_E_SUCCESS) goto error;
+ len = write(fd, buf, read_size);
+ } while (read_size);
+
+ close(fd);
+
+ mapi_object_release(&obj_stream);
+ close(fd);
+ talloc_free(mem_ctx);
+ return true;
+
+error:
+ mapi_object_release(&obj_stream);
+ close(fd);
+ talloc_free(mem_ctx);
+ return false;
+}
+
+static enum MAPISTATUS openchangeclient_fetchmail(mapi_object_t *obj_store,
+ struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ bool status;
+ TALLOC_CTX *mem_ctx;
+ mapi_object_t obj_tis;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_message;
+ mapi_object_t obj_table;
+ mapi_object_t obj_tb_attach;
+ mapi_object_t obj_attach;
+ uint64_t id_inbox;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet rowset;
+ struct SRowSet rowset_attach;
+ uint32_t i, j;
+ uint32_t count;
+ const uint8_t *has_attach;
+ const uint32_t *attach_num;
+ const char *attach_filename;
+ const uint32_t *attach_size;
+
+ mem_ctx = talloc_named(NULL, 0, "openchangeclient_fetchmail");
+
+ mapi_object_init(&obj_tis);
+ mapi_object_init(&obj_inbox);
+ mapi_object_init(&obj_table);
+
+ if (oclient->pf == true) {
+ retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_inbox, oclient->folder);
+ MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
+ } else {
+ if (oclient->folder) {
+ retval = GetDefaultFolder(obj_store, &id_inbox, olFolderTopInformationStore);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = OpenFolder(obj_store, id_inbox, &obj_tis);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = openchangeclient_getdir(mem_ctx, &obj_tis, &obj_inbox, oclient->folder);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+ } else {
+ retval = GetReceiveFolder(obj_store, &id_inbox, NULL);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = OpenFolder(obj_store, id_inbox, &obj_inbox);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+ }
+ }
+
+ retval = GetContentsTable(&obj_inbox, &obj_table, 0, &count);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ printf("MAILBOX (%u messages)\n", count);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ while ((retval = QueryRows(&obj_table, count, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND && rowset.cRows) {
+ count -= rowset.cRows;
+ for (i = 0; i < rowset.cRows; i++) {
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(obj_store,
+ rowset.aRow[i].lpProps[0].value.d,
+ rowset.aRow[i].lpProps[1].value.d,
+ &obj_message, 0);
+ if (GetLastError() == MAPI_E_SUCCESS) {
+ struct SPropValue *lpProps;
+ struct SRow aRow;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_HASATTACH);
+ lpProps = talloc_zero(mem_ctx, struct SPropValue);
+ retval = GetProps(&obj_message, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ aRow.ulAdrEntryPad = 0;
+ aRow.cValues = count;
+ aRow.lpProps = lpProps;
+
+ retval = octool_message(mem_ctx, &obj_message);
+
+ has_attach = (const uint8_t *) get_SPropValue_SRow_data(&aRow, PR_HASATTACH);
+
+ /* If we have attachments, retrieve them */
+ if (has_attach && *has_attach) {
+ mapi_object_init(&obj_tb_attach);
+ retval = GetAttachmentTable(&obj_message, &obj_tb_attach);
+ if (retval == MAPI_E_SUCCESS) {
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_ATTACH_NUM);
+ retval = SetColumns(&obj_tb_attach, SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ MAPIFreeBuffer(SPropTagArray);
+
+ retval = QueryRows(&obj_tb_attach, 0xa, TBL_ADVANCE, &rowset_attach);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ for (j = 0; j < rowset_attach.cRows; j++) {
+ attach_num = (const uint32_t *)find_SPropValue_data(&(rowset_attach.aRow[j]), PR_ATTACH_NUM);
+ retval = OpenAttach(&obj_message, *attach_num, &obj_attach);
+ if (retval == MAPI_E_SUCCESS) {
+ struct SPropValue *lpProps2;
+ uint32_t count2;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x3,
+ PR_ATTACH_FILENAME,
+ PR_ATTACH_LONG_FILENAME,
+ PR_ATTACH_SIZE);
+ lpProps2 = talloc_zero(mem_ctx, struct SPropValue);
+ retval = GetProps(&obj_attach, SPropTagArray, &lpProps2, &count2);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ aRow.ulAdrEntryPad = 0;
+ aRow.cValues = count2;
+ aRow.lpProps = lpProps2;
+
+ attach_filename = get_filename(octool_get_propval(&aRow, PR_ATTACH_LONG_FILENAME));
+ if (!attach_filename || (attach_filename && !strcmp(attach_filename, ""))) {
+ attach_filename = get_filename(octool_get_propval(&aRow, PR_ATTACH_FILENAME));
+ }
+ attach_size = (const uint32_t *) octool_get_propval(&aRow, PR_ATTACH_SIZE);
+ printf("[%u] %s (%u Bytes)\n", j, attach_filename, attach_size ? *attach_size : 0);
+ fflush(0);
+ if (oclient->store_folder) {
+ status = store_attachment(obj_attach, attach_filename, *attach_size, oclient);
+ if (status == false) {
+ printf("A Problem was encountered while storing attachments on the filesystem\n");
+ MAPI_RETVAL_IF(status == false, MAPI_E_UNABLE_TO_COMPLETE, mem_ctx);
+
+ }
+ }
+ MAPIFreeBuffer(lpProps2);
+ }
+ }
+ errno = 0;
+ }
+ MAPIFreeBuffer(lpProps);
+ }
+ }
+ mapi_object_release(&obj_message);
+ }
+ }
+
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_inbox);
+ mapi_object_release(&obj_tis);
+
+ talloc_free(mem_ctx);
+
+ errno = 0;
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * send a mail to a user whom belongs to the Exchange organization
+ */
+
+static char **get_cmdline_recipients(TALLOC_CTX *mem_ctx, const char *recipients)
+{
+ char **usernames;
+ char *tmp = NULL;
+ uint32_t j = 0;
+
+ /* no recipients */
+ if (!recipients) {
+ return NULL;
+ }
+
+ if ((tmp = strtok((char *)recipients, ",")) == NULL) {
+ DEBUG(2, ("Invalid recipient string format\n"));
+ return NULL;
+ }
+
+ usernames = talloc_array(mem_ctx, char *, 2);
+ usernames[0] = strdup(tmp);
+
+ for (j = 1; (tmp = strtok(NULL, ",")) != NULL; j++) {
+ usernames = talloc_realloc(mem_ctx, usernames, char *, j+2);
+ usernames[j] = strdup(tmp);
+ }
+ usernames[j] = 0;
+
+ return (usernames);
+}
+
+/**
+ * We set external recipients at the end of aRow
+ */
+static bool set_external_recipients(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, const char *username, enum ulRecipClass RecipClass)
+{
+ uint32_t last;
+ struct SPropValue SPropValue;
+
+ SRowSet->aRow = talloc_realloc(mem_ctx, SRowSet->aRow, struct SRow, SRowSet->cRows + 2);
+ last = SRowSet->cRows;
+ SRowSet->aRow[last].cValues = 0;
+ SRowSet->aRow[last].lpProps = talloc_zero(mem_ctx, struct SPropValue);
+
+ /* PR_OBJECT_TYPE */
+ SPropValue.ulPropTag = PR_OBJECT_TYPE;
+ SPropValue.value.l = MAPI_MAILUSER;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_DISPLAY_TYPE */
+ SPropValue.ulPropTag = PR_DISPLAY_TYPE;
+ SPropValue.value.l = 0;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_GIVEN_NAME */
+ SPropValue.ulPropTag = PR_GIVEN_NAME;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_DISPLAY_NAME */
+ SPropValue.ulPropTag = PR_DISPLAY_NAME;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_7BIT_DISPLAY_NAME */
+ SPropValue.ulPropTag = PR_7BIT_DISPLAY_NAME;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_SMTP_ADDRESS */
+ SPropValue.ulPropTag = PR_SMTP_ADDRESS;
+ SPropValue.value.lpszA = username;
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ /* PR_ADDRTYPE */
+ SPropValue.ulPropTag = PR_ADDRTYPE;
+ SPropValue.value.lpszA = "SMTP";
+ SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
+
+ SetRecipientType(&(SRowSet->aRow[last]), RecipClass);
+
+ SRowSet->cRows += 1;
+ return true;
+}
+
+static bool set_usernames_RecipientType(TALLOC_CTX *mem_ctx, uint32_t *index, struct SRowSet *rowset,
+ char **usernames, struct SPropTagArray *flaglist,
+ enum ulRecipClass RecipClass)
+{
+ uint32_t i;
+ uint32_t count = *index;
+ static uint32_t counter = 0;
+
+ if (count == 0) counter = 0;
+ if (!usernames) return false;
+
+ for (i = 0; usernames[i]; i++) {
+ if (flaglist->aulPropTag[count] == MAPI_UNRESOLVED) {
+ set_external_recipients(mem_ctx, rowset, usernames[i], RecipClass);
+ }
+ if (flaglist->aulPropTag[count] == MAPI_RESOLVED) {
+ SetRecipientType(&(rowset->aRow[counter]), RecipClass);
+ counter++;
+ }
+ count++;
+ }
+
+ *index = count;
+
+ return true;
+}
+
+static char **collapse_recipients(TALLOC_CTX *mem_ctx, struct oclient *oclient)
+{
+ uint32_t count;
+ uint32_t i;
+ char **usernames;
+
+ if (!oclient->mapi_to && !oclient->mapi_cc && !oclient->mapi_bcc) return NULL;
+
+ count = 0;
+ for (i = 0; oclient->mapi_to && oclient->mapi_to[i]; i++, count++);
+ for (i = 0; oclient->mapi_cc && oclient->mapi_cc[i]; i++, count++);
+ for (i = 0; oclient->mapi_bcc && oclient->mapi_bcc[i]; i++, count++);
+
+ usernames = talloc_array(mem_ctx, char *, count + 1);
+ count = 0;
+
+ for (i = 0; oclient->mapi_to && oclient->mapi_to[i]; i++, count++) {
+ usernames[count] = talloc_strdup(mem_ctx, oclient->mapi_to[i]);
+ }
+
+ for (i = 0; oclient->mapi_cc && oclient->mapi_cc[i]; i++, count++) {
+ usernames[count] = talloc_strdup(mem_ctx, oclient->mapi_cc[i]);
+ }
+
+ for (i = 0; oclient->mapi_bcc && oclient->mapi_bcc[i]; i++, count++) {
+ usernames[count] = talloc_strdup(mem_ctx, oclient->mapi_bcc[i]);
+ }
+
+ usernames[count++] = 0;
+
+ return usernames;
+}
+
+/**
+ * Write a stream with MAX_READ_SIZE chunks
+ */
+
+#define MAX_READ_SIZE 0x1000
+
+static bool openchangeclient_stream(TALLOC_CTX *mem_ctx, mapi_object_t obj_parent,
+ mapi_object_t obj_stream, uint32_t mapitag,
+ uint32_t access_flags, struct Binary_r bin)
+{
+ enum MAPISTATUS retval;
+ DATA_BLOB stream;
+ uint32_t size;
+ uint32_t offset;
+ uint16_t read_size;
+
+ /* Open a stream on the parent for the given property */
+ retval = OpenStream(&obj_parent, mapitag, access_flags, &obj_stream);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* WriteStream operation */
+ printf("We are about to write %u bytes in the stream\n", bin.cb);
+ size = MAX_READ_SIZE;
+ offset = 0;
+ while (offset <= bin.cb) {
+ stream.length = size;
+ stream.data = talloc_size(mem_ctx, size);
+ memcpy(stream.data, bin.lpb + offset, size);
+
+ retval = WriteStream(&obj_stream, &stream, &read_size);
+ talloc_free(stream.data);
+ if (retval != MAPI_E_SUCCESS) return false;
+ printf(".");
+ fflush(0);
+
+ /* Exit when there is nothing left to write */
+ if (!read_size) return true;
+
+ offset += read_size;
+
+ if ((offset + size) > bin.cb) {
+ size = bin.cb - offset;
+ }
+ }
+
+ return true;
+}
+
+
+#define SETPROPS_COUNT 4
+
+/**
+ * Send a mail
+ */
+
+static enum MAPISTATUS openchangeclient_sendmail(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_store,
+ struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue SPropValue;
+ struct SRowSet *SRowSet = NULL;
+ struct SPropTagArray *flaglist = NULL;
+ mapi_id_t id_outbox;
+ mapi_object_t obj_outbox;
+ mapi_object_t obj_message;
+ mapi_object_t obj_stream;
+ uint32_t index = 0;
+ uint32_t msgflag;
+ struct SPropValue props[SETPROPS_COUNT];
+ uint32_t prop_count = 0;
+ uint32_t editor = 0;
+
+ mapi_object_init(&obj_outbox);
+ mapi_object_init(&obj_message);
+
+ if (oclient->pf == true) {
+ retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_outbox, oclient->folder);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ } else {
+ /* Get Sent Items folder but should be using olFolderOutbox */
+ retval = GetDefaultFolder(obj_store, &id_outbox, olFolderSentMail);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ /* Open outbox folder */
+ retval = OpenFolder(obj_store, id_outbox, &obj_outbox);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ }
+
+ /* Create the message */
+ retval = CreateMessage(&obj_outbox, &obj_message);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ /* Recipients operations */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
+ PR_OBJECT_TYPE,
+ PR_DISPLAY_TYPE,
+ PR_7BIT_DISPLAY_NAME,
+ PR_DISPLAY_NAME,
+ PR_SMTP_ADDRESS,
+ PR_GIVEN_NAME);
+
+ oclient->usernames = collapse_recipients(mem_ctx, oclient);
+
+ /* ResolveNames */
+ retval = ResolveNames(mapi_object_get_session(&obj_message), (const char **)oclient->usernames,
+ SPropTagArray, &SRowSet, &flaglist, 0);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ if (!SRowSet) {
+ SRowSet = talloc_zero(mem_ctx, struct SRowSet);
+ }
+
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, oclient->mapi_to, flaglist, MAPI_TO);
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, oclient->mapi_cc, flaglist, MAPI_CC);
+ set_usernames_RecipientType(mem_ctx, &index, SRowSet, oclient->mapi_bcc, flaglist, MAPI_BCC);
+
+ SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
+ SPropValue.value.l = 0;
+ SRowSet_propcpy(mem_ctx, SRowSet, SPropValue);
+
+ /* ModifyRecipients operation */
+ retval = ModifyRecipients(&obj_message, SRowSet);
+ MAPIFreeBuffer(SRowSet);
+ MAPIFreeBuffer(flaglist);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ /* set message properties */
+ msgflag = MSGFLAG_UNSENT;
+ oclient->subject = (!oclient->subject) ? "" : oclient->subject;
+ set_SPropValue_proptag(&props[0], PR_SUBJECT,
+ (const void *)oclient->subject);
+ set_SPropValue_proptag(&props[1], PR_MESSAGE_FLAGS,
+ (const void *)&msgflag);
+ prop_count = 2;
+
+ /* Set PR_BODY or PR_HTML or inline PR_HTML */
+ if (oclient->pr_body) {
+ editor = EDITOR_FORMAT_PLAINTEXT;
+ set_SPropValue_proptag(&props[3], PR_MSG_EDITOR_FORMAT, (const void *)&editor);
+
+ if (strlen(oclient->pr_body) > MAX_READ_SIZE) {
+ struct Binary_r bin;
+
+ bin.lpb = (uint8_t *)oclient->pr_body;
+ bin.cb = strlen(oclient->pr_body);
+ openchangeclient_stream(mem_ctx, obj_message, obj_stream, PR_BODY, 2, bin);
+ } else {
+ set_SPropValue_proptag(&props[2], PR_BODY,
+ (const void *)oclient->pr_body);
+ prop_count++;
+ }
+ } else if (oclient->pr_html_inline) {
+ editor = EDITOR_FORMAT_HTML;
+ set_SPropValue_proptag(&props[3], PR_MSG_EDITOR_FORMAT, (const void *)&editor);
+
+ if (strlen(oclient->pr_html_inline) > MAX_READ_SIZE) {
+ struct Binary_r bin;
+
+ bin.lpb = (uint8_t *)oclient->pr_html_inline;
+ bin.cb = strlen(oclient->pr_html_inline);
+ openchangeclient_stream(mem_ctx, obj_message, obj_stream, PR_HTML, 2, bin);
+ } else {
+ struct SBinary_short bin;
+
+ bin.cb = strlen(oclient->pr_html_inline);
+ bin.lpb = (uint8_t *)oclient->pr_html_inline;
+ set_SPropValue_proptag(&props[2], PR_HTML, (void *)&bin);
+ prop_count++;
+ }
+
+ } else if (&oclient->pr_html) {
+ editor = EDITOR_FORMAT_HTML;
+ set_SPropValue_proptag(&props[3], PR_MSG_EDITOR_FORMAT, (const void *)&editor);
+
+ if (oclient->pr_html.cb <= MAX_READ_SIZE) {
+ struct SBinary_short bin;
+
+ bin.cb = oclient->pr_html.cb;
+ bin.lpb = oclient->pr_html.lpb;
+
+ set_SPropValue_proptag(&props[2], PR_HTML, (void *)&bin);
+ prop_count++;
+ } else {
+ mapi_object_init(&obj_stream);
+ openchangeclient_stream(mem_ctx, obj_message, obj_stream, PR_HTML, 2, oclient->pr_html);
+ mapi_object_release(&obj_stream);
+ }
+ }
+
+ retval = SetProps(&obj_message, props, prop_count);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ /* attachment related code */
+ if (oclient->attach) {
+ uint32_t i;
+
+ for (i = 0; oclient->attach[i].filename; i++) {
+ mapi_object_t obj_attach;
+ mapi_object_t obj_stream;
+ struct SPropValue props_attach[3];
+ uint32_t count_props_attach;
+
+ mapi_object_init(&obj_attach);
+
+ retval = CreateAttach(&obj_message, &obj_attach);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ props_attach[0].ulPropTag = PR_ATTACH_METHOD;
+ props_attach[0].value.l = ATTACH_BY_VALUE;
+ props_attach[1].ulPropTag = PR_RENDERING_POSITION;
+ props_attach[1].value.l = 0;
+ props_attach[2].ulPropTag = PR_ATTACH_FILENAME;
+ printf("Sending %s:\n", oclient->attach[i].filename);
+ props_attach[2].value.lpszA = get_filename(oclient->attach[i].filename);
+ count_props_attach = 3;
+
+ /* SetProps */
+ retval = SetProps(&obj_attach, props_attach, count_props_attach);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ /* Stream operations */
+ openchangeclient_stream(mem_ctx, obj_attach, obj_stream, PR_ATTACH_DATA_BIN, 2, oclient->attach[i].bin);
+
+ /* Save changes on attachment */
+ retval = SaveChangesAttachment(&obj_message, &obj_attach, KeepOpenReadWrite);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ mapi_object_release(&obj_attach);
+ }
+ }
+
+ if (oclient->pf) {
+ retval = SaveChangesMessage(&obj_outbox, &obj_message, KeepOpenReadOnly);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ } else {
+ /* Submit the message */
+ retval = SubmitMessage(&obj_message);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ }
+
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_outbox);
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * delete a mail from user INBOX
+ */
+static bool openchangeclient_deletemail(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_store,
+ struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ mapi_id_t id_inbox;
+ mapi_id_t *id_messages;
+ uint32_t count_messages;
+ uint32_t count_rows;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_table;
+ uint32_t len;
+ uint32_t i;
+
+ if (!oclient->subject) {
+ printf("You need to specify at least a message subject pattern\n");
+ MAPI_RETVAL_IF(!oclient->subject, MAPI_E_INVALID_PARAMETER, NULL);
+ }
+
+ mapi_object_init(&obj_inbox);
+ mapi_object_init(&obj_table);
+
+ if (oclient->pf == true) {
+ retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_inbox, oclient->folder);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ } else {
+ retval = GetReceiveFolder(obj_store, &id_inbox, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(obj_store, id_inbox, &obj_inbox);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+
+ retval = GetContentsTable(&obj_inbox, &obj_table, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ while ((retval = QueryRows(&obj_table, 0x10, TBL_ADVANCE, &SRowSet)) == MAPI_E_SUCCESS) {
+ count_rows = SRowSet.cRows;
+ if (!count_rows) break;
+ id_messages = talloc_array(mem_ctx, uint64_t, count_rows);
+ count_messages = 0;
+
+ len = strlen(oclient->subject);
+
+ for (i = 0; i < count_rows; i++) {
+ if (!strncmp(SRowSet.aRow[i].lpProps[4].value.lpszA, oclient->subject, len)) {
+ id_messages[count_messages] = SRowSet.aRow[i].lpProps[1].value.d;
+ count_messages++;
+ }
+ }
+ if (count_messages) {
+ retval = DeleteMessage(&obj_inbox, id_messages, count_messages);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+ }
+
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_inbox);
+
+ return true;
+}
+
+
+static enum MAPISTATUS check_conflict_date(mapi_object_t *obj,
+ struct FILETIME *ft)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_store;
+ struct mapi_session *session;
+ struct mapi_session *session2;
+ bool conflict;
+
+ session = mapi_object_get_session(obj);
+ retval = MapiLogonEx(&session2, session->profile->profname, session->profile->password);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ mapi_object_init(&obj_store);
+ retval = OpenPublicFolder(session2, &obj_store);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ retval = IsFreeBusyConflict(&obj_store, ft, &conflict);
+ Logoff(&obj_store);
+
+ if (conflict == true) {
+ printf("[WARNING]: This start date conflicts with another appointment\n");
+ return MAPI_E_INVALID_PARAMETER;
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ * Send appointment
+ */
+
+static enum MAPISTATUS appointment_SetProps(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_message,
+ struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ struct SPropValue *lpProps;
+ struct FILETIME *start_date;
+ struct FILETIME *end_date;
+ uint32_t cValues = 0;
+ NTTIME nt;
+ struct tm tm;
+ uint32_t flag;
+ uint8_t flag2;
+
+ cValues = 0;
+ lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
+
+ if (oclient->subject) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_CONVERSATION_TOPIC,
+ (const void *) oclient->subject);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_NORMALIZED_SUBJECT,
+ (const void *) oclient->subject);
+ }
+ if (oclient->pr_body) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_BODY, (const void *)oclient->pr_body);
+ }
+ if (oclient->location) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidLocation, (const void *)oclient->location);
+ }
+ if (oclient->dtstart) {
+ if (!strptime(oclient->dtstart, DATE_FORMAT, &tm)) {
+ printf("Invalid date format: yyyy-mm-dd hh:mm:ss (e.g.: 2007-09-17 10:00:00)\n");
+ return MAPI_E_INVALID_PARAMETER;
+ }
+ unix_to_nt_time(&nt, mktime(&tm));
+ start_date = talloc(mem_ctx, struct FILETIME);
+ start_date->dwLowDateTime = (nt << 32) >> 32;
+ start_date->dwHighDateTime = (nt >> 32);
+
+ retval = check_conflict_date(obj_folder, start_date);
+ if (oclient->force == false) {
+ MAPI_RETVAL_IF(retval, retval, NULL);
+ }
+
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_START_DATE, (const void *)start_date);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidCommonStart, (const void *)start_date);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidAppointmentStartWhole, (const void *) start_date);
+ }
+ if (oclient->dtend) {
+ if (!strptime(oclient->dtend, DATE_FORMAT, &tm)) {
+ printf("Invalid date format: yyyy-mm-dd hh:mm:ss (e.g.:2007-09-17 18:30:00)\n");
+ return MAPI_E_INVALID_PARAMETER;
+ }
+ unix_to_nt_time(&nt, mktime(&tm));
+ end_date = talloc(mem_ctx, struct FILETIME);
+ end_date->dwLowDateTime = (nt << 32) >> 32;
+ end_date->dwHighDateTime = (nt >> 32);
+
+ retval = check_conflict_date(obj_folder, end_date);
+ if (oclient->force == false) {
+ MAPI_RETVAL_IF(retval, retval, NULL);
+ }
+
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_END_DATE, (const void *) end_date);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidCommonEnd, (const void *) end_date);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidAppointmentEndWhole, (const void *) end_date);
+ }
+
+ if (!oclient->update) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_CLASS, (const void *)"IPM.Appointment");
+
+ flag = 1;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_FLAGS, (const void *)&flag);
+
+ flag= MEETING_STATUS_NONMEETING;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidAppointmentStateFlags, (const void *) &flag);
+
+ flag = 30;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidReminderDelta, (const void *)&flag);
+
+ /* WARNING needs to replace private */
+ flag2 = oclient->private;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidPrivate, (const void *)&flag2);
+
+ oclient->label = (oclient->label == -1) ? 0 : oclient->label;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidAppointmentColor, (const void *) &oclient->label);
+
+ oclient->busystatus = (oclient->busystatus == -1) ? 0 : oclient->busystatus;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidBusyStatus, (const void *) &oclient->busystatus);
+ } else {
+ if (oclient->busystatus != -1) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidBusyStatus, (const void *) &oclient->busystatus);
+ }
+ if (oclient->label != -1) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidAppointmentColor, (const void *) &oclient->label);
+ }
+ }
+
+ flag = (oclient->private == true) ? 2 : 0;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_SENSITIVITY, (const void *)&flag);
+
+ retval = SetProps(obj_message, lpProps, cValues);
+ MAPIFreeBuffer(lpProps);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+
+static bool openchangeclient_sendappointment(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_calendar;
+ mapi_object_t obj_message;
+ mapi_id_t id_calendar;
+ char *uniq_id;
+
+ mapi_object_init(&obj_calendar);
+
+ if (oclient->pf == true) {
+ retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_calendar, oclient->folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+ } else {
+ /* Open Calendar default folder */
+ retval = GetDefaultFolder(obj_store, &id_calendar, olFolderCalendar);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(obj_store, id_calendar, &obj_calendar);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+
+ /* Create calendar message */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_calendar, &obj_message);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Set calendar message properties */
+ retval = appointment_SetProps(mem_ctx, &obj_calendar, &obj_message, oclient);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = SaveChangesMessage(&obj_calendar, &obj_message, KeepOpenReadOnly);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Fetch and Display the message unique ID */
+ uniq_id = build_uniqueID(mem_ctx, &obj_calendar, &obj_message);
+ printf(" %-25s: %s\n", "Unique ID", uniq_id);
+ fflush(0);
+ talloc_free(uniq_id);
+
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_calendar);
+
+ return true;
+}
+
+/**
+ * Create a contact
+ */
+static enum MAPISTATUS contact_SetProps(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_message,
+ struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ struct SPropValue *lpProps;
+ struct mapi_nameid *nameid;
+ struct SPropTagArray *SPropTagArray;
+ uint32_t cValues = 0;
+
+ /* Build the list of named properties we want to set */
+ nameid = mapi_nameid_new(mem_ctx);
+ mapi_nameid_string_add(nameid, "urn:schemas:contacts:fileas", PS_PUBLIC_STRINGS);
+
+ /* GetIDsFromNames and map property types */
+ SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
+ retval = GetIDsFromNames(obj_folder, nameid->count,
+ nameid->nameid, 0, &SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ mapi_nameid_SPropTagArray(nameid, SPropTagArray);
+ MAPIFreeBuffer(nameid);
+
+ cValues = 0;
+ lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
+
+ if (oclient->card_name) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_NORMALIZED_SUBJECT, (const void *)oclient->card_name);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidFileUnder, (const void *)oclient->card_name);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, SPropTagArray->aulPropTag[0], (const void *)oclient->card_name);
+ }
+ if (oclient->full_name) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_DISPLAY_NAME, (const void *)oclient->full_name);
+ }
+ if (oclient->email) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidEmail1OriginalDisplayName, (const void *)oclient->email);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidEmail1EmailAddress, (const void *)oclient->email);
+ }
+ if (!oclient->update) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_CLASS, (const void *)"IPM.Contact");
+ }
+ retval = SetProps(obj_message, lpProps, cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPIFreeBuffer(lpProps);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+static bool openchangeclient_sendcontact(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_contact;
+ mapi_object_t obj_message;
+ mapi_id_t id_contact;
+ char *uniq_id;
+
+ mapi_object_init(&obj_contact);
+
+ if (oclient->pf == true) {
+ retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_contact, oclient->folder);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ } else {
+ /* Open Contact default folder */
+ retval = GetDefaultFolder(obj_store, &id_contact, olFolderContacts);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(obj_store, id_contact, &obj_contact);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+
+ /* Create contact mesage */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_contact, &obj_message);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Set contact message properties */
+ retval = contact_SetProps(mem_ctx, &obj_contact, &obj_message, oclient);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = SaveChangesMessage(&obj_contact, &obj_message, KeepOpenReadOnly);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Fetch and Display the message unique ID */
+ uniq_id = build_uniqueID(mem_ctx, &obj_contact, &obj_message);
+ printf(" %-25s: %s\n", "Unique ID", uniq_id);
+ fflush(0);
+ talloc_free(uniq_id);
+
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_contact);
+
+ return true;
+}
+
+/**
+ * Create task
+ */
+static enum MAPISTATUS task_SetProps(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_message,
+ struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ struct SPropValue *lpProps;
+ struct FILETIME *start_date;
+ struct FILETIME *end_date;
+ uint32_t cValues = 0;
+ NTTIME nt;
+ struct tm tm;
+
+ cValues = 0;
+ lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
+
+ if (oclient->card_name) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_CONVERSATION_TOPIC, (const void *)oclient->card_name);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_NORMALIZED_SUBJECT, (const void *)oclient->card_name);
+ }
+
+ if (oclient->dtstart) {
+ if (!strptime(oclient->dtstart, DATE_FORMAT, &tm)) {
+ printf("Invalid date format (e.g.: 2007-06-01 22:30:00)\n");
+ return MAPI_E_INVALID_PARAMETER;
+ }
+ unix_to_nt_time(&nt, mktime(&tm));
+ start_date = talloc(mem_ctx, struct FILETIME);
+ start_date->dwLowDateTime = (nt << 32) >> 32;
+ start_date->dwHighDateTime = (nt >> 32);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidTaskStartDate, (const void *)start_date);
+ }
+
+ if (oclient->dtend) {
+ if (!strptime(oclient->dtend, DATE_FORMAT, &tm)) {
+ printf("Invalid date format (e.g.: 2007-06-01 22:30:00)\n");
+ return MAPI_E_INVALID_PARAMETER;
+ }
+ unix_to_nt_time(&nt, mktime(&tm));
+ end_date = talloc(mem_ctx, struct FILETIME);
+ end_date->dwLowDateTime = (nt << 32) >> 32;
+ end_date->dwHighDateTime = (nt >> 32);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidTaskDueDate, (const void *)end_date);
+ }
+
+ if (oclient->pr_body) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_BODY, (const void *)oclient->pr_body);
+ }
+
+ if (!oclient->update) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_CLASS, (const void *)"IPM.Task");
+ oclient->importance = (oclient->importance == -1) ? 1 : oclient->importance;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_IMPORTANCE, (const void *)&oclient->importance);
+ oclient->taskstatus = (oclient->taskstatus == -1) ? 0 : oclient->taskstatus;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidTaskStatus, (const void *)&oclient->taskstatus);
+ } else {
+ if (oclient->importance != -1) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_IMPORTANCE, (const void *)&oclient->importance);
+ }
+ if (oclient->taskstatus != -1) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidTaskStatus, (const void *)&oclient->taskstatus);
+ }
+ }
+
+ retval = SetProps(obj_message, lpProps, cValues);
+ MAPIFreeBuffer(lpProps);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+static bool openchangeclient_sendtask(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_task;
+ mapi_object_t obj_message;
+ mapi_id_t id_task;
+ char *uniq_id;
+
+ mapi_object_init(&obj_task);
+
+ if (oclient->pf == true) {
+ retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_task, oclient->folder);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ } else {
+ /* Open Contact default folder */
+ retval = GetDefaultFolder(obj_store, &id_task, olFolderTasks);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(obj_store, id_task, &obj_task);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+
+ /* Create contact mesage */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_task, &obj_message);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Set contact properties */
+ retval = task_SetProps(mem_ctx, &obj_message, oclient);
+
+ retval = SaveChangesMessage(&obj_task, &obj_message, KeepOpenReadOnly);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Fetch and Display the message unique ID */
+ uniq_id = build_uniqueID(mem_ctx, &obj_task, &obj_message);
+ printf(" %-25s: %s\n", "Unique ID", uniq_id);
+ fflush(0);
+ talloc_free(uniq_id);
+
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_task);
+
+ return true;
+}
+
+
+/**
+ * Send notes
+ */
+static enum MAPISTATUS note_SetProps(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_message,
+ struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ struct SPropValue *lpProps;
+ uint32_t cValues = 0;
+ uint32_t value;
+
+ cValues = 0;
+ lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
+
+ if (oclient->card_name) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_CONVERSATION_TOPIC, (const void *)oclient->card_name);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_SUBJECT, (const void *)oclient->card_name);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_NORMALIZED_SUBJECT, (const void *)oclient->card_name);
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_BODY, (const void *)oclient->card_name);
+ }
+
+ if (!oclient->update) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_CLASS, (const void *)"IPM.StickyNote");
+
+ value = 1;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_FLAGS, (const void *)&value);
+
+ value = 768;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_ICON_INDEX, (const void *)&value);
+
+ value = 272;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidSideEffects, (const void *)&value);
+
+ oclient->color = (oclient->color == -1) ? olYellow : oclient->color;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteColor, (const void *)&oclient->color);
+
+ oclient->width = (oclient->width == -1) ? 166 : oclient->width;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteWidth, (const void *)&oclient->width);
+
+ oclient->height = (oclient->height == -1) ? 200 : oclient->height;
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteHeight, (const void *)&oclient->height);
+
+ } else {
+ if (oclient->color != -1) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteColor, (const void *)&oclient->color);
+ }
+ if (oclient->width != -1) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteWidth, (const void *)&oclient->width);
+ }
+ if (oclient->height != -1) {
+ lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteHeight, (const void *)&oclient->height);
+ }
+ }
+
+
+ retval = SetProps(obj_message, lpProps, cValues);
+ MAPIFreeBuffer(lpProps);
+ MAPI_RETVAL_IF(retval, retval, NULL);
+
+ return MAPI_E_SUCCESS;
+}
+
+static bool openchangeclient_sendnote(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_note;
+ mapi_object_t obj_message;
+ mapi_id_t id_note;
+ char *uniq_id;
+
+ mapi_object_init(&obj_note);
+
+ if (oclient->pf == true) {
+ retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_note, oclient->folder);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ } else {
+ /* Open Contact default folder */
+ retval = GetDefaultFolder(obj_store, &id_note, olFolderNotes);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(obj_store, id_note, &obj_note);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+
+ /* Create contact mesage */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_note, &obj_message);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Set Note message properties */
+ retval = note_SetProps(mem_ctx, &obj_message, oclient);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = SaveChangesMessage(&obj_note, &obj_message, KeepOpenReadOnly);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Fetch and Display the message unique ID */
+ uniq_id = build_uniqueID(mem_ctx, &obj_note, &obj_message);
+ printf(" %-25s: %s\n", "Unique ID", uniq_id);
+ fflush(0);
+ talloc_free(uniq_id);
+
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_note);
+
+ return true;
+}
+
+
+static const char *get_container_class(TALLOC_CTX *mem_ctx, mapi_object_t *parent, mapi_id_t folder_id)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_folder;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProps;
+ uint32_t count;
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(parent, folder_id, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_CONTAINER_CLASS);
+ retval = GetProps(&obj_folder, SPropTagArray, &lpProps, &count);
+ MAPIFreeBuffer(SPropTagArray);
+ if ((lpProps[0].ulPropTag != PR_CONTAINER_CLASS) || (retval != MAPI_E_SUCCESS)) {
+ errno = 0;
+ return IPF_NOTE;
+ }
+ return lpProps[0].value.lpszA;
+}
+
+static bool get_child_folders(TALLOC_CTX *mem_ctx, mapi_object_t *parent, mapi_id_t folder_id, int count)
+{
+ enum MAPISTATUS retval;
+ bool ret;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_htable;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet rowset;
+ const char *name;
+ char *newname;
+ const char *comment;
+ const uint32_t *total;
+ const uint32_t *unread;
+ const uint32_t *child;
+ uint32_t index;
+ const uint64_t *fid;
+ int i;
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(parent, folder_id, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_init(&obj_htable);
+ retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
+ PR_DISPLAY_NAME,
+ PR_FID,
+ PR_COMMENT,
+ PR_CONTENT_UNREAD,
+ PR_CONTENT_COUNT,
+ PR_FOLDER_CHILD_COUNT);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND) && rowset.cRows) {
+ for (index = 0; index < rowset.cRows; index++) {
+ fid = (const uint64_t *)find_SPropValue_data(&rowset.aRow[index], PR_FID);
+ name = (const char *)find_SPropValue_data(&rowset.aRow[index], PR_DISPLAY_NAME);
+ comment = (const char *)find_SPropValue_data(&rowset.aRow[index], PR_COMMENT);
+ total = (const uint32_t *)find_SPropValue_data(&rowset.aRow[index], PR_CONTENT_COUNT);
+ unread = (const uint32_t *)find_SPropValue_data(&rowset.aRow[index], PR_CONTENT_UNREAD);
+ child = (const uint32_t *)find_SPropValue_data(&rowset.aRow[index], PR_FOLDER_CHILD_COUNT);
+
+ for (i = 0; i < count; i++) {
+ printf("| ");
+ }
+ newname = utf8tolinux(mem_ctx, name);
+ printf("|---+ %-15s : %-20s (Total: %u / Unread: %u - Container class: %s) [FID: 0x%"PRIx64"]\n", newname, comment, *total, *unread,
+ get_container_class(mem_ctx, parent, *fid), *fid);
+ MAPIFreeBuffer(newname);
+ if (*child) {
+ ret = get_child_folders(mem_ctx, &obj_folder, *fid, count + 1);
+ if (ret == false) return ret;
+ }
+
+ }
+ }
+ return true;
+}
+
+static bool get_child_folders_pf(TALLOC_CTX *mem_ctx, mapi_object_t *parent, mapi_id_t folder_id, int count)
+{
+ enum MAPISTATUS retval;
+ bool ret;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_htable;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet rowset;
+ const char *name;
+ char *newname;
+ const uint32_t *child;
+ uint32_t index;
+ const uint64_t *fid;
+ int i;
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(parent, folder_id, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_init(&obj_htable);
+ retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x3,
+ PR_DISPLAY_NAME,
+ PR_FID,
+ PR_FOLDER_CHILD_COUNT);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND) && rowset.cRows) {
+ for (index = 0; index < rowset.cRows; index++) {
+ fid = (const uint64_t *)find_SPropValue_data(&rowset.aRow[index], PR_FID);
+ name = (const char *)find_SPropValue_data(&rowset.aRow[index], PR_DISPLAY_NAME);
+ child = (const uint32_t *)find_SPropValue_data(&rowset.aRow[index], PR_FOLDER_CHILD_COUNT);
+
+ for (i = 0; i < count; i++) {
+ printf("| ");
+ }
+ newname = utf8tolinux(mem_ctx, name);
+ printf("|---+ %-15s [FID: 0x%"PRIx64"]\n", newname, *fid);
+ MAPIFreeBuffer(newname);
+ if (*child) {
+ ret = get_child_folders_pf(mem_ctx, &obj_folder, *fid, count + 1);
+ if (ret == false) return ret;
+ }
+
+ }
+ }
+ return true;
+}
+
+
+static bool openchangeclient_pf(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store)
+{
+ enum MAPISTATUS retval;
+ mapi_id_t id_pubroot;
+
+ retval = GetDefaultPublicFolder(obj_store, &id_pubroot, olFolderPublicRoot);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ return get_child_folders_pf(mem_ctx, obj_store, id_pubroot, 0);
+}
+
+
+static bool openchangeclient_mailbox(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_store)
+{
+ enum MAPISTATUS retval;
+ mapi_id_t id_mailbox;
+ struct SPropTagArray *SPropTagArray;
+ struct SPropValue *lpProps;
+ uint32_t cValues;
+ const char *mailbox_name;
+ char *utf8_mailbox_name;
+
+ /* Retrieve the mailbox folder name */
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_DISPLAY_NAME);
+ retval = GetProps(obj_store, SPropTagArray, &lpProps, &cValues);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ if (lpProps[0].value.lpszA) {
+ mailbox_name = lpProps[0].value.lpszA;
+ } else {
+ return false;
+ }
+
+ /* Prepare the directory listing */
+ retval = GetDefaultFolder(obj_store, &id_mailbox, olFolderTopInformationStore);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ utf8_mailbox_name = utf8tolinux(mem_ctx, mailbox_name);
+ printf("+ %s\n", utf8_mailbox_name);
+ MAPIFreeBuffer(utf8_mailbox_name);
+ return get_child_folders(mem_ctx, obj_store, id_mailbox, 0);
+}
+
+static bool openchangeclient_fetchitems(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, const char *item,
+ struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_tis;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_table;
+ mapi_object_t obj_message;
+ mapi_id_t fid;
+ uint32_t olFolder = 0;
+ struct SRowSet SRowSet;
+ struct SPropTagArray *SPropTagArray;
+ struct mapi_SPropValue_array properties_array;
+ uint32_t count;
+ uint32_t i;
+ char *id;
+
+ if (!item) return false;
+
+ mapi_object_init(&obj_tis);
+ mapi_object_init(&obj_folder);
+
+ for (i = 0; defaultFolders[i].olFolder; i++) {
+ if (!strncasecmp(defaultFolders[i].container_class, item, strlen(defaultFolders[i].container_class))) {
+ olFolder = defaultFolders[i].olFolder;
+ }
+ }
+
+ if (!olFolder) return false;
+
+ if (oclient->pf == true) {
+ retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_folder, oclient->folder);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ } else {
+ if (oclient->folder) {
+ retval = GetDefaultFolder(obj_store, &fid, olFolderTopInformationStore);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = OpenFolder(obj_store, fid, &obj_tis);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+
+ retval = openchangeclient_getdir(mem_ctx, &obj_tis, &obj_folder, oclient->folder);
+ MAPI_RETVAL_IF(retval, retval, mem_ctx);
+ } else {
+ retval = GetDefaultFolder(obj_store, &fid, olFolder);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* We now open the folder */
+ retval = OpenFolder(obj_store, fid, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+ }
+
+ /* Operations on the folder */
+ mapi_object_init(&obj_table);
+ retval = GetContentsTable(&obj_folder, &obj_table, 0, &count);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ printf("MAILBOX (%u messages)\n", count);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x8,
+ PR_FID,
+ PR_MID,
+ PR_INST_ID,
+ PR_INSTANCE_NUM,
+ PR_SUBJECT,
+ PR_MESSAGE_CLASS,
+ PR_RULE_MSG_PROVIDER,
+ PR_RULE_MSG_NAME);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ while ((retval = QueryRows(&obj_table, count, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND && SRowSet.cRows) {
+ count -= SRowSet.cRows;
+ for (i = 0; i < SRowSet.cRows; i++) {
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(&obj_folder,
+ SRowSet.aRow[i].lpProps[0].value.d,
+ SRowSet.aRow[i].lpProps[1].value.d,
+ &obj_message, 0);
+ if (retval != MAPI_E_NOT_FOUND) {
+ retval = GetPropsAll(&obj_message, &properties_array);
+ if (retval == MAPI_E_SUCCESS) {
+ id = talloc_asprintf(mem_ctx, ": %"PRIX64"/%"PRIX64,
+ SRowSet.aRow[i].lpProps[0].value.d,
+ SRowSet.aRow[i].lpProps[1].value.d);
+ mapi_SPropValue_array_named(&obj_message,
+ &properties_array);
+ switch (olFolder) {
+ case olFolderInbox:
+ mapidump_message(&properties_array, id);
+ break;
+ case olFolderCalendar:
+ mapidump_appointment(&properties_array, id);
+ break;
+ case olFolderContacts:
+ mapidump_contact(&properties_array, id);
+ break;
+ case olFolderTasks:
+ mapidump_task(&properties_array, id);
+ break;
+ case olFolderNotes:
+ mapidump_note(&properties_array, id);
+ break;
+ }
+ talloc_free(id);
+ mapi_object_release(&obj_message);
+ }
+ }
+ }
+ }
+
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_tis);
+
+ return true;
+}
+
+/**
+ * Update Item
+ *
+ * Edit the existing item specified on command line.
+ * The function first loops over the mailbox, looking for the folder
+ * ID, then it looks for the particular message ID. It finally opens
+ * it, set properties and save the message.
+ *
+ */
+static enum MAPISTATUS folder_lookup(TALLOC_CTX *mem_ctx,
+ uint64_t sfid,
+ mapi_object_t *obj_parent,
+ mapi_id_t folder_id,
+ mapi_object_t *obj_ret)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_htable;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ uint32_t i;
+ const uint64_t *fid;
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(obj_parent, folder_id, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ mapi_object_init(&obj_htable);
+ retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_FID);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND && SRowSet.cRows)) {
+ for (i = 0; i < SRowSet.cRows; i++) {
+ fid = (const uint64_t *)find_SPropValue_data(&SRowSet.aRow[i], PR_FID);
+ if (fid && *fid == sfid) {
+ retval = OpenFolder(&obj_folder, *fid, obj_ret);
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&obj_folder);
+ return MAPI_E_SUCCESS;
+ } else {
+ retval = folder_lookup(mem_ctx, sfid, &obj_folder, *fid, obj_ret);
+ if (retval == MAPI_E_SUCCESS) {
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&obj_folder);
+ return MAPI_E_SUCCESS;
+ }
+ }
+ }
+ }
+
+ mapi_object_release(&obj_htable);
+ mapi_object_release(&obj_folder);
+
+ errno = MAPI_E_NOT_FOUND;
+ return MAPI_E_NOT_FOUND;
+}
+
+static enum MAPISTATUS message_lookup(TALLOC_CTX *mem_ctx,
+ uint64_t smid,
+ mapi_object_t *obj_folder,
+ mapi_object_t *obj_message)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_htable;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet SRowSet;
+ uint32_t i;
+ const uint64_t *fid;
+ const uint64_t *mid;
+
+ mapi_object_init(&obj_htable);
+ retval = GetContentsTable(obj_folder, &obj_htable, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x2, PR_FID, PR_MID);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return retval;
+
+ while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND) && SRowSet.cRows) {
+ for (i = 0; i < SRowSet.cRows; i++) {
+ fid = (const uint64_t *)find_SPropValue_data(&SRowSet.aRow[i], PR_FID);
+ mid = (const uint64_t *)find_SPropValue_data(&SRowSet.aRow[i], PR_MID);
+ if (mid && *mid == smid) {
+ retval = OpenMessage(obj_folder, *fid, *mid, obj_message, MAPI_MODIFY);
+ mapi_object_release(&obj_htable);
+ return retval;
+ }
+ }
+ }
+
+ mapi_object_release(&obj_htable);
+
+ errno = MAPI_E_NOT_FOUND;
+ return MAPI_E_NOT_FOUND;
+}
+
+static bool openchangeclient_updateitem(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store,
+ struct oclient *oclient, const char *container_class)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_id_t id_tis;
+ char *fid_str;
+ uint64_t fid;
+ uint64_t mid;
+ const char *item = NULL;
+
+ item = oclient->update;
+
+ if (!item) {
+ DEBUG(0, ("Missing ID\n"));
+ errno = MAPI_E_INVALID_PARAMETER;
+ return false;
+ }
+
+ if (!container_class) {
+ DEBUG(0, ("Missing container class\n"));
+ errno = MAPI_E_INVALID_PARAMETER;
+ return false;
+ }
+
+ fid_str = strsep((char **)&item, "/");
+ if (!fid_str || !item) {
+ DEBUG(0, (" Invalid ID: %s\n", fid_str ? fid_str : "null"));
+ errno = MAPI_E_INVALID_PARAMETER;
+ return false;
+ }
+
+ fid = strtoull(fid_str, NULL, 16);
+ mid = strtoull(item, NULL, 16);
+
+ /* Step 1: search the folder from Top Information Store */
+ mapi_object_init(&obj_folder);
+ retval = GetDefaultFolder(obj_store, &id_tis, olFolderTopInformationStore);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = folder_lookup(mem_ctx, fid, obj_store, id_tis, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step 2: search the message */
+ mapi_object_init(&obj_message);
+ retval = message_lookup(mem_ctx, mid, &obj_folder, &obj_message);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step 3: edit the message */
+ if (!strcmp(container_class, IPF_APPOINTMENT)) {
+ retval = appointment_SetProps(mem_ctx, &obj_folder, &obj_message, oclient);
+ } else if (!strcmp(container_class, IPF_CONTACT)) {
+ retval = contact_SetProps(mem_ctx, &obj_folder, &obj_message, oclient);
+ } else if (!strcmp(container_class, IPF_TASK)) {
+ retval = task_SetProps(mem_ctx, &obj_message, oclient);
+ } else if (!strcmp(container_class, IPF_STICKYNOTE)) {
+ retval = note_SetProps(mem_ctx, &obj_message, oclient);
+ }
+
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step 4: save the message */
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+
+ return true;
+}
+
+/**
+ * Delete an item given its unique ID
+ */
+static bool openchangeclient_deleteitems(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store,
+ struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_id_t id_tis;
+ char *fid_str;
+ uint64_t fid;
+ uint64_t mid;
+ const char *item = NULL;
+
+ item = oclient->delete;
+
+ if (!item) {
+ DEBUG(0, ("Missing ID\n"));
+ errno = MAPI_E_INVALID_PARAMETER;
+ return false;
+ }
+
+ fid_str = strsep((char **)&item, "/");
+ if (!fid_str || !item) {
+ DEBUG(0, (" Invalid ID: %s\n", fid_str ? fid_str : "null"));
+ errno = MAPI_E_INVALID_PARAMETER;
+ return false;
+ }
+
+ fid = strtoull(fid_str, NULL, 16);
+ mid = strtoull(item, NULL, 16);
+
+ /* Step 1: search the folder from Top Information Store */
+ mapi_object_init(&obj_folder);
+ retval = GetDefaultFolder(obj_store, &id_tis, olFolderTopInformationStore);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = folder_lookup(mem_ctx, fid, obj_store, id_tis, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step 2: search the message within returned folder */
+ mapi_object_init(&obj_message);
+ retval = message_lookup(mem_ctx, mid, &obj_folder, &obj_message);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step 3: delete the message */
+ retval = DeleteMessage(&obj_folder, &mid, 1);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+
+ return true;
+}
+
+
+/**
+ * Dump email
+ *
+ * Assume msg is received in Inbox folder since we only register
+ * notifications for this folder.
+ *
+ */
+
+static enum MAPISTATUS openchangeclient_findmail(mapi_object_t *obj_store,
+ mapi_id_t msgid)
+{
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct SRowSet SRowSet;
+ struct SPropValue *lpProp;
+ struct mapi_SPropValue_array properties_array;
+ mapi_id_t fid;
+ const mapi_id_t *mid;
+ mapi_object_t obj_inbox;
+ mapi_object_t obj_table;
+ mapi_object_t obj_message;
+ struct SPropTagArray *SPropTagArray = NULL;
+ uint32_t count;
+ uint32_t i;
+ char *id;
+
+ mem_ctx = talloc_named(NULL, 0, "openchangeclient_findmail");
+
+ /* Get Inbox folder */
+ retval = GetDefaultFolder(obj_store, &fid, olFolderInbox);
+ MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
+
+ /* Open Inbox */
+ mapi_object_init(&obj_inbox);
+ retval = OpenFolder(obj_store, fid, &obj_inbox);
+ MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
+
+ /* Retrieve contents table */
+ mapi_object_init(&obj_table);
+ retval = GetContentsTable(&obj_inbox, &obj_table, 0, &count);
+ MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x2,
+ PR_FID,
+ PR_MID);
+ retval = SetColumns(&obj_table, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
+
+ while ((retval = QueryRows(&obj_table, 0xa, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND && SRowSet.cRows) {
+ for (i = 0; i < SRowSet.cRows; i++) {
+ lpProp = get_SPropValue_SRowSet(&SRowSet, PR_MID);
+ if (lpProp != NULL) {
+ mid = (const uint64_t *)get_SPropValue(lpProp, PR_MID);
+ if (*mid == msgid) {
+ mapi_object_init(&obj_message);
+ retval = OpenMessage(obj_store,
+ SRowSet.aRow[i].lpProps[0].value.d,
+ SRowSet.aRow[i].lpProps[1].value.d,
+ &obj_message, 0);
+ if (GetLastError() == MAPI_E_SUCCESS) {
+ retval = GetPropsAll(&obj_message, &properties_array);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ id = talloc_asprintf(mem_ctx, ": %"PRIX64"/%"PRIX64,
+ SRowSet.aRow[i].lpProps[0].value.d,
+ SRowSet.aRow[i].lpProps[1].value.d);
+ mapidump_message(&properties_array, id);
+ mapi_object_release(&obj_message);
+ talloc_free(id);
+
+ goto end;
+ }
+ mapi_object_release(&obj_message);
+ }
+ }
+ }
+ }
+end:
+ mapi_object_release(&obj_table);
+ mapi_object_release(&obj_inbox);
+
+ talloc_free(mem_ctx);
+ return MAPI_E_SUCCESS;
+}
+
+
+static int callback(uint16_t NotificationType, void *NotificationData, void *private_data)
+{
+ struct NewMailNotification *newmail;
+ struct HierarchyTableChange *htable;
+ struct ContentsTableChange *ctable;
+ struct ContentsTableChange *stable;
+ enum MAPISTATUS retval;
+
+ switch(NotificationType) {
+ case fnevNewMail:
+ case fnevNewMail|fnevMbit:
+ DEBUG(0, ("[+] New mail Received\n"));
+ newmail = (struct NewMailNotification *) NotificationData;
+ mapidump_newmail(newmail, "\t");
+ retval = openchangeclient_findmail((mapi_object_t *)private_data, newmail->MID);
+ mapi_errstr("openchangeclient_findmail", GetLastError());
+ break;
+ case fnevObjectCreated:
+ DEBUG(0, ("[+] Folder Created\n"));
+ break;
+ case fnevObjectDeleted:
+ DEBUG(0, ("[+] Folder Deleted\n"));
+ break;
+ case fnevObjectModified:
+ case fnevTbit|fnevObjectModified:
+ case fnevUbit|fnevObjectModified:
+ case fnevTbit|fnevUbit|fnevObjectModified:
+ DEBUG(0, ("[+] Folder Modified\n"));
+ break;
+ case fnevObjectMoved:
+ DEBUG(0, ("[+] Folder Moved\n"));
+ break;
+ case fnevObjectCopied:
+ DEBUG(0, ("[+] Folder Copied\n"));
+ break;
+ case fnevSearchComplete:
+ DEBUG(0, ("[+] Search complete in search folder\n"));
+ break;
+ case fnevTableModified:
+ htable = (struct HierarchyTableChange *) NotificationData;
+ DEBUG(0, ("[+] Hierarchy Table: "));
+ switch (htable->TableEvent) {
+ case TABLE_CHANGED:
+ DEBUG(0, (" changed\n"));
+ break;
+ case TABLE_ROW_ADDED:
+ DEBUG(0, ("row added\n"));
+ break;
+ case TABLE_ROW_DELETED:
+ DEBUG(0, ("row deleted\n"));
+ break;
+ case TABLE_ROW_MODIFIED:
+ DEBUG(0, ("row modified\n"));
+ break;
+ case TABLE_RESTRICT_DONE:
+ DEBUG(0, ("restriction done\n"));
+ break;
+ default:
+ DEBUG(0, ("\n"));
+ break;
+ }
+ break;
+ case fnevStatusObjectModified:
+ DEBUG(0, ("[+] ICS Notification\n"));
+ break;
+ case fnevMbit|fnevObjectCreated:
+ DEBUG(0, ("[+] Message created\n"));
+ break;
+ case fnevMbit|fnevObjectDeleted:
+ DEBUG(0, ("[+] Message deleted\n"));
+ case fnevMbit|fnevObjectModified:
+ DEBUG(0, ("[+] Message modified\n"));
+ case fnevMbit|fnevObjectMoved:
+ DEBUG(0, ("[+] Message moved\n"));
+ case fnevMbit|fnevObjectCopied:
+ DEBUG(0, ("[+] Message copied\n"));
+ case fnevMbit|fnevTableModified:
+ ctable = (struct ContentsTableChange *) NotificationData;
+ DEBUG(0, ("[+] Contents Table: "));
+ switch (ctable->TableEvent) {
+ case TABLE_CHANGED:
+ DEBUG(0, (" changed\n"));
+ break;
+ case TABLE_ROW_ADDED:
+ DEBUG(0, ("row added\n"));
+ break;
+ case TABLE_ROW_DELETED:
+ DEBUG(0, ("row deleted\n"));
+ break;
+ case TABLE_ROW_MODIFIED:
+ DEBUG(0, ("row modified\n"));
+ break;
+ case TABLE_RESTRICT_DONE:
+ DEBUG(0, ("restriction done\n"));
+ break;
+ default:
+ DEBUG(0, ("\n"));
+ break;
+ }
+ break;
+ case fnevMbit|fnevSbit|fnevObjectDeleted:
+ DEBUG(0, ("[+] A message is no longer part of a search folder\n"));
+ break;
+ case fnevMbit|fnevSbit|fnevObjectModified:
+ DEBUG(0, ("[+] A property on a message in a search folder has changed\n"));
+ case fnevMbit|fnevSbit|fnevTableModified:
+ stable = (struct ContentsTableChange *) NotificationData;
+ DEBUG(0, ("[+] Search Table: "));
+ switch (stable->TableEvent) {
+ case TABLE_CHANGED:
+ DEBUG(0, (" changed\n"));
+ break;
+ case TABLE_ROW_ADDED:
+ DEBUG(0, ("row added\n"));
+ break;
+ case TABLE_ROW_DELETED:
+ DEBUG(0, ("row deleted\n"));
+ break;
+ case TABLE_ROW_MODIFIED:
+ DEBUG(0, ("row modified\n"));
+ break;
+ case TABLE_RESTRICT_DONE:
+ DEBUG(0, ("restriction done\n"));
+ break;
+ default:
+ DEBUG(0, ("\n"));
+ break;
+ }
+ break;
+ default:
+ printf("[+] Unsupported notification (0x%x)\n", NotificationType);
+ break;
+ }
+
+ return 0;
+}
+
+
+static bool openchangeclient_notifications(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_inbox;
+ mapi_id_t fid;
+ uint32_t ulConnection;
+ uint16_t ulEventMask;
+
+ /* Register notification */
+ retval = RegisterNotification(0);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ if (oclient->pf == true) {
+ retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_inbox, oclient->folder);
+ if (retval != MAPI_E_SUCCESS) return retval;
+ } else {
+ /* Retrieve Inbox folder ID */
+ retval = GetDefaultFolder(obj_store, &fid, olFolderInbox);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Open Inbox folder */
+ mapi_object_init(&obj_inbox);
+ retval = OpenFolder(obj_store, fid, &obj_inbox);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+
+ /* subscribe Inbox to receive newmail notifications */
+ ulEventMask = fnevNewMail|fnevObjectCreated|fnevObjectDeleted|
+ fnevObjectModified|fnevObjectMoved|fnevObjectCopied|
+ fnevSearchComplete|fnevTableModified|fnevStatusObjectModified;
+ retval = Subscribe(obj_store, &ulConnection, ulEventMask, true, (mapi_notify_callback_t)callback);
+ retval = Subscribe(&obj_inbox, &ulConnection, ulEventMask, false, (mapi_notify_callback_t)callback);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* wait for notifications: infinite loop */
+ retval = MonitorNotification(mapi_object_get_session(obj_store), (void *)obj_store);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = Unsubscribe(mapi_object_get_session(obj_store), ulConnection);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_release(&obj_inbox);
+
+ return true;
+}
+
+
+static bool openchangeclient_mkdir(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_child;
+ mapi_object_t obj_tis;
+ mapi_id_t id_inbox;
+
+ mapi_object_init(&obj_tis);
+ mapi_object_init(&obj_folder);
+ mapi_object_init(&obj_child);
+
+ if (oclient->folder) {
+ retval = GetDefaultFolder(obj_store, &id_inbox, olFolderTopInformationStore);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(obj_store, id_inbox, &obj_tis);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = openchangeclient_getdir(mem_ctx, &obj_tis, &obj_folder, oclient->folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+ } else {
+ retval = GetDefaultFolder(obj_store, &id_inbox, olFolderInbox);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(obj_store, id_inbox, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+
+ retval = CreateFolder(&obj_folder, FOLDER_GENERIC, oclient->folder_name,
+ oclient->folder_comment, OPEN_IF_EXISTS, &obj_child);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_release(&obj_child);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_tis);
+
+ return true;
+}
+
+
+static bool openchangeclient_rmdir(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_child;
+ mapi_object_t obj_tis;
+ mapi_id_t id_inbox;
+
+ mapi_object_init(&obj_tis);
+ mapi_object_init(&obj_folder);
+ mapi_object_init(&obj_child);
+
+ if (oclient->folder) {
+ printf("Removing folder within %s\n", oclient->folder);
+ retval = GetDefaultFolder(obj_store, &id_inbox, olFolderTopInformationStore);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(obj_store, id_inbox, &obj_tis);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = openchangeclient_getdir(mem_ctx, &obj_tis, &obj_folder, oclient->folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+ } else {
+ retval = GetDefaultFolder(obj_store, &id_inbox, olFolderInbox);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = OpenFolder(obj_store, id_inbox, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+ }
+
+ retval = openchangeclient_getdir(mem_ctx, &obj_folder, &obj_child, oclient->folder_name);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = EmptyFolder(&obj_child);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ printf("obj_child fid = 0x%"PRIx64"\n", mapi_object_get_id(&obj_child));
+
+ retval = DeleteFolder(&obj_folder, mapi_object_get_id(&obj_child),
+ DEL_FOLDERS, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_release(&obj_child);
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_tis);
+
+ return true;
+}
+
+static bool openchangeclient_userlist(TALLOC_CTX *mem_ctx,
+ struct mapi_session *session)
+{
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet *SRowSet;
+ enum MAPISTATUS retval;
+ uint32_t i;
+ uint32_t count;
+ uint8_t ulFlags;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0xc,
+ PR_INSTANCE_KEY,
+ PR_ENTRYID,
+ PR_DISPLAY_NAME_UNICODE,
+ PR_EMAIL_ADDRESS_UNICODE,
+ PR_DISPLAY_TYPE,
+ PR_OBJECT_TYPE,
+ PR_ADDRTYPE_UNICODE,
+ PR_OFFICE_TELEPHONE_NUMBER_UNICODE,
+ PR_OFFICE_LOCATION_UNICODE,
+ PR_TITLE_UNICODE,
+ PR_COMPANY_NAME_UNICODE,
+ PR_ACCOUNT_UNICODE);
+
+ count = 0x7;
+ ulFlags = TABLE_START;
+ do {
+ count += 0x2;
+ retval = GetGALTable(session, SPropTagArray, &SRowSet, count, ulFlags);
+ if (SRowSet->cRows) {
+ for (i = 0; i < SRowSet->cRows; i++) {
+ mapidump_PAB_entry(&SRowSet->aRow[i]);
+ }
+ }
+ ulFlags = TABLE_CUR;
+ MAPIFreeBuffer(SRowSet);
+ } while (SRowSet->cRows == count);
+ mapi_errstr("GetPABTable", GetLastError());
+
+ MAPIFreeBuffer(SPropTagArray);
+
+ return true;
+}
+
+
+static bool openchangeclient_ocpf_syntax(struct oclient *oclient)
+{
+ int ret;
+ struct ocpf_file *element;
+
+ /* Sanity checks */
+ if (!oclient->ocpf_files || !oclient->ocpf_files->next) {
+ errno = MAPI_E_INVALID_PARAMETER;
+ return false;
+ }
+
+ /* Step 1. Initialize OCPF context */
+ ret = ocpf_init();
+ if (ret == -1) {
+ errno = MAPI_E_CALL_FAILED;
+ return false;
+ }
+
+ /* Step2. Parse OCPF files */
+ for (element = oclient->ocpf_files; element->next; element = element->next) {
+ ret = ocpf_parse(element->filename);
+ if (ret == -1) {
+ errno = MAPI_E_INVALID_PARAMETER;
+ return false;
+ }
+ }
+
+ /* Step3. Dump OCPF contents */
+ ocpf_dump();
+
+ /* Step4. Release OCPF context */
+ ret = ocpf_release();
+ if (ret == -1) {
+ errno = MAPI_E_CALL_FAILED;
+ return false;
+ }
+
+ return true;
+}
+
+
+static bool openchangeclient_ocpf_sender(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ int ret;
+ struct ocpf_file *element;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ uint32_t cValues = 0;
+ struct SPropValue *lpProps;
+
+ /* Sanity Check */
+ if (!oclient->ocpf_files || !oclient->ocpf_files->next) {
+ errno = MAPI_E_INVALID_PARAMETER;
+ return false;
+ }
+
+ /* Step1. Initialize OCPF context */
+ ret = ocpf_init();
+ if (ret == -1) {
+ errno = MAPI_E_CALL_FAILED;
+ return false;
+ }
+
+ /* Step2. Parse OCPF files */
+ for (element = oclient->ocpf_files; element->next; element = element->next) {
+ ret = ocpf_parse(element->filename);
+ if (ret == -1) {
+ errno = MAPI_E_INVALID_PARAMETER;
+ return false;
+ }
+ }
+
+ /* Step3. Open destination folder using ocpf API */
+ mapi_object_init(&obj_folder);
+ retval = ocpf_OpenFolder(obj_store, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step4. Create the message */
+ mapi_object_init(&obj_message);
+ retval = CreateMessage(&obj_folder, &obj_message);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step5, Set message recipients */
+ retval = ocpf_set_Recipients(mem_ctx, &obj_message);
+ if (retval != MAPI_E_SUCCESS && GetLastError() != MAPI_E_NOT_FOUND) return false;
+ errno = MAPI_E_SUCCESS;
+
+ /* Step6. Set message properties */
+ retval = ocpf_set_SPropValue(mem_ctx, &obj_folder, &obj_message);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step7. Set message properties */
+ lpProps = ocpf_get_SPropValue(&cValues);
+
+ retval = SetProps(&obj_message, lpProps, cValues);
+ MAPIFreeBuffer(lpProps);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step8. Save message */
+ retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+
+ return true;
+}
+
+
+static bool openchangeclient_ocpf_dump(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ int ret;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_message;
+ mapi_id_t id_tis;
+ const char *fid_str;
+ uint64_t fid;
+ uint64_t mid;
+ const char *item = NULL;
+ char *filename = NULL;
+ struct mapi_SPropValue_array lpProps;
+
+
+ /* retrieve the FID/MID for ocpf_dump parameter */
+ item = oclient->ocpf_dump;
+
+ fid_str = strsep((char **)&item, "/");
+ if (!fid_str || !item) {
+ DEBUG(0, (" Invalid ID: %s\n", fid_str ? fid_str : "null"));
+ errno = MAPI_E_INVALID_PARAMETER;
+ return false;
+ }
+
+ fid = strtoull(fid_str, NULL, 16);
+ mid = strtoull(item, NULL, 16);
+
+ /* Step 1. search the folder from Top Information Store */
+ mapi_object_init(&obj_folder);
+ retval = GetDefaultFolder(obj_store, &id_tis, olFolderTopInformationStore);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ retval = folder_lookup(mem_ctx, fid, obj_store, id_tis, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step 2. search the message */
+ mapi_object_init(&obj_message);
+ retval = message_lookup(mem_ctx, mid, &obj_folder, &obj_message);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step 3. retrieve all message properties */
+ retval = GetPropsAll(&obj_message, &lpProps);
+
+ /* Step 4. save the message */
+ ret = ocpf_init();
+
+ filename = talloc_asprintf(mem_ctx, "%"PRIx64".ocpf", mid);
+ DEBUG(0, ("OCPF output file: %s\n", filename));
+
+ ret = ocpf_write_init(filename, fid);
+ talloc_free(filename);
+
+ ret = ocpf_write_auto(&obj_message, &lpProps);
+ if (ret == OCPF_SUCCESS) {
+ ret = ocpf_write_commit();
+ }
+
+ ret = ocpf_release();
+
+ mapi_object_release(&obj_message);
+ mapi_object_release(&obj_folder);
+
+ return true;
+}
+
+
+static bool openchangeclient_freebusy(mapi_object_t *obj_store, struct oclient *oclient)
+{
+ enum MAPISTATUS retval;
+ struct SRow aRow;
+ const char *message_name;
+ uint32_t i;
+ const uint32_t *publish_start;
+ const uint32_t *publish_end;
+ const struct LongArray_r *busy_months;
+ const struct BinaryArray_r *busy_events;
+ const struct LongArray_r *tentative_months;
+ const struct BinaryArray_r *tentative_events;
+ const struct LongArray_r *oof_months;
+ const struct BinaryArray_r *oof_events;
+ uint32_t year;
+ uint32_t event_year;
+
+ /* Step 1. Retrieve FreeBusy data for the given user */
+ retval = GetUserFreeBusyData(obj_store, oclient->freebusy, &aRow);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ /* Step 2. Dump properties */
+ message_name = (const char *) find_SPropValue_data(&aRow, PR_NORMALIZED_SUBJECT);
+ publish_start = (const uint32_t *) find_SPropValue_data(&aRow, PR_FREEBUSY_START_RANGE);
+ publish_end = (const uint32_t *) find_SPropValue_data(&aRow, PR_FREEBUSY_END_RANGE);
+ busy_months = (const struct LongArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_BUSY_MONTHS);
+ busy_events = (const struct BinaryArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_BUSY_EVENTS);
+ tentative_months = (const struct LongArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_TENTATIVE_MONTHS);
+ tentative_events = (const struct BinaryArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_TENTATIVE_EVENTS);
+ oof_months = (const struct LongArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_OOF_MONTHS);
+ oof_events = (const struct BinaryArray_r *) find_SPropValue_data(&aRow, PR_FREEBUSY_OOF_EVENTS);
+
+ year = GetFreeBusyYear(publish_start);
+
+ DEBUG(0, ("FreeBusy (%s):\n", message_name));
+ mapidump_date_SPropValue(aRow.lpProps[1], "* FreeBusy Last Modification Time");
+ mapidump_freebusy_date(*publish_start, "\t* FreeBusy Publishing Start:");
+ mapidump_freebusy_date(*publish_end, "\t *FreeBusy Publishing End: ");
+
+ if (busy_months && ((*(const uint32_t *) busy_months) != MAPI_E_NOT_FOUND) &&
+ busy_events && ((*(const uint32_t *) busy_events) != MAPI_E_NOT_FOUND)) {
+ DEBUG(0, ("\t* Busy Events:\n"));
+ for (i = 0; i < busy_months->cValues; i++) {
+ event_year = mapidump_freebusy_year(busy_months->lpl[i], year);
+ DEBUG(0, ("\t\t* %s %u:\n", mapidump_freebusy_month(busy_months->lpl[i], event_year), event_year));
+ mapidump_freebusy_event(&busy_events->lpbin[i], busy_months->lpl[i], event_year, "\t\t\t* ");
+ }
+ }
+
+ if (tentative_months && ((*(const uint32_t *) tentative_months) != MAPI_E_NOT_FOUND) &&
+ tentative_events && ((*(const uint32_t *) tentative_events) != MAPI_E_NOT_FOUND)) {
+ DEBUG(0, ("\t* Tentative Events:\n"));
+ for (i = 0; i < tentative_months->cValues; i++) {
+ event_year = mapidump_freebusy_year(tentative_months->lpl[i], year);
+ DEBUG(0, ("\t\t* %s %u:\n", mapidump_freebusy_month(tentative_months->lpl[i], event_year), event_year));
+ mapidump_freebusy_event(&tentative_events->lpbin[i], tentative_months->lpl[i], event_year, "\t\t\t* ");
+ }
+ }
+
+ if (oof_months && ((*(const uint32_t *) oof_months) != MAPI_E_NOT_FOUND) &&
+ oof_events && ((*(const uint32_t *) oof_events) != MAPI_E_NOT_FOUND)) {
+ DEBUG(0, ("\t* Out Of Office Events:\n"));
+ for (i = 0; i < oof_months->cValues; i++) {
+ event_year = mapidump_freebusy_year(oof_months->lpl[i], year);
+ DEBUG(0, ("\t\t* %s %u:\n", mapidump_freebusy_month(oof_months->lpl[i], event_year), event_year));
+ mapidump_freebusy_event(&oof_events->lpbin[i], oof_months->lpl[i], event_year, "\t\t\t* ");
+ }
+ }
+
+ MAPIFreeBuffer(aRow.lpProps);
+
+ return true;
+}
+
+
+static void list_argument(const char *label, struct oc_element *oc_items)
+{
+ uint32_t i;
+
+ printf("Use one of the following %s values:\n", label);
+ for (i = 0; oc_items[i].status; i++) {
+ printf("%s\n", oc_items[i].status);
+ }
+}
+
+
+static uint32_t oc_get_argument(const char *name, struct oc_element *oc_items, const char *label)
+{
+ uint32_t i;
+
+ for (i = 0; oc_items[i].status; i++) {
+ if (!strncasecmp(oc_items[i].status, name, strlen(oc_items[i].status))) {
+ return oc_items[i].index;
+ }
+ }
+ list_argument(label, oc_items);
+ exit (1);
+}
+
+
+int main(int argc, const char *argv[])
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct mapi_session *session = NULL;
+ mapi_object_t obj_store;
+ struct oclient oclient;
+ poptContext pc;
+ int opt;
+ bool opt_sendmail = false;
+ bool opt_sendappointment = false;
+ bool opt_sendcontact = false;
+ bool opt_sendtask = false;
+ bool opt_sendnote = false;
+ bool opt_fetchmail = false;
+ bool opt_deletemail = false;
+ bool opt_mailbox = false;
+ bool opt_dumpdata = false;
+ bool opt_notifications = false;
+ bool opt_mkdir = false;
+ bool opt_rmdir = false;
+ bool opt_userlist = false;
+ bool opt_ocpf_syntax = false;
+ bool opt_ocpf_sender = false;
+ const char *opt_profdb = NULL;
+ char *opt_profname = NULL;
+ const char *opt_password = NULL;
+ const char *opt_attachments = NULL;
+ const char *opt_fetchitems = NULL;
+ const char *opt_html_file = NULL;
+ const char *opt_mapi_to = NULL;
+ const char *opt_mapi_cc = NULL;
+ const char *opt_mapi_bcc = NULL;
+ const char *opt_debug = NULL;
+
+ enum {OPT_PROFILE_DB=1000, OPT_PROFILE, OPT_SENDMAIL, OPT_PASSWORD, OPT_SENDAPPOINTMENT,
+ OPT_SENDCONTACT, OPT_SENDTASK, OPT_FETCHMAIL, OPT_STOREMAIL, OPT_DELETEMAIL,
+ OPT_ATTACH, OPT_HTML_INLINE, OPT_HTML_FILE, OPT_MAPI_TO, OPT_MAPI_CC,
+ OPT_MAPI_BCC, OPT_MAPI_SUBJECT, OPT_MAPI_BODY, OPT_MAILBOX,
+ OPT_FETCHITEMS, OPT_MAPI_LOCATION, OPT_MAPI_STARTDATE, OPT_MAPI_ENDDATE,
+ OPT_MAPI_BUSYSTATUS, OPT_NOTIFICATIONS, OPT_DEBUG, OPT_DUMPDATA,
+ OPT_MAPI_EMAIL, OPT_MAPI_FULLNAME, OPT_MAPI_CARDNAME,
+ OPT_MAPI_TASKSTATUS, OPT_MAPI_IMPORTANCE, OPT_MAPI_LABEL, OPT_PF,
+ OPT_FOLDER, OPT_MAPI_COLOR, OPT_SENDNOTE, OPT_MKDIR, OPT_RMDIR,
+ OPT_FOLDER_NAME, OPT_FOLDER_COMMENT, OPT_USERLIST, OPT_MAPI_PRIVATE,
+ OPT_UPDATE, OPT_DELETEITEMS, OPT_OCPF_FILE, OPT_OCPF_SYNTAX,
+ OPT_OCPF_SENDER, OPT_OCPF_DUMP, OPT_FREEBUSY, OPT_FORCE};
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ {"database", 'f', POPT_ARG_STRING, NULL, OPT_PROFILE_DB, "set the profile database path", NULL },
+ {"pf", 0, POPT_ARG_NONE, NULL, OPT_PF, "access public folders instead of mailbox", NULL },
+ {"profile", 'p', POPT_ARG_STRING, NULL, OPT_PROFILE, "set the profile name", NULL },
+ {"password", 'P', POPT_ARG_STRING, NULL, OPT_PASSWORD, "set the profile password", NULL },
+ {"sendmail", 'S', POPT_ARG_NONE, NULL, OPT_SENDMAIL, "send a mail", NULL },
+ {"sendappointment", 0, POPT_ARG_NONE, NULL, OPT_SENDAPPOINTMENT, "send an appointment", NULL },
+ {"sendcontact", 0, POPT_ARG_NONE, NULL, OPT_SENDCONTACT, "send a contact", NULL },
+ {"sendtask", 0, POPT_ARG_NONE, NULL, OPT_SENDTASK, "send a task", NULL },
+ {"sendnote", 0, POPT_ARG_NONE, NULL, OPT_SENDNOTE, "send a note", NULL },
+ {"fetchmail", 'F', POPT_ARG_NONE, NULL, OPT_FETCHMAIL, "fetch user INBOX mails", NULL },
+ {"storemail", 'G', POPT_ARG_STRING, NULL, OPT_STOREMAIL, "retrieve a mail on the filesystem", NULL },
+ {"fetch-items", 'i', POPT_ARG_STRING, NULL, OPT_FETCHITEMS, "fetch specified user INBOX items", NULL },
+ {"freebusy", 0, POPT_ARG_STRING, NULL, OPT_FREEBUSY, "display free / busy information for the specified user", NULL },
+ {"force", 0, POPT_ARG_NONE, NULL, OPT_FORCE, "force openchangeclient behavior in some circumstances", NULL },
+ {"delete", 0, POPT_ARG_STRING, NULL, OPT_DELETEITEMS, "delete a message given its unique ID", NULL },
+ {"update", 'u', POPT_ARG_STRING, NULL, OPT_UPDATE, "update the specified item", NULL },
+ {"mailbox", 'm', POPT_ARG_NONE, NULL, OPT_MAILBOX, "list mailbox folder summary", NULL },
+ {"deletemail", 'D', POPT_ARG_NONE, NULL, OPT_DELETEMAIL, "delete a mail from user INBOX", NULL },
+ {"attachments", 'A', POPT_ARG_STRING, NULL, OPT_ATTACH, "send a list of attachments", NULL },
+ {"html-inline", 'I', POPT_ARG_STRING, NULL, OPT_HTML_INLINE, "send PR_HTML content", NULL },
+ {"html-file", 'W', POPT_ARG_STRING, NULL, OPT_HTML_FILE, "use HTML file as content", NULL },
+ {"to", 't', POPT_ARG_STRING, NULL, OPT_MAPI_TO, "set the To recipients", NULL },
+ {"cc", 'c', POPT_ARG_STRING, NULL, OPT_MAPI_CC, "set the Cc recipients", NULL },
+ {"bcc", 'b', POPT_ARG_STRING, NULL, OPT_MAPI_BCC, "set the Bcc recipients", NULL },
+ {"subject", 's', POPT_ARG_STRING, NULL, OPT_MAPI_SUBJECT, "set the mail subject", NULL },
+ {"body", 'B', POPT_ARG_STRING, NULL, OPT_MAPI_BODY, "set the mail body", NULL },
+ {"location", 0, POPT_ARG_STRING, NULL, OPT_MAPI_LOCATION, "set the item location", NULL },
+ {"label", 0, POPT_ARG_STRING, NULL, OPT_MAPI_LABEL, "set the event label", NULL },
+ {"dtstart", 0, POPT_ARG_STRING, NULL, OPT_MAPI_STARTDATE, "set the event start date", NULL },
+ {"dtend", 0, POPT_ARG_STRING, NULL, OPT_MAPI_ENDDATE, "set the event end date", NULL },
+ {"busystatus", 0, POPT_ARG_STRING, NULL, OPT_MAPI_BUSYSTATUS, "set the item busy status", NULL },
+ {"taskstatus", 0, POPT_ARG_STRING, NULL, OPT_MAPI_TASKSTATUS, "set the task status", NULL },
+ {"importance", 0, POPT_ARG_STRING, NULL, OPT_MAPI_IMPORTANCE, "Set the item importance", NULL },
+ {"email", 0, POPT_ARG_STRING, NULL, OPT_MAPI_EMAIL, "set the email address", NULL },
+ {"fullname", 0, POPT_ARG_STRING, NULL, OPT_MAPI_FULLNAME, "set the full name", NULL },
+ {"cardname", 0, POPT_ARG_STRING, NULL, OPT_MAPI_CARDNAME, "set a contact card name", NULL },
+ {"color", 0, POPT_ARG_STRING, NULL, OPT_MAPI_COLOR, "set the note color", NULL },
+ {"notifications", 0, POPT_ARG_NONE, NULL, OPT_NOTIFICATIONS, "monitor INBOX newmail notifications", NULL },
+ {"folder", 0, POPT_ARG_STRING, NULL, OPT_FOLDER, "set the folder to use instead of inbox", NULL },
+ {"mkdir", 0, POPT_ARG_NONE, NULL, OPT_MKDIR, "create a folder", NULL },
+ {"rmdir", 0, POPT_ARG_NONE, NULL, OPT_RMDIR, "delete a folder", NULL },
+ {"userlist", 0, POPT_ARG_NONE, NULL, OPT_USERLIST, "list Address Book entries", NULL },
+ {"folder-name", 0, POPT_ARG_STRING, NULL, OPT_FOLDER_NAME, "set the folder name", NULL },
+ {"folder-comment", 0, POPT_ARG_STRING, NULL, OPT_FOLDER_COMMENT, "set the folder comment", NULL },
+ {"debuglevel", 'd', POPT_ARG_STRING, NULL, OPT_DEBUG, "set Debug Level", NULL },
+ {"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMPDATA, "dump the hex data", NULL },
+ {"private", 0, POPT_ARG_NONE, NULL, OPT_MAPI_PRIVATE, "set the private flag on messages", NULL },
+ {"ocpf-file", 0, POPT_ARG_STRING, NULL, OPT_OCPF_FILE, "set OCPF file", NULL },
+ {"ocpf-dump", 0, POPT_ARG_STRING, NULL, OPT_OCPF_DUMP, "dump message into OCPF file", NULL },
+ {"ocpf-syntax", 0, POPT_ARG_NONE, NULL, OPT_OCPF_SYNTAX, "check OCPF files syntax", NULL },
+ {"ocpf-sender", 0, POPT_ARG_NONE, NULL, OPT_OCPF_SENDER, "send message using OCPF files contents", NULL },
+ POPT_OPENCHANGE_VERSION
+ {NULL, 0, 0, NULL, 0, NULL, NULL}
+ };
+
+ mem_ctx = talloc_named(NULL, 0, "openchangeclient");
+
+ init_oclient(&oclient);
+
+ pc = poptGetContext("openchangeclient", argc, argv, long_options, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_PF:
+ oclient.pf = true;
+ break;
+ case OPT_FOLDER:
+ oclient.folder = poptGetOptArg(pc);
+ break;
+ case OPT_DEBUG:
+ opt_debug = poptGetOptArg(pc);
+ break;
+ case OPT_DUMPDATA:
+ opt_dumpdata = true;
+ break;
+ case OPT_USERLIST:
+ opt_userlist = true;
+ break;
+ case OPT_MKDIR:
+ opt_mkdir = true;
+ break;
+ case OPT_RMDIR:
+ opt_rmdir = true;
+ break;
+ case OPT_FOLDER_NAME:
+ oclient.folder_name = poptGetOptArg(pc);
+ break;
+ case OPT_FOLDER_COMMENT:
+ oclient.folder_comment = poptGetOptArg(pc);
+ break;
+ case OPT_NOTIFICATIONS:
+ opt_notifications = true;
+ break;
+ case OPT_PROFILE_DB:
+ opt_profdb = poptGetOptArg(pc);
+ break;
+ case OPT_PROFILE:
+ opt_profname = talloc_strdup(mem_ctx, poptGetOptArg(pc));
+ break;
+ case OPT_PASSWORD:
+ opt_password = poptGetOptArg(pc);
+ break;
+ case OPT_MAILBOX:
+ opt_mailbox = true;
+ break;
+ case OPT_FETCHITEMS:
+ opt_fetchitems = poptGetOptArg(pc);
+ break;
+ case OPT_DELETEITEMS:
+ oclient.delete = poptGetOptArg(pc);
+ break;
+ case OPT_FREEBUSY:
+ oclient.freebusy = poptGetOptArg(pc);
+ break;
+ case OPT_UPDATE:
+ oclient.update = poptGetOptArg(pc);
+ break;
+ case OPT_SENDMAIL:
+ opt_sendmail = true;
+ break;
+ case OPT_SENDAPPOINTMENT:
+ opt_sendappointment = true;
+ break;
+ case OPT_SENDCONTACT:
+ opt_sendcontact = true;
+ break;
+ case OPT_SENDTASK:
+ opt_sendtask = true;
+ break;
+ case OPT_SENDNOTE:
+ opt_sendnote = true;
+ break;
+ case OPT_FETCHMAIL:
+ opt_fetchmail = true;
+ break;
+ case OPT_STOREMAIL:
+ oclient.store_folder = poptGetOptArg(pc);
+ break;
+ case OPT_DELETEMAIL:
+ opt_deletemail = true;
+ break;
+ case OPT_ATTACH:
+ opt_attachments = poptGetOptArg(pc);
+ break;
+ case OPT_HTML_INLINE:
+ oclient.pr_html_inline = poptGetOptArg(pc);
+ break;
+ case OPT_HTML_FILE:
+ opt_html_file = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_TO:
+ opt_mapi_to = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_CC:
+ opt_mapi_cc = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_BCC:
+ opt_mapi_bcc = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_SUBJECT:
+ oclient.subject = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_BODY:
+ oclient.pr_body = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_LOCATION:
+ oclient.location = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_STARTDATE:
+ oclient.dtstart = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_ENDDATE:
+ oclient.dtend = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_BUSYSTATUS:
+ oclient.busystatus = oc_get_argument(poptGetOptArg(pc),
+ oc_busystatus,
+ "busystatus");
+ break;
+ case OPT_MAPI_LABEL:
+ oclient.label = oc_get_argument(poptGetOptArg(pc),
+ oc_label,
+ "label");
+ break;
+ case OPT_MAPI_IMPORTANCE:
+ oclient.importance = oc_get_argument(poptGetOptArg(pc),
+ oc_importance,
+ "importance");
+ break;
+ case OPT_MAPI_TASKSTATUS:
+ oclient.taskstatus = oc_get_argument(poptGetOptArg(pc),
+ oc_taskstatus,
+ "taskstatus");
+ break;
+ case OPT_MAPI_COLOR:
+ oclient.color = oc_get_argument(poptGetOptArg(pc),
+ oc_color,
+ "color");
+ break;
+ case OPT_MAPI_EMAIL:
+ oclient.email = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_FULLNAME:
+ oclient.full_name = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_CARDNAME:
+ oclient.card_name = poptGetOptArg(pc);
+ break;
+ case OPT_MAPI_PRIVATE:
+ oclient.private = true;
+ break;
+ case OPT_OCPF_FILE:
+ {
+ struct ocpf_file *element;
+
+ if (!oclient.ocpf_files) {
+ oclient.ocpf_files = talloc_zero(mem_ctx, struct ocpf_file);
+ }
+
+ element = talloc_zero(mem_ctx, struct ocpf_file);
+ element->filename = talloc_strdup(mem_ctx, poptGetOptArg(pc));
+ DLIST_ADD(oclient.ocpf_files, element);
+ break;
+ }
+ case OPT_OCPF_SYNTAX:
+ opt_ocpf_syntax = true;
+ break;
+ case OPT_OCPF_SENDER:
+ opt_ocpf_sender = true;
+ break;
+ case OPT_OCPF_DUMP:
+ oclient.ocpf_dump = poptGetOptArg(pc);
+ break;
+ case OPT_FORCE:
+ oclient.force = true;
+ break;
+ }
+ }
+
+ /* Sanity check on options */
+
+ if (!opt_profdb) {
+ opt_profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, getenv("HOME"));
+ }
+
+ if (opt_sendmail && !opt_mapi_to && !opt_mapi_cc && !opt_mapi_bcc) {
+ printf("You need to specify at least one recipient\n");
+ exit (1);
+ }
+
+ if (opt_sendmail && (!oclient.pr_body && !oclient.pr_html_inline && !opt_html_file)) {
+ printf("No body specified (body, html-inline or html-file)\n");
+ exit (1);
+ }
+
+ if ((opt_sendmail && oclient.pf == true && !oclient.folder) ||
+ (oclient.pf == true && !oclient.folder && !opt_mailbox && !oclient.freebusy)) {
+ printf("--folder option is mandatory\n");
+ exit (1);
+ }
+
+ if (opt_html_file && oclient.pr_body) {
+ printf("PR_BODY and PR_HTML can't be set at the same time\n");
+ exit (1);
+ }
+
+ if (oclient.pr_body && oclient.pr_html_inline) {
+ printf("Inline HTML and PR_BODY content can't be set simulteanously\n");
+ exit (1);
+ }
+
+ if (opt_html_file && oclient.pr_html_inline) {
+ printf("PR_HTML from file and stdin can't be specified at the same time\n");
+ exit (1);
+ }
+
+ if (opt_html_file) {
+ oclient_read_file(mem_ctx, opt_html_file, &oclient, PR_HTML);
+ }
+
+ if (opt_attachments) {
+ if (oclient_parse_attachments(mem_ctx, opt_attachments, &oclient) == false) {
+ printf("Unable to parse one of the specified attachments\n");
+ exit (1);
+ }
+ }
+
+ if (opt_mkdir && !oclient.folder_name) {
+ printf("mkdir requires --folder-name to be defined\n");
+ exit (1);
+ }
+
+ /* One of the rare options which doesn't require MAPI to get
+ * initialized
+ */
+ if (opt_ocpf_syntax) {
+ bool ret = openchangeclient_ocpf_syntax(&oclient);
+ mapi_errstr("OCPF Syntax", GetLastError());
+ if (ret != true) {
+ exit(1);
+ }
+ exit (0);
+ }
+
+ /**
+ * Initialize MAPI subsystem
+ */
+
+ retval = MAPIInitialize(opt_profdb);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ /* debug options */
+ SetMAPIDumpData(opt_dumpdata);
+
+ if (opt_debug) {
+ SetMAPIDebugLevel(atoi(opt_debug));
+ }
+
+ /* If no profile is specified try to load the default one from
+ * the database
+ */
+
+ if (!opt_profname) {
+ retval = GetDefaultProfile(&opt_profname);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("GetDefaultProfile", GetLastError());
+ exit (1);
+ }
+ }
+
+ retval = MapiLogonEx(&session, opt_profname, opt_password);
+ talloc_free(opt_profname);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MapiLogonEx", GetLastError());
+ exit (1);
+ }
+
+ if (opt_userlist) {
+ openchangeclient_userlist(mem_ctx, session);
+ exit (0);
+ }
+
+ /**
+ * Open Default Message Store
+ */
+
+ mapi_object_init(&obj_store);
+ if (oclient.pf == true) {
+ retval = OpenPublicFolder(session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("OpenPublicFolder", GetLastError());
+ exit (1);
+ }
+ } else {
+ retval = OpenMsgStore(session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("OpenMsgStore", GetLastError());
+ exit (1);
+ }
+ }
+
+ /**
+ * OCPF sending command
+ */
+ if (opt_ocpf_sender) {
+ bool ret = openchangeclient_ocpf_sender(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("OCPF Sender", GetLastError());
+ if (ret != true) {
+ goto end;
+ }
+ }
+
+ if (oclient.ocpf_dump) {
+ bool ret = openchangeclient_ocpf_dump(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("OCPF Dump", GetLastError());
+ if (ret != true) {
+ goto end;
+ }
+ }
+
+ if (opt_fetchitems) {
+ bool ret = openchangeclient_fetchitems(mem_ctx, &obj_store, opt_fetchitems, &oclient);
+ mapi_errstr("fetchitems", GetLastError());
+ if (ret != true) {
+ goto end;
+ }
+ }
+
+ if (oclient.delete) {
+ bool ret = openchangeclient_deleteitems(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("deleteitems", GetLastError());
+ if (ret != true) {
+ goto end;
+ }
+ }
+
+ if (opt_mailbox) {
+ if (oclient.pf == true) {
+ bool ret = openchangeclient_pf(mem_ctx, &obj_store);
+ mapi_errstr("public folder", GetLastError());
+ if (ret != true) {
+ goto end;
+ }
+ } else {
+ bool ret = openchangeclient_mailbox(mem_ctx, &obj_store);
+ mapi_errstr("mailbox", GetLastError());
+ if (ret != true) {
+ goto end;
+ }
+ }
+ }
+
+ /* MAPI email operations */
+ if (opt_sendmail) {
+ /* recipients management */
+ oclient.mapi_to = get_cmdline_recipients(mem_ctx, opt_mapi_to);
+ oclient.mapi_cc = get_cmdline_recipients(mem_ctx, opt_mapi_cc);
+ oclient.mapi_bcc = get_cmdline_recipients(mem_ctx, opt_mapi_bcc);
+
+ retval = openchangeclient_sendmail(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("sendmail", GetLastError());
+ if (retval != true) {
+ goto end;
+ }
+ }
+
+ if (opt_fetchmail) {
+ retval = openchangeclient_fetchmail(&obj_store, &oclient);
+ mapi_errstr("fetchmail", GetLastError());
+ if (retval != true) {
+ goto end;
+ }
+ }
+
+ if (opt_deletemail) {
+ bool ret = openchangeclient_deletemail(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("deletemail", GetLastError());
+ if (ret != true) {
+ goto end;
+ }
+ }
+
+ /* MAPI calendar operations */
+ if (opt_sendappointment) {
+ bool ret;
+ if (!oclient.dtstart && !oclient.update) {
+ printf("You need to specify a start date (e.g: 2007-06-01 22:30:00)\n");
+ goto end;
+ }
+
+ if (!oclient.dtend && !oclient.update) {
+ printf("Setting default end date\n");
+ oclient.dtend = oclient.dtstart;
+ }
+
+ if (!oclient.update) {
+ ret = openchangeclient_sendappointment(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("sendappointment", GetLastError());
+ } else {
+ ret = openchangeclient_updateitem(mem_ctx, &obj_store, &oclient, IPF_APPOINTMENT);
+ mapi_errstr("update appointment", GetLastError());
+ }
+ if (ret != true) {
+ goto end;
+ }
+ }
+
+ if (oclient.freebusy) {
+ bool ret = openchangeclient_freebusy(&obj_store, &oclient);
+ mapi_errstr("freebusy", GetLastError());
+
+ if (ret != true) {
+ goto end;
+ }
+ }
+
+ /* MAPI contact operations */
+ if (opt_sendcontact) {
+ bool ret;
+ if (!oclient.update) {
+ ret = openchangeclient_sendcontact(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("sendcontact", GetLastError());
+ } else {
+ ret = openchangeclient_updateitem(mem_ctx, &obj_store, &oclient, IPF_CONTACT);
+ mapi_errstr("update contact", GetLastError());
+ }
+ if (ret != true) {
+ goto end;
+ }
+ }
+
+ /* MAPI task operations */
+ if (opt_sendtask) {
+ bool ret;
+ if (!oclient.dtstart && !oclient.update) {
+ printf("You need to specify a start date (e.g: 2007-06-01 22:30:00)\n");
+ goto end;
+ }
+
+ if (!oclient.dtend && !oclient.update) {
+ printf("Setting default end date\n");
+ oclient.dtend = oclient.dtstart;
+ }
+
+ if (!oclient.update) {
+ ret = openchangeclient_sendtask(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("sendtask", GetLastError());
+ } else {
+ ret = openchangeclient_updateitem(mem_ctx, &obj_store, &oclient, IPF_TASK);
+ mapi_errstr("update task", GetLastError());
+ }
+ if (ret != true) {
+ goto end;
+ }
+ }
+
+ /* MAPI note operations */
+ if (opt_sendnote) {
+ bool ret;
+ if (!oclient.update) {
+ ret = openchangeclient_sendnote(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("sendnote", GetLastError());
+ } else {
+ ret = openchangeclient_updateitem(mem_ctx, &obj_store, &oclient, IPF_STICKYNOTE);
+ mapi_errstr("update note", GetLastError());
+ }
+ if (ret != true) {
+ goto end;
+ }
+ }
+
+ /* Monitor newmail notifications */
+ if (opt_notifications) {
+ openchangeclient_notifications(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("notifications", GetLastError());
+ if (retval != true) {
+ goto end;
+ }
+ }
+
+ /* Folder operations */
+ if (opt_mkdir) {
+ openchangeclient_mkdir(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("mkdir", GetLastError());
+ if (retval != true) {
+ goto end;
+ }
+ }
+
+ if (opt_rmdir) {
+ openchangeclient_rmdir(mem_ctx, &obj_store, &oclient);
+ mapi_errstr("rmdir", GetLastError());
+ if (retval != true) {
+ goto end;
+ }
+ }
+
+ /* Uninitialize MAPI subsystem */
+end:
+ mapi_object_release(&obj_store);
+
+ MAPIUninitialize();
+
+ talloc_free(mem_ctx);
+
+ return 0;
+}
Added: trunk/openchange/utils/openchangeclient.h
===================================================================
--- trunk/openchange/utils/openchangeclient.h (rev 0)
+++ trunk/openchange/utils/openchangeclient.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,155 @@
+/*
+ Stand-alone MAPI application
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2007
+
+ 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 __OPENCHANGECLIENT_H__
+#define __OPENCHANGECLIENT_H__
+
+struct oc_property {
+ struct oc_property *prev;
+ struct oc_property *next;
+ uint32_t ulPropTag;
+ const void *data;
+ bool named;
+};
+
+struct ocpf_file {
+ struct ocpf_file *prev;
+ struct ocpf_file *next;
+ const char *filename;
+};
+
+struct attach {
+ const char *filename;
+ struct Binary_r bin;
+ int fd;
+};
+
+struct oclient {
+ struct oc_property *props;
+ const char *update;
+ const char *delete;
+ const char *subject;
+ const char *pr_body;
+ const char *pr_html_inline;
+ char **usernames;
+ char **mapi_to;
+ char **mapi_cc;
+ char **mapi_bcc;
+ struct Binary_r pr_html;
+ struct attach *attach;
+ uint32_t attach_num;
+ const char *store_folder;
+ const char *location;
+ const char *dtstart;
+ const char *dtend;
+ int busystatus;
+ int taskstatus;
+ int label;
+ bool private;
+ int importance;
+ int color;
+ int width;
+ int height;
+ const char *email;
+ const char *full_name;
+ const char *card_name;
+ const char *folder_name;
+ const char *folder_comment;
+ const char *freebusy;
+ bool force;
+ /* PF related options */
+ bool pf;
+ const char *folder;
+ /* OCPF related options */
+ struct ocpf_file *ocpf_files;
+ const char *ocpf_dump;
+};
+
+struct itemfolder {
+ const uint32_t olFolder;
+ const char *container_class;
+};
+
+struct itemfolder defaultFolders[] = {
+ {olFolderInbox, "Mail"},
+ {olFolderCalendar, "Appointment"},
+ {olFolderContacts, "Contact"},
+ {olFolderTasks, "Task"},
+ {olFolderNotes, "Note"},
+ {0 , NULL}
+};
+
+struct oc_element {
+ uint8_t index;
+ const char *status;
+};
+
+struct oc_element oc_busystatus[] = {
+ {BUSY_STATUS_FREE, "FREE"},
+ {BUSY_STATUS_TENTATIVE, "TENTATIVE"},
+ {BUSY_STATUS_BUSY, "BUSY"},
+ {BUSY_STATUS_OUTOFOFFICE, "OUTOFOFFICE"},
+ {0 , NULL}
+};
+
+struct oc_element oc_importance[] = {
+ {IMPORTANCE_LOW, "LOW"},
+ {IMPORTANCE_NORMAL, "NORMAL"},
+ {IMPORTANCE_HIGH, "HIGH"},
+ {0, NULL}
+};
+
+struct oc_element oc_taskstatus[] = {
+ {olTaskNotStarted, "NOTSTARTED"},
+ {olTaskInProgress, "PROGRESS"},
+ {olTaskComplete, "COMPLETED"},
+ {olTaskWaiting, "WAITING"},
+ {olTaskDeferred, "DEFERRED"},
+ {0, NULL}
+};
+
+struct oc_element oc_label[] = {
+ {0, "NONE"},
+ {1, "IMPORTANT"},
+ {2, "BUSINESS"},
+ {3, "PERSONAL"},
+ {4, "VACATION"},
+ {5, "MUST_ATTEND"},
+ {6, "TRAVEL_REQUIRED"},
+ {7, "NEEDS_PREPARATION"},
+ {8, "BIRTHDAY"},
+ {9, "ANNIVERSARY"},
+ {10, "PHONE_CALL"},
+ {0, NULL}
+};
+
+struct oc_element oc_color[] = {
+ {olBlue, "Blue"},
+ {olGreen, "Green"},
+ {olPink, "Pink"},
+ {olYellow, "Yellow"},
+ {olWhite, "White"},
+ {0, NULL}
+};
+
+#define DATE_FORMAT "%Y-%m-%d %H:%M:%S"
+
+#endif /* !__OPENCHANGECLIENT_H__ */
Added: trunk/openchange/utils/openchangepfadmin.c
===================================================================
--- trunk/openchange/utils/openchangepfadmin.c (rev 0)
+++ trunk/openchange/utils/openchangepfadmin.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,595 @@
+/*
+ Public Folders Administration Tool
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2007
+
+ 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 <libmapiadmin/libmapiadmin.h>
+#include <samba/popt.h>
+#include <param.h>
+
+#include "openchangepfadmin.h"
+#include "openchange-tools.h"
+
+static int32_t get_aclrights(const char *permission)
+{
+ uint32_t i;
+
+ if (!permission) return -1;
+
+ for (i = 0; aclrights[i].name != NULL; i++) {
+ if (!strcmp(permission, aclrights[i].name)) {
+ return aclrights[i].value;
+ }
+ }
+ return -1;
+}
+
+static void list_aclrights(void)
+{
+ uint32_t i;
+
+ printf("Valid permissions:\n");
+ for (i = 0; aclrights[i].name != NULL; i++) {
+ printf("\t%s\n", aclrights[i].name);
+ }
+}
+
+static int32_t check_IPF_class(const char *dirclass)
+{
+ uint32_t i;
+
+ if (!dirclass) return -1;
+
+ for (i = 0; IPF_class[i]; i++) {
+ if (!strcmp(dirclass, IPF_class[i])) {
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static void list_IPF_class(void)
+{
+ uint32_t i;
+
+ printf("Valid IPF Classes:\n");
+ for (i = 0; IPF_class[i] != NULL; i++) {
+ printf("\t%s\n", IPF_class[i]);
+ }
+}
+
+static char *utf8tolinux(TALLOC_CTX *mem_ctx, const char *wstring)
+{
+ char *newstr;
+
+ newstr = windows_to_utf8(mem_ctx, wstring);
+ return newstr;
+}
+
+static bool get_child_folders_pf(TALLOC_CTX *mem_ctx, mapi_object_t *parent, mapi_id_t folder_id, int count)
+{
+ enum MAPISTATUS retval;
+ bool ret;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_htable;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet rowset;
+ const char *name;
+ char *newname;
+ const uint32_t *child;
+ uint32_t index;
+ const uint64_t *fid;
+ int i;
+
+ mapi_object_init(&obj_folder);
+ retval = OpenFolder(parent, folder_id, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ mapi_object_init(&obj_htable);
+ retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, NULL);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x3,
+ PR_DISPLAY_NAME,
+ PR_FID,
+ PR_FOLDER_CHILD_COUNT);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return false;
+
+ while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND) && rowset.cRows) {
+ for (index = 0; index < rowset.cRows; index++) {
+ fid = (const uint64_t *)find_SPropValue_data(&rowset.aRow[index], PR_FID);
+ name = (const char *)find_SPropValue_data(&rowset.aRow[index], PR_DISPLAY_NAME);
+ child = (const uint32_t *)find_SPropValue_data(&rowset.aRow[index], PR_FOLDER_CHILD_COUNT);
+
+ for (i = 0; i < count; i++) {
+ printf("| ");
+ }
+ newname = utf8tolinux(mem_ctx, name);
+ printf("|---+ %-15s\n", newname);
+ MAPIFreeBuffer(newname);
+ if (*child) {
+ ret = get_child_folders_pf(mem_ctx, &obj_folder, *fid, count + 1);
+ if (ret == false) return ret;
+ }
+
+ }
+ }
+ return true;
+}
+
+static enum MAPISTATUS openchangepfadmin_getdir(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_container,
+ mapi_object_t *obj_child,
+ const char *folder)
+{
+ enum MAPISTATUS retval;
+ struct SPropTagArray *SPropTagArray;
+ struct SRowSet rowset;
+ mapi_object_t obj_htable;
+ char *newname;
+ const char *name;
+ const uint64_t *fid;
+ uint32_t index;
+
+ mapi_object_init(&obj_htable);
+ retval = GetHierarchyTable(obj_container, &obj_htable, 0, NULL);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x2,
+ PR_DISPLAY_NAME,
+ PR_FID);
+ retval = SetColumns(&obj_htable, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ if (retval != MAPI_E_SUCCESS) return MAPI_E_NOT_FOUND;
+
+ while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND) && rowset.cRows) {
+ for (index = 0; index < rowset.cRows; index++) {
+ fid = (const uint64_t *)find_SPropValue_data(&rowset.aRow[index], PR_FID);
+ name = (const char *)find_SPropValue_data(&rowset.aRow[index], PR_DISPLAY_NAME);
+
+ newname = utf8tolinux(mem_ctx, name);
+ if (newname && fid && !strcmp(newname, folder)) {
+ retval = OpenFolder(obj_container, *fid, obj_child);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+ return MAPI_E_SUCCESS;
+ }
+ MAPIFreeBuffer(newname);
+ }
+ }
+
+ errno = MAPI_E_NOT_FOUND;
+ return MAPI_E_NOT_FOUND;
+}
+
+static enum MAPISTATUS openchangepfadmin_mkdir(mapi_object_t *obj_container,
+ const char *name,
+ const char *comment,
+ const char *type)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_folder;
+ struct SPropValue props[1];
+ uint32_t prop_count = 0;
+
+ mapi_object_init(&obj_folder);
+ retval = CreateFolder(obj_container, FOLDER_GENERIC, name, comment, OPEN_IF_EXISTS, &obj_folder);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ if (type) {
+ set_SPropValue_proptag(&props[0], PR_CONTAINER_CLASS, (const void *) type);
+ prop_count++;
+
+ retval = SetProps(&obj_folder, props, prop_count);
+ mapi_object_release(&obj_folder);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+static enum MAPISTATUS openchangepfadmin_rmdir(TALLOC_CTX *mem_ctx,
+ mapi_object_t *obj_container,
+ const char *name)
+{
+ enum MAPISTATUS retval;
+ mapi_object_t obj_folder;
+
+ mapi_object_init(&obj_folder);
+
+ retval = openchangepfadmin_getdir(mem_ctx, obj_container, &obj_folder, name);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ retval = EmptyFolder(&obj_folder);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ retval = DeleteFolder(obj_container, mapi_object_get_id(&obj_folder),
+ DEL_FOLDERS, NULL);
+ MAPI_RETVAL_IF(retval, GetLastError(), NULL);
+
+ mapi_object_release(&obj_folder);
+
+ return MAPI_E_SUCCESS;
+}
+
+int main(int argc, const char *argv[])
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct mapi_session *session = NULL;
+ mapi_object_t obj_store;
+ mapi_object_t obj_ipm_subtree;
+ mapi_object_t obj_folder;
+ mapi_id_t id_pf;
+ poptContext pc;
+ int opt;
+ const char *opt_profdb = NULL;
+ char *opt_profname = NULL;
+ const char *opt_password = NULL;
+ const char *opt_comment = NULL;
+ const char *opt_dirclass = NULL;
+ const char *opt_adduser = NULL;
+ const char *opt_rmuser = NULL;
+ const char *opt_apassword = NULL;
+ const char *opt_adesc = NULL;
+ const char *opt_acomment = NULL;
+ const char *opt_afullname = NULL;
+ const char *opt_addright = NULL;
+ bool opt_rmright = false;
+ const char *opt_modright = NULL;
+ const char *opt_folder = NULL;
+ const char *opt_debug = NULL;
+ const char *opt_username = NULL;
+ int32_t opt_permission = -1;
+ bool opt_ipm_list = false;
+ bool opt_mkdir = false;
+ bool opt_rmdir = false;
+ bool opt_dumpdata = false;
+
+ enum {OPT_PROFILE_DB=1000, OPT_PROFILE, OPT_PASSWORD, OPT_IPM_LIST,
+ OPT_MKDIR, OPT_RMDIR, OPT_COMMENT, OPT_DIRCLASS, OPT_ACL,
+ OPT_ADDUSER, OPT_RMUSER, OPT_DEBUG, OPT_APASSWORD, OPT_ADESC,
+ OPT_ACOMMENT, OPT_AFULLNAME, OPT_ADDRIGHT, OPT_RMRIGHT,
+ OPT_MODRIGHT, OPT_USERNAME, OPT_FOLDER, 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"},
+ {"apassword", 0, POPT_ARG_STRING, NULL, OPT_APASSWORD, "set the account password", "PASSWORD"},
+ {"adesc", 0, POPT_ARG_STRING, NULL, OPT_ADESC, "set the account description", "DESCRIPTION"},
+ {"acomment", 0, POPT_ARG_STRING, NULL, OPT_ACOMMENT, "set the account comment", "COMMENT"},
+ {"afullname", 0, POPT_ARG_STRING, NULL, OPT_AFULLNAME, "set the account full name", "NAME"},
+ {"list",0, POPT_ARG_NONE, NULL, OPT_IPM_LIST, "list IPM subtree directories", NULL},
+ {"mkdir", 0, POPT_ARG_NONE, NULL, OPT_MKDIR, "create a Public Folder directory", NULL},
+ {"rmdir", 0, POPT_ARG_NONE, NULL, OPT_RMDIR, "delete a Public Folder directory", NULL},
+ {"comment", 0, POPT_ARG_STRING, NULL, OPT_COMMENT, "set the folder comment", "COMMENT"},
+ {"dirclass", 0, POPT_ARG_STRING, NULL, OPT_DIRCLASS, "set the folder class", "CLASS"},
+ {"adduser", 0, POPT_ARG_STRING, NULL, OPT_ADDUSER, "add Exchange user", "USERNAME"},
+ {"rmuser", 0, POPT_ARG_STRING, NULL, OPT_RMUSER, "delete Exchange user", "USERNAME"},
+ {"addright", 0, POPT_ARG_STRING, NULL, OPT_ADDRIGHT, "add MAPI permissions to PF folder", "RIGHT"},
+ {"rmright", 0, POPT_ARG_NONE, NULL, OPT_RMRIGHT, "remove MAPI permissions to PF folder", NULL},
+ {"modright", 0, POPT_ARG_STRING, NULL, OPT_MODRIGHT, "modify MAPI permissions to PF folder", "RIGHT"},
+ {"debuglevel", 0, POPT_ARG_STRING, NULL, OPT_DEBUG, "set debug level", "LEVEL"},
+ {"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMPDATA, "Dump the hex data", NULL},
+ {"folder", 0, POPT_ARG_STRING, NULL, OPT_FOLDER, "specify the Public Folder directory", "FOLDER"},
+ {"username", 0, POPT_ARG_STRING, NULL, OPT_USERNAME, "specify the username to use", "USERNAME"},
+ POPT_OPENCHANGE_VERSION
+ { NULL, 0, POPT_ARG_NONE, NULL, 0, NULL, NULL }
+ };
+
+ mem_ctx = talloc_named(NULL, 0, "openchangepfadmin");
+
+ pc = poptGetContext("openchangepfadmin", argc, argv, long_options, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_DEBUG:
+ opt_debug = poptGetOptArg(pc);
+ break;
+ case OPT_DUMPDATA:
+ opt_dumpdata = true;
+ break;
+ case OPT_PROFILE_DB:
+ opt_profdb = poptGetOptArg(pc);
+ break;
+ case OPT_PROFILE:
+ opt_profname = talloc_strdup(mem_ctx, poptGetOptArg(pc));
+ break;
+ case OPT_PASSWORD:
+ opt_password = poptGetOptArg(pc);
+ break;
+ case OPT_IPM_LIST:
+ opt_ipm_list = true;
+ break;
+ case OPT_MKDIR:
+ opt_mkdir = true;
+ break;
+ case OPT_RMDIR:
+ opt_rmdir = true;
+ break;
+ case OPT_COMMENT:
+ opt_comment = poptGetOptArg(pc);
+ break;
+ case OPT_DIRCLASS:
+ opt_dirclass = poptGetOptArg(pc);
+ break;
+ case OPT_ADDUSER:
+ opt_adduser = poptGetOptArg(pc);
+ break;
+ case OPT_RMUSER:
+ opt_rmuser = poptGetOptArg(pc);
+ break;
+ case OPT_APASSWORD:
+ opt_apassword = poptGetOptArg(pc);
+ break;
+ case OPT_ADESC:
+ opt_adesc = poptGetOptArg(pc);
+ break;
+ case OPT_ACOMMENT:
+ opt_acomment = poptGetOptArg(pc);
+ break;
+ case OPT_AFULLNAME:
+ opt_afullname = poptGetOptArg(pc);
+ break;
+ case OPT_ADDRIGHT:
+ opt_addright = poptGetOptArg(pc);
+ break;
+ case OPT_RMRIGHT:
+ opt_rmright = true;
+ break;
+ case OPT_MODRIGHT:
+ opt_modright = poptGetOptArg(pc);
+ break;
+ case OPT_FOLDER:
+ opt_folder = poptGetOptArg(pc);
+ break;
+ case OPT_USERNAME:
+ opt_username = poptGetOptArg(pc);
+ break;
+ default:
+ break;
+ };
+ }
+
+ /* Sanity check on options */
+
+ if ((opt_mkdir == true && !opt_folder) || (opt_rmdir == true && !opt_folder) ||
+ (opt_addright && !opt_folder) || (opt_rmright == true && !opt_folder) ||
+ (opt_modright && !opt_folder)) {
+ printf("You need to specify a directory with --folder option\n");
+ return (-1);
+ }
+
+ if ((opt_addright && !opt_username) || (opt_rmright == true && !opt_username) ||
+ (opt_modright && !opt_username)) {
+ printf("You need to specify a username with --username option\n");
+ return (-1);
+ }
+
+ /* dirclass sanity check */
+ if (opt_dirclass) {
+ if (check_IPF_class(opt_dirclass) == -1) {
+ list_IPF_class();
+ return (-1);
+ }
+ }
+
+ if (!opt_profdb) {
+ opt_profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, getenv("HOME"));
+ }
+
+ /**
+ * Initialize MAPI subsystem
+ */
+ retval = MAPIInitialize(opt_profdb);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", GetLastError());
+ exit (1);
+ }
+
+ /* debug options */
+ SetMAPIDumpData(opt_dumpdata);
+
+ if (opt_debug) {
+ SetMAPIDebugLevel(atoi(opt_debug));
+ }
+
+ /**
+ * If no profile is specified, try to load the default one
+ * from the database
+ */
+ if (!opt_profname) {
+ retval = GetDefaultProfile(&opt_profname);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("GetDefaultProfile", GetLastError());
+ exit (1);
+ }
+ }
+
+ retval = MapiLogonEx(&session, opt_profname, opt_password);
+ talloc_free(opt_profname);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MapiLogonEx", GetLastError());
+ exit (1);
+ }
+
+ /**
+ * User management operations
+ */
+
+ if (opt_adduser) {
+ struct mapiadmin_ctx *mapiadmin_ctx;
+
+ mapiadmin_ctx = mapiadmin_init(session);
+ mapiadmin_ctx->username = opt_adduser;
+ mapiadmin_ctx->password = opt_apassword;
+ mapiadmin_ctx->description = opt_adesc;
+ mapiadmin_ctx->comment = opt_acomment;
+ mapiadmin_ctx->fullname = opt_afullname;
+
+ retval = mapiadmin_user_add(mapiadmin_ctx);
+ mapi_errstr("mapiadmin_user_add", GetLastError());
+ if (retval != MAPI_E_SUCCESS) {
+ exit (1);
+ }
+ printf("username: %s\n", mapiadmin_ctx->username);
+ printf("password: %s\n", mapiadmin_ctx->password);
+ }
+
+ if (opt_rmuser) {
+ struct mapiadmin_ctx *mapiadmin_ctx;
+
+ mapiadmin_ctx = mapiadmin_init(session);
+ mapiadmin_ctx->username = opt_rmuser;
+
+ retval = mapiadmin_user_del(mapiadmin_ctx);
+ mapi_errstr("mapiadmin_user_del", GetLastError());
+ }
+
+ /**
+ * Open Public Folder Store
+ */
+
+ mapi_object_init(&obj_store);
+ retval = OpenPublicFolder(session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("OpenPublicFolder", GetLastError());
+ goto end;
+ }
+
+ /* Open IPM Subtree (All Public Folders) */
+ retval = GetDefaultPublicFolder(&obj_store, &id_pf, olFolderPublicIPMSubtree);
+ if (retval != MAPI_E_SUCCESS) {
+ goto end;
+ }
+
+ mapi_object_init(&obj_ipm_subtree);
+ retval = OpenFolder(&obj_store, id_pf, &obj_ipm_subtree);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("OpenFolder", GetLastError());
+ goto end;
+ }
+
+ /* create directory */
+ if (opt_mkdir == true) {
+ retval = openchangepfadmin_mkdir(&obj_ipm_subtree, opt_folder, opt_comment, opt_dirclass);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("mkdir", GetLastError());
+ goto end;
+ }
+ }
+
+ /* remove directory */
+ if (opt_rmdir == true) {
+ retval = openchangepfadmin_rmdir(mem_ctx, &obj_ipm_subtree, opt_folder);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("rmdir", GetLastError());
+ goto end;
+ }
+
+ }
+
+ /* add permissions */
+ if (opt_addright) {
+ if ((opt_permission = get_aclrights(opt_addright)) == -1) {
+ printf("Invalid permission\n");
+ list_aclrights();
+ goto end;
+ } else {
+ mapi_object_init(&obj_folder);
+ retval = openchangepfadmin_getdir(mem_ctx, &obj_ipm_subtree, &obj_folder, opt_folder);
+ if (retval != MAPI_E_SUCCESS) {
+ printf("Invalid directory\n");
+ goto end;
+ }
+ retval = AddUserPermission(&obj_folder, opt_username, opt_permission);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("AddUserPermission", GetLastError());
+ mapi_object_release(&obj_folder);
+ goto end;
+ }
+ mapi_object_release(&obj_folder);
+ }
+ printf("Permission %s added for %s on folder %s\n", opt_addright, opt_username, opt_folder);
+ }
+
+ /* remove permissions */
+ if (opt_rmright == true) {
+ mapi_object_init(&obj_folder);
+ retval = openchangepfadmin_getdir(mem_ctx, &obj_ipm_subtree, &obj_folder, opt_folder);
+ if (retval != MAPI_E_SUCCESS) {
+ printf("Invalid directory\n");
+ goto end;
+ }
+ retval = RemoveUserPermission(&obj_folder, opt_username);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("RemoveUserPermission", GetLastError());
+ mapi_object_release(&obj_folder);
+ goto end;
+ }
+ mapi_object_release(&obj_folder);
+ printf("Permission removed for %s on folder %s\n", opt_username, opt_folder);
+ }
+
+ /* modify permissions */
+ if (opt_modright) {
+ opt_permission = get_aclrights(opt_modright);
+ if (opt_permission == -1) {
+ printf("Invalid permission\n");
+ list_aclrights();
+ goto end;
+ } else {
+ mapi_object_init(&obj_folder);
+ retval = openchangepfadmin_getdir(mem_ctx, &obj_ipm_subtree, &obj_folder, opt_folder);
+ if (retval != MAPI_E_SUCCESS) {
+ printf("Invalid directory\n");
+ goto end;
+ }
+ retval = ModifyUserPermission(&obj_folder, opt_username, opt_permission);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("ModifyUserPermission", GetLastError());
+ mapi_object_release(&obj_folder);
+ goto end;
+ }
+ mapi_object_release(&obj_folder);
+ }
+ printf("Permission changed to %s for %s on folder %s\n", opt_modright, opt_username, opt_folder);
+ }
+
+ /* list directories */
+ if (opt_ipm_list == true) {
+ printf("+ All Public Folders\n");
+ get_child_folders_pf(mem_ctx, &obj_ipm_subtree, id_pf, 0);
+ }
+
+ /**
+ * Uninitialize MAPI subsystem
+ */
+end:
+ mapi_object_release(&obj_store);
+
+ MAPIUninitialize();
+ talloc_free(mem_ctx);
+ return 0;
+}
Added: trunk/openchange/utils/openchangepfadmin.h
===================================================================
--- trunk/openchange/utils/openchangepfadmin.h (rev 0)
+++ trunk/openchange/utils/openchangepfadmin.h 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,65 @@
+/*
+ Public Folders Administration Tool
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2007
+
+ 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 __OPENCHANGEPFADMIN_H__
+#define __OPENCHANGEPFADMIN_H__
+
+#define DEFAULT_PROFDB "%s/.openchange/profiles.ldb"
+
+struct aclrights {
+ const char *name;
+ uint32_t value;
+};
+
+const struct aclrights aclrights[] = {
+ {"RightsNone", 0x00000000},
+ {"RightsReadItems", 0x00000001},
+ {"RightsCreateItems", 0x00000002},
+ {"RightsEditOwn", 0x00000008},
+ {"RightsDeleteOwn", 0x00000010},
+ {"RightsEditAll", 0x00000020},
+ {"RightsDeleteAll", 0x00000040},
+ {"RightsCreateSubfolders", 0x00000080},
+ {"RightsFolderOwner", 0x00000100},
+ {"RightsFolderContact", 0x00000200},
+ {"RoleNone", 0x00000400},
+ {"RoleReviewer", 0x00000401},
+ {"RoleContributor", 0x00000402},
+ {"RoleNoneditingAuthor", 0x00000413},
+ {"RoleAuthor", 0x0000041B},
+ {"RoleEditor", 0x0000047B},
+ {"RolePublishAuthor", 0x0000049B},
+ {"RolePublishEditor", 0x000004FB},
+ {"RightsAll", 0x000005FB},
+ {"RoleOwner", 0x000007FB},
+ {NULL, 0}
+};
+
+const char * IPF_class[] = { IPF_APPOINTMENT,
+ IPF_CONTACT,
+ IPF_JOURNAL,
+ IPF_NOTE,
+ IPF_STICKYNOTE,
+ IPF_TASK,
+ IPF_POST,
+ NULL};
+
+#endif /* __OPENCHANGEPFADMIN_H__ */
Added: trunk/openchange/utils/schemaIDGUID.c
===================================================================
--- trunk/openchange/utils/schemaIDGUID.c (rev 0)
+++ trunk/openchange/utils/schemaIDGUID.c 2009-04-14 14:39:21 UTC (rev 2698)
@@ -0,0 +1,50 @@
+/*
+ MAPI Implementation
+
+ OpenChange Project
+
+ Copyright (C) Julien Kerihuel 2006
+
+ 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 <ldb.h>
+
+static void usage(void)
+{
+ printf("schemaIDGUID <base64 string>\n");
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ TALLOC_CTX *mem_ctx;
+ DATA_BLOB blob;
+ struct GUID *guid;
+ char *schemaIDGUID;
+
+ if (argc != 2) {
+ usage();
+ }
+
+ mem_ctx = talloc_named(NULL, 0, "SchemaIDGUID");
+
+ blob = data_blob_talloc(mem_ctx, argv[1], strlen(argv[1])+1);
+ blob.length = ldb_base64_decode((char *)blob.data);
+ guid = (struct GUID *) blob.data;
+ schemaIDGUID = GUID_string(mem_ctx, guid);
+ printf("%s\n", schemaIDGUID);
+ return (0);
+}
More information about the Pkg-samba-maint
mailing list