[Pkg-samba-maint] r2734 - in trunk/openchange: . debian libmapi libmapi/conf mapiproxy torture utils utils/mapitest utils/mapitest/modules

jelmer at alioth.debian.org jelmer at alioth.debian.org
Thu Apr 30 18:06:50 UTC 2009


Author: jelmer
Date: 2009-04-30 18:06:50 +0000 (Thu, 30 Apr 2009)
New Revision: 2734

Modified:
   trunk/openchange/.bzrignore
   trunk/openchange/ChangeLog
   trunk/openchange/debian/changelog
   trunk/openchange/exchange.idl
   trunk/openchange/libmapi/FXICS.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/IMessage.c
   trunk/openchange/libmapi/IMsgStore.c
   trunk/openchange/libmapi/IStoreFolder.c
   trunk/openchange/libmapi/IStream.c
   trunk/openchange/libmapi/IUnknown.c
   trunk/openchange/libmapi/IXPLogon.c
   trunk/openchange/libmapi/conf/mapi-properties
   trunk/openchange/libmapi/conf/mparse.pl
   trunk/openchange/libmapi/mapi_notification.h
   trunk/openchange/libmapi/x500.c
   trunk/openchange/mapiproxy/dcesrv_mapiproxy.c
   trunk/openchange/torture/mapi_newmail.c
   trunk/openchange/utils/mapitest/mapitest_common.c
   trunk/openchange/utils/mapitest/module.c
   trunk/openchange/utils/mapitest/modules/module_oxcfold.c
   trunk/openchange/utils/mapitest/modules/module_oxcnotif.c
   trunk/openchange/utils/mapitest/modules/module_oxcprpt.c
   trunk/openchange/utils/mapitest/modules/module_oxomsg.c
   trunk/openchange/utils/openchangeclient.c
Log:
Merge new upstream snapshot.

Modified: trunk/openchange/.bzrignore
===================================================================
--- trunk/openchange/.bzrignore	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/.bzrignore	2009-04-30 18:06:50 UTC (rev 2734)
@@ -64,3 +64,4 @@
 libmapi++/examples/messages
 bin/mapistore_test
 _trial_temp
+mapiproxy/libmapiproxy/openchangedb_property.c

Modified: trunk/openchange/ChangeLog
===================================================================
--- trunk/openchange/ChangeLog	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/ChangeLog	2009-04-30 18:06:50 UTC (rev 2734)
@@ -1,3 +1,121 @@
+2009-04-27
+    jkerihuel
+	[r1339]
+		Patch from Paolo Abeni <paolo.abeni at gmail.com>:
+		
+		call ProcessNotification() after each successful 
+		emsmdb_transaction() in all the libmapi calls.
+	[r1338]
+		Patch from Paolo Abeni <paolo.abeni at gmail.com>:
+		
+		Mapi notifications can occurs inside any emsmdb_transaction; currently
+		only the notification send by the server inside the
+		emsmdb_transaction_null() in MonitorNotification() are
+		parsed/processed/delivered to the appropriate callback.
+		
+		To be able to process all the received notifications, the notification
+		structure must comprise the private data to be passed to the
+		notification callback, since in the average mapi call this data is not
+		available. This patch modifies the Subscribe() call and the 
+		mapi_notification structure, adding the private_data parameter (also the 
+		related Subscribe() calls are update)  and add a libmapi call 
+		(DispatchNotifications) to force the notification dispatching in
+		a [quite] non blocking way
+
+2009-04-26
+    jkerihuel
+	[r1336]
+		Patch from Paolo Abeni <paolo.abeni at gmail.com>:
+		
+		ProcessNotification() is ignoring the handle value contained into the
+		processed notifications. This means that if many Subscribe() calls are
+		performed on different folders but with the same flags, all the
+		registered callback are [incorrectly] signaled with each received
+		notification.
+		
+		The attached patch match the handler contained into the notification
+		message against the notification object handle to avoid such
+		replication.
+
+2009-04-23
+    jkerihuel
+	[r1331]
+		Make sure delayed authenication is not called when server mode is enabled
+    bradh
+	[r1333]
+		Update property list to reflect current OAB props.
+		
+		This deletes a few incompatible properties. Cannot determine the history of the PR_MAILBEAT_ props.
+	[r1332]
+		Fix display of Folder ID values (one is filled with ., the other is prefixed with .16 instead of being filled.
+		
+		Also remove duplicate close() of file descriptor.
+	[r1330]
+		Typo fix.
+
+2009-04-22
+    bradh
+	[r1328]
+		Warning fix.
+
+2009-04-21
+    bradh
+	[r1326]
+		Implement RopTransportNewMail (0x51).
+		
+		Includes IDL, libmapi implementation, and basic mapitest coverage.
+		
+		Also fix a few doxygen / formatting things.
+
+2009-04-19
+    jkerihuel
+	[r1324]
+		- Add Redirect buffer support for OpenMsgStore and OpenPublicFolder.
+		This commit fixes the ecWrongServer (0x478) error users encounter
+		while running openchange based software in a clustered Exchange 
+		environment.
+
+2009-04-18
+    bradh
+	[r1322]
+		Implement RopCloneStream (0x3b) and RopWriteAndCommitStream (0x90).
+		
+		Includes IDL, implementation and mapitest tests.
+
+2009-04-17
+    bradh
+	[r1320]
+		Fix Search notifications.
+		
+		MS concurred that the docs are wrong.
+		
+		Patch by Paolo Abeni - thanks very much for the
+		investigation and the patch.
+	[r1319]
+		Update GetStoreState documentation.
+	[r1318]
+		Implement RopSetPropertiesNoReplicate (0x79).
+		
+		IDL was already done. mapitest for DeletePropertiesNoReplicate was
+		reused / updated.
+
+2009-04-16
+    bradh
+	[r1316]
+		Implement (IDL, libmapi, mapitest) RopHardDeleteMessagesAndSubfolders (0x92)
+		
+		Also fix some bugs in mapitest common code, and an incorrect sanity check in CreateFolder().
+
+2009-04-15
+    bradh
+	[r1314]
+		Implement RopHardDeleteMessages (0x91). 
+		
+		Includes IDL, implementation and mapitest.
+    jelmer
+	[r1313]
+		Ignore generated property file.
+
 2009-04-13
     bradh
 	[r1311]

Modified: trunk/openchange/debian/changelog
===================================================================
--- trunk/openchange/debian/changelog	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/debian/changelog	2009-04-30 18:06:50 UTC (rev 2734)
@@ -1,4 +1,4 @@
-openchange (1:0.8.2+svn1312-1) experimental; urgency=low
+openchange (1:0.8.2+svn1340-1) experimental; urgency=low
 
   * New upstream snapshot.
   * Build exchange2ical.

Modified: trunk/openchange/exchange.idl
===================================================================
--- trunk/openchange/exchange.idl	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/exchange.idl	2009-04-30 18:06:50 UTC (rev 2734)
@@ -837,6 +837,7 @@
 			op_MAPI_Abort				= 0x38,
 			op_MAPI_CopyTo				= 0x39,
 			op_MAPI_CopyToStream			= 0x3a,
+			op_MAPI_CloneStream			= 0x3b,
 			op_MAPI_GetTable			= 0x3e,
 			op_MAPI_GetRulesTable			= 0x3f,
 			op_MAPI_ModifyTable			= 0x40,
@@ -853,6 +854,7 @@
 			op_MAPI_FastTransferSourceGetBuffer	= 0x4e,
 			op_MAPI_FindRow				= 0x4f,
 			op_MAPI_Progress			= 0x50,
+			op_MAPI_TransportNewMail		= 0x51,
 			op_MAPI_GetNamesFromIDs			= 0x55,
 			op_MAPI_GetIDsFromNames			= 0x56,
 			op_MAPI_UpdateDeferredActionMessages	= 0x57,
@@ -894,6 +896,9 @@
 			op_MAPI_OpenPublicFolderByName		= 0x87,
 			op_MAPI_SetSyncNotificationGuid		= 0x88,
 			op_MAPI_FreeBookmark			= 0x89,
+			op_MAPI_WriteAndCommitStream		= 0x90,
+			op_MAPI_HardDeleteMessages		= 0x91,
+			op_MAPI_HardDeleteMessagesAndSubfolders	= 0x92,
 			op_MAPI_Logon				= 0xfe,
 			/****** custom MAPI opnum for mapiproxy ******/
 			op_MAPI_proxypack			= 0xa5
@@ -2219,6 +2224,15 @@
 		[switch_is(TableEvent)] ContentsTableChangeUnion	ContentsTableChangeUnion;
 	} ContentsTableChange;
 
+	/* SearchMessageCreatedNotification: case 0xc004 */
+	typedef [flag(NDR_NOALIGN)] struct {
+		hyper					FID;
+		hyper					MID;
+		hyper					SearchFID;
+		uint16					TagCount;
+		MAPITAGS				Tags[TagCount];
+	} SearchMessageCreatedNotification;
+
 	/* SearchMessageRemovedNotification: case 0xc008 */
 	typedef [flag(NDR_NOALIGN)] struct {
 		hyper					FID;
@@ -2230,7 +2244,6 @@
 	typedef [flag(NDR_NOALIGN)] struct {
 		hyper					FID;
 		hyper					MID;
-		hyper					SearchFID;
 		uint16					TagCount;
 		MAPITAGS				Tags[TagCount];
 	} SearchMessageModifiedNotification;
@@ -2255,6 +2268,7 @@
 		[case(0x8020)] MessageMoveCopyNotification		MessageMoveNotification;
 		[case(0x8040)] MessageMoveCopyNotification		MessageCopyNotification;
 		[case(0x8100)] ContentsTableChange			ContentsTableChange;
+		[case(0xc004)] SearchMessageCreatedNotification		SearchMessageCreatedNotification;
 		[case(0xc008)] SearchMessageRemovedNotification		SearchMessageRemovedNotification;
 		[case(0xc010)] SearchMessageModifiedNotification	SearchMessageModifiedNotification;
 		[case(0xc100)] ContentsTableChange			SearchTableChange;
@@ -2498,6 +2512,15 @@
 	} CopyToStream_repl;
 
 	/*************************/
