MSPOBJ.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:8k
源码类别:
Windows编程
开发平台:
Visual C++
- /*
- * M S P O B J . C
- *
- * Common code for implementation of objects in the sample message store
- * provider.
- *
- * Copyright (C) 1992-1995 Microsoft Corporation. All Rights Reserved.
- */
- #include "msp.h"
- /* Object Type to Neuter Function Map -------------------------------------- */
- LPFNNEUTER rgfnNeuter[] =
- {
- (LPFNNEUTER) 0, /* IMSProvider */
- (LPFNNEUTER) 0, /* IMSLogon */
- (LPFNNEUTER) IMS_Neuter, /* IMsgStore */
- (LPFNNEUTER) IFLD_Neuter, /* IMAPIFolder */
- (LPFNNEUTER) IMSG_Neuter, /* IMessage */
- (LPFNNEUTER) IATCH_Neuter, /* IAttach */
- (LPFNNEUTER) 0, /* IStream */
- (LPFNNEUTER) 0, /* IMAPITable */
- };
- /* Object Type to Interfaces Supported Map --------------------------------- */
- REFIID MSP_IIDs[] =
- {
- &IID_IMSProvider,
- &IID_IUnknown
- };
- REFIID MSL_IIDs[] =
- {
- &IID_IMSLogon,
- &IID_IUnknown
- };
- REFIID MS_IIDs[] =
- {
- &IID_IMsgStore,
- &IID_IMAPIProp,
- &IID_IUnknown
- };
- REFIID FLD_IIDs[] =
- {
- &IID_IMAPIFolder,
- &IID_IMAPIContainer,
- &IID_IMAPIProp,
- &IID_IUnknown
- };
- REFIID MSG_IIDs[] =
- {
- &IID_IMessage,
- &IID_IMAPIProp,
- &IID_IUnknown
- };
- REFIID ATCH_IIDs[] =
- {
- &IID_IAttachment,
- &IID_IMAPIProp,
- &IID_IUnknown
- };
- REFIID STM_IIDs[] =
- {
- &IID_IStream,
- &IID_IUnknown
- };
- REFIID TBL_IIDs[] =
- {
- &IID_IMAPITable,
- &IID_IUnknown
- };
- REFIID *rgpriid[] =
- {
- MSP_IIDs,
- MSL_IIDs,
- MS_IIDs,
- FLD_IIDs,
- MSG_IIDs,
- ATCH_IIDs,
- STM_IIDs,
- TBL_IIDs
- };
- #define OBJ_IsInvalid(pobj, f)
- (IsBadWritePtr(pobj, sizeof(OBJ))
- || IsBadReadPtr((pobj)->lpVtbl, sizeof(OBJ_Vtbl))
- || (pobj)->lpVtbl->f != OBJ_##f
- || (pobj)->wType >= OT_MAX)
- /* OBJ_QueryInterface ------------------------------------------------------ */
- BOOL
- FQueryInterface(int wType, REFIID riid)
- {
- REFIID *priid = rgpriid[wType];
- while (1)
- {
- if (IsEqualGUID(riid, *priid))
- return (TRUE);
- if (*priid == &IID_IUnknown)
- break;
- priid += 1;
- }
- return (FALSE);
- }
- STDMETHODIMP
- OBJ_QueryInterface(POBJ pobj, REFIID riid, LPVOID * ppvObj)
- {
- if ( OBJ_IsInvalid(pobj, QueryInterface)
- || IsBadReadPtr(riid, sizeof(IID))
- || IsBadWritePtr(ppvObj, sizeof(LPVOID)))
- return ResultFromScode(E_INVALIDARG);
- /* Even if an error is returned, must zero *ppvObj */
- *ppvObj = 0;
- if (FQueryInterface(pobj->wType, riid))
- {
- UlAddRef(pobj);
- *ppvObj = pobj;
- return (0);
- }
- return (ResultFromScode(E_NOINTERFACE));
- }
- /* OBJ_AddRef -------------------------------------------------------------- */
- STDMETHODIMP_(ULONG) OBJ_AddRef(POBJ pobj)
- {
- LONG cRef;
- if (OBJ_IsInvalid(pobj, AddRef))
- {
- TraceSz1("Sample MS: OBJ_AddRef(pobj=%08lX): Object is invalid and "
- "is being ignored", pobj);
- return (0);
- }
- OBJ_EnterCriticalSection(pobj);
- #ifdef DEBUG
- if (pobj->wType == OT_MSGSTORE)
- Assert(!OBJ_TestFlag(pobj, MSF_BEINGDESTROYED));
- #endif
- AssertSz1( pobj->wType == OT_MSGSTORE
- || pobj->cRef >= 1, "OBJ_AddRef(): Bogus cRef (%08lX)", pobj->cRef);
- cRef = ++pobj->cRef;
- OBJ_LeaveCriticalSection(pobj);
- return (cRef);
- }
- /* OBJ_Release ------------------------------------------------------------- */
- /* Used by Message Store, Message, and Attachment objects. All other objects */
- /* have their own implementations of Release. */
- STDMETHODIMP_(ULONG) OBJ_Release(POBJ pobj)
- {
- LONG cRef;
- if (!pobj)
- return (0);
- if (OBJ_IsInvalid(pobj, Release))
- {
- TraceSz1("SampleMS: OBJ_Release(pobj=%08lX): Object is invalid and is "
- "being ignored", pobj);
- return (0);
- }
- OBJ_EnterCriticalSection(pobj);
- AssertSz(pobj->cRef > 0, "OBJ_Release(): Too many releases");
- cRef = --pobj->cRef;
- if (cRef == 0)
- {
- if (pobj->wType != OT_MSGSTORE)
- pobj->lpVtbl = 0;
- if (pobj->pobjHead == 0)
- {
- OBJ_Destroy(pobj);
- return (0);
- }
- }
- OBJ_LeaveCriticalSection(pobj);
- return (cRef);
- }
- /* OBJ_Enqueue / OBJ_Dequeue / OBJ_Destroy --------------------------------- */
- void OBJ_Enqueue(POBJ pobj, POBJ pobjParent)
- {
- pobj->pobjParent = pobjParent;
- pobj->pobjNext = pobjParent->pobjHead;
- pobjParent->pobjHead = pobj;
- }
- void OBJ_Dequeue(POBJ pobj)
- {
- if (pobj->pobjParent != NULL)
- {
- POBJ *ppobj = &pobj->pobjParent->pobjHead;
- while (TRUE)
- {
- POBJ pobjCur = *ppobj;
- if (pobjCur == NULL)
- break;
- if (pobjCur == pobj)
- {
- *ppobj = pobj->pobjNext;
- break;
- }
- ppobj = &pobjCur->pobjNext;
- }
- pobj->pobjParent = 0;
- }
- }
- /*
- * OBJ_Destroy
- *
- * Destroy an object. If this object was the last thing causing the parent to
- * exist, then we should destroy the parent, and so on up the chain. There are
- * two actual critical sections in the sample store. One is in the msp (message
- * store provider) object. The other is in the msl (message store logon) object.
- * All other objects in the sample store contain a pointer to the msl object's
- * critical section (they all share it). When we arrive at this routine, we
- * should have the object's critical section locked, i.e., the msl critical
- * section should be locked. That's why there are calls to leave a critical
- * section that aren't balanced with an enter.
- */
- void OBJ_Destroy(POBJ pobj)
- {
- PIMS pims;
- POBJ pobjParent;
- LPFNNEUTER lpfnNeuter;
- LPMAPISUP psup;
- pims = pobj->pims;
- while (1)
- {
- /* Call a routine to make the object free any memory */
- /* or other structures it has. (We call this "neutering" the object.) */
- if ((lpfnNeuter = rgfnNeuter[pobj->wType]) != 0)
- lpfnNeuter(pobj);
- pobjParent = pobj->pobjParent;
- if (pobj == (POBJ) pims)
- {
- if (pobjParent != NULL)
- {
- /* The parent in this case is the msp (message store provider) */
- /* object. We need to get its critical section in order to */
- /* safely dequeue the message store object. */
- OBJ_EnterCriticalSection(pobjParent);
- OBJ_Dequeue(pobj);
- OBJ_LeaveCriticalSection(pobjParent);
- }
- pobjParent = (POBJ) pims->pmsl;
- psup = pims->psup;
- pobj->lpVtbl = 0;
- LMFree(&pims->lmr, pobj);
- /* This leave balances the enter in the calling function. */
- /* Since we just freed the message store object, we can't leave */
- /* critical section using that pointer. Therefore, use the msl */
- /* (message store logon) object's critical section instead. They */
- /* are the same (see header comment at top of function). */
- OBJ_LeaveCriticalSection(pobjParent);
- UlRelease(psup); /* do this last */
- break;
- }
- OBJ_Dequeue(pobj);
- pobj->lpVtbl = 0;
- LMFree(&pims->lmr, pobj);
- pobj = pobjParent;
- if (pobj == 0 || pobj->cRef || pobj->pobjHead)
- {
- /* This leave balances the enter in the calling function. */
- OBJ_LeaveCriticalSection((POBJ) pims);
- break;
- }
- }
- }