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

Windows编程

开发平台:

Visual C++

  1. /*
  2.  *  M S P A T C H . C
  3.  *
  4.  *  Code for the MAPI Sample Store Provider implementation of the
  5.  *  IAttach object.  The implementation is, in reality, a thin
  6.  *  wrapping layer around the implementation of IMessage on
  7.  *  IStorage.  We wrap the IAttach object returned by IMsgOnIStg so
  8.  *  that we can handle those methods (like GetLastError) not
  9.  *  understood by a standalone attachment (e.g. one embedded in a
  10.  *  word document) but which makes sense for a message in the
  11.  *  context of a message store.
  12.  *
  13.  *  Copyright 1992-1995 Microsoft Corporation.  All Rights Reserved.
  14.  */
  15. #include "msp.h"
  16. #define ATCH_ValidateParameters(pobj, intf, method, arglist)        
  17.         OBJ_ValidateParameters(pobj, intf, method, sizeof(IATCH), &vtblIATCH, arglist)
  18. #define IATCH_EnterCriticalSection(piatch) OBJ_EnterCriticalSection((POBJ)piatch)
  19. #define IATCH_LeaveCriticalSection(piatch) OBJ_LeaveCriticalSection((POBJ)piatch)
  20. /* Manifest constants */
  21. #define cInitIATCHProps         3
  22. #define grfInitIATCHPropAttr    (PROPATTR_MANDATORY | PROPATTR_READABLE)
  23. /* Global variables */
  24. /* Dispatch table for IAttach objects */
  25. IATCH_Vtbl vtblIATCH =
  26. {
  27.     (IATCH_QueryInterface_METHOD *)     OBJ_QueryInterface,
  28.     (IATCH_AddRef_METHOD *)             OBJ_AddRef,
  29.     (IATCH_Release_METHOD *)            OBJ_Release,
  30.     (IATCH_GetLastError_METHOD *)       IMS_GetLastError,
  31.     IATCH_SaveChanges,
  32.     IATCH_GetProps,
  33.     IATCH_GetPropList,
  34.     IATCH_OpenProperty,
  35.     IATCH_SetProps,
  36.     IATCH_DeleteProps,
  37.     IATCH_CopyTo,
  38.     IATCH_CopyProps,
  39.     (IATCH_GetNamesFromIDs_METHOD *)    IMS_GetNamesFromIDs,
  40.     (IATCH_GetIDsFromNames_METHOD *)    IMS_GetIDsFromNames
  41. };
  42. /*
  43.  *  Object methods
  44.  */
  45. /*
  46.  *  IATCH_SaveChanges
  47.  *
  48.  *  Purpose:
  49.  *      Saves changes made to an attachment object and all of its
  50.  *      sub-objects (messages, et al.).  Since the IMessage on
  51.  *      IStorage implementation handles the invalidation of objects
  52.  *      after SaveChanges is called, we do not need to worry about
  53.  *      it at this level.
  54.  *
  55.  *  Arguments:
  56.  *      piatch      Pointer to the object.
  57.  *      ulFlags     Flags.  The following are defined:
  58.  *                  KEEP_OPEN_READONLY  Do not invalidate the
  59.  *                                      object, make it read-only.
  60.  *                  KEEP_OPEN_READWRITE Don't invalidate the
  61.  *                                      object, keep it open
  62.  *                                      read/write.
  63.  *
  64.  *  Returns:
  65.  *      HRESULT
  66.  *
  67.  *  Side effects:
  68.  *      None.
  69.  *
  70.  *  Errors:
  71.  */
  72. STDMETHODIMP IATCH_SaveChanges(PIATCH piatch, ULONG ulFlags)
  73. {
  74.     HRESULT hr;
  75.     PIMSG pimsg;
  76.     PLMR plmr;
  77.     ATCH_ValidateParameters(
  78.             piatch,
  79.             IMAPIProp,
  80.             SaveChanges,
  81.             (piatch, 
  82.             ulFlags));
  83.     IATCH_EnterCriticalSection(piatch);
  84.     pimsg = (PIMSG) piatch->pobjParent;
  85.     plmr = &piatch->pims->lmr;
  86.     if (!OBJ_TestFlag(piatch, OBJF_MODIFY))
  87.     {
  88.         hr = ResultFromScode(MAPI_E_NO_ACCESS);
  89.         goto exit;
  90.     }
  91.     hr = piatch->lpattach->lpVtbl->SaveChanges(piatch->lpattach, ulFlags);
  92.     if (hr != hrSuccess)
  93.         goto exit;
  94.     if (!(ulFlags & KEEP_OPEN_READWRITE))
  95.         OBJ_ClearFlag(piatch, OBJF_MODIFY);
  96. exit:
  97.     IATCH_LeaveCriticalSection(piatch);
  98.     DebugTraceResult(IATCH_SaveChanges, hr);
  99.     return HrCheckHr(hr, IMAPIProp_SaveChanges);
  100. }
  101. /*
  102.  *  IATCH_GetProps
  103.  *
  104.  *  Purpose:
  105.  *      Returns to the caller the value(s) of one or more
  106.  *      properties existent on an IATCH object.  The order of the
  107.  *      properties in the returned lppPropArray structure exactly
  108.  *      matches the order in which the properties were requested in
  109.  *      lpPropTagArray.  The caller must free the returned
  110.  *      structure by calling MAPIFreeBuffer(*lppPropArray), but
  111.  *      only if the function returns zero or the error
  112.  *      MAPI_W_ERRORS_RETURNED.  Uses the IMessage on IStorage
  113.  *      property interface implementation.
  114.  *
  115.  *  Arguments:
  116.  *      piatch          Pointer to the object.
  117.  *       ptaga          Pointer to a counted array of property tags of
  118.  *                      properties requested
  119.  *       ulFlags        UNICODE / String8
  120.  *       pcval          Pointer to number of values returned
  121.  *       ppval          Pointer to a variable in which the address of the
  122.  *                      returned property values is placed
  123.  *
  124.  *  Returns:
  125.  *      HRESULT
  126.  *
  127.  *  Side effects:
  128.  *      None.
  129.  *
  130.  *  Errors:
  131.  *      If the call succeeded overall but access to one or more
  132.  *      properties failed, the function returns the warning
  133.  *      MAPI_W_ERRORS_RETURNED.  The calling application should
  134.  *      then check the Property Tag of each of the returned
  135.  *      properties to determine which ones failed.  Those that fail
  136.  *      have their Property Type set to PT_ERROR and their value (a
  137.  *      ULONG) indicates which error occurred.
  138.  *
  139.  *      MAPI_E_NO_ACCESS    The caller does not have access
  140.  *                                  to the requested properties.
  141.  *      MAPI_W_ERRORS_RETURNED      See above.
  142.  *      MAPI_E_CALL_FAILED          The mechanism for making the
  143.  *                                  call to the service provider
  144.  *                                  failed.
  145.  */
  146. STDMETHODIMP IATCH_GetProps(PIATCH piatch, LPSPropTagArray ptaga, ULONG ulFlags,
  147.     ULONG *pcval, LPSPropValue *ppval)
  148. {
  149.     HRESULT hr;
  150.     ATCH_ValidateParameters(
  151.             piatch,
  152.             IMAPIProp,
  153.             GetProps,
  154.             (piatch, 
  155.             ptaga, 
  156.             ulFlags,
  157.             pcval, 
  158.             ppval));
  159.     #ifdef VALIDATE
  160.     if (ulFlags & MAPI_UNICODE)
  161.         return ResultFromScode(MAPI_E_BAD_CHARWIDTH);
  162.     #endif
  163.         
  164.     IATCH_EnterCriticalSection(piatch);
  165.     /* Pass the call off to IMessage */
  166.     hr = piatch->lpattach->lpVtbl->GetProps(piatch->lpattach, ptaga, ulFlags, 
  167.             pcval, ppval);
  168.     /* Wrap specific store properties. Note that this function takes as an */
  169.     /* argument the HRESULT from the previous GetProps call. */
  170.     /* We aren't ignoring the error. */
  171.     hr = HrWrap_GetProps(hr, piatch->pims, 0, NULL, pcval, ppval, FALSE,
  172.         (ptaga != NULL), (POBJ)piatch);
  173.     IATCH_LeaveCriticalSection(piatch);
  174.     DebugTraceResult(IATCH_GetProps, hr);
  175.     return HrCheckHr(hr, IMAPIProp_GetProps);
  176. }
  177. /*
  178.  *  IATCH_GetPropList
  179.  *
  180.  *  Purpose:
  181.  *      Returns a list of all the properties currently accessible.
  182.  *      Uses the IMessage on IStorage property implementation.
  183.  *
  184.  *  Arguments:
  185.  *      piatch              Pointer to the object.
  186.  *      ulFlags             UNICODE / String8
  187.  *      lppPropTagArray     Location in which to return a pointer
  188.  *                          to a counted array of property tags.
  189.  *
  190.  *  Returns:
  191.  *      HRESULT
  192.  *
  193.  *  Side effects:
  194.  *      None.
  195.  *
  196.  *  Errors:
  197.  *      MAPI_E_NO_ACCESS    The caller does not have access
  198.  *                                  to the requested properties.
  199.  *      MAPI_E_CALL_FAILED          The mechanism for making the
  200.  *                                  call to the service provider
  201.  *                                  failed.
  202.  */
  203. STDMETHODIMP
  204. IATCH_GetPropList(PIATCH piatch, ULONG ulFlags, LPSPropTagArray *lppPropTagArray)
  205. {
  206.     HRESULT hr;
  207.     ATCH_ValidateParameters(
  208.             piatch,
  209.             IMAPIProp,
  210.             GetPropList,
  211.             (piatch, 
  212.             ulFlags, 
  213.             lppPropTagArray));
  214.     #ifdef VALIDATE
  215.     if (ulFlags & MAPI_UNICODE)
  216.         return ResultFromScode(MAPI_E_BAD_CHARWIDTH);
  217.     #endif
  218.         
  219.     IATCH_EnterCriticalSection(piatch);
  220.     hr = piatch->lpattach->lpVtbl->GetPropList(piatch->lpattach, ulFlags,
  221.         lppPropTagArray);
  222.     IATCH_LeaveCriticalSection(piatch);
  223.     DebugTraceResult(IATCH_GetPropList, hr);
  224.     return HrCheckHr(hr, IMAPIProp_GetPropList);
  225. }
  226. /*
  227.  *  IATCH_OpenProperty
  228.  *
  229.  *  Purpose:
  230.  *      Open a requested interface on a property for further
  231.  *      access.  Commonly used for stream access to a large binary
  232.  *      or text property.  This is the only way to access a
  233.  *      property of type PT_OBJECT, and may be used on other
  234.  *      properties depending on the implementation.  Uses the
  235.  *      IMessage on IStorage property implementation.
  236.  *
  237.  *  Arguments:
  238.  *      piatch      Pointer to the object.
  239.  *      ulPropTag   Property tag for the desired property.  Only
  240.  *                  the ID bits of the tag are used; the type bits
  241.  *                  are ignored.
  242.  *      lpiid       Pointer to the GUID identifying which interface
  243.  *                  is desired.
  244.  *      lppUnk      Location in which to return a pointer to the
  245.  *                  newly created interface pointer.
  246.  *
  247.  *  Returns:
  248.  *      HRESULT
  249.  *
  250.  *  Side effects:
  251.  *      None.
  252.  *
  253.  *  Errors:
  254.  *      MAPI_E_CALL_FAILED      An error occurred opening a
  255.  *                              supported interface.
  256.  *      MAPI_E_NO_SUPPORT   The requested interface is not
  257.  *                              available on the given property.
  258.  */
  259. STDMETHODIMP IATCH_OpenProperty(PIATCH piatch, ULONG ulPropTag, LPCIID lpiid,
  260.     ULONG ulInterfaceOptions, ULONG ulFlags, LPUNKNOWN * lppUnk)
  261. {
  262.     HRESULT hr;
  263.     LPUNKNOWN lpunk = NULL;
  264.     PIMSG pimsg = NULL;
  265.     LPSPropTagArray ptaga = NULL;
  266.     ATCH_ValidateParameters(
  267.             piatch,
  268.             IMAPIProp,
  269.             OpenProperty,
  270.             (piatch, 
  271.             ulPropTag, 
  272.             lpiid,
  273.             ulInterfaceOptions, 
  274.             ulFlags, 
  275.             lppUnk));
  276.     IATCH_EnterCriticalSection(piatch);
  277.     /* If input parameters are okay, make OpenProperty call on lpmsg. */
  278.     hr = piatch->lpattach->lpVtbl->OpenProperty(piatch->lpattach,
  279.         ulPropTag, lpiid, ulInterfaceOptions, ulFlags, &lpunk);
  280.     if (hr != hrSuccess)
  281.         goto exit;
  282.     /* If it's a message in message, we need to wrap the returned object */
  283.     if (ulPropTag == PR_ATTACH_DATA_OBJ
  284.         && IsEqualIID(lpiid, (LPIID) &IID_IMessage))
  285.     {
  286.         hr = NewIMSGInIATCH((LPMESSAGE) lpunk, (POBJ) piatch, ulFlags, &pimsg);
  287.         if (hr != hrSuccess)
  288.             goto exit;
  289.         hr = pimsg->lpVtbl->GetPropList(pimsg, 0, /* ansi */
  290.                 &ptaga);
  291.         if (hr != hrSuccess)
  292.             goto exit;
  293.         if (ptaga->cValues == 0)
  294.         {
  295.             hr = InitIMSGProps(pimsg);
  296.             if (hr != hrSuccess)
  297.                 goto exit;
  298.         }
  299.         *lppUnk = (LPUNKNOWN) pimsg;
  300.     }
  301.     else
  302.         *lppUnk = lpunk;
  303. exit:
  304.     LMFree(&piatch->pims->lmr, ptaga);
  305.     if (hr != hrSuccess)
  306.     {
  307.         UlRelease(pimsg);
  308.         UlRelease(lpunk);
  309.     }
  310.     IATCH_LeaveCriticalSection(piatch);
  311.     DebugTraceResult(IATCH_OpenProperty, hr);
  312.     return HrCheckHr(hr, IMAPIProp_OpenProperty);
  313. }
  314. /*
  315.  *  IATCH_SetProps
  316.  *
  317.  *  Purpose:
  318.  *      Sets the value of one or more properties.  This call passes
  319.  *      a number of Property Value structures.  The Property Tag in
  320.  *      each indicates which property is having its values set and
  321.  *      the value indicates what should be stored.  The caller must
  322.  *      free the returned property problem structure by calling
  323.  *      MAPIFreeBuffer(*pprba), but only if the call
  324.  *      succeeded overall.  Uses the IMessage on IStorage property
  325.  *      implementation.
  326.  *
  327.  *  Arguments:
  328.  *      piatch          Pointer to the object.
  329.  *      cValues         Number of values in pval.
  330.  *      pval            Pointer to a Property Value array.
  331.  *      pprba           Location in which to return a pointer to a
  332.  *                      counted array of property problem
  333.  *                      structures.
  334.  *
  335.  *  Returns:
  336.  *      HRESULT.  If the call succeeds overall, a zero is returned.
  337.  *      If there are problems with setting some or all of the
  338.  *      selected values, and a non-NULL is passed for pprba,
  339.  *      then a SPropProblemArray structure is returned with details
  340.  *      about each problem.  The value returned in pprba is
  341.  *      only valid if zero is returned in the HRESULT.  If an error
  342.  *      occurs on the call such that a non-zero value is returned
  343.  *      for the HRESULT then the contents of *pprba are
  344.  *      undefined.  In particular, do not use or free the structure
  345.  *      if an error occurs on the call.
  346.  *
  347.  *  Side effects:
  348.  *      None.
  349.  *
  350.  *  Errors:
  351.  *      MAPI_E_NO_ACCESS    The caller does not have access
  352.  *                                  to the requested properties.
  353.  *      MAPI_E_CALL_FAILED          The mechanism for making the
  354.  *                                  call to the service provider
  355.  *                                  failed.
  356.  */
  357. STDMETHODIMP IATCH_SetProps(PIATCH piatch, ULONG cValues, LPSPropValue pval,
  358.     LPSPropProblemArray *pprba)
  359. {
  360.     HRESULT hr;
  361.     ATCH_ValidateParameters(
  362.             piatch,
  363.             IMAPIProp,
  364.             SetProps,
  365.             (piatch, 
  366.             cValues, 
  367.             pval,
  368.             pprba));
  369.     IATCH_EnterCriticalSection(piatch);
  370.     hr = piatch->lpattach->lpVtbl->SetProps(piatch->lpattach, cValues,
  371.         pval, pprba);
  372.     IATCH_LeaveCriticalSection(piatch);
  373.     DebugTraceResult(IATCH_SetProps, hr);
  374.     return HrCheckHr(hr, IMAPIProp_SetProps);
  375. }
  376. /*
  377.  *  IATCH_DeleteProps
  378.  *
  379.  *  Purpose:
  380.  *      Deletes the list of properties given in ptaga.
  381.  *      The caller must free the returned property problem
  382.  *      structure by calling MAPIFreeBuffer(*pprba), but only
  383.  *      if the call succeeded overall.  Uses the IMessage on
  384.  *      IStorage property implementation.
  385.  *
  386.  *  Arguments:
  387.  *      piatch          Pointer to the object.
  388.  *      ptaga   Pointer to an array of Property Tags
  389.  *                      identifying the properties to delete.
  390.  *      pprba       Location in which to return a pointer to a
  391.  *                      counted array of property problem
  392.  *                      structures.
  393.  *
  394.  *  Returns:
  395.  *      HRESULT.  If the call succeeds overall, a zero is returned.
  396.  *      If there are problems with deleting some or all of the
  397.  *      selected values, and a non-NULL is passed for pprba,
  398.  *      then a SPropProblemArray structure is returned with details
  399.  *      about each problem.  The value returned in pprba is
  400.  *      only valid if zero is returned in the HRESULT.  If an error
  401.  *      occurs on the call such that a non-zero value is returned
  402.  *      for the HRESULT then the contents of *pprba are
  403.  *      undefined.  In particular, do not use or free the structure
  404.  *      if an error occurs on the call.
  405.  *
  406.  *  Side effects:
  407.  *      None.
  408.  *
  409.  *  Errors:
  410.  *      MAPI_E_NO_ACCESS    The caller does not have access
  411.  *                                  to the requested properties.
  412.  *      MAPI_E_CALL_FAILED          The mechanism for making the
  413.  *                                  call to the service provider
  414.  *                                  failed.
  415.  */
  416. STDMETHODIMP IATCH_DeleteProps(PIATCH piatch, LPSPropTagArray ptaga,
  417.     LPSPropProblemArray * pprba)
  418. {
  419.     HRESULT hr;
  420.     ATCH_ValidateParameters(
  421.             piatch,
  422.             IMAPIProp,
  423.             DeleteProps,
  424.             (piatch, 
  425.             ptaga,
  426.             pprba));
  427.     IATCH_EnterCriticalSection(piatch);
  428.     hr = piatch->lpattach->lpVtbl->DeleteProps(piatch->lpattach, ptaga, pprba);
  429.     IATCH_LeaveCriticalSection(piatch);
  430.     DebugTraceResult(IATCH_DeleteProps, hr);
  431.     return HrCheckHr(hr, IMAPIProp_DeleteProps);
  432. }
  433. /*
  434.  *  IATCH_CopyTo
  435.  *
  436.  *  Purpose:
  437.  *      Copies the contents of the current object to a destination
  438.  *      object.  The entire contents, including contained objects,
  439.  *      are copied, or optionally the caller can provide a list of
  440.  *      properties that are not to be copied.  Previous information
  441.  *      in the destination object which is not overwritten by
  442.  *      copied data is neither deleted nor modified.
  443.  *
  444.  *  Arguments:
  445.  *      piatch          Pointer to the source object.
  446.  *      ciidExcl        Count of the excluded interfaces in
  447.  *                      rgiidExcl.
  448.  *      rgiidExcl   Array of interface IDs specifying
  449.  *                      interfaces not to be attempted in trying to
  450.  *                      copy supplemental information to the
  451.  *                      destination object.
  452.  *      ptagaExcl   Counted array of property tags of
  453.  *                      properties that are not to be copied to the
  454.  *                      destination object.  NULL indicates all
  455.  *                      properties are to be copied.
  456.  *      ulUIParam       Handle of parent window cast to ULONG.
  457.  *      lpProgress      Callback for doing progress UI.
  458.  *      piidDst     Interface ID of the interface of lpDestObj,
  459.  *                      the destination object.
  460.  *      lpDestObj       Pointer to the open destination object.
  461.  *      ulFlags         Flags.  Defined as follows:
  462.  *                      MAPI_MOVE       Indicates a move operation.
  463.  *                                      The default is to copy.
  464.  *                      MAPI_NOREPLACE  Indicates that existing
  465.  *                                      properties should not be
  466.  *                                      overridden.  The default is
  467.  *                                      to overwrite existing
  468.  *                                      properties.
  469.  *                      MAPI_DIALOG     Display a progress dialog
  470.  *                                      as the operation proceeds.
  471.  *                      MAPI_STD_DIALOG Use MAPI standard dialog
  472.  *                                      instead of
  473.  *                                      provider-specific dialog.
  474.  *      pprba       Pointer to a variable that is filled in
  475.  *                      with a pointer to a set of property
  476.  *                      problems.  If NULL, no problem set is
  477.  *                      returned on an error.
  478.  *
  479.  *  Returns:
  480.  *      HRESULT
  481.  *
  482.  *  Side effects:
  483.  *      None.
  484.  *
  485.  *  Errors:
  486.  */
  487. STDMETHODIMP IATCH_CopyTo(PIATCH piatch, ULONG ciidExcl, LPCIID rgiidExcl,
  488.     LPSPropTagArray ptagaExcl, ULONG ulUIParam, LPMAPIPROGRESS
  489.     lpProgress, LPCIID piidDst, LPVOID lpDestObj, ULONG ulFlags,
  490.     LPSPropProblemArray * pprba)
  491. {
  492.     HRESULT hr;
  493.     ATCH_ValidateParameters(
  494.             piatch,
  495.             IMAPIProp,
  496.             CopyTo,
  497.             (piatch, 
  498.             ciidExcl, 
  499.             rgiidExcl,
  500.             ptagaExcl, 
  501.             ulUIParam, 
  502.             lpProgress, 
  503.             piidDst, 
  504.             lpDestObj, 
  505.             ulFlags,
  506.             pprba));
  507.     IATCH_EnterCriticalSection(piatch);
  508.     hr = piatch->lpattach->lpVtbl->CopyTo(piatch->lpattach, ciidExcl,
  509.         rgiidExcl, ptagaExcl, ulUIParam, lpProgress, piidDst,
  510.         lpDestObj, ulFlags, pprba);
  511.     IATCH_LeaveCriticalSection(piatch);
  512.     DebugTraceResult(IATCH_CopyTo, hr);
  513.     return HrCheckHr(hr, IMAPIProp_CopyTo);
  514. }
  515. /*
  516.  *  IATCH_CopyProps
  517.  *
  518.  *  Purpose:
  519.  *      Copies the specified properties of the current object to a destination
  520.  *      object.
  521.  *
  522.  *  Arguments:
  523.  *      piatch          Pointer to the source object.
  524.  *      ptagaIncl       Counted array of property tags of
  525.  *                      properties that are to be copied to the
  526.  *                      destination object.
  527.  *      ulUIParam       Handle of parent window cast to ULONG.
  528.  *      lpProgress      Callback for doing progress UI.
  529.  *      piidDst     Interface ID of the interface of lpDestObj,
  530.  *                      the destination object.
  531.  *      lpDestObj       Pointer to the open destination object.
  532.  *      ulFlags         Flags.  Defined as follows:
  533.  *                      MAPI_MOVE       Indicates a move operation.
  534.  *                                      The default is to copy.
  535.  *                      MAPI_NOREPLACE  Indicates that existing
  536.  *                                      properties should not be
  537.  *                                      overridden.  The default is
  538.  *                                      to overwrite existing
  539.  *                                      properties.
  540.  *                      MAPI_DIALOG     Display a progress dialog
  541.  *                                      as the operation proceeds.
  542.  *                      MAPI_DECLINE_OK
  543.  *      pprba       Pointer to a variable that is filled in
  544.  *                      with a pointer to a set of property
  545.  *                      problems.  If NULL, no problem set is
  546.  *                      returned on an error.
  547.  *
  548.  *  Returns:
  549.  *      HRESULT
  550.  *
  551.  *  Side effects:
  552.  *      None.
  553.  *
  554.  *  Errors:
  555.  */
  556. STDMETHODIMP IATCH_CopyProps(PIATCH piatch,
  557.     LPSPropTagArray ptagaIncl, ULONG ulUIParam, LPMAPIPROGRESS
  558.     lpProgress, LPCIID piidDst, LPVOID lpDestObj, ULONG ulFlags,
  559.     LPSPropProblemArray * pprba)
  560. {
  561.     HRESULT hr;
  562.     ATCH_ValidateParameters(
  563.             piatch,
  564.             IMAPIProp,
  565.             CopyProps,
  566.             (piatch,
  567.             ptagaIncl, 
  568.             ulUIParam, 
  569.             lpProgress, 
  570.             piidDst, 
  571.             lpDestObj, 
  572.             ulFlags,
  573.             pprba));
  574.     IATCH_EnterCriticalSection(piatch);
  575.     hr = piatch->lpattach->lpVtbl->CopyProps(piatch->lpattach,
  576.         ptagaIncl, ulUIParam, lpProgress, piidDst,
  577.         lpDestObj, ulFlags, pprba);
  578.     IATCH_LeaveCriticalSection(piatch);
  579.     DebugTraceResult(IATCH_CopyProps, hr);
  580.     return HrCheckHr(hr, IMAPIProp_CopyProps);
  581. }
  582. /*
  583.  *  External functions
  584.  */
  585. /*
  586.  * IATCH_Neuter
  587.  *
  588.  * Purpose
  589.  *  free storage for an attachment
  590.  *
  591.  * Parameter
  592.  *      piatch      pointer to the open attachment
  593.  *
  594.  */
  595. void IATCH_Neuter(PIATCH piatch)
  596. {
  597.     UlRelease(piatch->lpattach);
  598. }
  599. /*
  600.  *  HrNewIATCH
  601.  *
  602.  *  Purpose:
  603.  *      Allocates and initializes an IATCH object (internal
  604.  *      implementation of IAttach).  This is just a thin wrapper
  605.  *      around the attachment object of the IMessage on IStorage
  606.  *      implementation -- we wrap it to catch certain methods,
  607.  *      see below.
  608.  *
  609.  *  Arguments:
  610.  *      lpattach    Pointer to an attachment object returned by
  611.  *                  IMessage on IStorage.
  612.  *      pimsg       Pointer to the attachment's parent message object.
  613.  *      fModify     TRUE if the caller wants the attach opened for writing.
  614.  *      ppiatch Location in which to return a pointer to the
  615.  *                  newly created IATCH instance.
  616.  *
  617.  *  Returns:
  618.  *      HRESULT
  619.  *
  620.  *  Side effects:
  621.  *      None.
  622.  *
  623.  *  Errors:
  624.  *      MAPI_E_NOT_ENOUGH_MEMORY    Could not allocate space for
  625.  *                                  the IATCH instance.
  626.  */
  627. HRESULT HrNewIATCH(LPATTACH lpattach, PIMSG pimsg, BOOL fModify, PIATCH * ppiatch)
  628. {
  629.     HRESULT hr = hrSuccess;
  630.     PIATCH piatchNew = NULL;
  631.     SCODE sc;
  632.     PIMS pims;
  633.     AssertSz(lpattach, "Bad lpattach");
  634.     AssertSz(pimsg, "Bad pimsg");
  635.     AssertSz(ppiatch, "Bad ppiatch");
  636.     pims = pimsg->pims;
  637.     /* Allocate and initialize IATCH instance */
  638.     sc = LMAllocZ(&pims->lmr, sizeof(IATCH), &piatchNew);
  639.     if (sc != S_OK)
  640.     {
  641.         hr = ResultFromScode(sc);
  642.         goto exit;
  643.     }
  644.     /* Initialize member variables */
  645.     OBJ_Initialize(piatchNew, &vtblIATCH, OT_ATTACH, pims, pims->pcs);
  646.     UlAddRef(lpattach); /* we're keeping a reference */
  647.     piatchNew->lpattach = lpattach;
  648.     if (fModify)
  649.         OBJ_SetFlag(piatchNew, OBJF_MODIFY);
  650.     OBJ_Enqueue((POBJ) piatchNew, (POBJ) pimsg);
  651.     *ppiatch = piatchNew;
  652. exit:
  653.     if (hr != hrSuccess)
  654.         LMFree(&pims->lmr, piatchNew);
  655.     DebugTraceResult(HrNewIATCH, hr);
  656.     return hr;
  657. }