+	/* EcDoRpc Function 0x3b */
+	typedef [flag(NDR_NOALIGN)] struct {
+		uint8		handle_idx;
+	} CloneStream_req;
+
+	typedef [flag(NDR_NOALIGN)] struct {
+	} CloneStream_repl;
+
+	/*************************/
 	/* EcDoRpc Function 0x3e */
 	typedef [flag(NDR_NOALIGN)] struct {
 		uint8		handle_idx;
@@ -2730,6 +2753,18 @@
 		uint32		TotalTaskCount;
 	} Progress_repl;
 
+	/**************************/
+	/* EcDoRpc Function 0x51  */
+	typedef [flag(NDR_NOALIGN)] struct {
+		hyper		MessageId;
+		hyper		FolderId;
+		astring		MessageClass;
+		uint32		MessageFlags;
+	} TransportNewMail_req;
+
+	typedef [flag(NDR_NOALIGN)] struct {
+	} TransportNewMail_repl;
+
 	/*************************/
 	/* EcDoRpc Function 0x55 */
 	typedef [enum8bit] enum {
@@ -3280,6 +3315,41 @@
 	} FreeBookmark_repl;
 
 	/*************************/
+	/* EcDoRpc Function 0x90 */
+	typedef [flag(NDR_NOALIGN)] struct {
+		[subcontext(2), flag(NDR_REMAINING)] DATA_BLOB	data;
+	} WriteAndCommitStream_req;
+
+
+	typedef [flag(NDR_NOALIGN)] struct {
+		uint16		WrittenSize;
+	} WriteAndCommitStream_repl;
+
+	/**************************/
+	/* EcDoRpc Function 0x91  */
+	typedef [flag(NDR_NOALIGN)] struct {
+		boolean8	WantAsynchronous;
+		boolean8	NotifyNonRead;
+		uint16		MessageIdCount;
+		hyper		MessageIds[MessageIdCount];
+	} HardDeleteMessages_req;
+
+	typedef [flag(NDR_NOALIGN)] struct {
+		boolean8	PartialCompletion;
+	} HardDeleteMessages_repl;
+
+	/*************************/
+	/* EcDoRpc Function 0x92 */
+	typedef [flag(NDR_NOALIGN)] struct {
+		boolean8	WantAsynchronous;
+		boolean8	WantDeleteAssociated;
+	} HardDeleteMessagesAndSubfolders_req;
+
+	typedef [flag(NDR_NOALIGN)] struct {
+		boolean8	PartialCompletion;
+	} HardDeleteMessagesAndSubfolders_repl;
+
+	/*************************/
 	/* EcDoRpc Function 0xFE */
 	typedef [public,bitmap8bit] bitmap {
 		LogonPrivate	= 0x1,
@@ -3434,6 +3504,7 @@
 		[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_CloneStream)] CloneStream_req mapi_CloneStream;
 		[case(op_MAPI_GetTable)] GetTable_req mapi_GetTable;
 		[case(op_MAPI_GetRulesTable)] GetRulesTable_req mapi_GetRulesTable;
 		[case(op_MAPI_ModifyTable)] ModifyTable_req mapi_ModifyTable;
@@ -3450,6 +3521,7 @@
 		[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_TransportNewMail)] TransportNewMail_req mapi_TransportNewMail;
 		[case(op_MAPI_GetNamesFromIDs)] GetNamesFromIDs_req mapi_GetNamesFromIDs;
 		[case(op_MAPI_GetIDsFromNames)] GetIDsFromNames_req mapi_GetIDsFromNames;
 		[case(op_MAPI_UpdateDeferredActionMessages)] UpdateDeferredActionMessages_req mapi_UpdateDeferredActionMessages;
@@ -3490,6 +3562,9 @@
 		[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_WriteAndCommitStream)] WriteAndCommitStream_req mapi_WriteAndCommitStream;
+		[case(op_MAPI_HardDeleteMessages)] HardDeleteMessages_req mapi_HardDeleteMessages;
+		[case(op_MAPI_HardDeleteMessagesAndSubfolders)] HardDeleteMessagesAndSubfolders_req mapi_HardDeleteMessagesAndSubfolders;
 		[case(op_MAPI_Logon)] Logon_req mapi_Logon;
 		[case(op_MAPI_proxypack)] proxypack_req mapi_proxypack;
 	} EcDoRpc_MAPI_REQ_UNION;
@@ -3551,6 +3626,7 @@
 		[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_CloneStream)] CloneStream_repl mapi_CloneStream;
 		[case(op_MAPI_GetTable)] GetTable_repl mapi_GetTable;
 		[case(op_MAPI_GetRulesTable)] GetRulesTable_repl mapi_GetRulesTable;
 		[case(op_MAPI_ModifyTable)] ModifyTable_repl mapi_ModifyTable;
@@ -3567,6 +3643,7 @@
 		[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_TransportNewMail)] TransportNewMail_repl mapi_TransportNewMail;
 		[case(op_MAPI_GetNamesFromIDs)] GetNamesFromIDs_repl mapi_GetNamesFromIDs;
 		[case(op_MAPI_GetIDsFromNames)] GetIDsFromNames_repl mapi_GetIDsFromNames;
 		[case(op_MAPI_UpdateDeferredActionMessages)] UpdateDeferredActionMessages_repl mapi_UpdateDeferredActionMessages;
@@ -3608,6 +3685,9 @@
 		[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_WriteAndCommitStream)] WriteAndCommitStream_repl mapi_WriteAndCommitStream;
+		[case(op_MAPI_HardDeleteMessages)] HardDeleteMessages_repl mapi_HardDeleteMessages;
+		[case(op_MAPI_HardDeleteMessagesAndSubfolders)] HardDeleteMessagesAndSubfolders_repl mapi_HardDeleteMessagesAndSubfolders;
 		[case(op_MAPI_Logon)] Logon_repl mapi_Logon;
 		[case(op_MAPI_proxypack)] proxypack_repl mapi_proxypack;
 

Modified: trunk/openchange/libmapi/FXICS.c
===================================================================
--- trunk/openchange/libmapi/FXICS.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/FXICS.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -101,6 +101,8 @@
 	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);
+
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
 	
 	/* Retrieve output parameters */
 	reply = &mapi_response->mapi_repl->u.mapi_GetLocalReplicaIds;

Modified: trunk/openchange/libmapi/IMAPIContainer.c
===================================================================
--- trunk/openchange/libmapi/IMAPIContainer.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IMAPIContainer.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -132,6 +132,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* set object session, handle and logon_id */
 	mapi_object_set_session(obj_table, session);
 	mapi_object_set_handle(obj_table, mapi_response->handles[1]);
@@ -256,6 +258,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* set object session, handle and logon_id */
 	mapi_object_set_session(obj_table, session);
 	mapi_object_set_handle(obj_table, mapi_response->handles[1]);
@@ -349,6 +353,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* set object session, handle and logon_id */
 	mapi_object_set_session(obj_table, session);
 	mapi_object_set_handle(obj_table, mapi_response->handles[1]);
@@ -444,6 +450,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* set object session, handle and logon_id */
 	mapi_object_set_session(obj_table, session);
 	mapi_object_set_handle(obj_table, mapi_response->handles[1]);
@@ -542,6 +550,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 	
@@ -660,6 +670,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -747,6 +759,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	reply = &mapi_response->mapi_repl->u.mapi_GetSearchCriteria;
 
 	res = &reply->res;

Modified: trunk/openchange/libmapi/IMAPIFolder.c
===================================================================
--- trunk/openchange/libmapi/IMAPIFolder.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IMAPIFolder.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -103,6 +103,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* set object session and handle */
 	mapi_object_set_session(obj_message, session);
 	mapi_object_set_handle(obj_message, mapi_response->handles[1]);
@@ -189,6 +191,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -197,6 +201,89 @@
 
 
 /**
+   \details Hard delete one or more messages
+
+   This function hard deletes one or more messages based on their
+   ids from a specified folder.
+
+   \param obj_folder the folder to hard 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_INVALID_PARAMETER: the parent folder was not valid
+   - MAPI_E_CALL_FAILED: A network problem was encountered during the
+     transaction
+
+   \sa OpenFolder, CreateMessage, GetLastError
+*/
+_PUBLIC_ enum MAPISTATUS HardDeleteMessage(mapi_object_t *obj_folder,
+					   mapi_id_t *id_messages,
+					   uint16_t cn_messages)
+{
+	struct mapi_request		*mapi_request;
+	struct mapi_response		*mapi_response;
+	struct EcDoRpc_MAPI_REQ		*mapi_req;
+	struct HardDeleteMessages_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, "HardDeleteMessages");
+	size = 0;
+
+	/* Fill the HardDeleteMessages operation */
+	request.WantAsynchronous = 0x0;
+	size += sizeof (uint8_t);
+	request.NotifyNonRead = 0x1;
+	size += sizeof(uint8_t);
+	request.MessageIdCount = cn_messages;
+	size += sizeof(uint16_t);
+	request.MessageIds = id_messages;
+	size += request.MessageIdCount * sizeof(mapi_id_t);
+
+	/* Fill the MAPI_REQ request */
+	mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+	mapi_req->opnum = op_MAPI_HardDeleteMessages;
+	mapi_req->logon_id = mapi_object_get_logon_id(obj_folder);
+	mapi_req->handle_idx = 0;
+	mapi_req->u.mapi_HardDeleteMessages = 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
@@ -264,6 +351,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	*ulStatus = mapi_response->mapi_repl->u.mapi_SetMessageStatus.ulOldStatus;
 
 	talloc_free(mapi_response);
@@ -364,6 +453,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	*ulOldStatus = mapi_response->mapi_repl->u.mapi_SetMessageStatus.ulOldStatus;
 
 	talloc_free(mapi_response);
@@ -463,6 +554,8 @@
 	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);
+
+	OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
 	
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
@@ -525,7 +618,7 @@
 	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);
+	OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
 
 	logon_id = mapi_object_get_logon_id(obj_parent);
 
@@ -611,6 +704,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Set object session, handle and id */
 	mapi_object_init(obj_child);
 	mapi_object_set_session(obj_child, session);
