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

  1. /*
  2.  *  S M H C F G . C
  3.  *
  4.  *  Sample mail handling hook configuration
  5.  *  Copyright 1992-95 Microsoft Corporation.  All Rights Reserved.
  6.  */
  7.  
  8. #include "_pch.h"
  9.  
  10. /*
  11.  *  Configuration Properties
  12.  *  
  13.  *  sptConfigProps
  14.  *  
  15.  *      This is the set of properties that we expect to find in the
  16.  *      provider's profile section.
  17.  *  
  18.  *  sptRule
  19.  *  
  20.  *      This is the set of properties that are expected to be found in
  21.  *      each rule's profile section.
  22.  */
  23. const SizedSPropTagArray (cpMax, sptConfigProps) =
  24. {
  25.     cpMax,
  26.     {
  27.         PR_SMH_FLAGS,
  28.         PR_SMH_RULES,
  29.         PR_SMH_EXCLUSIONS
  30.     }
  31. };
  32. const SizedSPropTagArray (cpRLMax, sptRule) =
  33. {
  34.     cpRLMax,
  35.     {
  36.         PR_DISPLAY_NAME,
  37.         PR_RULE_TYPE,
  38.         PR_RULE_DATA,
  39.         PR_RULE_FLAGS,
  40.         PR_RULE_TARGET_ENTRYID,
  41.         PR_RULE_TARGET_PATH,
  42.         PR_RULE_STORE_ENTRYID,
  43.         PR_RULE_STORE_DISPLAY_NAME,
  44.         PR_RULE_SOUND_FILENAME
  45.     }
  46. };
  47.  
  48.  
  49. /*
  50.  *  Configuration event name
  51.  */
  52. const TCHAR lpszConfigEvt[] = "SMH_CONFIGURATION_EVENT";
  53.  
  54.  
  55. /*
  56.  *  HrOpenSingleProvider()
  57.  *  
  58.  *  Purpose:
  59.  *  
  60.  *      Opens the profile section of this service provider.  This is done
  61.  *      by opening the message service table and querying all rows.
  62.  *      Since the SMH service contains only one provider, there is only
  63.  *      one row in the table.  This contains our profile section.  Use
  64.  *      the PR_PROFILE_UID to open the section.
  65.  *  
  66.  *  Arguments:
  67.  *  
  68.  *      lpadmin         the IProfileAdmin object
  69.  *      lppprof [OUT]   on return contains the profile section obj
  70.  *  
  71.  *  Returns:
  72.  *  
  73.  *      (HRESULT)
  74.  *      lppprof [OUT]   contains the profile section object iff the call
  75.  *                      is successful.
  76.  */
  77. HRESULT
  78. HrOpenSingleProvider (LPPROVIDERADMIN lpadmin, LPPROFSECT FAR * lppprof)
  79. {
  80.     HRESULT hr;
  81.     LPMAPITABLE lptbl = NULL;
  82.     LPSRowSet lprws = NULL;
  83.     SPropTagArray sptProvider = {1, {PR_PROVIDER_UID}};
  84.     SRestriction res = {0};
  85.  
  86.     res.rt = RES_EXIST;
  87.     res.res.resExist.ulPropTag = PR_PROVIDER_DLL_NAME;
  88.  
  89.     hr = lpadmin->lpVtbl->GetProviderTable (lpadmin, 0, &lptbl);
  90.     if (!HR_FAILED (hr))
  91.     {
  92.         hr = lptbl->lpVtbl->SetColumns (lptbl, &sptProvider, 0L);
  93.         if (!HR_FAILED (hr))
  94.         {
  95.             hr = lptbl->lpVtbl->Restrict (lptbl, &res, 0);
  96.             if (!HR_FAILED (hr))
  97.             {
  98.                 hr = lptbl->lpVtbl->QueryRows (lptbl, 10, 0, &lprws);
  99.                 if (!HR_FAILED (hr) && lprws->cRows)
  100.                 {
  101.                     Assert (lprws->cRows == 1);
  102.                     Assert (lprws->aRow[0].cValues == 1);
  103.                     Assert (lprws->aRow[0].lpProps);
  104.                     Assert (lprws->aRow[0].lpProps[0].ulPropTag == PR_PROVIDER_UID);
  105.                     hr = lpadmin->lpVtbl->OpenProfileSection (lpadmin,
  106.                         (LPMAPIUID)lprws->aRow[0].lpProps[0].Value.bin.lpb,
  107.                         NULL,
  108.                         MAPI_MODIFY,
  109.                         lppprof);
  110.                     MAPIFreeBuffer (lprws->aRow[0].lpProps);
  111.                 }
  112.                 MAPIFreeBuffer (lprws);
  113.             }
  114.         }
  115.         UlRelease (lptbl);
  116.     }
  117.     DebugTraceResult (HrOpenSingleProvider, hr);
  118.     return hr;
  119. }
  120.  
  121.  
  122. /*
  123.  *  HrMergeValues()
  124.  *  
  125.  *  Purpose:
  126.  *  
  127.  *      Merges two property value arrays into one.  By making a copy of
  128.  *      the first and then adding/replacing props from the second.
  129.  *  
  130.  *      IMPORTANT: if there are any property values that are separately
  131.  *      allocated with either MAPIAllocateBuffer() or MAPIAllocateMore(),
  132.  *      then these property values must remain valid as long as the
  133.  *      merged property array is expected to be valid.
  134.  *  
  135.  *  Returns:
  136.  *  
  137.  *      (HRESULT)
  138.  */
  139. HRESULT
  140. HrMergeValues (ULONG cval1,
  141.     LPSPropValue lpval1,
  142.     ULONG cval2,
  143.     LPSPropValue lpval2,
  144.     LPALLOCATEBUFFER lpfnAlloc,
  145.     ULONG FAR * lpcvalMerged,
  146.     LPSPropValue FAR * lppvalMerged)
  147. {
  148.     SCODE sc;
  149.     LPSPropValue lpval = NULL;
  150.     UINT cb;
  151.     UINT ip;
  152.  
  153.     cb = (UINT)(cval1 + cval2) * sizeof(SPropValue);
  154.     sc = (*lpfnAlloc)(cb, &lpval);
  155.     if (!FAILED (sc))
  156.     {
  157.         /* Slurp the original data across */
  158.  
  159.         memcpy (lpval, lpval1, (UINT)cval1 * sizeof(SPropValue));
  160.  
  161.         /* Move the new stuff over */
  162.  
  163.         while (cval2--)
  164.         {
  165.             for (ip = 0; ip < (UINT)cval1; ip++)
  166.             {
  167.                 /* See if we match properties */
  168.  
  169.                 if (PROP_ID (lpval[ip].ulPropTag) == PROP_ID (lpval2[cval2].ulPropTag))
  170.                 {
  171.                     /* We matched, but are we a real property */
  172.  
  173.                     if (PROP_TYPE (lpval2[cval2].ulPropTag) != PT_ERROR)
  174.                         lpval[ip] = lpval2[cval2];
  175.                     break;
  176.                 }
  177.             }
  178.             if (ip == cval1)
  179.                 lpval[cval1++] = lpval2[cval2];
  180.         }
  181.         *lpcvalMerged = cval1;
  182.         *lppvalMerged = lpval;
  183.     }
  184.     DebugTraceSc (HrMergeValues(), sc);
  185.     return ResultFromScode (sc);
  186. }
  187.  
  188.  
  189. /*
  190.  *  UlChkReqProps()
  191.  *  
  192.  *  Purpose:
  193.  *  
  194.  *      Checks a property value array and sets bits in the return value
  195.  *      for properties that are present and non-NULL
  196.  *  
  197.  *  Returns:
  198.  *  
  199.  *      (ULONG) where the Nth bit is set iff the property value
  200.  *      structure at index N is valid and non-NULL
  201.  */
  202. ULONG
  203. UlChkReqProps (ULONG cval, LPSPropValue lpval)
  204. {
  205.     ULONG ul;
  206.  
  207.     Assert (cval <= 32);
  208.     for (ul = 0; cval--; )
  209.     {
  210.         if ((lpval[cval].ulPropTag != PR_NULL) &&
  211.             (PROP_TYPE(lpval[cval].ulPropTag) != PT_ERROR))
  212.         {
  213.             /* Mark the property as being there */
  214.  
  215.             ul |= (1 << cval);
  216.         }
  217.     }
  218.     return ul;
  219. }
  220.  
  221. /*
  222.  *  HrGetConfigEvent()
  223.  *  
  224.  *  Purpose:
  225.  *  
  226.  *      Gets the configuration event handle.  The handle is used to
  227.  *      signal logged in handlers that their configuration has been
  228.  *      modified and, at the next reasonable chance, should be reloaded.
  229.  *  
  230.  *      Called at SMH init time only.
  231.  *  
  232.  *  Arguments:
  233.  *  
  234.  *      lphevt  [OUT]   contains the handle iff the call succeeds
  235.  *  
  236.  *  Returns:
  237.  *  
  238.  *      (HRESULT)
  239.  */
  240. #ifdef  WIN32
  241. HRESULT
  242. HrGetConfigEvent (HANDLE FAR * lphevt)
  243. {
  244.     HANDLE hevt = NULL;
  245.         
  246.     if (!(hevt = CreateEvent (NULL, TRUE, FALSE, lpszConfigEvt)) &&
  247.         !(hevt = OpenEvent (EVENT_MODIFY_STATE, FALSE, lpszConfigEvt)))
  248.         ResultFromScode (MAPI_E_NOT_ENOUGH_RESOURCES);
  249.  
  250.     *lphevt = hevt;
  251.     return hrSuccess;
  252. }
  253. #endif  /* WIN32 */
  254.  
  255.  
  256. /*
  257.  *  SignalConfigChanged()
  258.  *  
  259.  *  Purpose:
  260.  *  
  261.  *      Sets the configuration event such that logged in hooks can update
  262.  *      their configuration on the fly.
  263.  *  
  264.  *      Called from within the service entry when configuration changes
  265.  *      are commited.
  266.  */
  267. #ifdef  WIN32
  268. VOID
  269. SignalConfigChanged (VOID)
  270. {
  271.     HANDLE hevt = NULL;
  272.     
  273.     if (hevt = OpenEvent (EVENT_MODIFY_STATE, FALSE, lpszConfigEvt))
  274.     {
  275.         SetEvent (hevt);
  276.         CloseHandle (hevt);
  277.     }
  278.     return;
  279. }
  280. #endif  /* WIN32 */
  281.  
  282.  
  283. /*
  284.  *  FConfigChanged()
  285.  *  
  286.  *  Purpose:
  287.  *  
  288.  *      Tests the configuration event such that logged in hooks can update
  289.  *      their configuration on the fly if the configuration has changed.
  290.  *  
  291.  *      Called from within the SMH object at regualr intervals
  292.  *  
  293.  *  Returns:
  294.  *  
  295.  *      TRUE iff the config changed
  296.  *  
  297.  */
  298. #ifdef  WIN32
  299. BOOL
  300. FConfigChanged (HANDLE hevt)
  301. {
  302.     ULONG dw;
  303.  
  304.     dw = WaitForSingleObject (hevt, 0);
  305.     Assert (dw != WAIT_ABANDONED);
  306.     return (dw == WAIT_OBJECT_0);
  307. }
  308. #endif  /* WIN32 */
  309.  
  310.  
  311. /*
  312.  *  SMH_ServiceEntry()
  313.  *  
  314.  *  Purpose:
  315.  *  
  316.  *      The ServiceEntry() function is the MAPI entry point to configure
  317.  *      a service for use in a profile.  The call can then bring up UI to
  318.  *      ensure configuration of the SMH provider.
  319.  *  
  320.  *  Parameters:
  321.  *  
  322.  *      hinst           DLL instance
  323.  *      lpmalloc        OLE style allocator (used by PropSheet())
  324.  *      lpsup           MAPI profile support object
  325.  *      ulUIParam       hwnd that is to be used as UI parent
  326.  *      ulFlags         configuration flags
  327.  *      ulContext       configuration action
  328.  *      cval            count of caller supplied properties
  329.  *      lpval           caller supplied properties to be configured
  330.  *      lpadmin         IProviderAdmin object
  331.  *      lppmerr [OUT]   extended error information
  332.  *  
  333.  *  Operation:
  334.  *  
  335.  *      The ServiceEntry() uses the IProviderAdmin object to open its
  336.  *      profile section and retrieve the current set of properties.  The
  337.  *      caller supplied properties are then merged into the set of
  338.  *      current properties.
  339.  *  
  340.  *      If either this set of properties is not sufficient for
  341.  *      configuration or the caller specifically asked for configuration
  342.  *      UI, then ServiceEntry() will make calls to bring up its config
  343.  *      UI.
  344.  *  
  345.  *      ServiceEntry() recognizes several configuration flags.  If
  346.  *      SERVICE_UI_ALWAYS and/or SERVICE_UI_ALLOWED are set, UI is
  347.  *      allowed and we be brought up if appropriate.  Is
  348.  *      MSG_SERVICE_UI_READ_ONLY is set, then the UI should not 
  349.  *      allow the configuration to be modified.
  350.  *  
  351.  *      The configuration contexts MSG_SERVICE_DELETE, MSG_SERVICE_INSTALL, 
  352.  *      and MSG_SERVICE_UNINSTALL are ignored and no action is taken.
  353.  *      MSG_SERVICE_CONFIGURE and MSG_SERVICE_CREATE allow the caller to
  354.  *      create or update the configuration properties in this providers
  355.  *      profile section. 
  356.  *  
  357.  *      SMH will not return extended information in the MAPIERROR in case
  358.  *      of error
  359.  */
  360. HRESULT STDAPICALLTYPE
  361. SMH_ServiceEntry(
  362.     HINSTANCE hinst,
  363.     LPMALLOC lpmalloc,
  364.     LPMAPISUP lpsup,
  365.     ULONG ulUIParam,
  366.     ULONG ulFlags,
  367.     ULONG ulContext,
  368.     ULONG cval,
  369.     LPSPropValue lpval,
  370.     LPPROVIDERADMIN lpadmin,
  371.     LPMAPIERROR FAR * lppmerr)
  372. {
  373.     HRESULT hr = hrSuccess;
  374.     BOOL fUI = FALSE;
  375.     BOOL fSave = FALSE;
  376.     LPALLOCATEBUFFER lpfnAlloc = NULL;
  377.     LPALLOCATEMORE lpfnAllocMore = NULL;
  378.     LPFREEBUFFER lpfnFree = NULL;
  379.     LPPROFSECT lpprof = NULL;
  380.     LPPROFSECT lpprofSvc = NULL;
  381.     LPSPropValue lpvalCur = NULL;
  382.     LPSPropValue lpvalNew = NULL;
  383.     LPSMHDLG lpsmhdlg = NULL;
  384.     ULONG cvalCur;
  385.     ULONG cvalNew;
  386.     ULONG ulMyFlags;
  387.  
  388.     if ((ulContext == MSG_SERVICE_INSTALL) ||
  389.         (ulContext == MSG_SERVICE_UNINSTALL))
  390.         goto ret;
  391.  
  392.     if ((ulContext != MSG_SERVICE_CONFIGURE) &&
  393.         (ulContext != MSG_SERVICE_CREATE) &&
  394.         (ulContext != MSG_SERVICE_DELETE))
  395.     {
  396.         hr = ResultFromScode (MAPI_E_NO_SUPPORT);
  397.         goto ret;
  398.     }
  399.  
  400.     if (ulFlags & MAPI_UNICODE)
  401.     {
  402.         /* Unicode is not supported by SMH */
  403.  
  404.         hr = ResultFromScode (MAPI_E_BAD_CHARWIDTH);
  405.         goto ret;
  406.     }
  407.  
  408.     /* Find out our UI options */
  409.  
  410.     fUI = !!(ulFlags & SERVICE_UI_ALWAYS);
  411.     ulMyFlags = (ulFlags & MSG_SERVICE_UI_READ_ONLY)
  412.         ? UI_READONLY
  413.         : 0;
  414.  
  415.     /* Get memory routines */
  416.  
  417.     hr = lpsup->lpVtbl->GetMemAllocRoutines (lpsup,
  418.                             &lpfnAlloc,
  419.                             &lpfnAllocMore,
  420.                             &lpfnFree);
  421.     if (HR_FAILED (hr))
  422.         goto ret;
  423.  
  424.     /* Open the profile section */
  425.  
  426.     hr = HrOpenSingleProvider (lpadmin, &lpprof);
  427.     if (HR_FAILED (hr))
  428.         goto ret;
  429.  
  430.     /* Get the values already in the profile */
  431.  
  432.     hr = lpprof->lpVtbl->GetProps (lpprof,
  433.                             (LPSPropTagArray)&sptConfigProps,
  434.                             0,
  435.                             &cvalCur,
  436.                             &lpvalCur);
  437.     if (HR_FAILED (hr))
  438.         goto ret;
  439.  
  440.     if (ulContext != MSG_SERVICE_DELETE)
  441.     {
  442.         /* Merge what was in the profile with what was passed in */
  443.  
  444.         hr = HrMergeValues (cvalCur,
  445.                             lpvalCur,
  446.                             cval,
  447.                             lpval,
  448.                             lpfnAlloc,
  449.                             &cvalNew,
  450.                             &lpvalNew);
  451.         if (HR_FAILED (hr))
  452.             goto ret;
  453.  
  454.         /* If we dont have all the props we need, then
  455.          *  we will have to ask for them
  456.          */
  457.         fUI |= (REQ_PROPS != (UlChkReqProps (cvalNew, lpvalNew) & REQ_PROPS));
  458.         if ((REQ_PROPS != (UlChkReqProps (cvalNew, lpvalNew) & REQ_PROPS)) &&
  459.             (!(ulFlags & (SERVICE_UI_ALLOWED | SERVICE_UI_ALWAYS)) ||
  460.             (ulFlags & MSG_SERVICE_UI_READ_ONLY)))
  461.         {
  462.             /* We need UI but can't have it. */
  463.  
  464.             hr = ResultFromScode (MAPI_E_UNCONFIGURED);
  465.             goto ret;
  466.         }
  467.  
  468.         if (fUI)
  469.         {
  470.             /* Do the config dialog */
  471.  
  472.             if (!FAILED ((*lpfnAlloc) (sizeof(SMHDLG), &lpsmhdlg)))
  473.             {
  474.                 memset (lpsmhdlg, 0, sizeof(SMHDLG));
  475.                 lpsmhdlg->hinst = hinst;
  476.                 lpsmhdlg->hwnd = (HWND)ulUIParam;
  477.                 lpsmhdlg->lpfnAlloc = lpfnAlloc;
  478.                 lpsmhdlg->lpfnAllocMore = lpfnAllocMore;
  479.                 lpsmhdlg->lpfnFree = lpfnFree;
  480.                 lpsmhdlg->lpmalloc = lpmalloc;
  481.                 lpsmhdlg->lpspt = (LPSPropTagArray)&sptConfigProps;
  482.                 lpsmhdlg->lpvalSMH = lpvalNew;
  483.                 lpsmhdlg->lpsec = lpprof;
  484.                 lpsmhdlg->lpsup = lpsup;
  485.                 lpsmhdlg->lpadmin = lpadmin;
  486.                 lpsmhdlg->ulFlags = ulMyFlags;
  487.                 hr = HrDisplayPropSheets (hinst, (HWND)ulUIParam, lpsmhdlg);
  488.                 fSave = lpsmhdlg->fDirty;
  489.                 (*lpfnFree) (lpsmhdlg);
  490.             }
  491.             else
  492.             {
  493.                 hr = ResultFromScode (MAPI_E_NOT_ENOUGH_MEMORY);
  494.                 goto ret;
  495.             }
  496.         }
  497.  
  498.         /* Set what we got and save the changes */
  499.  
  500.         if (fSave)
  501.         {
  502.             HRESULT hrT;
  503.             
  504.             hrT = lpprof->lpVtbl->SaveChanges (lpprof, 0);
  505.             if (HR_FAILED (hrT))
  506.             {
  507.                 hr = hrT;
  508.                 goto ret;
  509.             }
  510.             SignalConfigChanged ();
  511.         }
  512.  
  513.         /* Open the service profile section and set PR_SERVICE_EXTRA_UIDS */
  514.  
  515.         if (!HR_FAILED (lpadmin->lpVtbl->OpenProfileSection (lpadmin,
  516.                                             NULL,
  517.                                             NULL,
  518.                                             MAPI_MODIFY,
  519.                                             &lpprofSvc)))
  520.         {
  521.             lpvalNew[ipRules].ulPropTag = PR_SERVICE_EXTRA_UIDS;
  522.             if (!HR_FAILED (HrSetOneProp ((LPMAPIPROP)lpprofSvc, &lpvalNew[ipRules])))
  523.                 (void)lpprofSvc->lpVtbl->SaveChanges (lpprofSvc, 0);
  524.  
  525.             UlRelease (lpprofSvc);
  526.         }
  527.     }
  528.     
  529. ret:
  530.  
  531.     if (lpfnFree)
  532.     {
  533.         (*lpfnFree) (lpvalCur);
  534.         (*lpfnFree) (lpvalNew);
  535.     }
  536.  
  537.     UlRelease (lpprof);
  538.     DebugTraceResult (SMH_ServiceEntry, hr);
  539.     return hr;
  540. };
  541.