MSPFLD.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:151k
源码类别:
Windows编程
开发平台:
Visual C++
- /*
- * M S P F L D . C
- *
- * Code that implements the object methods of IMAPIFolder.
- *
- * Copyright 1992-1995 Microsoft Corporation. All Rights Reserved.
- */
- #include "msp.h"
- #define FLD_ValidateParameters(pobj, intf, method, arglist)
- OBJ_ValidateParameters(pobj, intf, method, sizeof(IFLD), &vtblIFLD, arglist)
- static BOOL IFLD_IsInvalid(PIFLD pifld);
- static HRESULT HrCreateContTblMutex(HANDLE *phCTMutex);
- static BOOL FFoldInSameStore(PIFLD pifld, PIFLD lpDestFld);
- static BOOL FIsAncestor(PIFLD pifldAncestor, PIFLD pifldDescendent);
- static HRESULT HrGetSortOrder(PIFLD pifld, LPSSortOrderSet *lppsSortOrder);
- static HRESULT HrFillHierarchyTable(PIFLD pifld, LPTABLEDATA lptbl);
- static HRESULT HrIsRead(PIFLD pifld, PEID peidMsg, BOOL *pfRead);
- static HRESULT HrCreateFolder(PIFLD pifldParent, LPSTR szName, LPSTR szComment,
- BOOL fOpenIfExists, PIFLD *ppifldNew, BOOL *pfCreated);
- static HRESULT HrDeleteSubDirectory(PIFLD pifldParent, PEID peidToDelete,
- ULONG ulFlags, BOOL fContentsOnly);
- static HRESULT HrCopyContents(PIFLD pifldSrc, PIFLD pifldDst, ULONG ulFlags,
- LPSPropTagArray ptagaExcl);
- static BOOL FFolderExists(PEID peid, PIMS pims);
- static HRESULT HrSetSubFolderProp(PIFLD pifld, BOOL fSubFolder);
- static HRESULT HrSetOneROFolderProp(PIFLD pifld, LONG lValue, ULONG ulPT);
- static HRESULT HrEIDFromDisplayName(LPMAPITABLE pmt, LPSTR szName, PLMR plmr,
- PEID *ppeid);
- static HRESULT HrCreateMessageList(PIFLD pifld, LPENTRYLIST *lppEntryList);
- static void DestroyMessageList(PLMR plmr, LPENTRYLIST *lppEntryList);
- #define NUM_RW_FOLDER_PROPS 2 /* number read write initial folder props */
- #define IFLD_EnterCriticalSection(pifld) OBJ_EnterCriticalSection((POBJ)pifld)
- #define IFLD_LeaveCriticalSection(pifld) OBJ_LeaveCriticalSection((POBJ)pifld)
- CALLERRELEASE ViewRelease;
- TCHAR szSubfolderPropFile[] = TEXT("subfoldr.prp");
- TCHAR szAllFilesTemplate[] = TEXT("*.*");
- /* properties excluded on a copy of folders' .prp file */
- const static SizedSPropTagArray(13, sptaExclFldProps) =
- {
- 13,
- {
- PR_CONTENT_COUNT,
- PR_CONTENT_UNREAD,
- PR_ENTRYID,
- PR_INSTANCE_KEY,
- PR_PARENT_ENTRYID,
- PR_OBJECT_TYPE,
- PR_STORE_ENTRYID,
- PR_STORE_RECORD_KEY,
- PR_RECORD_KEY,
- PR_FOLDER_TYPE,
- PR_SUBFOLDERS,
- PR_MESSAGE_RECIPIENTS,
- PR_MESSAGE_ATTACHMENTS
- }
- };
- /* read only property proptags */
- /* order must match order initialized on CreateFolderStorage */
- #define NUM_RO_FOLDER_PROPS 11 /* number read only initial folder props */
- const static SizedSPropTagArray(NUM_RO_FOLDER_PROPS, sptaReadOnly) =
- {
- NUM_RO_FOLDER_PROPS,
- {
- PR_OBJECT_TYPE,
- PR_RECORD_KEY,
- PR_FOLDER_TYPE,
- PR_CONTENT_COUNT,
- PR_CONTENT_UNREAD,
- PR_STORE_ENTRYID,
- PR_STORE_RECORD_KEY,
- PR_SUBFOLDERS,
- PR_ENTRYID,
- PR_PARENT_ENTRYID,
- PR_INSTANCE_KEY
- }
- };
- /* read only property attributes */
- const static SizedSPropAttrArray(NUM_RO_FOLDER_PROPS, spaReadOnly) =
- {
- NUM_RO_FOLDER_PROPS,
- {
- PROPATTR_READABLE,
- PROPATTR_READABLE,
- PROPATTR_READABLE,
- PROPATTR_READABLE,
- PROPATTR_READABLE,
- PROPATTR_READABLE,
- PROPATTR_READABLE,
- PROPATTR_READABLE,
- PROPATTR_READABLE,
- PROPATTR_READABLE,
- PROPATTR_READABLE
- }
- };
- /* initial sort order set for a contents table */
- static SizedSSortOrderSet(1, sSortOrderContentsDefault) =
- {
- 1,
- 0,
- 0,
- {
- PR_INSTANCE_KEY, /* the index column */
- TABLE_SORT_ASCEND
- }
- };
- /* message status property array */
- static SPropTagArray sptaMessageStatus =
- {
- 1,
- {
- PR_MESSAGE_FLAGS
- }
- };
- /* DISPATCH TABLE */
- IFLD_Vtbl vtblIFLD =
- {
- (IFLD_QueryInterface_METHOD *) OBJ_QueryInterface,
- (IFLD_AddRef_METHOD *) OBJ_AddRef,
- IFLD_Release,
- (IFLD_GetLastError_METHOD *) IMS_GetLastError,
- (IFLD_SaveChanges_METHOD *) IMS_SaveChanges,
- IFLD_GetProps,
- IFLD_GetPropList,
- IFLD_OpenProperty,
- IFLD_SetProps,
- IFLD_DeleteProps,
- IFLD_CopyTo,
- IFLD_CopyProps,
- (IFLD_GetNamesFromIDs_METHOD *) IMS_GetNamesFromIDs,
- (IFLD_GetIDsFromNames_METHOD *) IMS_GetIDsFromNames,
- IFLD_GetContentsTable,
- IFLD_GetHierarchyTable,
- (IFLD_OpenEntry_METHOD *) IMS_OpenEntry,
- IFLD_SetSearchCriteria,
- IFLD_GetSearchCriteria,
- IFLD_CreateMessage,
- IFLD_CopyMessages,
- IFLD_DeleteMessages,
- IFLD_CreateFolder,
- IFLD_CopyFolder,
- IFLD_DeleteFolder,
- IFLD_SetReadFlags,
- IFLD_GetMessageStatus,
- IFLD_SetMessageStatus,
- IFLD_SaveContentsSort,
- IFLD_EmptyFolder
- };
- /****************************************************
- * Methods on IMAPIFolder *
- *****************************************************/
- /****************************************************************
- Folder properties are all implemented by creating a file
- (FOLDER.PRP) inside each folder and using message properties
- on it.
- *************************************************************/
- /***************************************************************************
- - IFLD_Release
- -
- * Purpose:
- * Given a valid folder object, decrements the reference count, and if
- * zero, NULLS out the lpVtbl. If no child objects of the folder remain
- * open, and no contents or hierarchy tables remain open, the routine
- * also destroys the object (see OBJ_Destroy for details of that action).
- *
- * This release method is very similar to the standard one found in
- * mspobj.c. The only difference is that this one also checks for any
- * open contents or hierarchy tables, and doesn't actually destroy
- * the folder until they are gone. See ViewRelease() for the other side
- * of this implementation.
- *
- * Parameters
- * pifld The folder object to release
- *
- * Returns:
- * ULONG: The value of the reference count on the whole object. When
- * fully released, it is zero. This information can be used for
- * diagnostic and testing purposes only. It CANNOT be used by
- * shipping code. See the OLE 2.0 programmers reference for more
- * details. Note that this function will also return zero when
- * the identity of the object has been destroyed. Therefore,
- * clients may not rely on zero having any special significance
- * other than for debugging purposes.
- */
- STDMETHODIMP_(ULONG) IFLD_Release(PIFLD pifld)
- {
- LONG cRef;
- POBJ pobj;
- if (IFLD_IsInvalid(pifld))
- {
- TraceSz1("SampleMS: IFLD_Release(pifld=%08lX): Folder is invalid and is "
- "being ignored", pifld);
- return (0);
- }
- IFLD_EnterCriticalSection(pifld);
- pobj = (POBJ) pifld;
- AssertSz(pobj->cRef > 0, "IFLD_Release(): Too many releases");
- cRef = --pobj->cRef;
- if (cRef == 0)
- {
- pobj->lpVtbl = 0; /* should prevent being called again. */
- if ( pobj->pobjHead == 0
- && pifld->lptblContents == NULL
- && pifld->lptblHierarchy == NULL)
- {
- OBJ_Destroy(pobj); /* will leave the critical section */
- return (0);
- }
- }
- IFLD_LeaveCriticalSection(pifld);
- return (cRef);
- }
- /***************************************************************************
- - IFLD_GetProps
- -
- * Purpose:
- * Returns in pcval and ppval the values of the properties
- * in ptaga. If the latter is NULL, all properties in the folder
- * are returned.
- *
- * Parameters
- * pifld The folder object whose properties are requested
- * ptaga Pointer to a counted array of property tags of
- * properties requested
- * ulFlags UNICODE / String8
- * pcval Pointer to number of values returned
- * ppval Pointer to a variable in which the address of the
- * returned property values is placed
- *
- * Returns:
- * HRESULT
- *
- */
- STDMETHODIMP IFLD_GetProps(PIFLD pifld, LPSPropTagArray ptaga, ULONG ulFlags,
- ULONG *pcval, LPSPropValue *ppval)
- {
- LPMESSAGE lpmsg = NULL; /* open property message */
- HRESULT hr = hrSuccess;
- FLD_ValidateParameters(
- pifld,
- IMAPIProp,
- GetProps,
- (pifld,
- ptaga,
- ulFlags,
- pcval,
- ppval));
- #ifdef VALIDATE
- if (ulFlags & MAPI_UNICODE)
- return ResultFromScode(MAPI_E_BAD_CHARWIDTH);
- #endif
- IFLD_EnterCriticalSection(pifld);
- /* open the property message */
- hr = HrOpenPropertyMessageRetry(pifld->peid, pifld->pims, FALSE, &lpmsg);
- if (hr != hrSuccess)
- goto exit;
- /* Pass the call off to IMessage */
- hr = lpmsg->lpVtbl->GetProps(lpmsg, ptaga, ulFlags, pcval, ppval);
- UlRelease(lpmsg);
- {if(HR_SUCCEEDED(hr))
- {
- LPSPropValue pvalStoreSupMask = PpropFindProp(*ppval, *pcval,
- PROP_TAG(PT_UNSPECIFIED, PROP_ID(PR_STORE_SUPPORT_MASK)));
- if(pvalStoreSupMask)
- {
- pvalStoreSupMask->ulPropTag = PR_STORE_SUPPORT_MASK;
- pvalStoreSupMask->Value.l = SMS_SUPPORTMASK;
- /* fix up hr */
- if(ptaga->cValues == 1)
- hr = hrSuccess;
- }
- }
- }
- /* Wrap internal properties. Note that this function takes as an */
- /* argument the HRESULT from the previous IMessage::GetProps call. */
- /* We aren't ignoring the error. */
- hr = HrWrap_GetProps(hr, pifld->pims, pifld->cval, pifld->pval, pcval,
- ppval, FALSE, (ptaga != NULL), (POBJ)pifld);
- exit:
- IFLD_LeaveCriticalSection(pifld);
- #ifdef DEBUG
- if (GetScode(hr) != MAPI_W_ERRORS_RETURNED)
- DebugTraceResult(IFLD_GetProps, hr);
- #endif
- return HrCheckHr(hr, IMAPIProp_GetProps);
- }
- /***************************************************************************
- - IFLD_GetPropList
- -
- * Purpose:
- * Returns in ptaga the list of all currently accessible properties
- * of pifld.
- *
- * Parameters
- * pifld The folder object whose properties are requested
- * ulFlags UNICODE / String8
- * pptaga Pointer to a counted array of property tags of
- * properties requested
- * Returns:
- * hr
- *
- */
- STDMETHODIMP IFLD_GetPropList(PIFLD pifld, ULONG ulFlags, LPSPropTagArray *pptaga)
- {
- HRESULT hr;
- LPMESSAGE lpmsg = NULL;
- FLD_ValidateParameters(
- pifld,
- IMAPIProp,
- GetPropList,
- (pifld,
- ulFlags,
- pptaga));
- #ifdef VALIDATE
- if (ulFlags & MAPI_UNICODE)
- return ResultFromScode(MAPI_E_BAD_CHARWIDTH);
- #endif
- IFLD_EnterCriticalSection(pifld);
- /* open the property message */
- hr = HrOpenPropertyMessageRetry(pifld->peid, pifld->pims, FALSE,
- &lpmsg);
- /* If the property message was successfully opened, then pass the */
- /* call off to IMessage */
- if (hr == hrSuccess)
- hr = lpmsg->lpVtbl->GetPropList(lpmsg, ulFlags, pptaga);
- UlRelease(lpmsg);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_GetPropList, hr);
- return HrCheckHr(hr, IMAPIProp_GetPropList);
- }
- /***************************************************************************
- - IFLD_OpenProperty
- -
- * Purpose:
- * Returns in *lppUnk a pointer to a newly created interface for the
- * propery of pifld in ulPropTag
- * Not supported on folders.
- *
- * Parameters
- * pifld the folder object whose property interface is requested
- * ulPropTag Property tag for the desired property--only ID is used.
- * lpiid Pointer to the GUID for the interface
- * ulInterfaceOptions Specifies interface-specific behavior
- * ulFlags MAPI_CREATE, MAPI_MODIFY, MAPI_DEFERRED_ERRORS
- * lppUnk Pointer to the newly created interface pointer
- *
- * Returns:
- * hr
- *
- */
- STDMETHODIMP IFLD_OpenProperty(PIFLD pifld, ULONG ulPropTag, LPCIID lpiid,
- ULONG ulInterfaceOptions, ULONG ulFlags, LPUNKNOWN *lppUnk)
- {
- SCODE sc;
- FLD_ValidateParameters(
- pifld,
- IMAPIProp,
- OpenProperty,
- (pifld,
- ulPropTag,
- lpiid,
- ulInterfaceOptions,
- ulFlags,
- lppUnk));
- sc = MAPI_E_NO_SUPPORT;
- DebugTraceSc(IFLD_OpenProperty, sc);
- return ResultFromScode(sc);
- }
- /***************************************************************************
- - IFLD_SetProps
- -
- * Purpose:
- * Sets the properties in pval for pifld.
- * lppProblems is a pointer to a structure of problems,
- * NULL If there weren't any.
- *
- * Parameters
- * pifld the folder object whose properties are to be set
- * cValues count of properties to be set
- * pval Pointer to a an array of property value structures.
- * ppErr Pointer to address of a property problem structure
- * to be returned.
- *
- * Returns:
- * hr PROP_E_SECURITY_VIOLATION, PROP_E_CALL_FAILED,
- * PROP_E_CALL_FAILED
- *
- */
- STDMETHODIMP IFLD_SetProps(PIFLD pifld, ULONG cValues, LPSPropValue pval,
- LPSPropProblemArray *ppErr)
- {
- LPMESSAGE lpmsgNew = NULL; /* new instance of property message */
- HRESULT hr;
- FLD_ValidateParameters(
- pifld,
- IMAPIProp,
- SetProps,
- (pifld,
- cValues,
- pval,
- ppErr));
- IFLD_EnterCriticalSection(pifld);
- if (!OBJ_TestFlag(pifld, OBJF_MODIFY))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- /* open the property message */
- hr = HrOpenPropertyMessageRetry(pifld->peid, pifld->pims,
- TRUE, &lpmsgNew);
- if (hr != hrSuccess)
- goto exit;
- /* set props on the property message */
- hr = lpmsgNew->lpVtbl->SetProps(lpmsgNew, cValues, pval, ppErr);
- if (hr != hrSuccess)
- goto exit;
- hr = lpmsgNew->lpVtbl->SaveChanges(lpmsgNew, KEEP_OPEN_READWRITE);
- if (hr != hrSuccess)
- goto exit;
- /* Must release the message before trying to update the hierarchy */
- /* table. Multiple opens on the internal message are not allowed by */
- /* IStorage. */
- UlRelease(lpmsgNew);
- lpmsgNew = NULL;
- /* If this isn't the root folder, get the parent entryid, and call */
- /* ChangeTable so that any new properties are updated in its */
- /* hierarchy table row. */
- if (FIsRoot(pifld->peid) == FALSE)
- {
- PEID peidParent = NULL;
- PIMS pims = pifld->pims;
- hr = HrGetParentEID(&pims->lmr, pifld->peid, &peidParent);
- if (hr == hrSuccess)
- {
- ChangeTable(pims, peidParent, pifld->peid, MAPI_FOLDER,
- TABLE_ROW_MODIFIED, TRUE);
- LMFree(&pims->lmr, peidParent);
- }
- else
- {
- TraceSz1("Sample MS: IFLD_SetProps: failed to change hierarchy "
- "table. sc == %sn", SzDecodeScode(GetScode(hr)));
- hr = hrSuccess;
- }
- }
- exit:
- UlRelease(lpmsgNew);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_SetProps, hr);
- return HrCheckHr(hr, IMAPIProp_SetProps);
- }
- /***************************************************************************
- - IFLD_DeleteProps
- -
- * Purpose:
- * Deletes the properties in ptaga for pifld. ppErr
- * is a pointer to a structure of problems, NULL If there weren't any.
- *
- * Parameters
- * pifld the folder object whose properties are to be deleted
- * ptaga Pointer to a counted array of property tags of the
- * properties to be deleted. Must not be NULL.
- * ppErr Pointer to address of a property problem structure
- * to be returned.
- * Returns:
- * hr PROP_E_SECURITY_VIOLATION, PROP_E_CALL_FAILED,
- * PROP_E_CALL_FAILED
- */
- STDMETHODIMP IFLD_DeleteProps(PIFLD pifld, LPSPropTagArray ptaga,
- LPSPropProblemArray *ppErr)
- {
- LPMESSAGE lpmsgNew = NULL; /* new instance of property message */
- HRESULT hr = hrSuccess;
- FLD_ValidateParameters(
- pifld,
- IMAPIProp,
- DeleteProps,
- (pifld,
- ptaga,
- ppErr));
- IFLD_EnterCriticalSection(pifld);
- if (!OBJ_TestFlag(pifld, OBJF_MODIFY))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- /* open the property message */
- hr = HrOpenPropertyMessageRetry(pifld->peid,
- pifld->pims, TRUE, &lpmsgNew);
- if (hr != hrSuccess)
- goto exit;
- /* Pass the call off to IMessage */
- hr = lpmsgNew->lpVtbl->DeleteProps(lpmsgNew, ptaga, ppErr);
- if (hr != hrSuccess)
- goto exit;
- hr = lpmsgNew->lpVtbl->SaveChanges(lpmsgNew, KEEP_OPEN_READWRITE);
- if (hr != hrSuccess)
- goto exit;
- /* Must release the message before trying to update the hierarchy */
- /* table. Multiple opens on the internal message are not allowed by */
- /* IStorage. */
- UlRelease(lpmsgNew);
- lpmsgNew = NULL;
- /* If this isn't the root folder, get the parent entryid, and call */
- /* ChangeTable so that any new properties are updated in its */
- /* hierarchy table row. */
- if (FIsRoot(pifld->peid) == FALSE)
- {
- PEID peidParent = NULL;
- PIMS pims = pifld->pims;
- hr = HrGetParentEID(&pims->lmr, pifld->peid, &peidParent);
- if (hr == hrSuccess)
- {
- ChangeTable(pims, peidParent, pifld->peid, MAPI_FOLDER,
- TABLE_ROW_MODIFIED, TRUE);
- LMFree(&pims->lmr, peidParent);
- }
- else
- {
- TraceSz1("Sample MS: IFLD_DeleteProps: failed to change hierarchy "
- "table. sc == %sn", SzDecodeScode(GetScode(hr)));
- hr = hrSuccess;
- }
- }
- exit:
- UlRelease(lpmsgNew);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_DeleteProps, hr);
- return HrCheckHr(hr, IMAPIProp_DeleteProps);
- }
- /***************************************************************************
- - IFLD_CopyTo
- -
- * Purpose:
- * Copy the properties and/or contents of the current object
- * to a destination object
- *
- * Parameters
- * pifldSrc current object
- * ciidExcl Count of excluded interfaces in rgiidExcl
- * rgiidExcl Array of iid's specifying excluded interfaces
- * ptagaExcl Pointer to a counted array of property tags of
- * properties not to be copied, can be NULL
- * ulUIParam Handle of parent window cast to ULONG, NULL if
- * no dialog requested
- * piidDst Interface ID of the interface of lpDestObj
- * lpDestObj destination object
- * ulFlags MAPI_MOVE, MAPI_NOREPLACE, MAPI_DIALOG, MAPI_DECLINE_OK
- * pprba Pointer to address of a property problem
- * structure to be returned.
- *
- * Returns:
- * hr
- *
- * Side effects:
- *
- * Errors:
- */
- STDMETHODIMP IFLD_CopyTo(PIFLD pifldSrc, ULONG ciidExcl, LPCIID rgiidExcl,
- LPSPropTagArray ptagaExcl, ULONG ulUIParam, LPMAPIPROGRESS lpProgress,
- LPCIID piidDst, LPVOID lpDestObj, ULONG ulFlagsIn,
- LPSPropProblemArray *pprba)
- {
- HRESULT hr = hrSuccess;
- BOOL fIsIMapiProp = TRUE; /* TRUE if are to copy as imapiprop */
- BOOL fIsIMAPIFolder = TRUE; /* TRUE if are to copy as IMAPIFolder */
- SCODE sc = S_OK;
- LPCIID piid;
- LPCIID piidMax;
- ULONG ulFlags;
- FLD_ValidateParameters(
- pifldSrc,
- IMAPIProp,
- CopyTo,
- (pifldSrc,
- ciidExcl,
- rgiidExcl,
- ptagaExcl,
- ulUIParam,
- lpProgress,
- piidDst,
- lpDestObj,
- ulFlagsIn,
- pprba));
- IFLD_EnterCriticalSection(pifldSrc);
- /* Turn off MAPI_DIALOG flag, since we don't support it. */
- ulFlags = (ulFlagsIn & ~MAPI_DIALOG);
- piid = rgiidExcl;
- piidMax = piid + ciidExcl;
- /* find the interface to copy : IMAPIPROP or IMAPIFOLDER */
- while (piid < piidMax)
- {
- if (IsEqualIID(piid, &IID_IMAPIFolder))
- fIsIMAPIFolder = FALSE;
- else if (IsEqualIID(piid, (LPIID) &IID_IMAPIProp))
- fIsIMapiProp = FALSE;
- piid++;
- }
- /* make sure that the destination can support this */
- if (fIsIMAPIFolder && !IsEqualIID(piidDst, (LPIID) &IID_IMAPIFolder))
- {
- LPMAPIFOLDER pfld = NULL;
- hr = ((LPUNKNOWN) lpDestObj)->lpVtbl->QueryInterface(lpDestObj,
- (LPIID) &IID_IMAPIFolder, (LPVOID *) &pfld);
- if (hr != hrSuccess)
- {
- Assert(GetScode(hr) == MAPI_E_INTERFACE_NOT_SUPPORTED);
- goto exit;
- }
- UlRelease(pfld);
- }
- else if (fIsIMapiProp &&
- !(IsEqualIID(piidDst, (LPIID) &IID_IMAPIProp) ||
- IsEqualIID(piidDst, (LPIID) &IID_IMAPIFolder)))
- {
- LPMAPIPROP pmp = NULL;
- hr = ((LPUNKNOWN) lpDestObj)->lpVtbl->QueryInterface(lpDestObj,
- (LPIID) &IID_IMAPIProp, (LPVOID *) &pmp);
- if (hr != hrSuccess)
- {
- Assert(GetScode(hr) == MAPI_E_INTERFACE_NOT_SUPPORTED);
- goto exit;
- }
- UlRelease(pmp);
- }
- if (!FFoldInSameStore(pifldSrc, (PIFLD) lpDestObj))
- {
- LPMAPISUP psup = pifldSrc->pims->psup;
- /* leave critical section before calling back to MAPI */
- IFLD_LeaveCriticalSection(pifldSrc);
- /* call MAPI's CopyProps */
- hr = psup->lpVtbl->DoCopyTo(psup, (LPIID) &IID_IMAPIFolder, (LPVOID) pifldSrc,
- ciidExcl, rgiidExcl, ptagaExcl, ulUIParam,
- lpProgress, piidDst, lpDestObj, ulFlagsIn, pprba);
- DebugTraceResult(IFLD_CopyTo, hr);
- return (HrCheckHr(hr, IMAPIProp_CopyTo));
- }
- /* copy them as folders */
- if (fIsIMAPIFolder)
- {
- PIFLD pifldDst = (PIFLD) lpDestObj;
- /* make sure we have write access */
- if (!OBJ_TestFlag(pifldDst, OBJF_MODIFY))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- if (!FContainsProp(PR_CONTAINER_HIERARCHY, ptagaExcl))
- {
- /* can not move or copy a folder to a decendant or itself */
- if (FIsAncestor(pifldSrc, pifldDst))
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- }
- else if (ulFlags & MAPI_MOVE)
- {
- /* Can't set MAPI_MOVE and also exclude subfolders. */
- hr = ResultFromScode(MAPI_E_INVALID_PARAMETER);
- }
- if (hr != hrSuccess)
- goto exit;
- if (!(ulFlags & MAPI_NOREPLACE))
- {
- /* Empty the destination folder before beginning. */
- hr = pifldDst->lpVtbl->EmptyFolder(pifldDst, 0, NULL, 0);
- if (hr != hrSuccess)
- goto exit;
- }
- /* copy the contents of the source folder to the destination folder */
- hr = HrCopyContents(pifldSrc, pifldDst, ulFlags, ptagaExcl);
- if (hr != hrSuccess)
- goto exit;
- }
- /* copy the properties */
- if (fIsIMapiProp || fIsIMAPIFolder)
- {
- LPMESSAGE lpmsg;
- BOOL fModify = FALSE;
- if (ulFlags & MAPI_MOVE)
- fModify = TRUE;
- hr = HrOpenPropertyMessageRetry(pifldSrc->peid,
- pifldSrc->pims, fModify, &lpmsg);
- if (hr != hrSuccess)
- goto exit;
- hr = lpmsg->lpVtbl->CopyTo(lpmsg, ciidExcl,
- rgiidExcl, ptagaExcl, ulUIParam, lpProgress,
- (LPIID) &IID_IMAPIProp, lpDestObj, ulFlags, pprba);
- if (hr == hrSuccess && fModify)
- lpmsg->lpVtbl->SaveChanges(lpmsg, KEEP_OPEN_READWRITE);
- UlRelease(lpmsg);
- }
- exit:
- IFLD_LeaveCriticalSection(pifldSrc);
- DebugTraceResult(IFLD_CopyTo, hr);
- return HrCheckHr(hr, IMAPIProp_CopyTo);
- }
- /***************************************************************************
- - IFLD_CopyProps
- -
- * Purpose:
- * Copy the properties and/or contents of the current object
- * to a destination object
- *
- * Parameters
- * pifldSrc current object
- * ptagaIncl Pointer to a counted array of property tags of
- * properties to be copied
- * ulUIParam Handle of parent window cast to ULONG, NULL if
- * no dialog requested
- * piidDst Interface ID of the interface of lpDestObj
- * lpDestObj destination object
- * ulFlags MAPI_MOVE, MAPI_NOREPLACE, MAPI_DIALOG, MAPI_DECLINE_OK
- * pprba Pointer to address of a property problem
- * structure to be returned.
- *
- * Returns:
- * hr
- *
- * Side effects:
- *
- * Errors:
- */
- STDMETHODIMP IFLD_CopyProps(PIFLD pifldSrc,
- LPSPropTagArray ptagaIncl, ULONG ulUIParam, LPMAPIPROGRESS lpProgress,
- LPCIID piidDst, LPVOID lpDestObj, ULONG ulFlagsIn,
- LPSPropProblemArray *pprba)
- {
- HRESULT hr = hrSuccess;
- #ifdef WHEN_WORKING
- PIFLD pifldDst = NULL; /* lpDestObj if it's a folder */
- BOOL fIsIMAPIFolder; /* TRUE if are to copy as IMAPIFolder */
- SCODE sc = S_OK;
- LPIID piid;
- LPIID piidMax;
- ULONG ulFlags;
- #endif /* WHEN_WORKING */
- FLD_ValidateParameters(
- pifldSrc,
- IMAPIProp,
- CopyProps,
- (pifldSrc,
- ptagaIncl,
- ulUIParam,
- lpProgress,
- piidDst,
- lpDestObj,
- ulFlagsIn,
- pprba));
- IFLD_EnterCriticalSection(pifldSrc);
- #ifdef WHEN_WORKING
- /* Turn off MAPI_DIALOG flag, since we don't support it. */
- ulFlags = (ulFlagsIn & ~MAPI_DIALOG);
- fIsIMAPIFolder = FContainsProp(PR_CONTAINER_HIERARCHY, ptagaIncl)
- || FContainsProp(PR_CONTAINER_CONTENTS, ptagaIncl);
- /* make sure that the destination can support this */
- if (fIsIMAPIFolder && !IsEqualIID(piidDst, (LPIID) &IID_IMAPIFolder))
- {
- LPMAPIFOLDER pfld = NULL;
- hr = ((LPUNKNOWN) lpDestObj)->lpVtbl->QueryInterface(lpDestObj,
- (LPIID) &IID_IMAPIFolder, (LPVOID *) &pfld);
- if (hr != hrSuccess)
- {
- Assert(GetScode(hr) == MAPI_E_INTERFACE_NOT_SUPPORTED);
- goto exit;
- }
- UlRelease(pfld);
- }
- else if (!(IsEqualIID(piidDst, (LPIID) &IID_IMAPIProp) ||
- IsEqualIID(piidDst, (LPIID) &IID_IMAPIFolder)))
- {
- LPMAPIPROP pmp = NULL;
- hr = ((LPUNKNOWN) lpDestObj)->lpVtbl->QueryInterface(lpDestObj,
- (LPIID) &IID_IMAPIProp, (LPVOID *) &pmp);
- if (hr != hrSuccess)
- {
- Assert(GetScode(hr) == MAPI_E_INTERFACE_NOT_SUPPORTED);
- goto exit;
- }
- UlRelease(pmp);
- }
- if (!FFoldInSameStore(pifldSrc, (PIFLD) lpDestObj))
- {
- LPMAPISUP psup = pifldSrc->pims->psup;
- /* leave critical section before calling back to MAPI */
- IFLD_LeaveCriticalSection(pifldSrc);
- /* call MAPI's CopyProps */
- hr = psup->lpVtbl->DoCopyProps(psup, (LPIID) &IID_IMAPIFolder,
- (LPVOID) pifldSrc, ptagaIncl, ulUIParam,
- lpProgress, piidDst, lpDestObj, ulFlagsIn, pprba);
- DebugTraceResult(IFLD_CopyProps, hr);
- return (HrCheckHr(hr, IMAPIProp_CopyProps));
- }
- /* copy them as folders */
- if (fIsIMAPIFolder)
- {
- PIFLD pifldDst = (PIFLD) lpDestObj;
- /* make sure we have write access */
- if (!OBJ_TestFlag(pifldDst, OBJF_MODIFY))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- if (FContainsProp(PR_CONTAINER_HIERARCHY, ptagaIncl))
- {
- /* can not move or copy a folder to a decendant or itself */
- if (FIsAncestor(pifldSrc, pifldDst))
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- }
- else if (ulFlags & MAPI_MOVE)
- {
- /* Can't set MAPI_MOVE and also exclude subfolders. */
- hr = ResultFromScode(MAPI_E_INVALID_PARAMETER);
- }
- if (hr != hrSuccess)
- goto exit;
- if (!(ulFlags & MAPI_NOREPLACE))
- {
- /* Empty the destination folder before beginning. */
- hr = pifldDst->lpVtbl->EmptyFolder(pifldDst, 0, NULL, 0);
- if (hr != hrSuccess)
- goto exit;
- }
- if (FContainsProp(PR_CONTAINER_CONTENTS, ptagaIncl))
- {
- /* copy the contents of the source folder to the destination folder */
- hr = HrCopyContents(pifldSrc, pifldDst, ulFlags, NULL);
- }
- if (hr != hrSuccess)
- goto exit;
- }
- /* copy the properties */
- /* //$ Rebuild ptagaIncl without Contents and Hierarchy */
- {
- LPMESSAGE lpmsg;
- BOOL fModify = FALSE;
- if (ulFlags & MAPI_MOVE)
- fModify = TRUE;
- hr = HrOpenPropertyMessageRetry(pifldSrc->peid,
- pifldSrc->pims, fModify, &lpmsg);
- if (hr != hrSuccess)
- goto exit;
- hr = lpmsg->lpVtbl->CopyProps(lpmsg,
- ptagaIncl, ulUIParam, lpProgress,
- (LPIID) &IID_IMAPIProp, lpDestObj, ulFlags, pprba);
- if (hr == hrSuccess && fModify)
- lpmsg->lpVtbl->SaveChanges(lpmsg, KEEP_OPEN_READWRITE);
- UlRelease(lpmsg);
- }
- exit:
- IFLD_LeaveCriticalSection(pifldSrc);
- #else
- IFLD_LeaveCriticalSection(pifldSrc);
- /* call MAPI's CopyProps */
- hr = pifldSrc->pims->psup->lpVtbl->DoCopyProps(pifldSrc->pims->psup,
- (LPIID) &IID_IMAPIFolder, (LPVOID) pifldSrc, ptagaIncl, ulUIParam,
- lpProgress, piidDst, lpDestObj, ulFlagsIn, pprba);
- #endif /* WHEN_WORKING */
- DebugTraceResult(IFLD_CopyProps, hr);
- return HrCheckHr(hr, IMAPIProp_CopyProps);
- }
- /***************************************************************************
- - IFLD_GetContentsTable
- -
- * Purpose:
- * Returns a table with the summary information about the messages
- * in the folder
- *
- * Parameters
- * pifld the folder object
- * ulFlags MAPI_DEFERRED_ERRORS, MAPI_ASSOCIATED
- * lppTable location to place the table object
- *
- * Returns:
- *
- * Side effects:
- *
- * Errors:
- */
- STDMETHODIMP IFLD_GetContentsTable(PIFLD pifld, ULONG ulFlags,
- LPMAPITABLE *lppTable)
- {
- HRESULT hr = hrSuccess;
- SCODE sc;
- HANDLE hFindFile = FAILED_SEARCH;
- LPTSTR szMessageTemplate = NULL; /* template for a message name */
- LPSSortOrderSet lpsSortOrder = NULL;
- BOOL fTableCreated = FALSE;
- BOOL fInMutex = FALSE;
- PIMS pims;
- FLD_ValidateParameters(
- pifld,
- IMAPIContainer,
- GetContentsTable,
- (pifld,
- ulFlags,
- lppTable));
- #ifdef VALIDATE
- if (ulFlags & MAPI_ASSOCIATED)
- return ResultFromScode(MAPI_E_NO_SUPPORT);
- if (ulFlags & MAPI_UNICODE)
- return ResultFromScode(MAPI_E_BAD_CHARWIDTH);
- #endif
- IFLD_EnterCriticalSection(pifld);
- pims = pifld->pims;
- /* If the table mutex doesn't yet exist on this process, create it. */
- if (pims->hContTblMutex == NULL)
- {
- hr = HrCreateContTblMutex(&pims->hContTblMutex);
- if (hr != hrSuccess)
- goto exit;
- }
- if (pifld->lptblContents == NULL)
- {
- PINST pinst = (PINST) PvGetInstanceGlobals();
- PLMR plmr = &pifld->pims->lmr;
- if (pinst == NULL)
- {
- hr = ResultFromScode(MAPI_E_CALL_FAILED);
- goto exit;
- }
- /* create the data for the table */
- sc = CreateTable((LPIID) &IID_IMAPITableData,
- plmr->lpAllocBuf, plmr->lpAllocMore,
- plmr->lpFreeBuf, pinst->lpmalloc, TBLTYPE_DYNAMIC,
- PR_INSTANCE_KEY, (LPSPropTagArray) &sPropTagsContents,
- &(pifld->lptblContents));
- if (sc != S_OK)
- {
- hr = ResultFromScode(sc);
- goto exit;
- }
- fTableCreated = TRUE;
- /* Get the table mutex so that we can access the file without */
- /* crossing paths with another process. */
- WaitForSingleObject(pims->hContTblMutex, INFINITE);
- fInMutex = TRUE;
- hr = HrReadTableFromDisk(pifld->lptblContents, (POBJ) pifld,
- pifld->peid->szPath, CONTENTS_COLUMNS, szContentsFileName);
- if (hr != hrSuccess)
- {
- /* non-fatal. If the data on disk is missing or invalid, we */
- /* should regenerate the data via HrSyncContentsTable. */
- TraceSz1("SMS: Error %s reading table from disk. Regenerating "
- "table on disk.", SzDecodeScode(GetScode(hr)));
- hr = hrSuccess;
- }
- }
- /* If we don't already have the mutex, get it so that we can access */
- /* the file without crossing paths with another process. */
- if (!fInMutex)
- {
- WaitForSingleObject(pims->hContTblMutex, INFINITE);
- fInMutex = TRUE;
- }
- hr = HrSyncContentsTable(pifld, TRUE);
- Assert(fInMutex);
- ReleaseMutex(pims->hContTblMutex);
- fInMutex = FALSE;
- if (hr != hrSuccess)
- goto exit;
- /* open a view to the table */
- /* get the sort order from the PR_SMS_CONTENTS_SORT_ORDER property */
- hr = HrGetSortOrder(pifld, &lpsSortOrder);
- if (hr != hrSuccess)
- goto exit;
- /* get the view */
- hr = pifld->lptblContents->lpVtbl->HrGetView(pifld->lptblContents,
- lpsSortOrder, ViewRelease, (ULONG) pifld, lppTable);
- if (hr != hrSuccess)
- goto exit;
- /* record this view in pifld */
- pifld->cContentsViews++;
- exit:
- if (fInMutex)
- ReleaseMutex(pims->hContTblMutex);
- /* free the sort order */
- LMFree(&pifld->pims->lmr, lpsSortOrder);
- /* remove the table if it is created in error */
- if (hr != hrSuccess && fTableCreated)
- {
- UlRelease(pifld->lptblContents);
- pifld->cContentsViews = 0;
- pifld->lptblContents = NULL;
- }
- CloseIDSearch(&hFindFile, &szMessageTemplate);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_GetContentsTable, hr);
- return HrCheckHr(hr, IMAPIFolder_GetContentsTable);
- }
- /***************************************************************************
- - IFLD_GetHierarchyTable
- -
- * Purpose:
- * Returns a table with the summary information about the child
- * folders of the current folder
- *
- * Parameters
- * pifld the folder object
- * ulFlags CONVENIENT_DEPTH if set indicates pre-order traversal
- * MAPI_DEFERRED_ERRORS
- * MAPI_UNICODE
- * lppTable location to place the table object
- *
- * Returns:
- *
- * Side effects:
- *
- * Errors:
- */
- STDMETHODIMP IFLD_GetHierarchyTable(PIFLD pifld, ULONG ulFlags,
- LPMAPITABLE *lppTable)
- {
- HRESULT hr;
- LPTABLEDATA lptad = NULL;
- FLD_ValidateParameters(
- pifld,
- IMAPIContainer,
- GetHierarchyTable,
- (pifld,
- ulFlags,
- lppTable));
- #ifdef VALIDATE
- if (ulFlags & MAPI_UNICODE)
- return ResultFromScode(MAPI_E_BAD_CHARWIDTH);
- #endif
- IFLD_EnterCriticalSection(pifld);
- /* if table needs refreshing */
- if (pifld->lptblHierarchy == NULL)
- {
- PINST pinst = (PINST) PvGetInstanceGlobals();
- SCODE sc;
- PLMR plmr = &pifld->pims->lmr;
- pifld->cHierarchyViews = 0;
- if (pinst == NULL)
- {
- hr = ResultFromScode(MAPI_E_CALL_FAILED);
- goto exit;
- }
- /* create the table */
- sc = CreateTable((LPIID) &IID_IMAPITableData,
- plmr->lpAllocBuf, plmr->lpAllocMore,
- plmr->lpFreeBuf, pinst->lpmalloc, TBLTYPE_DYNAMIC,
- PR_INSTANCE_KEY, (LPSPropTagArray) &sPropTagsHierarchy, &lptad);
- if (sc != S_OK)
- {
- hr = ResultFromScode(sc);
- goto exit;
- }
- /* add a row or traversal for each subfolder of pifld */
- /* Note that the sample store only supports a max depth of 1. */
- hr = HrFillHierarchyTable(pifld, lptad);
- if (hr != hrSuccess)
- goto exit;
- pifld->lptblHierarchy = lptad;
- lptad = NULL;
- }
- /* open a view to the table */
- hr = pifld->lptblHierarchy->lpVtbl->HrGetView(pifld->lptblHierarchy,
- NULL, ViewRelease, (ULONG) pifld, lppTable);
- if (hr != hrSuccess)
- goto exit;
- /* record this view in pifld */
- pifld->cHierarchyViews++;
- exit:
- /* remove the table if it is created in error */
- if (hr != hrSuccess && lptad)
- UlRelease(lptad);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_GetHierarchyTable, hr);
- return HrCheckHr(hr, IMAPIFolder_GetHierarchyTable);
- }
- /***************************************************************************
- - IFLD_CreateMessage
- -
- * Purpose:
- * Creates a new message in the store
- *
- * Parameters
- * pifld the folder object
- * ulFlags flags. Valid flags to pass are MAPI_DEFERRED_ERRORS
- * and MAPI_ASSOCIATED. The sample store doesn't support
- * MAPI_ASSOCIATED, so the code returns no support if
- * that flag is passed.
- * piid reserved for future use
- * lppMessage location to place the message object
- *
- * Returns:
- *
- * Side effects:
- *
- * Errors:
- */
- STDMETHODIMP IFLD_CreateMessage(PIFLD pifld, LPCIID piid, ULONG ulFlags,
- LPMESSAGE *lppMessage)
- {
- HRESULT hr;
- PEID peid = NULL;
- ULONG ulSeqNumber;
- PIMSG pimsg = NULL;
- LPTSTR szFull = NULL;
- FLD_ValidateParameters(
- pifld,
- IMAPIFolder,
- CreateMessage,
- (pifld,
- piid,
- ulFlags,
- lppMessage));
- #ifdef VALIDATE
- if (ulFlags & MAPI_ASSOCIATED)
- return ResultFromScode(MAPI_E_NO_SUPPORT);
- if (piid && !FQueryInterface(OT_MESSAGE, piid))
- return ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
- #endif
- IFLD_EnterCriticalSection(pifld);
- if (!OBJ_TestFlag(pifld, OBJF_MODIFY))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- /* create the message */
- hr = HrNewEID(pifld, pifld->pims, TEMP_EXT, &ulSeqNumber, &peid);
- if (hr != hrSuccess)
- goto exit;
- hr = HrNewIMSG(peid, pifld->pims, TRUE, TRUE, ulSeqNumber, &szFull, &pimsg);
- if (hr != hrSuccess)
- goto exit;
- hr = InitIMSGProps(pimsg);
- if (hr != hrSuccess)
- goto exit;
- /* folder contents counts and tables are not updated until message */
- /* has changes saved */
- exit:
- LMFree(&pifld->pims->lmr, peid);
- if (hr == hrSuccess)
- *lppMessage = (LPMESSAGE) pimsg;
- else if (pimsg)
- {
- UlRelease(pimsg);
- Assert(szFull);
- DeleteFile(szFull);
- }
- FreeNull(szFull);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_CreateMessage, hr);
- return HrCheckHr(hr, IMAPIFolder_CreateMessage);
- }
- /***************************************************************************
- - IFLD_CopyMessages
- -
- * Purpose:
- * Moves/Copies messages from the source folder to the destination folder
- * EntryId's are not changed here since they get stamped in when the
- * messages are opened.
- *
- * Parameters
- * pifld the source folder
- * lpMsgList the list of messages to be moved/copied
- * piid the interface id of destination folder
- * lpfolderDst the destination folder
- * ulUIParam Handle of parent window,
- * ignored if MESSAGE_DIALOG not set
- * lpProgress points to progress dialog object
- * ulFlags MAPI_DECLINE_OK, MESSAGE_MOVE, or MESSAGE_DIALOG
- */
- STDMETHODIMP IFLD_CopyMessages(PIFLD pifld, LPENTRYLIST lpMsgList,
- LPCIID piid, LPMAPIFOLDER lpfolderDst, ULONG ulUIParam,
- LPMAPIPROGRESS lpProgress, ULONG ulFlags)
- {
- LONG cHandled = 0; /* number messages copied/moved */
- LPTSTR szSrcName = NULL; /* name of file to be moved */
- LPTSTR szDestName = NULL; /* name of the file after it is moved */
- ULONG cbSrcPath = 0; /* length in bytes of path to src fld */
- ULONG cbDestPath = 0; /* length in bytes of path to dest fld */
- ULONG cbStorePath = 0; /* length in bytes of path to root of store */
- TCHAR szBlanks[CCH_NAME] = TEXT(" . ");
- HRESULT hr = hrSuccess;
- PIFLD pifldDst;
- BOOL fMove;
- SBinary *psb;
- SBinary *psbMax;
- PIMS pims;
- FLD_ValidateParameters(
- pifld,
- IMAPIFolder,
- CopyMessages,
- (pifld,
- lpMsgList,
- piid,
- lpfolderDst,
- ulUIParam,
- lpProgress,
- ulFlags));
- IFLD_EnterCriticalSection(pifld);
- pifldDst = (PIFLD) lpfolderDst;
- pims = pifld->pims;
- /* if the folders aren't in the same store, call back to MAPI */
- if (!FFoldInSameStore(pifld, pifldDst))
- {
- /* leave critical section before calling back to MAPI */
- IFLD_LeaveCriticalSection(pifld);
- return pims->psup->lpVtbl->CopyMessages(pims->psup,
- (LPIID) &IID_IMAPIFolder, (LPVOID) pifld, lpMsgList, piid,
- (LPVOID) lpfolderDst, ulUIParam, lpProgress, ulFlags);
- }
- fMove = !!(ulFlags & MESSAGE_MOVE);
- if ( !OBJ_TestFlag(pifldDst, OBJF_MODIFY)
- || ( fMove
- && !OBJ_TestFlag(pifld, OBJF_MODIFY)))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- if (fMove)
- {
- /* If moving messages and the source and destination are the same */
- /* folder, we are done even before we begin. */
- ULONG ulTheSame;
- hr = pims->lpVtbl->CompareEntryIDs(pims,
- CbEID(pifldDst->peid), (LPENTRYID) pifldDst->peid,
- CbEID(pifld->peid), (LPENTRYID) pifld->peid, 0L, &ulTheSame);
- if (hr != hrSuccess)
- goto exit;
- if (ulTheSame)
- {
- hr = hrSuccess;
- goto exit;
- }
- }
- /* get storage for the path names */
- cbStorePath = Cbtszsize(pims->szStorePath);
- cbSrcPath = cbStorePath + CbEIDPath(pifld->peid);
- if (FIsRoot(pifld->peid))
- cbSrcPath--;
- cbDestPath = cbStorePath + CbEIDPath(pifldDst->peid);
- if (FIsRoot(pifldDst->peid))
- cbDestPath--;
- hr = HrFullPathName(pims->szStorePath, pifld->peid->szPath,
- szBlanks, &szSrcName);
- if (hr != hrSuccess)
- goto exit;
- hr = HrFullPathName(pims->szStorePath, pifldDst->peid->szPath,
- szBlanks, &szDestName);
- if (hr != hrSuccess)
- goto exit;
- psb = lpMsgList->lpbin;
- psbMax = psb + lpMsgList->cValues;
- /* move/copy each message */
- while (psb < psbMax)
- {
- ULONG ulMF;
- ULONG ulObjType;
- BOOL fLocked;
- BOOL fRead;
- PIMSG pimsg;
- LPSTR szRelativePath;
- PEID peidNewID;
- PEID peidToCopy;
- ULONG cbEntryID;
- cbEntryID = psb->cb;
- peidToCopy = (PEID) (psb->lpb);
- if ( FIsInvalidEID(cbEntryID, peidToCopy, pims)
- || !FIsMessage((PEID) peidToCopy))
- {
- hr = ResultFromScode(MAPI_E_INVALID_PARAMETER);
- goto exit;
- }
- /* open the message */
- hr = pifld->lpVtbl->OpenEntry(pifld, CbEID(peidToCopy),
- (LPENTRYID) peidToCopy, NULL, 0L, &ulObjType,
- (LPUNKNOWN *) &pimsg);
- if (hr != hrSuccess)
- goto exit;
- Assert(ulObjType == MAPI_MESSAGE);
- /* retrieve the PR_MESSAGE_FLAGS property */
- hr = HrGetSingleProp((LPMAPIPROP) pimsg->lpmsg, &pims->lmr,
- PR_MESSAGE_FLAGS, &ulMF);
- UlRelease(pimsg);
- if (hr != hrSuccess)
- goto exit;
- fLocked = !!(ulMF & MSGFLAG_SUBMIT);
- fRead = !!(ulMF & MSGFLAG_READ);
- /* if the message is locked then this is an error */
- if (fLocked)
- {
- hr = ResultFromScode(MAPI_E_INVALID_PARAMETER);
- goto exit;
- }
- /* store in szSrcName the root relative path of the message to be moved*/
- lstrcpy(szSrcName + cbSrcPath, SzBaseName(peidToCopy));
- /* store in szDestName the store relative path name of */
- /* destination file */
- if (fMove)
- lstrcpy(szDestName + cbDestPath, SzBaseName(peidToCopy));
- else
- {
- /* If we're copying, we need to generate a new filename for the */
- /* message, or else we will have two messages with the same */
- /* filename, and copying again (or moving back) will fail. */
- PEID peidTemp = NULL;
- hr = HrNewEID(pifld, pims, MESSAGE_EXT, NULL, &peidTemp);
- if (hr != hrSuccess)
- goto exit;
- lstrcpy(szDestName + cbDestPath, SzBaseName(peidTemp));
- LMFree(&pims->lmr, peidTemp);
- }
- /* either move or copy the message */
- if (fMove)
- {
- if (!MoveFile(szSrcName, szDestName))
- {
- TraceSz1("MoveFile failed: OS error %08lX.", GetLastError());
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- /* remove this message from contents tables */
- (void) HrIncrementOneROProp(pifld, -1, PR_CONTENT_COUNT);
- if (!fRead)
- (void) HrIncrementOneROProp(pifld, -1, PR_CONTENT_UNREAD);
- ChangeTable(pims, pifld->peid, peidToCopy, MAPI_MESSAGE,
- TABLE_ROW_DELETED, TRUE);
- }
- else
- {
- if (!CopyFile(szSrcName, szDestName, TRUE))
- {
- TraceSz1("CopyFile failed: OS error %08lX.", GetLastError());
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- }
- /* get new entryid for this message */
- hr = HrFullToRelative(szDestName, pims, &szRelativePath);
- if (hr != hrSuccess)
- goto exit;
- hr = HrConstructEID(&(peidToCopy->uidResource), &pims->lmr,
- szRelativePath, &peidNewID);
- FreeNull(szRelativePath);
- if (hr != hrSuccess)
- goto exit;
- /* If we're copying, then we just used a new name for the file. */
- /* Note that PR_RECORD_KEY, PR_ENTRYID, PR_INSTANCE_KEY, and */
- /* PR_PARENT_ENTRYID are now different, but since these are stored */
- /* in the opened msg, everything should be fine. */
- /* add a row to the contents table of the destination folder */
- (void) HrIncrementOneROProp(pifldDst, 1, PR_CONTENT_COUNT);
- if (!fRead)
- (void) HrIncrementOneROProp(pifldDst, 1, PR_CONTENT_UNREAD);
- ChangeTable(pims, pifldDst->peid, peidNewID, MAPI_MESSAGE,
- TABLE_ROW_ADDED, TRUE);
- LMFree(&pims->lmr, peidNewID);
- cHandled++;
- psb++;
- }
- exit:
- FreeNull(szDestName);
- FreeNull(szSrcName);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_CopyMessages, hr);
- return HrCheckHr(hr, IMAPIFolder_CopyMessages);
- }
- /***************************************************************************
- - IFLD_DeleteMessages
- -
- * Purpose:
- * Deletes from the folder pifld all messages in the list lpMsgList
- *
- * Parameters
- * pifld the folder from which messages are to be deleted
- * lpMsgList the list of messages to be deleted
- * ulUIParam handle to main window, cast to ULONG
- * lpProgress points to progress dialog information
- * ulFlags MESSAGE_DIALOG
- *
- * Returns:
- *
- * Side effects:
- *
- * Errors:
- */
- STDMETHODIMP IFLD_DeleteMessages(PIFLD pifld, LPENTRYLIST lpMsgList,
- ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
- {
- PEID peidToDelete = NULL; /* pointer to next eid to be deleted */
- LONG cDeleted = 0; /* number messages deleted */
- LONG cUnreadDeleted = 0; /* number of unread messages deleted */
- LPTSTR szToDeleteName = NULL; /* name of the next message to be deleted */
- HRESULT hr = hrSuccess;
- LPTSTR szBlankName = TEXT(" . ");
- ULONG cchPath; /* length of path to message */
- BOOL fIsRead; /* TRUE if deleting a read message */
- DWORD dwErr;
- FLD_ValidateParameters(
- pifld,
- IMAPIFolder,
- DeleteMessages,
- (pifld,
- lpMsgList,
- ulUIParam,
- lpProgress,
- ulFlags));
- IFLD_EnterCriticalSection(pifld);
- if (!OBJ_TestFlag(pifld, OBJF_MODIFY))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- hr = HrFullPathName(pifld->pims->szStorePath, pifld->peid->szPath,
- szBlankName, &szToDeleteName);
- if (hr != hrSuccess)
- goto exit;
- cchPath = lstrlen(szToDeleteName) - lstrlen(szBlankName);
- /* delete each message in lpMsgList up until the first error */
- while ((ULONG) cDeleted < lpMsgList->cValues)
- {
- peidToDelete = (PEID) (lpMsgList->lpbin[cDeleted].lpb);
- /* make sure that this is a message's eid */
- if (!FIsMessage(peidToDelete))
- {
- hr = ResultFromScode(MAPI_E_INVALID_PARAMETER);
- goto exit;
- }
- /* make sure the message is not submitted */
- if (FIsSubmittedMessage(pifld->pims, peidToDelete))
- {
- hr = ResultFromScode(MAPI_E_SUBMITTED);
- goto exit;
- }
- /* See if it has been read */
- hr = HrIsRead(pifld, peidToDelete, &fIsRead);
- if (hr != hrSuccess)
- goto exit;
- /* remove the message from disk */
- lstrcpy(szToDeleteName + cchPath, SzBaseName(peidToDelete));
- if (!DeleteFile(szToDeleteName))
- {
- dwErr = GetLastError();
- if ((dwErr != ERROR_FILE_NOT_FOUND && dwErr != ERROR_PATH_NOT_FOUND)
- || lpMsgList->cValues == 1)
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- }
- /* remove this message from any open tables */
- ChangeTable(pifld->pims, pifld->peid, peidToDelete, MAPI_MESSAGE,
- TABLE_ROW_DELETED, TRUE);
- if (!fIsRead)
- cUnreadDeleted++;
- cDeleted++;
- }
- exit:
- FreeNull(szToDeleteName);
- if (cDeleted)
- (void) HrIncrementOneROProp(pifld, -cDeleted, PR_CONTENT_COUNT);
- if (cUnreadDeleted)
- (void) HrIncrementOneROProp(pifld, -cUnreadDeleted, PR_CONTENT_UNREAD);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_DeleteMessages, hr);
- return HrCheckHr(hr, IMAPIFolder_DeleteMessages);
- }
- /***************************************************************************
- - IFLD_CreateFolder
- -
- * Purpose:
- * Create a new folder within the message store
- *
- * Parameters
- * pifld the parent folder of the newly created folder
- * ulFldType type of folder to be created
- * szFldName name of the new folder
- * szComment comment string for the new folder
- * piid Reserved; must be NULL.
- * ulFlags MAPI_UNICODE and/or MAPI_DEFERRED_ERRORS
- * lppfolder pointer to variable to receive new folder object
- *
- */
- STDMETHODIMP IFLD_CreateFolder(PIFLD pifld, ULONG ulFldType, LPSTR szFldName,
- LPSTR szComment, LPCIID piid, ULONG ulFlags, LPMAPIFOLDER *lppfolder)
- {
- HRESULT hr;
- PIFLD pifldNew = NULL;
- FLD_ValidateParameters(
- pifld,
- IMAPIFolder,
- CreateFolder,
- (pifld,
- ulFldType,
- szFldName,
- szComment,
- piid,
- ulFlags,
- lppfolder));
- #ifdef VALIDATE
- if (ulFlags & MAPI_UNICODE)
- return ResultFromScode(MAPI_E_BAD_CHARWIDTH);
- if (piid && !FQueryInterface(OT_FOLDER, piid))
- return ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
- #endif
- /* Sample store can only create generic folders. */
- if (ulFldType != FOLDER_GENERIC)
- return ResultFromScode(MAPI_E_NO_SUPPORT);
- IFLD_EnterCriticalSection(pifld);
- if (!OBJ_TestFlag(pifld, OBJF_MODIFY))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- hr = HrCreateFolder(pifld, szFldName, szComment,
- !!(ulFlags & OPEN_IF_EXISTS), &pifldNew, NULL);
- if (hr != hrSuccess)
- UlRelease(pifldNew);
- else
- *lppfolder = (LPMAPIFOLDER) pifldNew;
- exit:
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_CreateFolder, hr);
- return HrCheckHr(hr, IMAPIFolder_CreateFolder);
- }
- /***************************************************************************
- - IFLD_CopyFolder
- -
- * Purpose:
- * Copy my child folder to the specified parent
- *
- * Parameters
- * pifld the parent folder of the newly created folder
- * cbEntryID length of entry ID of folder to copy
- * lpEntryID entry ID of folder to copy
- * lpiid interface to the destination folder
- * lpfolder pointer to destination object
- * szNewName new name to give the copied folder, may be NULL
- * ulUIParam Handle of parent window,
- * ignored if MESSAGE_DIALOG not set
- * lpProgress points to progress dialog information
- * ulFlags control flags
- *
- */
- STDMETHODIMP IFLD_CopyFolder(PIFLD pifld, ULONG cbEntryID, LPENTRYID lpEntryID,
- LPCIID piid, LPVOID lpfolder, LPSTR szNewName,
- ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
- {
- HRESULT hr;
- FLD_ValidateParameters(
- pifld,
- IMAPIFolder,
- CopyFolder,
- (pifld,
- cbEntryID,
- lpEntryID,
- piid,
- lpfolder,
- szNewName,
- ulUIParam,
- lpProgress,
- ulFlags));
- #ifdef VALIDATE
- if (ulFlags & MAPI_UNICODE)
- return ResultFromScode(MAPI_E_BAD_CHARWIDTH);
- #endif
- /* For now, all we do is call back to mapi. */
- hr = pifld->pims->psup->lpVtbl->CopyFolder(pifld->pims->psup,
- (LPIID) &IID_IMAPIFolder, (LPVOID) pifld, cbEntryID, lpEntryID,
- piid, lpfolder, szNewName, ulUIParam, lpProgress, ulFlags);
- DebugTraceResult(IFLD_CopyFolder, hr);
- return HrCheckHr(hr, IMAPIFolder_CopyFolder);
- }
- /***************************************************************************
- - IFLD_DeleteFolder
- -
- * Purpose:
- * Deletes a subfolder
- *
- * Parameters
- * pifld the current folder
- * cbEntryID byte count of lpEntryID
- * lpEntryID entryID of subfolder to be deleted
- * ulUIParam handle to main window cast to ULONG
- * lpProgress pointer to progess dialog information
- * ulFlags DEL_MESSAGES and/or DEL_FOLDERS
- * and/or FOLDER_DIALOG
- *
- * Returns:
- *
- * Errors:
- */
- STDMETHODIMP IFLD_DeleteFolder(PIFLD pifld, ULONG cbEntryID,
- LPENTRYID lpEntryID, ULONG ulUIParam, LPMAPIPROGRESS lpProgress,
- ULONG ulFlags)
- {
- HRESULT hr = hrSuccess;
- FLD_ValidateParameters(
- pifld,
- IMAPIFolder,
- DeleteFolder,
- (pifld,
- cbEntryID,
- lpEntryID,
- ulUIParam,
- lpProgress,
- ulFlags));
- IFLD_EnterCriticalSection(pifld);
- if (FIsInvalidEID(cbEntryID, (PEID) lpEntryID, pifld->pims)
- || !FIsFolder((PEID) lpEntryID))
- {
- hr = ResultFromScode(MAPI_E_INVALID_ENTRYID);
- goto exit;
- }
- if (!OBJ_TestFlag(pifld, OBJF_MODIFY))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- /* delete this subdirectory of the current directory */
- hr = HrDeleteSubDirectory(pifld, (PEID) lpEntryID, ulFlags, FALSE);
- exit:
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_DeleteFolder, hr);
- return HrCheckHr(hr, IMAPIFolder_DeleteFolder);
- }
- STDMETHODIMP IFLD_SetSearchCriteria(PIFLD pifld, LPSRestriction lpRestriction,
- LPENTRYLIST lpentrylist, ULONG ulSearchFlags)
- {
- DebugTraceSc(IFLD_SetSearchCriteria, MAPI_E_NO_SUPPORT);
- return ResultFromScode(MAPI_E_NO_SUPPORT);
- }
- STDMETHODIMP IFLD_GetSearchCriteria(PIFLD pifld, ULONG ulFlags,
- LPSRestriction *lppRestriction, LPENTRYLIST *lppfolderList,
- ULONG *lpulSearchState)
- {
- DebugTraceSc(IFLD_GetSearchCriteria, MAPI_E_NO_SUPPORT);
- return ResultFromScode(MAPI_E_NO_SUPPORT);
- }
- /***************************************************************************
- - IFLD_SetReadFlags
- -
- * Purpose:
- * Sets the READ flag for each of the given messages.
- *
- * Parameters
- * pifld the source folder
- * lpMsgList the list of messages to be moved/copied
- * ulUIParam Handle of parent window,
- * ignored if MESSAGE_DIALOG not set
- * lpProgress points to progress dialog object
- * ulFlags SUPPRESS_RECEIPT, CLEAR_READ_FLAG
- */
- STDMETHODIMP IFLD_SetReadFlags(PIFLD pifld, LPENTRYLIST lpMsgList,
- ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
- {
- HRESULT hr = hrSuccess;
- LPENTRYLIST pelst = NULL;
- BOOL fFreeList = FALSE;
- SBinary *psb;
- SBinary *psbMax;
- BOOL fMultipleNotifs = TRUE;
- FLD_ValidateParameters(
- pifld,
- IMAPIFolder,
- SetReadFlags,
- (pifld,
- lpMsgList,
- ulUIParam,
- lpProgress,
- ulFlags));
- IFLD_EnterCriticalSection(pifld);
- if (!OBJ_TestFlag(pifld, OBJF_MODIFY))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- pelst = lpMsgList;
- if (pelst == NULL)
- {
- /* Create the message list if the caller didn't give us one. */
- hr = HrCreateMessageList(pifld, &pelst);
- if (hr != hrSuccess)
- goto exit;
- fFreeList = TRUE;
- }
- if (pelst->cValues > 5)
- fMultipleNotifs = FALSE;
- psb = pelst->lpbin;
- psbMax = psb + pelst->cValues;
- /* Call IMessage::SetReadFlag on each message */
- while (psb < psbMax)
- {
- ULONG ulObjType;
- PIMSG pimsg;
- PEID peid;
- ULONG cbEntryID;
- cbEntryID = psb->cb;
- peid = (PEID) (psb->lpb);
- if ( FIsInvalidEID(cbEntryID, peid, pifld->pims)
- || !FIsMessage((PEID) peid))
- {
- hr = ResultFromScode(MAPI_E_INVALID_PARAMETER);
- goto exit;
- }
- /* open the message */
- hr = pifld->lpVtbl->OpenEntry(pifld, CbEID(peid),
- (LPENTRYID) peid, NULL, 0L, &ulObjType,
- (LPUNKNOWN *) &pimsg);
- if (hr != hrSuccess)
- goto exit;
- Assert(ulObjType == MAPI_MESSAGE);
- hr = pimsg->lpVtbl->SetReadFlag(pimsg, ulFlags);
- if (hr == hrSuccess && fMultipleNotifs)
- ChangeTable(pimsg->pims, pifld->peid, pimsg->peid, MAPI_MESSAGE,
- TABLE_ROW_MODIFIED, TRUE);
- UlRelease(pimsg);
- if (hr != hrSuccess)
- goto exit;
- psb++;
- }
- /* If several messages changed, then just send one notification to */
- /* re-sync the entire contents table on other processes. */
- if (!fMultipleNotifs)
- ChangeTable(pifld->pims, pifld->peid, NULL, MAPI_MESSAGE,
- TABLE_CHANGED, TRUE);
- exit:
- if (fFreeList)
- DestroyMessageList(&pifld->pims->lmr, &pelst);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_SetReadFlags, hr);
- return HrCheckHr(hr, IMAPIFolder_SetReadFlags);
- }
- /***************************************************************************
- - GetMessageStatus
- -
- * Purpose:
- * Retrieves the status associated with a message in a folder
- *
- * Parameters
- * pifld the current folder
- * cbEntryID byte count of lpEntryID
- * lpEntryID entryID of the message
- * ulFlags reserved for future use, must be 0
- * lpulMessageStatus pointer to variable to receive the status
- *
- */
- STDMETHODIMP IFLD_GetMessageStatus(PIFLD pifld, ULONG cbEntryID,
- LPENTRYID lpEntryID, ULONG ulFlags, ULONG *lpulMessageStatus)
- {
- LPMESSAGE lpmsgMsg = NULL; /* lpEntryID as an open message */
- ULONG ulObjType; /* type of object opened */
- HRESULT hr = hrSuccess;
- FLD_ValidateParameters(
- pifld,
- IMAPIFolder,
- GetMessageStatus,
- (pifld,
- cbEntryID,
- lpEntryID,
- ulFlags,
- lpulMessageStatus));
- IFLD_EnterCriticalSection(pifld);
- if (FIsInvalidEID(cbEntryID, (PEID) lpEntryID, pifld->pims)
- || !FIsMessage((PEID) lpEntryID))
- {
- hr = ResultFromScode(MAPI_E_INVALID_ENTRYID);
- goto exit;
- }
- /* open up lpEntryID */
- hr = pifld->lpVtbl->OpenEntry(pifld, cbEntryID,
- lpEntryID, NULL, 0L, &ulObjType, (LPUNKNOWN *) &lpmsgMsg);
- if (hr != hrSuccess)
- goto exit;
- /* get the property */
- hr = HrGetSingleProp((LPMAPIPROP) lpmsgMsg, &pifld->pims->lmr,
- PR_MSG_STATUS, lpulMessageStatus);
- if (hr != hrSuccess)
- goto exit;
- exit:
- UlRelease(lpmsgMsg);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_GetMessageStatus, hr);
- return HrCheckHr(hr, IMAPIFolder_GetMessageStatus);
- }
- /***************************************************************************
- - SetMessageStatus
- -
- * Purpose:
- * Sets the 32-bit status associated with a message in a folder
- *
- * Parameters
- * pifld the current folder
- * cbEntryID byte count of lpentryID
- * lpEntryID entryID of the message
- * ulNewStatus new status to be assigned
- * ulNewStatusMask mask applied to new status indicating bits to set
- * lpulOldStatus pointer to variable to hold previous status
- *
- */
- STDMETHODIMP IFLD_SetMessageStatus(PIFLD pifld, ULONG cbEntryID,
- LPENTRYID lpEntryID, ULONG ulNewStatus, ULONG ulNewStatusMask,
- ULONG *lpulOldStatus)
- {
- PIMSG pimsg = NULL;
- LPMESSAGE lpmsg;
- ULONG ulObjType; /* type of object just opened */
- HRESULT hr = hrSuccess;
- ULONG ulStatus;
- FLD_ValidateParameters(
- pifld,
- IMAPIFolder,
- SetMessageStatus,
- (pifld,
- cbEntryID,
- lpEntryID,
- ulNewStatus,
- ulNewStatusMask,
- lpulOldStatus));
- IFLD_EnterCriticalSection(pifld);
- if (FIsInvalidEID(cbEntryID, (PEID) lpEntryID, pifld->pims) ||
- !FIsMessage((PEID) lpEntryID))
- {
- hr = ResultFromScode(MAPI_E_INVALID_ENTRYID);
- goto exit;
- }
- if ( ulNewStatusMask
- && !OBJ_TestFlag(pifld, OBJF_MODIFY))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- /* open up lpEntryID */
- hr = pifld->lpVtbl->OpenEntry(pifld, CbEID((PEID) lpEntryID),
- lpEntryID, NULL, 0L, &ulObjType, (LPUNKNOWN *) &pimsg);
- if (hr != hrSuccess)
- goto exit;
- lpmsg = pimsg->lpmsg;
- /* get the old status */
- hr = HrGetSingleProp((LPMAPIPROP) lpmsg, &pifld->pims->lmr,
- PR_MSG_STATUS, &ulStatus);
- if (hr != hrSuccess)
- goto exit;
- if (lpulOldStatus)
- *lpulOldStatus = ulStatus;
- if (ulNewStatusMask)
- {
- ulNewStatus &= ulNewStatusMask;
- ulStatus &= ~ulNewStatusMask;
- ulStatus |= ulNewStatus;
- hr = HrSetOneROProp(lpmsg, &pifld->pims->lmr, PR_MSG_STATUS,
- &ulStatus);
- if (hr != hrSuccess)
- goto exit;
- hr = lpmsg->lpVtbl->SaveChanges(lpmsg, KEEP_OPEN_READWRITE);
- UlRelease(pimsg);
- pimsg = NULL;
- if (hr != hrSuccess)
- goto exit;
- ChangeTable(pifld->pims, pifld->peid, (PEID) lpEntryID, MAPI_MESSAGE,
- TABLE_ROW_MODIFIED, TRUE);
- }
- exit:
- UlRelease(pimsg);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_SetMessageStatus, hr);
- return HrCheckHr(hr, IMAPIFolder_SetMessageStatus);
- }
- /***************************************************************************
- - IFLD_SaveContentsSort
- -
- * Purpose:
- * set default sort order for contents tables on pifld
- *
- * Parameters
- * pifld the current folder
- * lpSortCriteria points to the sort criteria
- * ulFlags RECURSIVE_SORT
- *
- */
- STDMETHODIMP IFLD_SaveContentsSort(PIFLD pifld, LPSSortOrderSet lpSortCriteria,
- ULONG ulFlags)
- {
- SPropValue pval; /* sort order property value */
- LPSPropProblemArray pprba = NULL;
- HRESULT hr = hrSuccess;
- FLD_ValidateParameters(
- pifld,
- IMAPIFolder,
- SaveContentsSort,
- (pifld,
- lpSortCriteria,
- ulFlags));
- IFLD_EnterCriticalSection(pifld);
- pval.Value.MVl.lpl = NULL;
- /* store the sort order in pval */
- pval.ulPropTag = PR_SMS_CONTENTS_SORT_ORDER;
- pval.Value.MVl.cValues = 2 * lpSortCriteria->cSorts;
- pval.Value.MVl.lpl = (LONG *) lpSortCriteria->aSort;
- /* set the sort order property */
- hr = pifld->lpVtbl->SetProps(pifld, 1, &pval, &pprba);
- if (pprba)
- {
- LMFree(&pifld->pims->lmr, pprba);
- hr = ResultFromScode(MAPI_E_CALL_FAILED);
- }
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_SaveContentsSort, hr);
- return HrCheckHr(hr, IMAPIFolder_SaveContentsSort);
- }
- /*
- * IFLD_EmptyFolder
- *
- * Purpose:
- * This function empties a folder based on the flags given. It will never
- * actually delete the folder itself, and will only empty the specified
- * items.
- *
- * Parameters
- * pifld The address of the folder object to empty.
- * ulUIParam Handle of the parent window. (for progress). NYI
- * lpProgress Address of progress dialog object
- * ulFlags Control flags. Setting DEL_ASSOCIATED causes FAI
- * to also be deleted. The FOLDER_DIALOG flag is NYI.
- * DEL_ASSOCIATED has no meaning to the sample store.
- *
- * Returns:
- */
- STDMETHODIMP IFLD_EmptyFolder(PIFLD pifld, ULONG ulUIParam,
- LPMAPIPROGRESS lpProgress, ULONG ulFlags)
- {
- HRESULT hr;
- PIFLD pifldParent = NULL;
- FLD_ValidateParameters(
- pifld,
- IMAPIFolder,
- EmptyFolder,
- (pifld,
- ulUIParam,
- lpProgress,
- ulFlags));
- IFLD_EnterCriticalSection(pifld);
- if (!OBJ_TestFlag(pifld, OBJF_MODIFY))
- {
- hr = ResultFromScode(MAPI_E_NO_ACCESS);
- goto exit;
- }
- /* Empty the folder. */
- hr = HrOpenParent(pifld->pims, pifld->peid, MAPI_MODIFY, &pifldParent);
- if (hr != hrSuccess)
- goto exit;
- hr = HrDeleteSubDirectory(pifldParent, pifld->peid,
- (DEL_MESSAGES | DEL_FOLDERS), TRUE);
- if (hr != hrSuccess)
- goto exit;
- exit:
- UlRelease(pifldParent);
- IFLD_LeaveCriticalSection(pifld);
- DebugTraceResult(IFLD_EmptyFolder, hr);
- return HrCheckHr(hr, IMAPIFolder_EmptyFolder);
- }
- /****************************************************
- * Private Functions *
- ****************************************************/
- /*
- * IFLD_IsInvalid
- *
- * Purpose check if pifld points to an invalid folder.
- *
- * Parameter
- * pifld pointer to the folder
- *
- * Returns: BOOL - TRUE means the folder is invalid.
- */
- static BOOL IFLD_IsInvalid(PIFLD pifld)
- {
- return (IsBadWritePtr(pifld, sizeof(IFLD)) ||
- pifld->lpVtbl != &vtblIFLD);
- }
- /*
- * HrCreateContTblMutex
- *
- * Purpose
- * Create the contents table mutex, and return it to the caller.
- *
- * Arguments
- * phCTMutex: Pointer to the location to return the new mutex.
- *
- * Returns:
- * HRESULT: Will return an error only if the CreateMutex call fails.
- */
- static HRESULT HrCreateContTblMutex(HANDLE *phCTMutex)
- {
- HRESULT hr = hrSuccess;
- HANDLE hMutex;
- LPTSTR szMutexName = "SMS_CONTTBLFILE_MUTEX";
- hMutex = CreateMutex(NULL, FALSE, szMutexName);
- if (hMutex)
- *phCTMutex = hMutex;
- #ifndef WIN16
- else
- {
- TraceSz1("SampleMS: HrCreateContTblMutex: call to"
- " CreateMutex failed (error %08lX)", GetLastError());
- hr = ResultFromScode(MAPI_E_CALL_FAILED);
- }
- #endif
- DebugTraceResult(HrCreateContTblMutex, hr);
- return hr;
- }
- /*
- * FFoldInSameStore
- *
- * Purpose
- * Given that the source folder is a folder object within
- * our store (i.e. it's a PIFLD, not LPMAPIFOLDER), check if the
- * destination folder object is also within the same store.
- *
- * Parameters
- * pifld: The folder that we already know is within this store.
- * lpDestFld: The folder that we are checking. It may not be in this store.
- *
- * Returns: BOOL - TRUE means the folders are both in this store.
- *
- */
- static BOOL FFoldInSameStore(PIFLD pifld, PIFLD lpDestFld)
- {
- if (IsBadWritePtr(lpDestFld, sizeof(IFLD)))
- return FALSE;
- if (lpDestFld->lpVtbl != &vtblIFLD)
- return FALSE;
- if (pifld->pims != lpDestFld->pims)
- return FALSE;
- return TRUE;
- }
- /***************************************************************************
- * IFLD_Neuter
- *
- * Purpose Free all memory allocated inside a folder object, and release
- * any objects held inside a folder object. Leaves the object
- * itself alone (the caller will free it).
- *
- * Argument pifld the folder to be cleaned out.
- *
- */
- void IFLD_Neuter(PIFLD pifld)
- {
- /* free allocated memory */
- FreeNull(pifld->peid);
- LMFree(&pifld->pims->lmr, pifld->pval);
- /* remove any tables */
- if (pifld->lptblContents)
- {
- TraceSz1("SampleMS (IFLD_Neuter): %d contents table views left",
- pifld->cContentsViews);
- UlRelease(pifld->lptblContents);
- pifld->cContentsViews = 0;
- pifld->lptblContents = NULL;
- }
- if (pifld->lptblHierarchy)
- {
- TraceSz1("SampleMS (IFLD_Neuter): %d hierarchy table views left",
- pifld->cHierarchyViews);
- UlRelease(pifld->lptblHierarchy);
- pifld->cHierarchyViews = 0;
- pifld->lptblHierarchy = NULL;
- }
- return;
- }
- /*
- - ViewRelease
- -
- * Purpose:
- * Call back function from itable on release of a view
- * removes the view from the list of open views
- * releases the table if there are no more open views on it
- *
- * Parameters
- * ulCallerData pointer to folder object
- * lptbl pointer to the table on which this is a view
- * lpvtView pointer to the view that was released
- *
- *
- */
- STDAPI_(void)ViewRelease(ULONG ulCallerData, LPTABLEDATA lptbl,
- LPMAPITABLE lpvtView)
- {
- PIFLD pifld; /* folder object for this view */
- ULONG *pulViewsLeft; /* ptr to number of open views left */
- LPTABLEDATA *pptbl; /* ptr to folder's internal table data */
- pifld = (PIFLD) ulCallerData;
- /* do nothing if the folder is invalid. Don't use IFLD_IsInvalid */
- /* because the folder may have already been released, and we still */
- /* want to release the view in that case. */
- if (IsBadWritePtr(pifld, sizeof(IFLD)))
- return;
- IFLD_EnterCriticalSection(pifld);
- /* find the kind of table this view is on */
- if (pifld->lptblContents == lptbl)
- {
- pulViewsLeft = &(pifld->cContentsViews);
- pptbl = &(pifld->lptblContents);
- }
- else if (pifld->lptblHierarchy == lptbl)
- {
- pulViewsLeft = &(pifld->cHierarchyViews);
- pptbl = &(pifld->lptblHierarchy);
- }
- else
- {
- /* invalid table */
- TrapSz("Invalid call to ViewRelease");
- goto exit;
- }
- AssertSz(*pptbl == lptbl, "Different table data given to ViewRelease");
- /* decrement count of views and release*/
- /* the table data if the viewlist is empty */
- if (--(*pulViewsLeft) == 0)
- {
- POBJ pobj = (POBJ) pifld;
- UlRelease(lptbl);
- *pptbl = NULL;
- /* These tests are the same as IFLD_Release in this module. That is */
- /* the release method that folders use. */
- if ( pobj->cRef == 0
- && pobj->pobjHead == 0
- && pifld->lptblContents == NULL
- && pifld->lptblHierarchy == NULL)
- {
- OBJ_Destroy(pobj); /* will leave the critical section */
- return;
- }
- }
- exit:
- IFLD_LeaveCriticalSection(pifld);
- return;
- }
- /*
- * HrIsRead
- *
- * Purpose
- * Given a parent folder and the entryid of a message, determine
- * whether the message has been read (i.e., whether the MSGFLAG_READ
- * bit inside the PR_MESSAGE_FLAGS property is set).
- *
- * Parameters
- * pifld A pointer to the parent folder object of the message.
- * peidMsg The entryid of the message.
- * pfRead A pointer to the location to return a BOOL saying
- * whether or not the message was read. Set to TRUE
- * if the message was read, FALSE otherwise.
- */
- static HRESULT HrIsRead(PIFLD pifld, PEID peidMsg, BOOL *pfRead)
- {
- HRESULT hr;
- PIMSG pimsg = NULL; /* opened version of lpidMsg */
- ULONG ulObjType; /* type of object opened */
- ULONG ulMF;
- /* open the message */
- hr = pifld->lpVtbl->OpenEntry(pifld, CbEID(peidMsg), (LPENTRYID) peidMsg,
- NULL, 0L, &ulObjType, (LPUNKNOWN *) &pimsg);
- if (hr != hrSuccess)
- goto exit;
- Assert(ulObjType == MAPI_MESSAGE);
- /* retrieve the PR_MESSAGE_FLAGS property */
- hr = HrGetSingleProp((LPMAPIPROP) pimsg->lpmsg, &pifld->pims->lmr,
- PR_MESSAGE_FLAGS, &ulMF);
- /* set pfRead: no PR_MESSAGE_FLAGS means unread */
- /* The "!!" operator is used to change a bit that is set anywhere in a */
- /* word to exactly TRUE (only one bit set at the far right of the word). */
- /* The first "!" is NOT, which makes all zeros in the value into TRUE, */
- /* and anything else into FALSE. The second "!" reverses that back, so */
- /* that all zeros become FALSE, and anything else becomes TRUE. */