@@ -692,6 +787,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -781,6 +878,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	if (PartialCompletion) {
 		*PartialCompletion = mapi_response->mapi_repl->u.mapi_DeleteFolder.PartialCompletion;
 	}
@@ -889,6 +988,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -999,6 +1100,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 	
@@ -1089,6 +1192,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* TODO: parse response */
 
 	talloc_free(mapi_response);
@@ -1097,3 +1202,76 @@
 	return MAPI_E_SUCCESS;
 }
 
+/**
+   \details Hard delete the contents of a folder, including subfolders
+
+   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_INVALID_PARAMETER: obj_folder is not valid
+   - MAPI_E_CALL_FAILED: A network problem was encountered during the
+     transaction
+
+   \sa DeleteFolder, EmptyFolder
+*/
+_PUBLIC_ enum MAPISTATUS HardDeleteMessagesAndSubfolders(mapi_object_t *obj_folder)
+{
+	struct mapi_request				*mapi_request;
+	struct mapi_response				*mapi_response;
+	struct EcDoRpc_MAPI_REQ				*mapi_req;
+	struct HardDeleteMessagesAndSubfolders_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, "HardDeleteMessagesAndSubfolders");
+	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_HardDeleteMessagesAndSubfolders;
+	mapi_req->logon_id = mapi_object_get_logon_id(obj_folder);
+	mapi_req->handle_idx = 0;
+	mapi_req->u.mapi_HardDeleteMessagesAndSubfolders = 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;
+}

Modified: trunk/openchange/libmapi/IMAPIProp.c
===================================================================
--- trunk/openchange/libmapi/IMAPIProp.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IMAPIProp.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -135,6 +135,8 @@
 	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);
+
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
 	
 	/* Read the SPropValue array from data blob.
 	   fixme: replace the memory context by the object one.
@@ -254,6 +256,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	if (named == true) {
 		mapi_nameid_unmap_SPropValue(nameid, lpProps, PropCount);
 	}
@@ -347,6 +351,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -417,6 +423,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Get the repsonse */
 	proptags->cValues = mapi_response->mapi_repl->u.mapi_GetPropList.count;
 	if (proptags->cValues) {
@@ -506,6 +514,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	reply = &mapi_response->mapi_repl->u.mapi_GetPropsAll;
 	properties->cValues = reply->properties.cValues;
 	properties->lpProps = talloc_steal((TALLOC_CTX *)session, reply->properties.lpProps);
@@ -584,13 +594,127 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
 	return MAPI_E_SUCCESS;
 }
 
+/**
+   \details Set one or more properties on a given object without 
+    invoking replication.
 
+   This function sets one or more properties on a specified object. It
+   is the same as SetProps, except if the object is a folder, where
+   this function does not result in folder properties being replicated.
+
+   \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_INVALID_PARAMETER: obj is not valid
+   - MAPI_E_CALL_FAILED: A network problem was encountered during the
+     transaction
+
+   \sa SetProps, DeletePropertiesNoReplicate
+*/
+_PUBLIC_ enum MAPISTATUS SetPropertiesNoReplicate(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 SetPropertiesNoReplicate_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, "SetPropertiesNoReplicate");
+	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_SetPropertiesNoReplicate;
+	mapi_req->logon_id = mapi_object_get_logon_id(obj);
+	mapi_req->handle_idx = 0;
+	mapi_req->u.mapi_SetPropertiesNoReplicate = 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 Deletes property values from an object without invoking
    replication.
@@ -660,6 +784,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -746,6 +872,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Fill in count */
 	reply = &mapi_response->mapi_repl->u.mapi_GetNamesFromIDs;
 	*count = reply->count;
@@ -867,6 +995,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* 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);
@@ -968,6 +1098,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Fill [out] parameters */
 	reply = &mapi_response->mapi_repl->u.mapi_QueryNamedProperties;
 
@@ -1079,6 +1211,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
+
 	if (problemCount) {
 		*problemCount = mapi_response->mapi_repl->u.mapi_CopyProperties.PropertyProblemCount;
 		*problems = talloc_array((TALLOC_CTX *)session[0], struct PropertyProblem, *problemCount);
@@ -1195,6 +1329,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
+
 	if (problemCount) {
 		*problemCount = mapi_response->mapi_repl->u.mapi_CopyTo.PropertyProblemCount;
 		*problems = talloc_array((TALLOC_CTX *)session[0], struct PropertyProblem, *problemCount);

Modified: trunk/openchange/libmapi/IMAPISession.c
===================================================================
--- trunk/openchange/libmapi/IMAPISession.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IMAPISession.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -29,6 +29,96 @@
  */
 
 
+static enum MAPISTATUS FindGoodServer(struct mapi_session *session, const char *legacyDN, bool server)
+{
+	enum MAPISTATUS		retval;
+	struct nspi_context	*nspi;
+	struct StringsArray_r	pNames;
+	struct SRowSet		*SRowSet;
+	struct SPropTagArray	*SPropTagArray = NULL;
+	struct SPropTagArray	*MId_array;
+	struct StringArray_r	*MVszA = NULL;
+	const char		*binding = NULL;
+	char			*HomeMDB = NULL;
+	char			*server_dn;
+	int			i;
+
+	/* Sanity checks */
+	OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, NULL);
+	OPENCHANGE_RETVAL_IF(!session->nspi->ctx, MAPI_E_END_OF_SESSION, NULL);
+	OPENCHANGE_RETVAL_IF(!legacyDN, MAPI_E_INVALID_PARAMETER, NULL);
+
+	nspi = (struct nspi_context *) session->nspi->ctx;
+
+	if (server == false) {
+		/* Step 1. Retrieve a MID for our legacyDN */
+		pNames.Count = 0x1;
+		pNames.Strings = (const char **) talloc_array(nspi->mem_ctx, char **, 1);
+		pNames.Strings[0] = (const char *) talloc_strdup(pNames.Strings, legacyDN);
+
+		MId_array = talloc_zero(nspi->mem_ctx, struct SPropTagArray);
+		retval = nspi_DNToMId(nspi, &pNames, &MId_array);
+		MAPIFreeBuffer(pNames.Strings);
+		OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+		/* Step 2. Retrieve the Server DN associated to this MId */
+		SRowSet = talloc_zero(nspi->mem_ctx, struct SRowSet);
+		SPropTagArray = set_SPropTagArray(nspi->mem_ctx, 0x1, PR_EMS_AB_HOME_MDB);
+		retval = nspi_GetProps(nspi, SPropTagArray, MId_array, &SRowSet);
+		MAPIFreeBuffer(SPropTagArray);
+		MAPIFreeBuffer(MId_array);
+		OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+		HomeMDB = (char *)find_SPropValue_data(&(SRowSet->aRow[0]), PR_EMS_AB_HOME_MDB);
+		OPENCHANGE_RETVAL_IF(!HomeMDB, MAPI_E_NOT_FOUND, SRowSet);
+		server_dn = x500_truncate_dn_last_elements(nspi->mem_ctx, HomeMDB, 1);
+		MAPIFreeBuffer(SRowSet);
+	} else {
+		server_dn = talloc_strdup(nspi->mem_ctx, legacyDN);
+	}
+
+	/* Step 3. Retrieve the MId for this server DN */
+	pNames.Count = 0x1;
+	pNames.Strings = (const char **) talloc_array(nspi->mem_ctx, char **, 1);
+	pNames.Strings[0] = (const char *) talloc_strdup(pNames.Strings, server_dn);
+	MId_array = talloc_zero(nspi->mem_ctx, struct SPropTagArray);
+	retval = nspi_DNToMId(nspi, &pNames, &MId_array);
+	MAPIFreeBuffer(pNames.Strings);
+	OPENCHANGE_RETVAL_IF(retval, retval, server_dn);
+
+	/* Step 4. Retrieve the binding strings associated to this DN */
+	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_array, &SRowSet);
+	MAPIFreeBuffer(SPropTagArray);
+	MAPIFreeBuffer(MId_array);
+	MAPIFreeBuffer(server_dn);
+	OPENCHANGE_RETVAL_IF(retval, retval, SRowSet);
+
+	/* Step 5. Extract host from ncacn_ip_tcp binding string */
+	MVszA = (struct StringArray_r *) find_SPropValue_data(&(SRowSet->aRow[0]), PR_EMS_AB_NETWORK_ADDRESS);
+	OPENCHANGE_RETVAL_IF(!MVszA, MAPI_E_NOT_FOUND, SRowSet);
+	for (i = 0; i != MVszA->cValues; i++) {
+		if (!strncasecmp(MVszA->lppszA[i], "ncacn_ip_tcp:", 13)) {
+			binding = MVszA->lppszA[i] + 13;
+			break;
+		}
+	}
+	MAPIFreeBuffer(SRowSet);
+	OPENCHANGE_RETVAL_IF(!binding, MAPI_E_NOT_FOUND, NULL);
+
+	/* Step 6. Close the existing session and initiates it again */
+	talloc_free(session->emsmdb);
+	session->emsmdb = talloc_zero(session, struct mapi_provider);
+	talloc_set_destructor((void *)session->emsmdb, (int (*)(void *))emsmdb_disconnect_dtor);
+	session->profile->server = talloc_strdup(session->profile, binding);
+	retval = Logon(session, session->emsmdb, PROVIDER_ID_EMSMDB);
+	OPENCHANGE_RETVAL_IF(retval, retval, NULL);
+
+	return MAPI_E_SUCCESS;
+}
+
+
 /**
    \details Open the Public Folder store
 
@@ -63,6 +153,7 @@
 	TALLOC_CTX		*mem_ctx;
 	mapi_object_store_t	*store;
 	uint8_t			logon_id;
+	bool			retry = false;
 
 	/* Sanity checks */
 	OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
@@ -73,6 +164,7 @@
 	retval = GetNewLogonId(session, &logon_id);
 	OPENCHANGE_RETVAL_IF(retval, MAPI_E_FAILONEPROVIDER, NULL);
 
+retry:
 	mem_ctx = talloc_named(NULL, 0, "OpenPublicFolder");
 	size = 0;
 
@@ -105,8 +197,17 @@
 	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;
