MSPOBJ.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:8k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * M S P O B J . C
  3.  *
  4.  * Common code for implementation of objects in the sample message store
  5.  * provider.
  6.  *
  7.  * Copyright (C) 1992-1995 Microsoft Corporation. All Rights Reserved.
  8.  */
  9. #include "msp.h"
  10. /* Object Type to Neuter Function Map -------------------------------------- */
  11. LPFNNEUTER rgfnNeuter[] =
  12. {
  13.     (LPFNNEUTER) 0,             /* IMSProvider */
  14.     (LPFNNEUTER) 0,             /* IMSLogon */
  15.     (LPFNNEUTER) IMS_Neuter,    /* IMsgStore */
  16.     (LPFNNEUTER) IFLD_Neuter,   /* IMAPIFolder */
  17.     (LPFNNEUTER) IMSG_Neuter,   /* IMessage */
  18.     (LPFNNEUTER) IATCH_Neuter,  /* IAttach */
  19.     (LPFNNEUTER) 0,             /* IStream */
  20.     (LPFNNEUTER) 0,             /* IMAPITable */
  21. };
  22. /* Object Type to Interfaces Supported Map --------------------------------- */
  23. REFIID MSP_IIDs[] =
  24. {
  25.     &IID_IMSProvider,
  26.     &IID_IUnknown
  27. };
  28. REFIID MSL_IIDs[] =
  29. {
  30.     &IID_IMSLogon,
  31.     &IID_IUnknown
  32. };
  33. REFIID MS_IIDs[] =
  34. {
  35.     &IID_IMsgStore,
  36.     &IID_IMAPIProp,
  37.     &IID_IUnknown
  38. };
  39. REFIID FLD_IIDs[] =
  40. {
  41.     &IID_IMAPIFolder,
  42.     &IID_IMAPIContainer,
  43.     &IID_IMAPIProp,
  44.     &IID_IUnknown
  45. };
  46. REFIID MSG_IIDs[] =
  47. {
  48.     &IID_IMessage,
  49.     &IID_IMAPIProp,
  50.     &IID_IUnknown
  51. };
  52. REFIID ATCH_IIDs[] =
  53. {
  54.     &IID_IAttachment,
  55.     &IID_IMAPIProp,
  56.     &IID_IUnknown
  57. };
  58. REFIID STM_IIDs[] =
  59. {
  60.     &IID_IStream,
  61.     &IID_IUnknown
  62. };
  63. REFIID TBL_IIDs[] =
  64. {
  65.     &IID_IMAPITable,
  66.     &IID_IUnknown
  67. };
  68. REFIID *rgpriid[] =
  69. {
  70.     MSP_IIDs,
  71.     MSL_IIDs,
  72.     MS_IIDs,
  73.     FLD_IIDs,
  74.     MSG_IIDs,
  75.     ATCH_IIDs,
  76.     STM_IIDs,
  77.     TBL_IIDs
  78. };
  79. #define OBJ_IsInvalid(pobj, f)                                  
  80.     (IsBadWritePtr(pobj, sizeof(OBJ))                           
  81.     || IsBadReadPtr((pobj)->lpVtbl, sizeof(OBJ_Vtbl))           
  82.     || (pobj)->lpVtbl->f != OBJ_##f                             
  83.     || (pobj)->wType >= OT_MAX)
  84. /* OBJ_QueryInterface ------------------------------------------------------ */
  85. BOOL 
  86. FQueryInterface(int wType, REFIID riid)
  87. {
  88.     REFIID *priid = rgpriid[wType];
  89.     while (1)
  90.     {
  91.         if (IsEqualGUID(riid, *priid))
  92.             return (TRUE);
  93.         if (*priid == &IID_IUnknown)
  94.             break;
  95.         priid += 1;
  96.     }
  97.     return (FALSE);
  98. }
  99. STDMETHODIMP 
  100. OBJ_QueryInterface(POBJ pobj, REFIID riid, LPVOID * ppvObj)
  101. {
  102.     if (    OBJ_IsInvalid(pobj, QueryInterface)
  103.         ||  IsBadReadPtr(riid, sizeof(IID))
  104.         ||  IsBadWritePtr(ppvObj, sizeof(LPVOID)))
  105.         return ResultFromScode(E_INVALIDARG);
  106.     /* Even if an error is returned, must zero *ppvObj */
  107.     *ppvObj = 0;
  108.     if (FQueryInterface(pobj->wType, riid))
  109.     {
  110.         UlAddRef(pobj);
  111.         *ppvObj = pobj;
  112.         return (0);
  113.     }
  114.     return (ResultFromScode(E_NOINTERFACE));
  115. }
  116. /* OBJ_AddRef -------------------------------------------------------------- */
  117. STDMETHODIMP_(ULONG) OBJ_AddRef(POBJ pobj)
  118. {
  119.     LONG cRef;
  120.     if (OBJ_IsInvalid(pobj, AddRef))
  121.     {
  122.         TraceSz1("Sample MS: OBJ_AddRef(pobj=%08lX): Object is invalid and "
  123.             "is being ignored", pobj);
  124.         return (0);
  125.     }
  126.     OBJ_EnterCriticalSection(pobj);
  127. #ifdef DEBUG
  128.     if (pobj->wType == OT_MSGSTORE)
  129.         Assert(!OBJ_TestFlag(pobj, MSF_BEINGDESTROYED));
  130. #endif
  131.     AssertSz1(      pobj->wType == OT_MSGSTORE
  132.               ||    pobj->cRef >= 1, "OBJ_AddRef(): Bogus cRef (%08lX)", pobj->cRef);
  133.     cRef = ++pobj->cRef;
  134.     OBJ_LeaveCriticalSection(pobj);
  135.     return (cRef);
  136. }
  137. /* OBJ_Release ------------------------------------------------------------- */
  138. /* Used by Message Store, Message, and Attachment objects. All other objects */
  139. /* have their own implementations of Release. */
  140. STDMETHODIMP_(ULONG) OBJ_Release(POBJ pobj)
  141. {
  142.     LONG cRef;
  143.     if (!pobj)
  144.         return (0);
  145.     if (OBJ_IsInvalid(pobj, Release))
  146.     {
  147.         TraceSz1("SampleMS: OBJ_Release(pobj=%08lX): Object is invalid and is "
  148.             "being ignored", pobj);
  149.         return (0);
  150.     }
  151.     OBJ_EnterCriticalSection(pobj);
  152.     AssertSz(pobj->cRef > 0, "OBJ_Release(): Too many releases");
  153.     cRef = --pobj->cRef;
  154.     if (cRef == 0)
  155.     {
  156.         if (pobj->wType != OT_MSGSTORE)
  157.             pobj->lpVtbl = 0;
  158.         if (pobj->pobjHead == 0)
  159.         {
  160.             OBJ_Destroy(pobj);
  161.             return (0);
  162.         }
  163.     }
  164.     OBJ_LeaveCriticalSection(pobj);
  165.     return (cRef);
  166. }
  167. /* OBJ_Enqueue / OBJ_Dequeue / OBJ_Destroy --------------------------------- */
  168. void OBJ_Enqueue(POBJ pobj, POBJ pobjParent)
  169. {
  170.     pobj->pobjParent = pobjParent;
  171.     pobj->pobjNext = pobjParent->pobjHead;
  172.     pobjParent->pobjHead = pobj;
  173. }
  174. void OBJ_Dequeue(POBJ pobj)
  175. {
  176.     if (pobj->pobjParent != NULL)
  177.     {
  178.         POBJ *ppobj = &pobj->pobjParent->pobjHead;
  179.         while (TRUE)
  180.         {
  181.             POBJ pobjCur = *ppobj;
  182.             if (pobjCur == NULL)
  183.                 break;
  184.             if (pobjCur == pobj)
  185.             {
  186.                 *ppobj = pobj->pobjNext;
  187.                 break;
  188.             }
  189.             ppobj = &pobjCur->pobjNext;
  190.         }
  191.         pobj->pobjParent = 0;
  192.     }
  193. }
  194. /* 
  195.  * OBJ_Destroy
  196.  * 
  197.  * Destroy an object. If this object was the last thing causing the parent to
  198.  * exist, then we should destroy the parent, and so on up the chain. There are
  199.  * two actual critical sections in the sample store. One is in the msp (message
  200.  * store provider) object. The other is in the msl (message store logon) object.
  201.  * All other objects in the sample store contain a pointer to the msl object's 
  202.  * critical section (they all share it). When we arrive at this routine, we 
  203.  * should have the object's critical section locked, i.e., the msl critical
  204.  * section should be locked. That's why there are calls to leave a critical
  205.  * section that aren't balanced with an enter.
  206.  */
  207. void OBJ_Destroy(POBJ pobj)
  208. {
  209.     PIMS pims;
  210.     POBJ pobjParent;
  211.     LPFNNEUTER lpfnNeuter;
  212.     LPMAPISUP psup;
  213.     pims = pobj->pims;
  214.     while (1)
  215.     {
  216.         /* Call a routine to make the object free any memory */
  217.         /* or other structures it has. (We call this "neutering" the object.) */
  218.         if ((lpfnNeuter = rgfnNeuter[pobj->wType]) != 0)
  219.             lpfnNeuter(pobj);
  220.         pobjParent = pobj->pobjParent;
  221.         if (pobj == (POBJ) pims)
  222.         {
  223.             if (pobjParent != NULL)
  224.             {
  225.                 /* The parent in this case is the msp (message store provider) */
  226.                 /* object. We need to get its critical section in order to */
  227.                 /* safely dequeue the message store object. */
  228.                 OBJ_EnterCriticalSection(pobjParent);
  229.                 OBJ_Dequeue(pobj);
  230.                 OBJ_LeaveCriticalSection(pobjParent);
  231.             }
  232.             pobjParent = (POBJ) pims->pmsl;
  233.             psup = pims->psup;
  234.             pobj->lpVtbl = 0;
  235.             LMFree(&pims->lmr, pobj);
  236.             /* This leave balances the enter in the calling function. */
  237.             /* Since we just freed the message store object, we can't leave */
  238.             /* critical section using that pointer. Therefore, use the msl */
  239.             /* (message store logon) object's critical section instead. They */
  240.             /* are the same (see header comment at top of function). */
  241.             OBJ_LeaveCriticalSection(pobjParent);
  242.             UlRelease(psup);    /* do this last */
  243.             break;
  244.         }
  245.         OBJ_Dequeue(pobj);
  246.         pobj->lpVtbl = 0;
  247.         LMFree(&pims->lmr, pobj);
  248.         pobj = pobjParent;
  249.         if (pobj == 0 || pobj->cRef || pobj->pobjHead)
  250.         {
  251.             /* This leave balances the enter in the calling function. */
  252.             OBJ_LeaveCriticalSection((POBJ) pims);
  253.             break;
  254.         }
  255.     }
  256. }