home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / trialva / ibmcppw / sdk / mapi / win16 / dev / sample.ms / mspatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-11  |  22.2 KB  |  679 lines

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