+	if (retval == ecWrongServer && retry == false && mapi_response->mapi_repl->us.mapi_Logon.ServerName) {
+		retval = FindGoodServer(session, mapi_response->mapi_repl->us.mapi_Logon.ServerName, true);
+		OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+		talloc_free(mem_ctx);
+		retry = true;
+		goto retry;
+	}
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* retrieve object session, handle and logon_id */
 	mapi_object_set_session(obj_store, session);
 	mapi_object_set_handle(obj_store, mapi_response->handles[0]);
@@ -218,6 +319,7 @@
 	mapi_object_store_t	*store;
 	char			*mailbox;
 	uint8_t			logon_id;
+	bool			retry = false;
 
 	/* sanity checks */
 	OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
@@ -228,6 +330,7 @@
 	retval = GetNewLogonId(session, &logon_id);
 	OPENCHANGE_RETVAL_IF(retval, MAPI_E_FAILONEPROVIDER, NULL);
 
+retry:
 	mem_ctx = talloc_named(NULL, 0, "OpenMsgStore");
 	size = 0;
 
@@ -268,8 +371,17 @@
 	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;
+	if (retval == ecWrongServer && retry == false) {
+		retval = FindGoodServer(session, mailbox, false);
+		OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
+		talloc_free(mem_ctx);
+		retry = true;
+		goto retry;
+	}
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* set object session, handle and logon_id */
 	mapi_object_set_session(obj_store, session);
 	mapi_object_set_handle(obj_store, mapi_response->handles[0]);

Modified: trunk/openchange/libmapi/IMAPISupport.c
===================================================================
--- trunk/openchange/libmapi/IMAPISupport.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IMAPISupport.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -37,11 +37,13 @@
 
    \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 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.
+   \param private_data the data to be passed at the callback function
+   when invoked
    
    The Notification Flags can take the following values:
    - fnevCriticalError
@@ -71,7 +73,8 @@
 _PUBLIC_ enum MAPISTATUS Subscribe(mapi_object_t *obj, uint32_t	*connection, 
 				   uint16_t NotificationFlags,
 				   bool WholeStore,
-				   mapi_notify_callback_t notify_callback)
+				   mapi_notify_callback_t notify_callback,
+				   void	*private_data)
 {
 	TALLOC_CTX			*mem_ctx;
 	struct mapi_request		*mapi_request;
@@ -153,6 +156,7 @@
 
 	notification->NotificationFlags = NotificationFlags;
 	notification->callback = notify_callback;
+	notification->private_data = private_data;
 
 	DLIST_ADD(notify_ctx->notifications, notification);
 
@@ -215,10 +219,8 @@
 	return MAPI_E_SUCCESS;
 }
 
-
-static enum MAPISTATUS ProcessNotification(struct mapi_notify_ctx *notify_ctx, 
-					   struct mapi_response *mapi_response,
-					   void *private_data)
+enum MAPISTATUS ProcessNotification(struct mapi_notify_ctx *notify_ctx, 
+					   struct mapi_response *mapi_response)
 {
 	struct notifications	*notification;
 	void			*NotificationData;
@@ -228,6 +230,8 @@
 
 	for (i = 0; mapi_response->mapi_repl[i].opnum; i++) {
 		if (mapi_response->mapi_repl[i].opnum == op_MAPI_Notify) {
+			mapi_handle_t	handle = mapi_response->mapi_repl[i].u.mapi_Notify.NotificationHandle;
+
 			switch(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationType) {
 			case fnevNewMail:
 			case fnevMbit|fnevNewMail:
@@ -298,12 +302,14 @@
 				break;
 			}
 			notification = notify_ctx->notifications;
+
 			while (notification->ulConnection) {
-				if (notification->NotificationFlags & mapi_response->mapi_repl[i].u.mapi_Notify.NotificationType) {
+				if ((notification->NotificationFlags & mapi_response->mapi_repl[i].u.mapi_Notify.NotificationType) && 
+				    (handle == mapi_object_get_handle(&(notification->obj_notif)))) {
 					if (notification->callback) {
 						notification->callback(mapi_response->mapi_repl[i].u.mapi_Notify.NotificationType,
 								       (void *)NotificationData,
-								       (void *)private_data);
+								       notification->private_data);
 					}
 				}
 				notification = notification->next;
@@ -313,7 +319,45 @@
 	return MAPI_E_SUCCESS;
 }
 
+/**
+   \details Force notification of pending events
 
+   This function force the server to send any pending notificaion and
+   process them. These MAPI notifications are next compared to the
+   registered ones and the callback specified in Subscribe() called if
+   it matches.
+
+   \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
+*/
+_PUBLIC_ enum MAPISTATUS DispatchNotifications(struct mapi_session *session)
+{
+	struct mapi_response	*mapi_response;
+	enum MAPISTATUS		retval;
+	NTSTATUS		status;
+
+	/* 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);
+
+	status = emsmdb_transaction_null((struct emsmdb_context *)session->emsmdb->ctx, &mapi_response);
+	if (!NT_STATUS_IS_OK(status))
+		return MAPI_E_CALL_FAILED;
+
+	retval = ProcessNotification(session->notify_ctx, mapi_response);
+	talloc_free(mapi_response);
+	return retval;
+}
+
+
 /**
    \details Wait for notifications and process them
 
@@ -366,7 +410,7 @@
 			if (!NT_STATUS_IS_OK(status)) {
 				err = -1;
 			} else {
-				retval = ProcessNotification(notify_ctx, mapi_response, private_data);
+				retval = ProcessNotification(notify_ctx, mapi_response);
 				OPENCHANGE_RETVAL_IF(retval, retval, NULL);
 			}
 		}

Modified: trunk/openchange/libmapi/IMAPITable.c
===================================================================
--- trunk/openchange/libmapi/IMAPITable.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IMAPITable.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -101,6 +101,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval && (retval != MAPI_W_ERRORS_RETURNED), retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* recopy property tags into table */
 	/* fixme: obj_table->private_data should be initialized during opening, not here */
 	if (obj_table->private_data == NULL) {
@@ -186,6 +188,8 @@
 	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);
+
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
 	
 	if (Numerator) {
 		*Numerator = mapi_response->mapi_repl->u.mapi_QueryPosition.Numerator;
@@ -282,6 +286,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* 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);
@@ -364,6 +370,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* get columns SPropTagArray */
 	table = (mapi_object_table_t *)obj_table->private_data;
 	OPENCHANGE_RETVAL_IF(!table, MAPI_E_INVALID_OBJECT, mem_ctx);
@@ -460,6 +468,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	reply = &mapi_response->mapi_repl->u.mapi_SeekRow;
 	*row = reply->RowsSought;
 
@@ -554,6 +564,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	reply = &mapi_response->mapi_repl->u.mapi_SeekRowBookmark;
 	*row = reply->RowsSought;
 
@@ -648,6 +660,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -719,6 +733,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	reply = &mapi_response->mapi_repl->u.mapi_CreateBookmark;
 
 	mapi_table = (mapi_object_table_t *)obj_table->private_data;
@@ -830,6 +846,8 @@
 			retval = mapi_response->mapi_repl->error_code;
 			OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+			OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 			MAPIFreeBuffer(bookmark->bin.lpb);
 			DLIST_REMOVE(table->bookmark, bookmark);
 
@@ -918,6 +936,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -1046,6 +1066,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -1144,6 +1166,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	if (TableStatus) {
 		reply = &mapi_response->mapi_repl->u.mapi_Restrict;
 		*TableStatus = reply->TableStatus;
@@ -1265,6 +1289,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* 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);
@@ -1352,6 +1378,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Retrieve TableStatus */
 	reply = &mapi_response->mapi_repl->u.mapi_GetStatus;
 	*TableStatus = reply->TableStatus;
@@ -1424,6 +1452,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Retrieve TableStatus */
 	reply = &mapi_response->mapi_repl->u.mapi_Abort;
 	*TableStatus = reply->TableStatus;
@@ -1529,6 +1559,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* 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);
@@ -1625,6 +1657,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Retrieve the RowCount */
 	reply = &mapi_response->mapi_repl->u.mapi_CollapseRow;
 	*rowCount = reply->CollapsedRowCount;
@@ -1718,6 +1752,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Retrieve the CollapseState */
 	reply = &mapi_response->mapi_repl->u.mapi_GetCollapseState;
 	CollapseState->cb = reply->CollapseState.cb;
@@ -1808,6 +1844,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	reply = &mapi_response->mapi_repl->u.mapi_SetCollapseState;
 
 	mapi_table = (mapi_object_table_t *)obj_table->private_data;

Modified: trunk/openchange/libmapi/IMessage.c
===================================================================
--- trunk/openchange/libmapi/IMessage.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IMessage.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -126,6 +126,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Set object session and handle */
 	mapi_object_set_session(obj_attach, session);
 	mapi_object_set_handle(obj_attach, mapi_response->handles[1]);
@@ -204,6 +206,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 	
@@ -283,6 +287,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* 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]);
@@ -371,6 +377,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Set object session and handle */
 	mapi_object_set_session(obj_attach, session);
 	mapi_object_set_handle(obj_attach, mapi_response->handles[1]);
@@ -709,6 +717,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -790,6 +800,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Retrieve the recipients */
 	reply = &mapi_response->mapi_repl->u.mapi_ReadRecipients;
 	*RowCount = reply->RowCount;
@@ -865,6 +877,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 	
@@ -940,6 +954,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -1028,6 +1044,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 	
@@ -1118,6 +1136,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
+
 	/* store the message_id */
 	mapi_object_set_id(obj_message, mapi_response->mapi_repl->u.mapi_SaveChangesMessage.MessageId);
 
@@ -1177,6 +1197,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Retrieve reply parameters */
 	reply = &mapi_response->mapi_repl->u.mapi_TransportSend;
 	if (!reply->NoPropertiesReturned) {
@@ -1306,6 +1328,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -1438,6 +1462,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Set object session and handle */
 	mapi_object_set_session(obj_embeddedmsg, session);
 	mapi_object_set_handle(obj_embeddedmsg, mapi_response->handles[1]);

Modified: trunk/openchange/libmapi/IMsgStore.c
===================================================================
--- trunk/openchange/libmapi/IMsgStore.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IMsgStore.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -99,6 +99,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);	
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Set object session, id and handle */
 	mapi_object_set_session(obj_folder, session);
 	mapi_object_set_id(obj_folder, id_folder);
@@ -187,6 +189,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
+
 	*IsGhosted = mapi_response->mapi_repl->u.mapi_PublicFolderIsGhosted.IsGhosted;
 	
 	talloc_free(mapi_response);
@@ -272,6 +276,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Set object session and handle */
 	mapi_object_set_session(obj_child, session);
 	mapi_object_set_handle(obj_child, mapi_response->handles[1]);
@@ -292,7 +298,9 @@
    \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
+   \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
@@ -353,6 +361,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -439,6 +449,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	*id_folder = mapi_response->mapi_repl->u.mapi_GetReceiveFolder.folder_id;
 
 	talloc_free(mapi_response);
@@ -459,6 +471,8 @@
    Developers are required to call MAPIFreeBuffer(SRowSet.aRow) when
    they don't need the folder table data anymore.
 
+   \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
@@ -511,6 +525,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	reply = &mapi_response->mapi_repl->u.mapi_GetReceiveFolderTable;
 
 	/* Retrieve the ReceiveFolderTable entries */
@@ -608,6 +624,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Retrieve the FolderId parameter */
 	reply = &mapi_response->mapi_repl->u.mapi_GetTransportFolder;
 	*FolderId = reply->FolderId;
@@ -704,6 +722,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Retrieve GetOwningServers response */
 	response = mapi_response->mapi_repl->u.mapi_GetOwningServers;
 
@@ -727,16 +747,22 @@
 
 
 /**
-   \details Gets the current store state for the loggued user
+   \details Gets the current store state for the logged in user
 
+   This operation must be performed against a user store (not against
+   a Public Folder store). The StoreState will have the 
+   STORE_HAS_SEARCHES flag set if there are any active search folders.
+   There are (currently) no other flags in the StoreState.
+
    \param obj_store the store object
-   \param StoreState pointer on the store state returned by the server
+   \param StoreState pointer to 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_INVALID_PARAMETER: obj_store or StoreState are not valid
    - MAPI_E_CALL_FAILED: A network problem was encountered during the
      transaction
  */
@@ -784,6 +810,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Retrieve the StoreState */
 	*StoreState = mapi_response->mapi_repl->u.mapi_GetStoreState.StoreState;
 
@@ -825,3 +853,85 @@
 
 	return MAPI_E_SUCCESS;
 }
