home *** CD-ROM | disk | FTP | other *** search
- /*
- * S M H C F G . C
- *
- * Sample mail handling hook configuration
- * Copyright 1992-95 Microsoft Corporation. All Rights Reserved.
- */
-
- #include "_pch.h"
-
- /*
- * Configuration Properties
- *
- * sptConfigProps
- *
- * This is the set of properties that we expect to find in the
- * provider's profile section.
- *
- * sptRule
- *
- * This is the set of properties that are expected to be found in
- * each rule's profile section.
- */
- const SizedSPropTagArray (cpMax, sptConfigProps) =
- {
- cpMax,
- {
- PR_SMH_FLAGS,
- PR_SMH_RULES,
- PR_SMH_EXCLUSIONS
- }
- };
- const SizedSPropTagArray (cpRLMax, sptRule) =
- {
- cpRLMax,
- {
- PR_DISPLAY_NAME,
- PR_RULE_TYPE,
- PR_RULE_DATA,
- PR_RULE_FLAGS,
- PR_RULE_TARGET_ENTRYID,
- PR_RULE_TARGET_PATH,
- PR_RULE_STORE_ENTRYID,
- PR_RULE_STORE_DISPLAY_NAME,
- PR_RULE_SOUND_FILENAME
- }
- };
-
-
- /*
- * Configuration event name
- */
- const TCHAR lpszConfigEvt[] = "SMH_CONFIGURATION_EVENT";
-
-
- /*
- * HrOpenSingleProvider()
- *
- * Purpose:
- *
- * Opens the profile section of this service provider. This is done
- * by opening the message service table and querying all rows.
- * Since the SMH service contains only one provider, there is only
- * one row in the table. This contains our profile section. Use
- * the PR_PROFILE_UID to open the section.
- *
- * Arguments:
- *
- * lpadmin the IProfileAdmin object
- * lppprof [OUT] on return contains the profile section obj
- *
- * Returns:
- *
- * (HRESULT)
- * lppprof [OUT] contains the profile section object iff the call
- * is successful.
- */
- HRESULT
- HrOpenSingleProvider (LPPROVIDERADMIN lpadmin, LPPROFSECT FAR * lppprof)
- {
- HRESULT hr;
- LPMAPITABLE lptbl = NULL;
- LPSRowSet lprws = NULL;
- SPropTagArray sptProvider = {1, {PR_PROVIDER_UID}};
- SRestriction res = {0};
-
- res.rt = RES_EXIST;
- res.res.resExist.ulPropTag = PR_PROVIDER_DLL_NAME;
-
- hr = lpadmin->lpVtbl->GetProviderTable (lpadmin, 0, &lptbl);
- if (!HR_FAILED (hr))
- {
- hr = lptbl->lpVtbl->SetColumns (lptbl, &sptProvider, 0L);
- if (!HR_FAILED (hr))
- {
- hr = lptbl->lpVtbl->Restrict (lptbl, &res, 0);
- if (!HR_FAILED (hr))
- {
- hr = lptbl->lpVtbl->QueryRows (lptbl, 10, 0, &lprws);
- if (!HR_FAILED (hr) && lprws->cRows)
- {
- Assert (lprws->cRows == 1);
- Assert (lprws->aRow[0].cValues == 1);
- Assert (lprws->aRow[0].lpProps);
- Assert (lprws->aRow[0].lpProps[0].ulPropTag == PR_PROVIDER_UID);
- hr = lpadmin->lpVtbl->OpenProfileSection (lpadmin,
- (LPMAPIUID)lprws->aRow[0].lpProps[0].Value.bin.lpb,
- NULL,
- MAPI_MODIFY,
- lppprof);
- MAPIFreeBuffer (lprws->aRow[0].lpProps);
- }
- MAPIFreeBuffer (lprws);
- }
- }
- UlRelease (lptbl);
- }
- DebugTraceResult (HrOpenSingleProvider, hr);
- return hr;
- }
-
-
- /*
- * HrMergeValues()
- *
- * Purpose:
- *
- * Merges two property value arrays into one. By making a copy of
- * the first and then adding/replacing props from the second.
- *
- * IMPORTANT: if there are any property values that are separately
- * allocated with either MAPIAllocateBuffer() or MAPIAllocateMore(),
- * then these property values must remain valid as long as the
- * merged property array is expected to be valid.
- *
- * Returns:
- *
- * (HRESULT)
- */
- HRESULT
- HrMergeValues (ULONG cval1,
- LPSPropValue lpval1,
- ULONG cval2,
- LPSPropValue lpval2,
- LPALLOCATEBUFFER lpfnAlloc,
- ULONG FAR * lpcvalMerged,
- LPSPropValue FAR * lppvalMerged)
- {
- SCODE sc;
- LPSPropValue lpval = NULL;
- UINT cb;
- UINT ip;
-
- cb = (UINT)(cval1 + cval2) * sizeof(SPropValue);
- sc = (*lpfnAlloc)(cb, &lpval);
- if (!FAILED (sc))
- {
- /* Slurp the original data across */
-
- memcpy (lpval, lpval1, (UINT)cval1 * sizeof(SPropValue));
-
- /* Move the new stuff over */
-
- while (cval2--)
- {
- for (ip = 0; ip < (UINT)cval1; ip++)
- {
- /* See if we match properties */
-
- if (PROP_ID (lpval[ip].ulPropTag) == PROP_ID (lpval2[cval2].ulPropTag))
- {
- /* We matched, but are we a real property */
-
- if (PROP_TYPE (lpval2[cval2].ulPropTag) != PT_ERROR)
- lpval[ip] = lpval2[cval2];
- break;
- }
- }
- if (ip == cval1)
- lpval[cval1++] = lpval2[cval2];
- }
- *lpcvalMerged = cval1;
- *lppvalMerged = lpval;
- }
- DebugTraceSc (HrMergeValues(), sc);
- return ResultFromScode (sc);
- }
-
-
- /*
- * UlChkReqProps()
- *
- * Purpose:
- *
- * Checks a property value array and sets bits in the return value
- * for properties that are present and non-NULL
- *
- * Returns:
- *
- * (ULONG) where the Nth bit is set iff the property value
- * structure at index N is valid and non-NULL
- */
- ULONG
- UlChkReqProps (ULONG cval, LPSPropValue lpval)
- {
- ULONG ul;
-
- Assert (cval <= 32);
- for (ul = 0; cval--; )
- {
- if ((lpval[cval].ulPropTag != PR_NULL) &&
- (PROP_TYPE(lpval[cval].ulPropTag) != PT_ERROR))
- {
- /* Mark the property as being there */
-
- ul |= (1 << cval);
- }
- }
- return ul;
- }
-
- /*
- * HrGetConfigEvent()
- *
- * Purpose:
- *
- * Gets the configuration event handle. The handle is used to
- * signal logged in handlers that their configuration has been
- * modified and, at the next reasonable chance, should be reloaded.
- *
- * Called at SMH init time only.
- *
- * Arguments:
- *
- * lphevt [OUT] contains the handle iff the call succeeds
- *
- * Returns:
- *
- * (HRESULT)
- */
- #ifdef WIN32
- HRESULT
- HrGetConfigEvent (HANDLE FAR * lphevt)
- {
- HANDLE hevt = NULL;
-
- if (!(hevt = CreateEvent (NULL, TRUE, FALSE, lpszConfigEvt)) &&
- !(hevt = OpenEvent (EVENT_MODIFY_STATE, FALSE, lpszConfigEvt)))
- ResultFromScode (MAPI_E_NOT_ENOUGH_RESOURCES);
-
- *lphevt = hevt;
- return hrSuccess;
- }
- #endif /* WIN32 */
-
-
- /*
- * SignalConfigChanged()
- *
- * Purpose:
- *
- * Sets the configuration event such that logged in hooks can update
- * their configuration on the fly.
- *
- * Called from within the service entry when configuration changes
- * are commited.
- */
- #ifdef WIN32
- VOID
- SignalConfigChanged (VOID)
- {
- HANDLE hevt = NULL;
-
- if (hevt = OpenEvent (EVENT_MODIFY_STATE, FALSE, lpszConfigEvt))
- {
- SetEvent (hevt);
- CloseHandle (hevt);
- }
- return;
- }
- #endif /* WIN32 */
-
-
- /*
- * FConfigChanged()
- *
- * Purpose:
- *
- * Tests the configuration event such that logged in hooks can update
- * their configuration on the fly if the configuration has changed.
- *
- * Called from within the SMH object at regualr intervals
- *
- * Returns:
- *
- * TRUE iff the config changed
- *
- */
- #ifdef WIN32
- BOOL
- FConfigChanged (HANDLE hevt)
- {
- ULONG dw;
-
- dw = WaitForSingleObject (hevt, 0);
- Assert (dw != WAIT_ABANDONED);
- return (dw == WAIT_OBJECT_0);
- }
- #endif /* WIN32 */
-
-
- /*
- * SMH_ServiceEntry()
- *
- * Purpose:
- *
- * The ServiceEntry() function is the MAPI entry point to configure
- * a service for use in a profile. The call can then bring up UI to
- * ensure configuration of the SMH provider.
- *
- * Parameters:
- *
- * hinst DLL instance
- * lpmalloc OLE style allocator (used by PropSheet())
- * lpsup MAPI profile support object
- * ulUIParam hwnd that is to be used as UI parent
- * ulFlags configuration flags
- * ulContext configuration action
- * cval count of caller supplied properties
- * lpval caller supplied properties to be configured
- * lpadmin IProviderAdmin object
- * lppmerr [OUT] extended error information
- *
- * Operation:
- *
- * The ServiceEntry() uses the IProviderAdmin object to open its
- * profile section and retrieve the current set of properties. The
- * caller supplied properties are then merged into the set of
- * current properties.
- *
- * If either this set of properties is not sufficient for
- * configuration or the caller specifically asked for configuration
- * UI, then ServiceEntry() will make calls to bring up its config
- * UI.
- *
- * ServiceEntry() recognizes several configuration flags. If
- * SERVICE_UI_ALWAYS and/or SERVICE_UI_ALLOWED are set, UI is
- * allowed and we be brought up if appropriate. Is
- * MSG_SERVICE_UI_READ_ONLY is set, then the UI should not
- * allow the configuration to be modified.
- *
- * The configuration contexts MSG_SERVICE_DELETE, MSG_SERVICE_INSTALL,
- * and MSG_SERVICE_UNINSTALL are ignored and no action is taken.
- * MSG_SERVICE_CONFIGURE and MSG_SERVICE_CREATE allow the caller to
- * create or update the configuration properties in this providers
- * profile section.
- *
- * SMH will not return extended information in the MAPIERROR in case
- * of error
- */
- HRESULT STDAPICALLTYPE
- SMH_ServiceEntry(
- HINSTANCE hinst,
- LPMALLOC lpmalloc,
- LPMAPISUP lpsup,
- ULONG ulUIParam,
- ULONG ulFlags,
- ULONG ulContext,
- ULONG cval,
- LPSPropValue lpval,
- LPPROVIDERADMIN lpadmin,
- LPMAPIERROR FAR * lppmerr)
- {
- HRESULT hr = hrSuccess;
- BOOL fUI = FALSE;
- BOOL fSave = FALSE;
- LPALLOCATEBUFFER lpfnAlloc = NULL;
- LPALLOCATEMORE lpfnAllocMore = NULL;
- LPFREEBUFFER lpfnFree = NULL;
- LPPROFSECT lpprof = NULL;
- LPPROFSECT lpprofSvc = NULL;
- LPSPropValue lpvalCur = NULL;
- LPSPropValue lpvalNew = NULL;
- LPSMHDLG lpsmhdlg = NULL;
- ULONG cvalCur;
- ULONG cvalNew;
- ULONG ulMyFlags;
-
- if ((ulContext == MSG_SERVICE_INSTALL) ||
- (ulContext == MSG_SERVICE_UNINSTALL))
- goto ret;
-
- if ((ulContext != MSG_SERVICE_CONFIGURE) &&
- (ulContext != MSG_SERVICE_CREATE) &&
- (ulContext != MSG_SERVICE_DELETE))
- {
- hr = ResultFromScode (MAPI_E_NO_SUPPORT);
- goto ret;
- }
-
- if (ulFlags & MAPI_UNICODE)
- {
- /* Unicode is not supported by SMH */
-
- hr = ResultFromScode (MAPI_E_BAD_CHARWIDTH);
- goto ret;
- }
-
- /* Find out our UI options */
-
- fUI = !!(ulFlags & SERVICE_UI_ALWAYS);
- ulMyFlags = (ulFlags & MSG_SERVICE_UI_READ_ONLY)
- ? UI_READONLY
- : 0;
-
- /* Get memory routines */
-
- hr = lpsup->lpVtbl->GetMemAllocRoutines (lpsup,
- &lpfnAlloc,
- &lpfnAllocMore,
- &lpfnFree);
- if (HR_FAILED (hr))
- goto ret;
-
- /* Open the profile section */
-
- hr = HrOpenSingleProvider (lpadmin, &lpprof);
- if (HR_FAILED (hr))
- goto ret;
-
- /* Get the values already in the profile */
-
- hr = lpprof->lpVtbl->GetProps (lpprof,
- (LPSPropTagArray)&sptConfigProps,
- 0,
- &cvalCur,
- &lpvalCur);
- if (HR_FAILED (hr))
- goto ret;
-
- if (ulContext != MSG_SERVICE_DELETE)
- {
- /* Merge what was in the profile with what was passed in */
-
- hr = HrMergeValues (cvalCur,
- lpvalCur,
- cval,
- lpval,
- lpfnAlloc,
- &cvalNew,
- &lpvalNew);
- if (HR_FAILED (hr))
- goto ret;
-
- /* If we dont have all the props we need, then
- * we will have to ask for them
- */
- fUI |= (REQ_PROPS != (UlChkReqProps (cvalNew, lpvalNew) & REQ_PROPS));
- if ((REQ_PROPS != (UlChkReqProps (cvalNew, lpvalNew) & REQ_PROPS)) &&
- (!(ulFlags & (SERVICE_UI_ALLOWED | SERVICE_UI_ALWAYS)) ||
- (ulFlags & MSG_SERVICE_UI_READ_ONLY)))
- {
- /* We need UI but can't have it. */
-
- hr = ResultFromScode (MAPI_E_UNCONFIGURED);
- goto ret;
- }
-
- if (fUI)
- {
- /* Do the config dialog */
-
- if (!FAILED ((*lpfnAlloc) (sizeof(SMHDLG), &lpsmhdlg)))
- {
- memset (lpsmhdlg, 0, sizeof(SMHDLG));
- lpsmhdlg->hinst = hinst;
- lpsmhdlg->hwnd = (HWND)ulUIParam;
- lpsmhdlg->lpfnAlloc = lpfnAlloc;
- lpsmhdlg->lpfnAllocMore = lpfnAllocMore;
- lpsmhdlg->lpfnFree = lpfnFree;
- lpsmhdlg->lpmalloc = lpmalloc;
- lpsmhdlg->lpspt = (LPSPropTagArray)&sptConfigProps;
- lpsmhdlg->lpvalSMH = lpvalNew;
- lpsmhdlg->lpsec = lpprof;
- lpsmhdlg->lpsup = lpsup;
- lpsmhdlg->lpadmin = lpadmin;
- lpsmhdlg->ulFlags = ulMyFlags;
- hr = HrDisplayPropSheets (hinst, (HWND)ulUIParam, lpsmhdlg);
- fSave = lpsmhdlg->fDirty;
- (*lpfnFree) (lpsmhdlg);
- }
- else
- {
- hr = ResultFromScode (MAPI_E_NOT_ENOUGH_MEMORY);
- goto ret;
- }
- }
-
- /* Set what we got and save the changes */
-
- if (fSave)
- {
- HRESULT hrT;
-
- hrT = lpprof->lpVtbl->SaveChanges (lpprof, 0);
- if (HR_FAILED (hrT))
- {
- hr = hrT;
- goto ret;
- }
- SignalConfigChanged ();
- }
-
- /* Open the service profile section and set PR_SERVICE_EXTRA_UIDS */
-
- if (!HR_FAILED (lpadmin->lpVtbl->OpenProfileSection (lpadmin,
- NULL,
- NULL,
- MAPI_MODIFY,
- &lpprofSvc)))
- {
- lpvalNew[ipRules].ulPropTag = PR_SERVICE_EXTRA_UIDS;
- if (!HR_FAILED (HrSetOneProp ((LPMAPIPROP)lpprofSvc, &lpvalNew[ipRules])))
- (void)lpprofSvc->lpVtbl->SaveChanges (lpprofSvc, 0);
-
- UlRelease (lpprofSvc);
- }
- }
-
- ret:
-
- if (lpfnFree)
- {
- (*lpfnFree) (lpvalCur);
- (*lpfnFree) (lpvalNew);
- }
-
- UlRelease (lpprof);
- DebugTraceResult (SMH_ServiceEntry, hr);
- return hr;
- };
-