+
+
+/**
+   \details Notify the store of a new message to be processed
+
+   \param obj_folder the folder that the message is in
+   \param obj_msg the message to be processed
+   \param MessageClass the message class of the message to be processed
+   \param MessageFlags the message flags on 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_INVALID_PARAMETER: one the parameters is invalid
+   - MAPI_E_CALL_FAILED: A network problem was encountered during the
+   transaction
+
+   \sa GetReceiveFolder, GetReceiveFolderTable
+ */
+_PUBLIC_ enum MAPISTATUS TransportNewMail(mapi_object_t *obj_folder, mapi_object_t *obj_msg,
+					  const char *MessageClass, uint32_t MessageFlags)
+{
+	struct mapi_request		*mapi_request;
+	struct mapi_response		*mapi_response;
+	struct EcDoRpc_MAPI_REQ		*mapi_req;
+	struct TransportNewMail_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(!obj_msg, MAPI_E_INVALID_PARAMETER, NULL);
+	OPENCHANGE_RETVAL_IF(!MessageClass, 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, "TransportNewMail");
+
+	/* Fill the TransportNewMail operation */
+	size = 0;
+	request.MessageId = mapi_object_get_id(obj_msg);
+	size += sizeof (uint64_t);
+	request.FolderId = mapi_object_get_id(obj_folder);
+	size += sizeof (uint64_t);
+	request.MessageClass = MessageClass;
+	size += strlen(MessageClass) + 1;
+	request.MessageFlags = MessageFlags;
+	size += sizeof(uint32_t);
+
+	/* Fill the MAPI_REQ request */
+	mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+	mapi_req->opnum = op_MAPI_TransportNewMail;
+	mapi_req->logon_id = mapi_object_get_logon_id(obj_folder);
+	mapi_req->handle_idx = 0;
+	mapi_req->u.mapi_TransportNewMail = 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;
+}

Modified: trunk/openchange/libmapi/IStoreFolder.c
===================================================================
--- trunk/openchange/libmapi/IStoreFolder.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IStoreFolder.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -121,6 +121,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Set object session and handle */
 	mapi_object_set_session(obj_message, session);
 	mapi_object_set_handle(obj_message, mapi_response->handles[1]);

Modified: trunk/openchange/libmapi/IStream.c
===================================================================
--- trunk/openchange/libmapi/IStream.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IStream.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -117,6 +117,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Set object session and handle */
 	mapi_object_set_session(obj_stream, session);
 	mapi_object_set_handle(obj_stream, mapi_response->handles[1]);
@@ -209,6 +211,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* copy no more than sz_data into buffer */
 	*ByteRead = mapi_response->mapi_repl->u.mapi_ReadStream.data.length;
 	if (*ByteRead > 0) {
@@ -305,6 +309,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	*WrittenSize = mapi_response->mapi_repl->u.mapi_WriteStream.WrittenSize;
 
 	talloc_free(mapi_response);
@@ -373,6 +379,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -439,6 +447,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	*StreamSize = mapi_response->mapi_repl->u.mapi_GetStreamSize.StreamSize;
 
 	talloc_free(mapi_response);
@@ -530,6 +540,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	*NewPosition = mapi_response->mapi_repl->u.mapi_SeekStream.NewPosition;
 
 	talloc_free(mapi_response);
@@ -603,6 +615,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -697,6 +711,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
+
 	*ReadByteCount = mapi_response->mapi_repl->u.mapi_CopyToStream.ReadByteCount;
 	*WrittenByteCount = mapi_response->mapi_repl->u.mapi_CopyToStream.WrittenByteCount;
 
@@ -866,3 +882,171 @@
 
 	return MAPI_E_SUCCESS;
 }
+
+/**
+   \details Clone a source stream to another stream
+
+   \param obj_src the source stream object
+   \param obj_dst the destination stream 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: source or destination streams are not valid.
+   - MAPI_E_CALL_FAILED: A network problem was encountered during the
+   transaction
+   
+   \sa OpenStream
+*/
+_PUBLIC_ enum MAPISTATUS CloneStream(mapi_object_t *obj_src, mapi_object_t *obj_dst)
+{
+	struct mapi_request	*mapi_request;
+	struct mapi_response	*mapi_response;
+	struct EcDoRpc_MAPI_REQ	*mapi_req;
+	struct CloneStream_req	request;
+	struct mapi_session	*session;
+	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 = mapi_object_get_session(obj_src);
+	OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
+
+	mem_ctx = talloc_named(NULL, 0, "CloneStream");
+	size = 0;
+
+	/* Fill the CloneStream operation */
+	request.handle_idx = 0x1; /* destionation */
+	size += sizeof (uint8_t);
+
+	/* Fill the MAPI_REQ request */
+	mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
+	mapi_req->opnum = op_MAPI_CloneStream;
+	mapi_req->logon_id = mapi_object_get_logon_id(obj_src);
+	mapi_req->handle_idx = 0;
+	mapi_req->u.mapi_CloneStream = 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] = 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);
+
+	mapi_object_set_handle(obj_dst, mapi_response->handles[1]);
+	mapi_object_set_session(obj_dst, session);
+	mapi_object_set_logon_id(obj_dst, mapi_object_get_logon_id(obj_src));
+
+	talloc_free(mapi_response);
+	talloc_free(mem_ctx);
+
+	return MAPI_E_SUCCESS;
+}
+
+/**
+   \details Write and commit a buffer to the stream
+
+   This function writes and commits the contents of a DATA_BLOB 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 the stream or blob were 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 WriteStream, CommitStream
+  */
+_PUBLIC_ enum MAPISTATUS WriteAndCommitStream(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 WriteAndCommitStream_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(!blob, MAPI_E_INVALID_PARAMETER, NULL);
+	OPENCHANGE_RETVAL_IF(blob->length > 0x7000, MAPI_E_TOO_BIG, NULL);
+
+	mem_ctx = talloc_named(NULL, 0, "WriteAndCommitStream");
+
+	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_WriteAndCommitStream;
+	mapi_req->logon_id = mapi_object_get_logon_id(obj_stream);
+	mapi_req->handle_idx = 0;
+	mapi_req->u.mapi_WriteAndCommitStream = 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_WriteAndCommitStream.WrittenSize;
+
+	talloc_free(mapi_response);
+	talloc_free(mem_ctx);
+	
+	errno = 0;
+	return MAPI_E_SUCCESS;
+}
+

Modified: trunk/openchange/libmapi/IUnknown.c
===================================================================
--- trunk/openchange/libmapi/IUnknown.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IUnknown.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -145,6 +145,8 @@
 	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_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 
@@ -235,7 +237,9 @@
 	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);
-	
+
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	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];
@@ -317,7 +321,9 @@
 	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);
-	
+
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	*id = mapi_response->mapi_repl->u.mapi_IdFromLongTermId.Id;
 
 	talloc_free(mapi_response);

Modified: trunk/openchange/libmapi/IXPLogon.c
===================================================================
--- trunk/openchange/libmapi/IXPLogon.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/IXPLogon.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -93,6 +93,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	/* Retrieve Address Types */
 	response = &mapi_response->mapi_repl->u.mapi_AddressTypes;
 	*lpcAdrType = response->cValues;
@@ -163,9 +165,10 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
-
 	return MAPI_E_SUCCESS;
 }
 
@@ -249,6 +252,8 @@
 	retval = mapi_response->mapi_repl->error_code;
 	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
 
+	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
+
 	talloc_free(mapi_response);
 	talloc_free(mem_ctx);
 

Modified: trunk/openchange/libmapi/conf/mapi-properties
===================================================================
--- trunk/openchange/libmapi/conf/mapi-properties	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/conf/mapi-properties	2009-04-30 18:06:50 UTC (rev 2734)
@@ -915,16 +915,17 @@
 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
+0x6800001e  PR_OAB_NAME
+0x68010003  PR_OAB_SEQUENCE
+0x6802001e  PR_OAB_CONTAINER_GUID
+0x68030003  PR_OAB_MESSAGE_CLASS
+0x6804001e  PR_OAB_DN
+0x68051003  PR_OAB_TRUNCATED_PROPS
+0x68060102  PR_OAB_SHA_HASH
+0x68070003  PR_OAB_LANGID
+0x68080003  PR_OAB_FILETYPE
+0x68090003  PR_OAB_COMPRESSED_SIZE
+0x680A0003  PR_OAB_FILE_SIZE
 0x68340003  PR_VIEW_STYLE
 0x683A0003  PR_VIEW_MAJORVERSION
 0x6844101e  PR_DELEGATES_DISPLAY_NAMES

Modified: trunk/openchange/libmapi/conf/mparse.pl
===================================================================
--- trunk/openchange/libmapi/conf/mparse.pl	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/conf/mparse.pl	2009-04-30 18:06:50 UTC (rev 2734)
@@ -532,6 +532,12 @@
     mparse "	return (e);			\\";
     mparse "} while (0);";
     mparse "";
+    mparse "#define OPENCHANGE_CHECK_NOTIFICATION(s,r)		\\";
+    mparse "do {						\\";
+    mparse "	if (s->notify_ctx)				\\";
+    mparse "		ProcessNotification(s->notify_ctx, r);	\\";
+    mparse "} while (0);";
+    mparse "";
     mparse "/* Status macros for MAPI */";
     mparse "typedef unsigned long	SCODE;";
     mparse "";

Modified: trunk/openchange/libmapi/mapi_notification.h
===================================================================
--- trunk/openchange/libmapi/mapi_notification.h	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/mapi_notification.h	2009-04-30 18:06:50 UTC (rev 2734)
@@ -32,6 +32,7 @@
 	uint32_t		NotificationFlags;	/* events mask associated */
 	mapi_id_t		parentID;		/* parent EntryID == FID here */
 	mapi_notify_callback_t	callback;		/* callback to run when */
+	void			*private_data;		/* private data for the callback */
 	struct mapi_object     	obj_notif;		/* notification object */
 	struct notifications	*prev;
 	struct notifications	*next;

Modified: trunk/openchange/libmapi/x500.c
===================================================================
--- trunk/openchange/libmapi/x500.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/libmapi/x500.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -56,7 +56,41 @@
 	return str;
 }
 
+
 /**
+   \details Truncate a DN element
+
+   \param mem_ctx pointer to the memory context
+   \param dn pointer to a valid DN
+   \param elcount the number of elements to remove from the end of the
+   DN
+
+   \return pointer to an allocated substring on success, otherwise
+   NULL
+ */
+_PUBLIC_ char *x500_truncate_dn_last_elements(TALLOC_CTX *mem_ctx, const char *dn, uint32_t elcount)
+{
+	char *tmp_dn;
+	int	i;
+
+	if ((dn == NULL) || (dn[0] == '\0') || !elcount) return NULL;
+
+	tmp_dn = talloc_strdup(mem_ctx, dn);
+	for (i = strlen(tmp_dn); i > 0; i--) {
+		if (tmp_dn[i] == '/') {
+			elcount -= 1;
+			if (elcount == 0) {
+				tmp_dn[i] = '\0';
+				return tmp_dn;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+
+/**
  * Retrieve the servername from a string
  * We should definitively find a better way to handle this
  */

Modified: trunk/openchange/mapiproxy/dcesrv_mapiproxy.c
===================================================================
--- trunk/openchange/mapiproxy/dcesrv_mapiproxy.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/mapiproxy/dcesrv_mapiproxy.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -176,7 +176,7 @@
 
 static NTSTATUS mapiproxy_op_bind_proxy(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
 {
-	NTSTATUS				status;
+	NTSTATUS				status = NT_STATUS_OK;
 	const struct ndr_interface_table	*table;
 	struct dcesrv_mapiproxy_private		*private;
 	bool					delegated;
@@ -310,7 +310,7 @@
 	}
 
 	/* If remote connection bind/auth has been delayed */
-	if (private->connected == false) {
+	if (private->connected == false && private->server_mode == false) {
 		status = mapiproxy_op_connect(dce_call, table, NULL);
 
 		if (!NT_STATUS_IS_OK(status)) {

Modified: trunk/openchange/torture/mapi_newmail.c
===================================================================
--- trunk/openchange/torture/mapi_newmail.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/torture/mapi_newmail.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -98,11 +98,11 @@
 
 	/* newmail and created|modified object notifications in inbox */
 	ulEventMask = fnevObjectCreated;
-	retval = Subscribe(&obj_inbox, &ulConnection, ulEventMask, false, (mapi_notify_callback_t)callback);
+	retval = Subscribe(&obj_inbox, &ulConnection, ulEventMask, false, (mapi_notify_callback_t)callback, (void*) &obj_store);
 	mapi_errstr("Subscribe", GetLastError());
 
 	ulEventMask = fnevNewMail;
-	retval = Subscribe(&obj_inbox, &ulConnection, ulEventMask, false, (mapi_notify_callback_t)callback);
+	retval = Subscribe(&obj_inbox, &ulConnection, ulEventMask, false, (mapi_notify_callback_t)callback, (void*) &obj_store);
 	mapi_errstr("Subscribe", GetLastError());
 
 

Modified: trunk/openchange/utils/mapitest/mapitest_common.c
===================================================================
--- trunk/openchange/utils/mapitest/mapitest_common.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/utils/mapitest/mapitest_common.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -369,6 +369,7 @@
 	struct SPropValue	lpProp[3];
 	int 			i;
 	uint32_t		format;
+	bool			ret;
 
 	context = mt->priv;
 
@@ -377,19 +378,18 @@
         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());
+	if (retval != MAPI_E_SUCCESS) {
+		mapitest_print_retval(mt, "Create the test folder");
 		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),
+		ret = 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));
+		if (! ret) {
+			mapitest_print(mt, "* %-35s\n", "Failed to create test message");
 			return false;
 		}
 
@@ -404,13 +404,11 @@
 		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;
 		}
 	}
@@ -419,10 +417,10 @@
 	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),
+		ret = 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());
+		if (! ret){
+			mapitest_print(mt, "* %-35s\n", "Failed to create test message");
 			return false;
 		}
 
@@ -465,13 +463,15 @@
 {
 	bool			ret = false;
 	struct mt_common_tf_ctx	*context;
+	enum MAPISTATUS		retval;
 
 	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) {
+	retval = OpenMsgStore(mt->session, &(context->obj_store));
+	if (retval != MAPI_E_SUCCESS) {
+		mapitest_print_retval(mt, "Failed OpenMsgStore");
 		return false;
 	}
 
@@ -490,8 +490,9 @@
 	}
 
 	mapi_object_init(obj_htable);
-	GetHierarchyTable(&(context->obj_top_folder), obj_htable, 0, count);
-	if (GetLastError() != MAPI_E_SUCCESS) {
+	retval = GetHierarchyTable(&(context->obj_top_folder), obj_htable, 0, count);
+	if (retval != MAPI_E_SUCCESS) {
+		mapitest_print_retval(mt, "Failed GetHierarchyTable");
 		return false;
 	}
 

Modified: trunk/openchange/utils/mapitest/module.c
===================================================================
--- trunk/openchange/utils/mapitest/module.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/utils/mapitest/module.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -95,6 +95,8 @@
 	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_add_test(suite, "HARDDELETEMESSAGES", "Hard delete messages", mapitest_oxcfold_HardDeleteMessages);
+	mapitest_suite_add_test(suite, "HARDDELETEMESSAGESANDSUBFOLDERS", "Hard delete messages and subfolders", mapitest_oxcfold_HardDeleteMessagesAndSubfolders);
 
 	mapitest_suite_register(mt, suite);
 	
@@ -121,6 +123,7 @@
 	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, "TRANSPORT-NEW-MAIL", "Submit a new message for processing", mapitest_oxomsg_TransportNewMail);
 	mapitest_suite_add_test(suite, "GET-TRANSPORT-FOLDER", "Retrieve the temporary transport folder ID", mapitest_oxomsg_GetTransportFolder);
 
 	mapitest_suite_register(mt, suite);
@@ -208,10 +211,11 @@
 	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, "PROPS-NOREPLICATE", "Set / delete a specific set of properties (no replicate)", mapitest_oxcprpt_NoReplicate);
 	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, "WRITE-COMMIT-STREAM", "Test atomic Write / Commit operation", mapitest_oxcprpt_WriteAndCommitStream);
 	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);
 

Modified: trunk/openchange/utils/mapitest/modules/module_oxcfold.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxcfold.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/utils/mapitest/modules/module_oxcfold.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -4,6 +4,7 @@
    OpenChange Project - FOLDER OBJECT PROTOCOL operations
 
    Copyright (C) Julien Kerihuel 2008
+   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
@@ -596,7 +597,7 @@
 
 
 /**
-   \details Test the MoveCopyMessages (0x33) opetation.
+   \details Test the MoveCopyMessages (0x33) operation.
 
    This function:
 	-# Log on the user private mailbox
@@ -946,3 +947,238 @@
 
 	return ret;
 }
+
+/**
+   \details Test the HardDeleteMessages (0x91) operation.
+
+   This function:
+	-# Log on the user private mailbox
+	-# Open the Inbox folder (source)
+	-# Creates 3 sample messages
+	-# Hard delete the sample messages
+
+   \param mt pointer to the top-level mapitest structure
+
+   \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcfold_HardDeleteMessages(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		contents;
+	struct mapi_SRestriction res;
+	struct SPropTagArray    *SPropTagArray;
+	struct SRowSet		SRowSet;
+	mapi_id_array_t		msg_id_array;
+	mapi_id_t		msgid[50];
+	mapi_id_t		id_folder;
+	uint32_t		i;
+	uint32_t		count = 0;
+
+	/* Step 1. Logon */
+	mapi_object_init(&obj_store);
+	retval = OpenMsgStore(mt->session, &obj_store);
+	mapitest_print_retval(mt, "OpenMsgStore");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+		goto cleanup;
+	}
+
+	/* Step 2. Open Source Inbox folder */
+	mapi_object_init(&obj_folder);
+	retval = GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+	mapitest_print_retval(mt, "GetDefaultFolder");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+		goto cleanup;
+	}
+
+	retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+	mapitest_print_retval(mt, "OpenFolder");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+		goto cleanup;
+	}
+
+	mapi_object_init(&(contents));
+	GetContentsTable(&(obj_folder), &(contents), 0, &count);
+	mapitest_print_retval(mt, "GetContentsTable");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+		goto cleanup;
+	}
+
+	/* Step 3. Create sample messages */
+	mapi_id_array_init(&msg_id_array);
+	for (i = 0; i < 3; i++) {
+		mapi_object_init(&obj_message);
+		ret = mapitest_common_message_create(mt, &obj_folder, &obj_message, MT_MAIL_SUBJECT);
+		if (!ret) {
+			mapitest_print(mt, "failed to create message %i\n", i);
+			ret = false;
+			goto cleanup;
+		}
+		
+		retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+		mapitest_print_retval(mt, "SaveChangesMessage");
+		if (retval != MAPI_E_SUCCESS) {
+			ret = false;
+			goto cleanup;
+		}
+		mapi_id_array_add_obj(&msg_id_array, &obj_message);
+		mapi_object_release(&obj_message);
+	}
+
+
+	/* Step 4. 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(&(contents), &res, NULL);
+	mapitest_print_retval(mt, "Restrict");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+		goto cleanup;
+	}
+
+	/* Step 5. Get the filtered rows */
+        SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_MID);
+        SetColumns(&(contents), SPropTagArray);
+	mapitest_print_retval(mt, "SetColumns");
+	MAPIFreeBuffer(SPropTagArray);
+
+	retval = QueryRows(&(contents), 50, 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;
+		}
+		mapitest_print(mt, "%i Messages created successfully\n", SRowSet.cRows);
+	}
+
+	/* Step 6. Delete Messages */
+	retval = HardDeleteMessage(&obj_folder, msgid, i); 
+	mapitest_print_retval(mt, "HardDeleteMessage");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+		goto cleanup;
+	}
+
+	/* Step 7. Check the restriction again */
+	retval = QueryRows(&(contents), 50, TBL_NOADVANCE, &SRowSet);
+	mapitest_print_retval(mt, "QueryRows");
+	if ( retval != MAPI_E_SUCCESS ) {
+		ret = false;
+		goto cleanup;
+	}
+
+	if (SRowSet.cRows == 0) {
+		mapitest_print(mt, "successfully deleted messages\n");
+	} else {
+		mapitest_print(mt, "failed to delete messages\n");
+		ret = false;
+	}
+
+cleanup:
+	/* Release */
+	mapi_object_release(&obj_folder);
+	mapi_object_release(&obj_store);
+
+	return ret;
+}
+
+/**
+   \details Test the HardDeleteMessagesAndSubfolder (0x92) operation.
+
+   This function:
+	-# Creates a filled test folder
+	-# Creates 2 subdirectories in the test folder
+	-# Hard deletes the sample messages and subdirectories
+
+   \param mt pointer to the top-level mapitest structure
+
+   \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxcfold_HardDeleteMessagesAndSubfolders(struct mapitest *mt)
+{
+	struct mt_common_tf_ctx	*context;
+	enum MAPISTATUS		retval;
+	bool			ret = true;
+	mapi_object_t		obj_htable;
+	mapi_object_t		subfolder1;
+	mapi_object_t		subfolder2;
+	uint32_t		unread = 0;
+	uint32_t		total = 0;
+
+        /* Step 1. Logon and create a filled test folder */
+        if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
+                return false;
+        }
+
+	context = mt->priv;
+
+	/* Step 2. Create two subfolders */
+	mapi_object_init(&subfolder1);
+	retval = CreateFolder(&(context->obj_test_folder), FOLDER_GENERIC,
+			      "SubFolder1", NULL /*folder comment*/,
+			      OPEN_IF_EXISTS, &subfolder1);
+	mapi_object_release(&subfolder1);
+	mapitest_print_retval(mt, "Create Subfolder1");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+		goto cleanup;
+	}
+
+	mapi_object_init(&subfolder2);
+	retval = CreateFolder(&(context->obj_test_folder), FOLDER_GENERIC,
+			      "SubFolder2", NULL /*folder comment*/,
+			      OPEN_IF_EXISTS, &subfolder2);
+	mapi_object_release(&subfolder2);
+	mapitest_print_retval(mt, "Create Subfolder2");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+		goto cleanup;
+	}
+
+	retval = GetFolderItemsCount(&(context->obj_test_folder), &unread, &total);
+	mapitest_print_retval(mt, "GetFolderItemsCount");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+		goto cleanup;
+	}
+	mapitest_print(mt, "* Folder count: %i (%i unread)\n", total, unread);
+
+	/* Step 3. Hard delete contents */
+	retval = HardDeleteMessagesAndSubfolders(&(context->obj_test_folder));
+	mapitest_print_retval(mt, "HardDeleteMessagesAndSubfolders");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+		goto cleanup;
+	}
+
+	/* Step 4. Check successful deletion */
+	retval = GetFolderItemsCount(&(context->obj_test_folder), &unread, &total);
+	mapitest_print_retval(mt, "GetFolderItemsCount");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+		goto cleanup;
+	}
+	mapitest_print(mt, "* Folder count: %i (%i unread)\n", total, unread);
+
+	if (total != 0 || unread != 0) {
+		ret = false;
+	}
+
+ cleanup:
+        /* Cleanup and release */
+        mapi_object_release(&obj_htable);
+        mapitest_common_cleanup(mt);
+
+        return ret;
+}

Modified: trunk/openchange/utils/mapitest/modules/module_oxcnotif.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxcnotif.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/utils/mapitest/modules/module_oxcnotif.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -78,7 +78,7 @@
 	}
 
 	/* Step 4. Subscribe for notifications */
-	retval = Subscribe(&obj_store, &tcon, fnevObjectCopied, true, cb);
+	retval = Subscribe(&obj_store, &tcon, fnevObjectCopied, true, cb, NULL);
 	mapitest_print_retval(mt, "Subscribe");
 	if (retval != MAPI_E_SUCCESS) {
 		return false;

Modified: trunk/openchange/utils/mapitest/modules/module_oxcprpt.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxcprpt.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/utils/mapitest/modules/module_oxcprpt.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -4,7 +4,7 @@
    OpenChange Project - PROPERTY AND STREAM OBJECT PROTOCOL operations
 
    Copyright (C) Julien Kerihuel 2008
-   Copyright (C) Brad Hards 2008
+   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
@@ -763,10 +763,10 @@
 
 
 /**
-   \details Test Stream operations. This test uses all related stream
+   \details Test Stream operations. This test uses related stream
    operations: OpenStream (0x2b), SetStreamSize (0x2f), WriteStream
    (0x2d), CommitStream (0x5d), ReadStream (0x2c), SeekStream (0x2e),
-   LockRegionStream (0x5b) and UnlockRegionStream (0x5c)
+   LockRegionStream (0x5b), UnlockRegionStream (0x5c), CloneStream (0x3b)
    
    This function:
    -# Logon 
@@ -786,6 +786,7 @@
    -# Lock a range of the stream
    -# TODO: test if the locking works
    -# Unlock a range of the stream
+   -# Clone the stream
    -# Delete the message;
 
    \param mt pointer to the top-level mapitest structure
@@ -801,6 +802,7 @@
 	mapi_object_t		obj_message;
 	mapi_object_t		obj_attach;
 	mapi_object_t		obj_stream;
+	mapi_object_t		obj_stream_clone;
 	mapi_id_t		id_folder;
 	DATA_BLOB		data;
 	struct SPropValue	attach[3];
@@ -1019,7 +1021,27 @@
 		ret = false;
 	}
 
-	/* Step 16. Delete the message */
+	/* Step 16. Clone the stream */
+	mapi_object_init(&obj_stream_clone);
+	retval = CloneStream(&obj_stream, &obj_stream_clone);
+	mapitest_print_retval(mt, "CloneStream");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+	}
+
+	/* Step 17. Test the clone */
+	retval = SeekStream(&obj_stream_clone, 0x0, 0, &NewPosition);
+	mapitest_print_retval(mt, "SeekStream");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+	}
+	retval = ReadStream(&obj_stream_clone, buf, MT_STREAM_MAX_SIZE, &read_size);
+	mapitest_print_retval_fmt(mt, "ReadStream", "(0x%x bytes read)", read_size);
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+	}
+
+	/* Delete the message */
 	errno = 0;
 	id_msgs[0] = mapi_object_get_id(&obj_message);
 	retval = DeleteMessage(&obj_folder, id_msgs, 1);
@@ -1029,6 +1051,7 @@
 	}
 
 	/* Release */
+	mapi_object_release(&obj_stream_clone);
 	mapi_object_release(&obj_stream);
 	mapi_object_release(&obj_attach);
 	mapi_object_release(&obj_message);
@@ -2270,15 +2293,15 @@
 
 
 /**
-   \details Test the DeletePropertiesNoReplicate (0x7a) operation
+   \details Test the SetPropertiesNoReplicate (0x79) and
+    DeletePropertiesNoReplicate (0x7a) operations
 
    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
+   -# Sets some properties on the test folder
+   -# Delete properties from the test folder
+   -# Deletes the test folder
 
    \todo It would be useful to test the problem return values
 
@@ -2286,73 +2309,66 @@
 
    \return true on success, otherwise false
  */
-_PUBLIC_ bool mapitest_oxcprpt_DeletePropertiesNoReplicate(struct mapitest *mt)
+_PUBLIC_ bool mapitest_oxcprpt_NoReplicate(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;
+	const char		*comment = NULL;
 	struct SPropValue	lpProp[3];
 	struct SPropTagArray	*SPropTagArray;
 	struct SPropValue	*lpProps;
 	uint32_t		cValues;
-	bool			result;
+	bool			ret = true;
 
 	/* 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 (retval != MAPI_E_SUCCESS) {
-		return false;
+		ret = false;
+		goto cleanup;
 	}
 	mapi_object_init(&obj_top_folder);
 	retval = GetDefaultFolder(&obj_store, &id_top_folder, olFolderTopInformationStore);
 	if (retval != MAPI_E_SUCCESS) {
-		return false;
+		ret = false;
+		goto cleanup;
 	}
 	retval = OpenFolder(&obj_store, id_top_folder, &obj_top_folder);
 	if (retval != MAPI_E_SUCCESS) {
-		return false;
+		ret = false;
+		goto cleanup;
 	}
 
-	/* Step 2: Create reference folder */
+	/* Step 2: Create test 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 (retval != MAPI_E_SUCCESS) {
-		return false;
+		ret = false;
+		goto cleanup;
 	}
 
-	/* Step 3: Create reference message */
-	mapi_object_init(&obj_ref_message);
-	result = 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 (!result) {
-		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");
+	/* Step 3: Set properties on the test folder */
+	name = talloc_asprintf(mt->mem_ctx, "Reference: %s", "new name");
+	comment = talloc_asprintf(mt->mem_ctx, "Reference: %s", "the folder comment");
 	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");
+	set_SPropValue_proptag(&lpProp[1], PR_COMMENT, (const void *)comment);
+	retval = SetPropertiesNoReplicate(&obj_ref_folder, lpProp, 2);
+	mapitest_print_retval_step_fmt(mt, "3.", "SetProps", "(%s)", "Set folder properties");
 	if (retval != MAPI_E_SUCCESS) {
-		return false;
+		ret = false;
+		goto cleanup;
 	}
 
 	/* 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);
+	SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_COMMENT);
+	retval = GetProps(&obj_ref_folder, SPropTagArray, &lpProps, &cValues);
 	MAPIFreeBuffer(SPropTagArray);
 	if (lpProps[0].value.lpszA) {
 		if (!strncmp(name, lpProps[0].value.lpszA, strlen(lpProps[0].value.lpszA))) {
@@ -2361,45 +2377,235 @@
 		} else {
 			mapitest_print(mt, "* Step 4.1. - 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))) {
+		if (!strncmp(comment, 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);
+			ret = false;
+			goto cleanup;
 		}
 	}
 
 	/* Step 5. Delete Properties */
-	SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_CONVERSATION_TOPIC);
-	retval = DeletePropertiesNoReplicate(&obj_ref_message, SPropTagArray);
+	SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_COMMENT);
+	retval = DeletePropertiesNoReplicate(&obj_ref_folder, SPropTagArray);
 	MAPIFreeBuffer(SPropTagArray);
-	mapitest_print_retval_step_fmt(mt, "5.", "DeletePropertiesNoReplicate", "PR_CONVERSATION_TOPIC");
+	mapitest_print_retval_step_fmt(mt, "5.", "DeletePropertiesNoReplicate", "PR_COMMENT");
 
 	/* Step 6. Double check with GetProps */
-	SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_CONVERSATION_TOPIC);
-	retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
+	SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_COMMENT);
+	retval = GetProps(&obj_ref_folder, SPropTagArray, &lpProps, &cValues);
 	MAPIFreeBuffer(SPropTagArray);
-	if (get_SPropValue(lpProps, PR_CONVERSATION_TOPIC) == NULL) {
-		mapitest_print(mt, "* Step 5.1. - GetProps verifier [SUCCESS]\n");
+	if (get_SPropValue(lpProps, PR_COMMENT) == NULL) {
+		mapitest_print(mt, "* Step 6.1. - GetProps verifier [SUCCESS]\n");
 	} else {
-		mapitest_print(mt, "* Step 5.1. - GetProps verifier [FAILURE]:\n");
+		mapitest_print(mt, "* Step 6.1. - GetProps verifier [FAILURE]:\n");
 	}
 
-	/* Step 7: cleanup folders */
+	/* Cleanup and release */
+cleanup:
 	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);
+	mapitest_print_retval_step(mt, "7.", "DeleteFolder");
 	mapi_object_release(&obj_ref_folder);
 	mapi_object_release(&obj_top_folder);
 	mapi_object_release(&obj_store);
 
+	return ret;
+}
 
-	return true;
+/**
+   \details Test WriteAndCommitStream (0x90) operation.
+
+   This function:
+   -# Logs in 
+   -# Opens the Outbox folder
+   -# Creates a test message
+   -# Creates an attachment on the test messages and set properties on the attachment
+   -# Opens a stream on the attachment
+   -# Sets the stream size
+   -# Write and commits into the stream
+   -# Saves the message
+   -# Gets stream size and compare values
+   -# Opens the stream again with different permissions
+   -# Reads the stream and compares buffers
+   -# Deletes the test message
+
+   \param mt pointer to the top-level mapitest structure
+
+   \return true on success, otherwise -1
+ */
+_PUBLIC_ bool mapitest_oxcprpt_WriteAndCommitStream(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;
+	const uint32_t		stream_len = 0x1000;
+	unsigned char		buf[0x1000];
+	uint32_t		StreamSize = 0;
+	uint16_t		read_size = 0;
+	uint16_t		write_len = 0;
+	uint32_t		offset = 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 (retval != MAPI_E_SUCCESS) {
+		return false;
+	}
+
+	/* Step 2. Open Inbox folder */
+	retval = GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
+	mapitest_print_retval(mt, "GetDefaultFolder");
+	if (retval != MAPI_E_SUCCESS) {
+		return false;
+	}
+
+	mapi_object_init(&obj_folder);
+	retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+	mapitest_print_retval(mt, "OpenFolder");
+	if (retval != 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;
+
+	data.length = stream_len;
+	data.data = (uint8_t *) stream;
+	retval = WriteAndCommitStream(&obj_stream, &data, &write_len);
+	mapitest_print_retval_fmt(mt, "WriteStream", "(0x%x bytes written)", write_len);
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+	}
+
+	/* Step 8. Save the attachment */
+	retval = SaveChangesAttachment(&obj_message, &obj_attach, KeepOpenReadOnly);
+	mapitest_print_retval(mt, "SaveChangesAttachment");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+	}
+
+	retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
+	mapitest_print_retval(mt, "SaveChangesMessage");
+	if (retval != MAPI_E_SUCCESS) {
+		ret = false;
+	}
+
+	/* Step 9. 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 10. 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");
+
+		}
+	}
+
+	/* 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;
 }
+

Modified: trunk/openchange/utils/mapitest/modules/module_oxomsg.c
===================================================================
--- trunk/openchange/utils/mapitest/modules/module_oxomsg.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/utils/mapitest/modules/module_oxomsg.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -470,7 +470,53 @@
 	return ret;
 }
 
+/**
+   \details Test the TransportNewMail (0x51) operation
 
+   This function:
+   -# Logs on to the user private mailbox
+   -# Create a filled test folder, and open it.
+   -# Perform the TransportNewMail operation
+   -# Clean up test environment
+
+   \param mt pointer on the top-level mapitest structure
+
+   \return true on success, otherwise false
+ */
+_PUBLIC_ bool mapitest_oxomsg_TransportNewMail(struct mapitest *mt)
+{
+	enum MAPISTATUS         retval;
+	mapi_object_t           obj_htable;
+	bool 			ret = true;
+	struct mt_common_tf_ctx	*context;
+	int			i;
+
+
+
+	/* Logon and create filled test folder*/
+	if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
+		return false;
+	}
+
+	context = mt->priv;
+
+	/* Perform the TransportNewMail operation */
+	for (i = 0; i<10; ++i) {
+		retval = TransportNewMail(&(context->obj_test_folder), &(context->obj_test_msg[i]), "IPM.Note", MSGFLAG_SUBMIT);
+		mapitest_print_retval(mt, "TransportNewMail");
+		if (retval != MAPI_E_SUCCESS) {
+			ret = false;
+		}
+	}
+
+	/* Clean up */
+	mapi_object_release(&obj_htable);
+	mapitest_common_cleanup(mt);
+
+	return ret;
+}
+
+
 /**
    \details Test the GetTransportFolder (0x6d) operation
 

Modified: trunk/openchange/utils/openchangeclient.c
===================================================================
--- trunk/openchange/utils/openchangeclient.c	2009-04-30 18:06:45 UTC (rev 2733)
+++ trunk/openchange/utils/openchangeclient.c	2009-04-30 18:06:50 UTC (rev 2734)
@@ -363,9 +363,7 @@
 	} while (read_size);
 	
 	close(fd);
-
 	mapi_object_release(&obj_stream);
-	close(fd);
 	talloc_free(mem_ctx);
 	return true;
 
@@ -1598,7 +1596,7 @@
 				printf("|   ");
 			}
 			newname = utf8tolinux(mem_ctx, name);
-			printf("|---+ %-15s : %-20s (Total: %u / Unread: %u - Container class: %s) [FID: 0x%.16"PRIx64"]\n", 
+			printf("|---+ %-15s : %-20s (Total: %u / Unread: %u - Container class: %s) [FID: 0x%016"PRIx64"]\n", 
 			       newname, comment?comment:"", total?*total:0, unread?*unread:0,
 			       get_container_class(mem_ctx, parent, *fid), *fid);
 			MAPIFreeBuffer(newname);
@@ -1653,7 +1651,7 @@
 				printf("|   ");
 			}
 			newname = utf8tolinux(mem_ctx, name);
-			printf("|---+ %-15s [FID: 0x.16%"PRIx64"]\n", newname, *fid);
+			printf("|---+ %-15s [FID: 0x%016"PRIx64"]\n", newname, *fid);
 			MAPIFreeBuffer(newname);
 			if (*child) {
 				ret = get_child_folders_pf(mem_ctx, &obj_folder, *fid, count + 1);
@@ -2316,8 +2314,10 @@
 	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);
+	retval = Subscribe(obj_store, &ulConnection, ulEventMask, true, (mapi_notify_callback_t)callback,
+		(void*) obj_store);
+	retval = Subscribe(&obj_inbox, &ulConnection, ulEventMask, false, (mapi_notify_callback_t)callback,
+		(void*) obj_store);
 	if (retval != MAPI_E_SUCCESS) return false;
 
 	/* wait for notifications: infinite loop */




More information about the Pkg-samba-maint mailing list