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

  1. /*
  2.  *  S M H P S . C
  3.  *
  4.  *  Sample mail handling hook configuration property sheets
  5.  *  Copyright 1992-95 Microsoft Corporation.  All Rights Reserved.
  6.  */
  7.  
  8. #include "_pch.h"
  9.  
  10. #ifndef WIN16
  11. #include <commctrl.h>
  12. #endif
  13.  
  14. extern LPTSTR lpszConfigEvt;
  15. extern SPropTagArray sptRule;
  16. extern SPropTagArray sptConfigProps;
  17.  
  18.  
  19. /*
  20.  *  sptDelEid
  21.  *
  22.  *  This is the set of properties that need to be deleted from a rule
  23.  *  profile section any time the rule is edited.  Otherwise, changes in
  24.  *  target folders may not be retained across edits.
  25.  */
  26. const static SizedSPropTagArray (2, sptDelEid) =
  27. {
  28.     2,
  29.     {
  30.         PR_RULE_TARGET_ENTRYID,
  31.         PR_RULE_STORE_ENTRYID
  32.     }
  33. };
  34.  
  35.  
  36. /*
  37.  *  SizeODButtons()
  38.  *
  39.  *  Purpose:
  40.  *
  41.  *      Set the control size for the two owner-draw buttons in the filter
  42.  *      page of the configuration property sheets.
  43.  *
  44.  *  Arguments:
  45.  *
  46.  *      hinst       the DLL instance
  47.  *      hdlg        the dialog in which the buttons will be drawn
  48.  */
  49. VOID
  50. SizeODButtons (HINSTANCE hInst, HWND hdlg)
  51. {
  52.     BITMAP  bitmap;
  53.     HBITMAP hbmp;
  54.  
  55.     if (!(hbmp = LoadBitmap (hInst, MAKEINTRESOURCE(ID_UpArrow))))
  56.         return;
  57.     GetObject (hbmp, sizeof(BITMAP), &bitmap);
  58.     SetWindowPos (GetDlgItem (hdlg, ID_FilterUp), NULL, 0, 0, bitmap.bmWidth,
  59.         bitmap.bmHeight, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
  60.     SetWindowPos (GetDlgItem (hdlg, ID_FilterDown), NULL, 0, 0, bitmap.bmWidth,
  61.         bitmap.bmHeight, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
  62.  
  63.     DeleteBitmap (hbmp);
  64. }
  65.  
  66.  
  67. /*
  68.  *  DrawODButton()
  69.  *
  70.  *  Purpose:
  71.  *
  72.  *      Draws the button control for either of the two owner-draw buttons
  73.  *      in the filter page of the configuration property sheets.
  74.  *
  75.  *  Arguments:
  76.  *
  77.  *      hinst       the DLL instance
  78.  *      pdi         the DRAWITEMSTRUCT info for drawing the button
  79.  */
  80. VOID
  81. DrawODButton (HINSTANCE hInst, DRAWITEMSTRUCT FAR * lpdi)
  82. {
  83.     HDC hDC;
  84.     HBITMAP hbmpOld;
  85.     HBITMAP hbmpArw;
  86.     WORD wBtnRes;
  87.     BITMAP bitmap;
  88.  
  89.     Assert (lpdi->CtlType == ODT_BUTTON);
  90.     if (!(hDC = CreateCompatibleDC (lpdi->hDC)))
  91.         return;
  92.  
  93.     /* Get the bitmap */
  94.  
  95.     if (lpdi->itemState & ODS_SELECTED)
  96.         wBtnRes = (lpdi->CtlID == ID_FilterUp) ? ID_UpArrowInv : ID_DownArrowInv;
  97.     else if (lpdi->itemState & ODS_DISABLED)
  98.         wBtnRes = (lpdi->CtlID == ID_FilterUp) ? ID_UpArrowDis : ID_DownArrowDis;
  99.     else
  100.         wBtnRes = (lpdi->CtlID == ID_FilterUp) ? ID_UpArrow : ID_DownArrow;
  101.  
  102.     /* blit the bitmap */
  103.  
  104.     if (!(hbmpArw = CreateMappedBitmap (hInst, wBtnRes, FALSE, NULL, 0)))
  105.         goto err;
  106.     hbmpOld = SelectObject (hDC, hbmpArw);
  107.     BitBlt (lpdi->hDC, 0, 0, lpdi->rcItem.right - lpdi->rcItem.left,
  108.         lpdi->rcItem.bottom - lpdi->rcItem.top, hDC, 0, 0, SRCCOPY);
  109.  
  110.     /* Draw a focus rectangle if the button has the focus */
  111.  
  112.     if(lpdi->itemState & ODS_FOCUS)
  113.     {
  114.         GetObject (hbmpArw, sizeof(BITMAP), &bitmap);
  115.         lpdi->rcItem.right = bitmap.bmWidth;
  116.         lpdi->rcItem.bottom = bitmap.bmHeight;
  117.         InflateRect (&lpdi->rcItem, -3, -3);
  118.         if (lpdi->itemState & ODS_SELECTED)
  119.             OffsetRect (&lpdi->rcItem, 1, 1);
  120.         DrawFocusRect (lpdi->hDC, &lpdi->rcItem);
  121.     }
  122.  
  123.     SelectObject (hDC, hbmpOld);
  124.     DeleteBitmap (hbmpArw);
  125. err:
  126.     DeleteDC (hDC);
  127. }
  128.  
  129.  
  130. /*
  131.  *  HrDeleteOneProp()
  132.  *
  133.  *  Purpose:
  134.  *
  135.  *      Small wrapper that allows the deletion of a single property.
  136.  *
  137.  *  Arguments:
  138.  *
  139.  *      lpmp        the IMAPIPROP object
  140.  *      ulPropTag   the property to delete
  141.  *
  142.  *  Returns:
  143.  *
  144.  *      (HRESULT)
  145.  */
  146. HRESULT
  147. HrDeleteOneProp (LPMAPIPROP lpmp, ULONG ulPropTag)
  148. {
  149.     SizedSPropTagArray (1,spt) = {1,{ulPropTag}};
  150.     return lpmp->lpVtbl->DeleteProps (lpmp, (LPSPropTagArray)&spt, NULL);
  151. }
  152.  
  153.  
  154. /*
  155.  *  FilterDesc_INITDIALOG()
  156.  *
  157.  *  Purpose:
  158.  *
  159.  *      Handles the WM_INITDIALOG message for the filter description
  160.  *      dialog.
  161.  *
  162.  *      The values for the current filter are passed in via the
  163.  *      short-term property value pointer in the SMHDLG struct.  The
  164.  *      values are then scanned and processed to fill out the state of
  165.  *      the dialog.
  166.  */
  167. BOOL
  168. FilterDesc_INITDIALOG (HWND hdlg, HWND hwndFocus, LPARAM lParam)
  169. {
  170.     BOOL fDisableOk = FALSE;
  171.     LPSPropValue lpval;
  172.  
  173.     MakeDlg3D (hdlg);
  174.     Edit_LimitText (GetDlgItem (hdlg, ID_Name), cchRuleMax);
  175.     SetWindowLong (hdlg, DWL_USER, lParam);
  176.     if (lpval = ((LPSMHDLG)lParam)->lpval)
  177.     {
  178.         Assert (!IsBadReadPtr (lpval, sizeof(SPropValue) * cpRLMax));
  179.         if (lpval[ipDisp].ulPropTag == PR_DISPLAY_NAME)
  180.             Edit_SetText (GetDlgItem (hdlg, ID_Name), lpval[ipDisp].Value.LPSZ);
  181.  
  182.         if (lpval[ipType].ulPropTag == PR_RULE_TYPE)
  183.         {
  184.             switch (lpval[ipType].Value.l)
  185.             {
  186.               case RL_RECIP:
  187.                 CheckRadioButton (hdlg, ID_Subject, ID_HasAttach, ID_AnyRecip);
  188.                 break;
  189.               case RL_TO:
  190.                 CheckRadioButton (hdlg, ID_Subject, ID_HasAttach, ID_ToRecip);
  191.                 break;
  192.               case RL_CC:
  193.                 CheckRadioButton (hdlg, ID_Subject, ID_HasAttach, ID_CcRecip);
  194.                 break;
  195.               case RL_BCC:
  196.                 CheckRadioButton (hdlg, ID_Subject, ID_HasAttach, ID_BccRecip);
  197.                 break;
  198.               case RL_SUBJECT:
  199.                 CheckRadioButton (hdlg, ID_Subject, ID_HasAttach, ID_Subject);
  200.                 break;
  201.               case RL_FROM:
  202.                 CheckRadioButton (hdlg, ID_Subject, ID_HasAttach, ID_Sender);
  203.                 break;
  204.               case RL_ATTACH:
  205.                 CheckRadioButton (hdlg, ID_Subject, ID_HasAttach, ID_HasAttach);
  206.                 break;
  207.               case RL_BODY:
  208.                 CheckRadioButton (hdlg, ID_Subject, ID_HasAttach, ID_Body);
  209.                 break;
  210.               case RL_CLASS:
  211.                 CheckRadioButton (hdlg, ID_Subject, ID_HasAttach, ID_MsgClass);
  212.                 break;
  213.               default:
  214.                 fDisableOk = TRUE;
  215.                 break;
  216.             }
  217.         }
  218.         else
  219.             fDisableOk = TRUE;
  220.  
  221.         if (lpval[ipData].ulPropTag == PR_RULE_DATA)
  222.             Edit_SetText (GetDlgItem (hdlg, ID_Value), lpval[ipData].Value.bin.lpb);
  223.         else
  224.             fDisableOk = TRUE;
  225.  
  226.         /* An empty or missing value here implies uses the default store */
  227.  
  228.         if (lpval[ipStore].ulPropTag == PR_RULE_STORE_DISPLAY_NAME)
  229.             Edit_SetText (GetDlgItem (hdlg, ID_Store), lpval[ipStore].Value.LPSZ);
  230.  
  231.         if (lpval[ipPath].ulPropTag == PR_RULE_TARGET_PATH)
  232.             Edit_SetText (GetDlgItem (hdlg, ID_Folder), lpval[ipPath].Value.LPSZ);
  233.         else
  234.             fDisableOk = TRUE;
  235.  
  236.         if (lpval[ipSound].ulPropTag == PR_RULE_SOUND_FILENAME)
  237.             Edit_SetText (GetDlgItem (hdlg, ID_Sound), lpval[ipSound].Value.LPSZ);
  238.         
  239.         if (lpval[ipRLFlags].ulPropTag == PR_RULE_FLAGS)
  240.         {
  241.             CheckDlgButton (hdlg, ID_NotMatch,
  242.                     !!(lpval[ipRLFlags].Value.l & RULE_NOT));
  243.             CheckDlgButton (hdlg, ID_TerminalTarg,
  244.                     !!(lpval[ipRLFlags].Value.l & RULE_TERMINAL));
  245.             CheckDlgButton (hdlg, ID_ArchTarg,
  246.                     !!(lpval[ipRLFlags].Value.l & RULE_ARCHIVED));
  247.             CheckDlgButton (hdlg, ID_ArchTargYr,
  248.                     !!(lpval[ipRLFlags].Value.l & RULE_ARCHIVED_BY_YEAR));
  249.             EnableWindow (GetDlgItem (hdlg, ID_ArchTargYr),
  250.                     !!(lpval[ipRLFlags].Value.l & RULE_ARCHIVED));
  251.  
  252.             if (lpval[ipRLFlags].Value.l & RULE_DELETE)
  253.             {
  254.                 CheckRadioButton (hdlg, ID_FilterMsg, ID_DeleteMsg, ID_DeleteMsg);
  255.                 EnableWindow (GetDlgItem (hdlg, ID_FolderTxt), FALSE);
  256.                 EnableWindow (GetDlgItem (hdlg, ID_Folder), FALSE);
  257.                 EnableWindow (GetDlgItem (hdlg, ID_StoreTxt), FALSE);
  258.                 EnableWindow (GetDlgItem (hdlg, ID_Store), FALSE);
  259.                 EnableWindow (GetDlgItem (hdlg, ID_SoundTxt), FALSE);
  260.                 EnableWindow (GetDlgItem (hdlg, ID_Sound), FALSE);
  261.                 EnableWindow (GetDlgItem (hdlg, ID_TerminalTarg), FALSE);
  262.                 EnableWindow (GetDlgItem (hdlg, ID_ArchTarg), FALSE);
  263.                 EnableWindow (GetDlgItem (hdlg, ID_ArchTargYr), FALSE);
  264.             }
  265.             else
  266.                 CheckRadioButton (hdlg, ID_FilterMsg, ID_DeleteMsg, ID_FilterMsg);
  267.         }
  268.         else
  269.         {
  270.             Button_Enable (GetDlgItem (hdlg, ID_ArchTargYr), FALSE);
  271.             CheckRadioButton (hdlg, ID_FilterMsg, ID_DeleteMsg, ID_FilterMsg);
  272.         }
  273.  
  274.         Button_Enable (GetDlgItem (hdlg, IDOK), !fDisableOk);
  275.     }
  276.     return TRUE;
  277. }
  278.  
  279.  
  280. /*
  281.  *  FilterDesc_COMMAND()
  282.  *
  283.  *  Purpose:
  284.  *
  285.  *      Handles the WM_COMMAND message for the filter description dialog
  286.  *
  287.  *      On IDOK, the values from the dialog are processed into the rule
  288.  *      properties and placed in the property value array hanging off of
  289.  *      the SMHDLG structure.
  290.  */
  291. BOOL FilterDesc_COMMAND (HWND hdlg, UINT id, HWND hwndCtl, UINT codeNotify)
  292. {
  293.     SCODE sc;
  294.     BOOL fCheck;
  295.     HWND hctrl;
  296.     LPSMHDLG lpsmhdlg;
  297.     LPSPropValue lpval;
  298.     LPTSTR lpsz = NULL;
  299.     UINT cb;
  300.  
  301.     lpsmhdlg = (LPSMHDLG)GetWindowLong (hdlg, DWL_USER);
  302.     lpval = lpsmhdlg->lpval;
  303.  
  304.     switch (id)
  305.     {
  306.       case IDOK:
  307.  
  308.         /* Get the rule name */
  309.  
  310.         hctrl = GetDlgItem (hdlg, ID_Name);
  311.         cb = Edit_GetTextLength (hctrl) + 1;
  312.         sc = (*lpsmhdlg->lpfnAllocMore) (cb, lpval, &(lpval[ipDisp].Value.lpszA));
  313.         if (FAILED (sc))
  314.             goto err;
  315.         memset (lpval[ipDisp].Value.LPSZ, 0, cb);
  316.         lpval[ipDisp].ulPropTag = PR_DISPLAY_NAME;
  317.         Edit_GetText (hctrl, lpval[ipDisp].Value.LPSZ, cb);
  318.  
  319.         /* Rule type */
  320.  
  321.         lpval[ipType].ulPropTag = PR_RULE_TYPE;
  322.  
  323.         /* Rule data */
  324.  
  325.         hctrl = GetDlgItem (hdlg, ID_Value);
  326.         cb = Edit_GetTextLength (hctrl) + 1;
  327.         sc = (*lpsmhdlg->lpfnAllocMore) (cb, lpval, &lpval[ipData].Value.bin.lpb);
  328.         if (FAILED (sc))
  329.             goto err;
  330.         memset (lpval[ipData].Value.bin.lpb, 0, cb);
  331.         lpval[ipData].ulPropTag = PR_RULE_DATA;
  332.         Edit_GetText (hctrl, lpval[ipData].Value.bin.lpb, cb);
  333.         lpval[ipData].Value.bin.cb = (ULONG)cb;
  334.  
  335.         /* Target store EID */
  336.  
  337.         lpval[ipSEID].ulPropTag = PR_NULL;
  338.  
  339.         /* Target store */
  340.  
  341.         hctrl = GetDlgItem (hdlg, ID_Store);
  342.         cb = Edit_GetTextLength (hctrl) + 1;
  343.         sc = (*lpsmhdlg->lpfnAllocMore) (cb, lpval, &(lpval[ipStore].Value.lpszA));
  344.         if (FAILED (sc))
  345.             goto err;
  346.         memset (lpval[ipStore].Value.LPSZ, 0, cb);
  347.         lpval[ipStore].ulPropTag = PR_RULE_STORE_DISPLAY_NAME;
  348.         Edit_GetText (hctrl, lpval[ipStore].Value.LPSZ, cb);
  349.  
  350.         /* Target folder EID */
  351.  
  352.         lpval[ipEID].ulPropTag = PR_NULL;
  353.  
  354.         /* Target folder */
  355.  
  356.         hctrl = GetDlgItem (hdlg, ID_Folder);
  357.         cb = Edit_GetTextLength (hctrl) + 1;
  358.         sc = (*lpsmhdlg->lpfnAllocMore) (cb, lpval, &(lpval[ipPath].Value.lpszA));
  359.         if (FAILED (sc))
  360.             goto err;
  361.         memset (lpval[ipPath].Value.LPSZ, 0, cb);
  362.         lpval[ipPath].ulPropTag = PR_RULE_TARGET_PATH;
  363.         Edit_GetText (hctrl, lpval[ipPath].Value.LPSZ, cb);
  364.  
  365.         /* Sound */
  366.  
  367.         hctrl = GetDlgItem (hdlg, ID_Sound);
  368.         cb = Edit_GetTextLength (hctrl) + 1;
  369.         sc = (*lpsmhdlg->lpfnAllocMore) (cb, lpval, &(lpval[ipSound].Value.lpszA));
  370.         if (FAILED (sc))
  371.             goto err;
  372.         memset (lpval[ipSound].Value.LPSZ, 0, cb);
  373.         lpval[ipSound].ulPropTag = PR_RULE_SOUND_FILENAME;
  374.         Edit_GetText (hctrl, lpval[ipSound].Value.LPSZ, cb);
  375.  
  376.         /* Flags */
  377.  
  378.         lpval[ipRLFlags].ulPropTag = PR_RULE_FLAGS;
  379.         lpval[ipRLFlags].Value.l = 0;
  380.         if (IsDlgButtonChecked (hdlg, ID_ArchTarg))
  381.         {
  382.             lpval[ipRLFlags].Value.l |= RULE_ARCHIVED;
  383.  
  384.             if (IsDlgButtonChecked (hdlg, ID_ArchTargYr))
  385.                 lpval[ipRLFlags].Value.l |= RULE_ARCHIVED_BY_YEAR;
  386.         }
  387.         if (IsDlgButtonChecked (hdlg, ID_NotMatch))
  388.             lpval[ipRLFlags].Value.l |= RULE_NOT;
  389.         if (IsDlgButtonChecked (hdlg, ID_TerminalTarg))
  390.             lpval[ipRLFlags].Value.l |= RULE_TERMINAL;
  391.         if (IsDlgButtonChecked (hdlg, ID_DeleteMsg))
  392.             lpval[ipRLFlags].Value.l |= RULE_DELETE;
  393.  
  394. err:
  395.         lpsmhdlg->sc = sc;
  396.         break;
  397.  
  398.       case IDCANCEL:
  399.         break;
  400.  
  401.       case ID_AnyRecip:
  402.         lpval[ipType].Value.l = RL_RECIP;
  403.         return TRUE;
  404.  
  405.       case ID_ToRecip:
  406.         lpval[ipType].Value.l = RL_TO;
  407.         return TRUE;
  408.  
  409.       case ID_CcRecip:
  410.         lpval[ipType].Value.l = RL_CC;
  411.         return TRUE;
  412.  
  413.       case ID_BccRecip:
  414.         lpval[ipType].Value.l = RL_BCC;
  415.         return TRUE;
  416.  
  417.       case ID_Subject:
  418.         lpval[ipType].Value.l = RL_SUBJECT;
  419.         return TRUE;
  420.  
  421.       case ID_Sender:
  422.         lpval[ipType].Value.l = RL_FROM;
  423.         return TRUE;
  424.  
  425.       case ID_HasAttach:
  426.         lpval[ipType].Value.l = RL_ATTACH;
  427.         return TRUE;
  428.  
  429.       case ID_Body:
  430.         lpval[ipType].Value.l = RL_BODY;
  431.         return TRUE;
  432.  
  433.       case ID_MsgClass:
  434.         lpval[ipType].Value.l = RL_CLASS;
  435.         return TRUE;
  436.  
  437.       case ID_FilterMsg:
  438.       case ID_DeleteMsg:
  439.         fCheck = IsDlgButtonChecked (hdlg, ID_FilterMsg);
  440.         EnableWindow (GetDlgItem (hdlg, ID_FolderTxt), fCheck);
  441.         EnableWindow (GetDlgItem (hdlg, ID_Folder), fCheck);
  442.         EnableWindow (GetDlgItem (hdlg, ID_StoreTxt), fCheck);
  443.         EnableWindow (GetDlgItem (hdlg, ID_Store), fCheck);
  444.         EnableWindow (GetDlgItem (hdlg, ID_SoundTxt), fCheck);
  445.         EnableWindow (GetDlgItem (hdlg, ID_Sound), fCheck);
  446.         EnableWindow (GetDlgItem (hdlg, ID_TerminalTarg), fCheck);
  447.         EnableWindow (GetDlgItem (hdlg, ID_ArchTarg), fCheck);
  448.         EnableWindow (GetDlgItem (hdlg, ID_ArchTargYr), fCheck && IsDlgButtonChecked (hdlg, ID_ArchTarg));
  449.         return TRUE;
  450.  
  451.       case ID_ArchTarg:
  452.         EnableWindow (GetDlgItem (hdlg, ID_ArchTargYr), IsDlgButtonChecked (hdlg, ID_ArchTarg));
  453.         return TRUE;
  454.  
  455.       default:
  456.         return FALSE;
  457.     }
  458.  
  459.     EndDialog (hdlg, id);
  460.     return TRUE;
  461. }
  462.  
  463.  
  464. /*
  465.  *  FilterDescProc()
  466.  *
  467.  *  Purpose:
  468.  *
  469.  *      Dispatches window messages to the proper function for processing
  470.  */
  471. BOOL CALLBACK
  472. FilterDescProc (HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  473. {
  474.     switch (msg)
  475.     {
  476.       case WM_INITDIALOG:
  477.  
  478.         FHandleWm (FilterDesc, hdlg, INITDIALOG, wParam, lParam);
  479.         return TRUE;
  480.  
  481.       case WM_COMMAND:
  482.  
  483.         FHandleWm (FilterDesc, hdlg, COMMAND, wParam, lParam);
  484.         Button_Enable (GetDlgItem(hdlg, IDOK),
  485.                 Edit_GetTextLength (GetDlgItem (hdlg, ID_Name)) &&
  486.                 Edit_GetTextLength (GetDlgItem (hdlg, ID_Value)) &&
  487.                 ((Edit_GetTextLength (GetDlgItem (hdlg, ID_Folder)) &&
  488.                   Edit_GetTextLength (GetDlgItem (hdlg, ID_Store))) ||
  489.                  IsDlgButtonChecked (hdlg, ID_DeleteMsg)) &&
  490.                 ((LPSMHDLG)GetWindowLong (hdlg, DWL_USER))->lpval[ipType].Value.l);
  491.         break;
  492.  
  493.       case WM_DRAWITEM:
  494.  
  495.         break;
  496.  
  497.       case WM_DESTROY:
  498.  
  499.         break;
  500.     }
  501.     return FALSE;
  502. }
  503.  
  504.  
  505. /*
  506.  *  ScEditFilterDesc()
  507.  *
  508.  *  Purpose:
  509.  *
  510.  *      Brings up the filter description dialog for the rule properties
  511.  *      found in the profile section muid passed in.
  512.  *
  513.  *  Arguments:
  514.  *
  515.  *      lpsmhdlg        the SMH dialog structure
  516.  *      hdlg            the parent dialog for the filter description
  517.  *      lpmuid          the profile secion UID
  518.  *      lppval  [OUT]   contains a pointer to the filter properties
  519.  *                      iff the call is succeeds
  520.  *
  521.  *  Returns:
  522.  *
  523.  *      (HRESULT)
  524.  *      lppval  [OUT]   this can be used to determine the name of the
  525.  *                      edited rule
  526.  */
  527. SCODE
  528. ScEditFilterDesc (LPSMHDLG lpsmhdlg,
  529.     HWND hdlg,
  530.     UINT ulFlags,
  531.     LPMAPIUID lpmuid,
  532.     LPSPropValue FAR * lppval)
  533. {
  534.     HRESULT hr;
  535.     LPPROFSECT lpsec = NULL;
  536.     LPSPropValue lpval = NULL;
  537.     ULONG cval;
  538.     UINT id;
  539.  
  540.     if (ulFlags == NEW_RULE)
  541.     {
  542.         hr = lpsmhdlg->lpsup->lpVtbl->NewUID (lpsmhdlg->lpsup, lpmuid);
  543.         if (HR_FAILED (hr))
  544.             goto ret;
  545.     }
  546.  
  547.     hr = lpsmhdlg->lpadmin->lpVtbl->OpenProfileSection (lpsmhdlg->lpadmin,
  548.                                         lpmuid,
  549.                                         NULL,
  550.                                         MAPI_MODIFY,
  551.                                         &lpsec);
  552.     if (HR_FAILED (hr))
  553.         goto ret;
  554.  
  555.     hr = lpsec->lpVtbl->GetProps (lpsec,
  556.                             (LPSPropTagArray)&sptRule,
  557.                             0,
  558.                             &cval,
  559.                             &lpval);
  560.     if (HR_FAILED (hr))
  561.         goto ret;
  562.  
  563.     lpsmhdlg->lpval = lpval;
  564.     id = DialogBoxParam (lpsmhdlg->hinst,
  565.                     MAKEINTRESOURCE (SMH_FilterDesc),
  566.                     GetParent(hdlg),
  567.                     FilterDescProc,
  568.                     (LPARAM)lpsmhdlg);
  569.     switch (id)
  570.     {
  571.       case (UINT)-1:
  572.  
  573.         hr = ResultFromScode (MAPI_E_CALL_FAILED);
  574.         break;
  575.  
  576.       case IDOK:
  577.  
  578.         /* Make changes into profile section */
  579.  
  580.         hr = lpsec->lpVtbl->SetProps (lpsec, cpRLMax, lpval, NULL);
  581.         if (!HR_FAILED (hr))
  582.         {
  583.             /* Delete store/folder entryid in case the path changed */
  584.  
  585.             lpval[ipEID].ulPropTag = PR_NULL;
  586.             lpval[ipSEID].ulPropTag = PR_NULL;
  587.             (void)lpsec->lpVtbl->DeleteProps (lpsec, (LPSPropTagArray)&sptDelEid, NULL);
  588.             hr = lpsec->lpVtbl->SaveChanges (lpsec, 0);
  589.             if (!HR_FAILED (hr))
  590.                 *lppval = lpval;
  591.         }
  592.         break;
  593.  
  594.       case IDCANCEL:
  595.  
  596.         hr = ResultFromScode (MAPI_E_USER_CANCEL);
  597.         break;
  598.     }
  599.  
  600. ret:
  601.  
  602.     UlRelease (lpsec);
  603.     MAPIFreeBuffer (lpsmhdlg->lpval);
  604.     lpsmhdlg->lpval = NULL;
  605.  
  606.     DebugTraceResult (ScEditFilterDesc(), hr);
  607.     return GetScode (hr);
  608. }
  609.  
  610.  
  611. /*
  612.  *  EnableFilterPageCtrls()
  613.  *
  614.  *  Purpose:
  615.  *
  616.  *      Enables the set of buttons on the filter page based on the
  617.  *      current selection in the filter list dialog
  618.  */
  619. VOID
  620. EnableFilterPageCtrls (HWND hdlg)
  621. {
  622.     BOOL fDelete;
  623.     BOOL fDown;
  624.     BOOL fEdit;
  625.     BOOL fUp;
  626.     HWND hctrl = GetDlgItem (hdlg, ID_FilterOrderLB);
  627.     UINT isel = ListBox_GetCurSel (hctrl);
  628.  
  629.     /* Enable Ctrls */
  630.  
  631.     fEdit = fDelete = fUp = fDown = ((isel == LB_ERR) ? FALSE : TRUE);
  632.     if (isel == 0)
  633.     {
  634.         fUp = FALSE;
  635.     }
  636.     if (isel == (UINT)(ListBox_GetCount (hctrl) - 1))
  637.     {
  638.         fDown = FALSE;
  639.     }
  640.  
  641.     Button_Enable (GetDlgItem (hdlg, ID_FilterUp), fUp);
  642.     Button_Enable (GetDlgItem (hdlg, ID_FilterDown), fDown);
  643.     Button_Enable (GetDlgItem (hdlg, ID_EditFilter), fEdit);
  644.     Button_Enable (GetDlgItem (hdlg, ID_RmvFilter), fDelete);
  645. }
  646.  
  647.  
  648. /*
  649.  *  FilterPage_INITDIALOG()
  650.  *
  651.  *  Purpose:
  652.  *
  653.  *      Handles the WM_INITDIALOG message for the filter description
  654.  *      dialog.
  655.  *
  656.  *      The current list of filters are processed and the name is
  657.  *      retrieved for use in the dialog.
  658.  */
  659. BOOL
  660. FilterPage_INITDIALOG (HWND hdlg, HWND hwndFocus, LPARAM lParam)
  661. {
  662.     SCODE sc;
  663.     HRESULT hr;
  664.     HWND hctrl;
  665.     LPMAPIUID lpmuid;
  666.     LPPROFSECT lpsec;
  667.     LPSMHDLG lpsmhdlg = (LPSMHDLG)(((PROPSHEETPAGE *)lParam)->lParam);
  668.     LPSPropValue lpval;
  669.     LPSPropValue lpvalSMH;
  670.     UINT irl = 0;
  671.     UINT crl;
  672.  
  673.     MakeDlg3D (hdlg);
  674.     SizeODButtons (lpsmhdlg->hinst, hdlg);
  675.     SetWindowLong (hdlg, DWL_USER, ((PROPSHEETPAGE *)lParam)->lParam);
  676.  
  677.     /* Load the filter LBX and create the mapping */
  678.  
  679.     if (lpvalSMH = lpsmhdlg->lpvalSMH)
  680.     {
  681.         if (lpvalSMH[ipRules].ulPropTag == PR_SMH_RULES)
  682.         {
  683.             hctrl = GetDlgItem (hdlg, ID_FilterOrderLB);
  684.             lpmuid = (LPMAPIUID)lpvalSMH[ipRules].Value.bin.lpb;
  685.             crl = (UINT)(lpvalSMH[ipRules].Value.bin.cb / sizeof(MAPIUID));
  686.             sc = (*lpsmhdlg->lpfnAlloc) (crl * sizeof(MAPIUID), &lpsmhdlg->lpmuid);
  687.             if (!FAILED (sc))
  688.             {
  689.                 lpsmhdlg->cmuidMax = crl;
  690.                 for (; crl--; lpmuid++)
  691.                 {
  692.                     hr = lpsmhdlg->lpadmin->lpVtbl->OpenProfileSection (lpsmhdlg->lpadmin,
  693.                                                         lpmuid,
  694.                                                         NULL,
  695.                                                         MAPI_MODIFY,
  696.                                                         &lpsec);
  697.                     if (!HR_FAILED (hr))
  698.                     {
  699.                         hr = HrGetOneProp ((LPMAPIPROP)lpsec, PR_DISPLAY_NAME, &lpval);
  700.                         if (!HR_FAILED (hr))
  701.                         {
  702.                             if ((ListBox_AddString (hctrl, lpval->Value.LPSZ) != LB_ERRSPACE)  &&
  703.                                 (ListBox_SetItemData (hctrl, irl, irl) != LB_ERR))
  704.                                 memcpy (&lpsmhdlg->lpmuid[irl++], lpmuid, sizeof(MAPIUID));
  705.                         }
  706.                     }
  707.  
  708.                     (*lpsmhdlg->lpfnFree) (lpval);
  709.                     lpval = NULL;
  710.  
  711.                     UlRelease (lpsec);
  712.                     lpsec = NULL;
  713.                 }
  714.  
  715.                 /* Set the selection to the first filter in the list */
  716.  
  717.                 ListBox_SetCurSel (hctrl, 0);
  718.             }
  719.             else
  720.             {
  721.                 lpsmhdlg->sc = sc;
  722.                 return FALSE;
  723.             }
  724.         }
  725.     }
  726.     lpsmhdlg->cmuid = irl;
  727.     EnableFilterPageCtrls (hdlg);
  728.     return TRUE;
  729. }
  730.  
  731.  
  732. /*
  733.  *  FilterPage_NOTIFY()
  734.  *
  735.  *  Purpose:
  736.  *
  737.  *      Handles the WM_NOTIFY message for the filter description dialog.
  738.  *      On PSN_APPLY, the filter order is computed and set in PR_SMH_RULES.
  739.  */
  740. BOOL
  741. FilterPage_NOTIFY (HWND hdlg, UINT id, NMHDR FAR * lpnmhdr)
  742. {
  743.     switch (lpnmhdr->code)
  744.     {
  745.       case PSN_KILLACTIVE:
  746.       case PSN_RESET:
  747.       case PSN_SETACTIVE:
  748.       default:
  749.  
  750.         break;
  751.  
  752.       case PSN_APPLY:
  753.  
  754.         {
  755.             SCODE sc = S_OK;
  756.             BOOL fWarn = FALSE;
  757.             HWND hctrl = GetDlgItem (hdlg, ID_FilterOrderLB);
  758.             LPMAPIUID lpmuid;
  759.             LPSMHDLG lpsmhdlg = (LPSMHDLG)GetWindowLong (hdlg, DWL_USER);
  760.             LPSPropValue lpval = lpsmhdlg->lpvalSMH;
  761.             UINT cb = lpsmhdlg->cmuid * sizeof(MAPIUID);
  762.             UINT crl;
  763.             UINT imuid;
  764.             UINT irl;
  765.  
  766.             if ((lpval[ipRules].ulPropTag != PR_SMH_RULES) ||
  767.                 (lpval[ipRules].Value.bin.cb < cb))
  768.             {
  769.                 /* There in no room at the inn */
  770.  
  771.                 sc = (*lpsmhdlg->lpfnAllocMore) (cb, lpval, &(lpval[ipRules].Value.bin.lpb));
  772.             }
  773.             if (!FAILED (sc))
  774.             {
  775.                 crl = ListBox_GetCount (hctrl);
  776.                 lpmuid = (LPMAPIUID)lpval[ipRules].Value.bin.lpb;
  777.                 for (cb = 0, irl = 0; irl < crl; irl++, cb += sizeof(MAPIUID))
  778.                 {
  779.                     imuid = (UINT)ListBox_GetItemData (hctrl, irl);
  780.                     memcpy (lpmuid++, &lpsmhdlg->lpmuid[imuid], sizeof(MAPIUID));
  781.                 }
  782.             }
  783.             lpval[ipRules].Value.bin.cb = cb;
  784.             lpval[ipRules].ulPropTag = PR_SMH_RULES;
  785.             sc = GetScode (lpsmhdlg->lpsec->lpVtbl->SetProps (lpsmhdlg->lpsec, cpMax, lpval, NULL));
  786.             lpsmhdlg->sc = (FAILED (sc) ? sc : (fWarn ? MAPI_W_ERRORS_RETURNED : S_OK));
  787.             lpsmhdlg->fDirty = (!FAILED (sc));
  788.         }
  789.         return TRUE;
  790.  
  791. #ifdef PSN_HASHELP
  792.       case PSN_HASHELP:
  793. #endif
  794.       case PSN_HELP:
  795.  
  796.         return TRUE;
  797.     }
  798.  
  799.     return FALSE;
  800. }
  801.  
  802.  
  803. /*
  804.  *  FilterPage_COMMAND()
  805.  *
  806.  *  Purpose:
  807.  *
  808.  *      Handles the WM_COMMAND message for the filter description dialog.
  809.  */
  810. BOOL
  811. FilterPage_COMMAND (HWND hdlg, UINT id, HWND hwndCtl, UINT codeNotify)
  812. {
  813.     SCODE sc;
  814.     HWND hctrl = GetDlgItem (hdlg, ID_FilterOrderLB);
  815.     LPSMHDLG lpsmhdlg = (LPSMHDLG)GetWindowLong (hdlg, DWL_USER);
  816.     LPSPropValue lpval = NULL;
  817.     LPMAPIUID lpmuidT = NULL;
  818.     UINT cb;
  819.     UINT irl = 0;
  820.     UINT imuid;
  821.     ULONG dwData;
  822.  
  823.     irl = ListBox_GetCurSel (hctrl);
  824.     switch (id)
  825.     {
  826.       case ID_NewFilter:
  827.  
  828.         if (lpsmhdlg->cmuid == lpsmhdlg->cmuidMax)
  829.         {
  830.             /* We need to grow the critter */
  831.  
  832.             cb = lpsmhdlg->cmuidMax * sizeof(MAPIUID);
  833.             sc = (*lpsmhdlg->lpfnAlloc) (cb + (GROW_SIZE * sizeof(MAPIUID)), &lpmuidT);
  834.             if (FAILED (sc))
  835.             {
  836.                 lpsmhdlg->sc = sc;
  837.                 break;
  838.             }
  839.             memset (&lpmuidT[lpsmhdlg->cmuid], 0, GROW_SIZE * sizeof(MAPIUID));
  840.  
  841.             if (cb && lpsmhdlg->lpmuid)
  842.                 memcpy (lpmuidT, lpsmhdlg->lpmuid, cb);
  843.  
  844.             (*lpsmhdlg->lpfnFree) (lpsmhdlg->lpmuid);
  845.             lpsmhdlg->lpmuid = lpmuidT;
  846.             lpsmhdlg->cmuidMax += GROW_SIZE;
  847.         }
  848.         imuid = lpsmhdlg->cmuid;
  849.         memset (&lpsmhdlg->lpmuid[imuid], 0, sizeof(MAPIUID));
  850.         sc = ScEditFilterDesc (lpsmhdlg, hdlg, NEW_RULE, &lpsmhdlg->lpmuid[imuid], &lpval);
  851.         if (!FAILED (sc))
  852.         {
  853.             if ((irl = ListBox_AddString (hctrl, lpval[ipDisp].Value.LPSZ)) != LB_ERR)
  854.             {
  855.                 ListBox_SetItemData (hctrl, irl, imuid);
  856.                 ListBox_SetCurSel (hctrl, irl);
  857.                 PropSheet_Changed (GetParent (hdlg), hdlg);
  858.                 lpsmhdlg->cmuid++;
  859.             }
  860.             else
  861.                 sc = MAPI_E_CALL_FAILED;
  862.         }
  863.         lpsmhdlg->sc = sc;
  864.         (*lpsmhdlg->lpfnFree) (lpval);
  865.         break;
  866.  
  867.       case ID_EditFilter:
  868.  
  869.         imuid = (UINT)ListBox_GetItemData (hctrl, irl);
  870.         sc = ScEditFilterDesc (lpsmhdlg, hdlg, EDIT_RULE, &lpsmhdlg->lpmuid[imuid], &lpval);
  871.         if (!FAILED (sc))
  872.         {
  873.             dwData = ListBox_GetItemData (hctrl, irl);
  874.             if ((ListBox_DeleteString (hctrl, irl) == LB_ERR) ||
  875.                 (ListBox_InsertString (hctrl, irl, lpval[ipDisp].Value.LPSZ) == LB_ERRSPACE) ||
  876.                 (ListBox_SetItemData (hctrl, irl, imuid) == LB_ERR))
  877.                 sc = MAPI_E_NOT_ENOUGH_MEMORY;
  878.  
  879.             ListBox_SetCurSel (hctrl, irl);
  880.             PropSheet_Changed (GetParent (hdlg), hdlg);
  881.         }
  882.         lpsmhdlg->sc = sc;
  883.         (*lpsmhdlg->lpfnFree) (lpval);
  884.         break;
  885.  
  886.       case ID_RmvFilter:
  887.  
  888.         if ((irl != LB_ERR) &&
  889.             (ListBox_DeleteString (hctrl, irl) == LB_ERR))
  890.             lpsmhdlg->sc = MAPI_E_CALL_FAILED;
  891.  
  892.         ListBox_SetCurSel (hctrl, irl);
  893.         break;
  894.  
  895.       case ID_FilterDown:
  896.  
  897.         if ((irl == LB_ERR) ||
  898.             (irl == (UINT)(ListBox_GetCount (hctrl) - 1)))
  899.                 break;
  900.  
  901.         dwData = ListBox_GetItemData (hctrl, irl + 1);
  902.         if ((ListBox_GetText (hctrl, irl + 1, lpsmhdlg->rgchT) == LB_ERR) ||
  903.             (dwData == LB_ERR))
  904.         {
  905.             lpsmhdlg->sc = MAPI_E_CALL_FAILED;
  906.             break;
  907.         }
  908.  
  909.         if ((ListBox_DeleteString (hctrl, irl + 1) == LB_ERR) ||
  910.             (ListBox_InsertString (hctrl, irl, lpsmhdlg->rgchT) == LB_ERRSPACE))
  911.         {
  912.             ListBox_ResetContent (hctrl);
  913.             lpsmhdlg->sc = MAPI_E_CALL_FAILED;
  914.             break;
  915.         }
  916.         else
  917.             ListBox_SetItemData (hctrl, irl, dwData);
  918.  
  919.         ListBox_SetCurSel (hctrl, irl + 1);
  920.         PropSheet_Changed (GetParent (hdlg), hdlg);
  921.         break;
  922.  
  923.       case ID_FilterUp:
  924.  
  925.         if ((irl == LB_ERR) || (irl == 0))
  926.             break;
  927.  
  928.         dwData = ListBox_GetItemData (hctrl, irl - 1);
  929.         if ((ListBox_GetText (hctrl, irl - 1, lpsmhdlg->rgchT) == LB_ERR) ||
  930.             (dwData == LB_ERR))
  931.         {
  932.             lpsmhdlg->sc = MAPI_E_CALL_FAILED;
  933.             break;
  934.         }
  935.  
  936.         if ((ListBox_DeleteString (hctrl, irl - 1) == LB_ERR) ||
  937.             (ListBox_InsertString (hctrl, irl, lpsmhdlg->rgchT) == LB_ERRSPACE))
  938.         {
  939.             ListBox_ResetContent (hctrl);
  940.             lpsmhdlg->sc = MAPI_E_CALL_FAILED;
  941.             break;
  942.         }
  943.         else
  944.             ListBox_SetItemData (hctrl, irl, dwData);
  945.  
  946.         ListBox_SetCurSel (hctrl, irl - 1);
  947.         PropSheet_Changed (GetParent (hdlg), hdlg);
  948.         break;
  949.  
  950.       default:
  951.         break;
  952.     }
  953.  
  954.     EnableFilterPageCtrls (hdlg);
  955.     return TRUE;
  956. }
  957.  
  958.  
  959. /*
  960.  *  FilterPageProc()
  961.  *
  962.  *  Purpose:
  963.  *
  964.  *      Dispatches window messages to the proper function for processing
  965.  */
  966. BOOL CALLBACK
  967. FilterPageProc (HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  968. {
  969.     switch (msg)
  970.     {
  971.       case WM_INITDIALOG:
  972.  
  973.         FHandleWm (FilterPage, hdlg, INITDIALOG, wParam, lParam);
  974.         return TRUE;
  975.  
  976.       case WM_COMMAND:
  977.  
  978.         FHandleWm (FilterPage, hdlg, COMMAND, wParam, lParam);
  979.         return TRUE;
  980.  
  981.       case WM_DRAWITEM:
  982.  
  983.         DrawODButton (((LPSMHDLG)GetWindowLong (hdlg, DWL_USER))->hinst,
  984.             (DRAWITEMSTRUCT FAR *)lParam);
  985.         break;
  986.  
  987.       case WM_DESTROY:
  988.  
  989.         break;
  990.  
  991.       case WM_NOTIFY:
  992.  
  993.         return FHandleWm (FilterPage, hdlg, NOTIFY, wParam, lParam);
  994.     }
  995.  
  996.     return FALSE;
  997. }
  998.  
  999.  
  1000. /*
  1001.  *  GeneralPage_INITDAILOG()
  1002.  *
  1003.  *  Purpose:
  1004.  *
  1005.  *      Handles the WM_INITDIALOG message for the filter description dialog
  1006.  */
  1007. BOOL
  1008. GeneralPage_INITDIALOG (HWND hdlg, HWND hwndFocus, LPARAM lParam)
  1009. {
  1010.     LPSMHDLG lpsmhdlg = (LPSMHDLG)(((PROPSHEETPAGE *)lParam)->lParam);
  1011.     LPSPropValue lpval = lpsmhdlg->lpvalSMH;
  1012.     ULONG ulFlags;
  1013.  
  1014.     MakeDlg3D (hdlg);
  1015.     SetWindowLong (hdlg, DWL_USER, ((PROPSHEETPAGE *)lParam)->lParam);
  1016.  
  1017.     ulFlags = (lpval[ipSMHFlags].ulPropTag == PR_SMH_FLAGS)
  1018.                 ? lpval[ipSMHFlags].Value.l
  1019.                 : 0;
  1020.  
  1021.     /* Enable/check the checkboxes based on SMH flags */
  1022.  
  1023.     CheckDlgButton (hdlg, ID_SentMail, !!(ulFlags & SMH_FILTER_SENTMAIL));
  1024.     CheckDlgButton (hdlg, ID_SentMailYr, !!(ulFlags & SMH_FILTER_SENTMAIL_YR));
  1025.     CheckDlgButton (hdlg, ID_Deleted, !!(ulFlags & SMH_FILTER_DELETED));
  1026.     CheckDlgButton (hdlg, ID_DeletedYr, !!(ulFlags & SMH_FILTER_DELETED_YR));
  1027.     CheckDlgButton (hdlg, ID_Inbound, !!(ulFlags & SMH_FILTER_INBOUND));
  1028.     CheckDlgButton (hdlg, ID_Unread, !!(ulFlags & SMH_UNREAD_VIEWER));
  1029.     EnableWindow (GetDlgItem (hdlg, ID_DeletedYr), !!(ulFlags & SMH_FILTER_DELETED));
  1030.     EnableWindow (GetDlgItem (hdlg, ID_SentMailYr), !!(ulFlags & SMH_FILTER_SENTMAIL));
  1031.     lpval[ipSMHFlags].ulPropTag = PR_SMH_FLAGS;
  1032.     lpval[ipSMHFlags].Value.l = ulFlags;
  1033.     return TRUE;
  1034. }
  1035.  
  1036. /*
  1037.  *  GeneralPage_NOTIFY()
  1038.  *
  1039.  *  Purpose:
  1040.  *
  1041.  *      Handles the WM_NOTIFY message for the filter description dialog.
  1042.  *      On PSN_APPLY, SMHFlags is recomputed from the checkbox states.
  1043.  */
  1044. BOOL
  1045. GeneralPage_NOTIFY (HWND hdlg, UINT id, NMHDR FAR * lpnmhdr)
  1046. {
  1047.     switch (lpnmhdr->code)
  1048.     {
  1049.       case PSN_KILLACTIVE:
  1050.       case PSN_RESET:
  1051.       case PSN_SETACTIVE:
  1052.       default:
  1053.  
  1054.         break;
  1055.  
  1056.       case PSN_APPLY:
  1057.         {
  1058.             LPSMHDLG lpsmhdlg = (LPSMHDLG)GetWindowLong (hdlg, DWL_USER);
  1059.             LPSPropValue lpval = lpsmhdlg->lpvalSMH;
  1060.  
  1061.             if (IsDlgButtonChecked (hdlg, ID_SentMail))
  1062.             {
  1063.                 lpval[ipSMHFlags].Value.l |= SMH_FILTER_SENTMAIL;
  1064.                 if (IsDlgButtonChecked (hdlg, ID_SentMailYr))
  1065.                     lpval[ipSMHFlags].Value.l |= SMH_FILTER_SENTMAIL_YR;
  1066.                 else
  1067.                     lpval[ipSMHFlags].Value.l &= ~SMH_FILTER_SENTMAIL_YR;
  1068.             }
  1069.             else
  1070.                 lpval[ipSMHFlags].Value.l &= ~(SMH_FILTER_SENTMAIL | SMH_FILTER_SENTMAIL_YR);
  1071.  
  1072.             if (IsDlgButtonChecked (hdlg, ID_Deleted))
  1073.             {
  1074.                 lpval[ipSMHFlags].Value.l |= SMH_FILTER_DELETED;
  1075.                 if (IsDlgButtonChecked (hdlg, ID_DeletedYr))
  1076.                     lpval[ipSMHFlags].Value.l |= SMH_FILTER_DELETED_YR;
  1077.                 else
  1078.                     lpval[ipSMHFlags].Value.l &= ~SMH_FILTER_DELETED_YR;
  1079.             }
  1080.             else
  1081.                 lpval[ipSMHFlags].Value.l &= ~(SMH_FILTER_DELETED | SMH_FILTER_DELETED_YR);
  1082.  
  1083.             if (IsDlgButtonChecked (hdlg, ID_Inbound))
  1084.                 lpval[ipSMHFlags].Value.l |= SMH_FILTER_INBOUND;
  1085.             else
  1086.                 lpval[ipSMHFlags].Value.l &= ~SMH_FILTER_INBOUND;
  1087.  
  1088.             if (IsDlgButtonChecked (hdlg, ID_Unread))
  1089.                 lpval[ipSMHFlags].Value.l |= SMH_UNREAD_VIEWER;
  1090.             else
  1091.                 lpval[ipSMHFlags].Value.l &= ~SMH_UNREAD_VIEWER;
  1092.  
  1093.             lpsmhdlg->sc = GetScode (lpsmhdlg->lpsec->lpVtbl->SetProps (lpsmhdlg->lpsec,
  1094.                 cpMax, lpval, NULL));
  1095.  
  1096.             lpsmhdlg->fDirty = (!FAILED (lpsmhdlg->sc));
  1097.         }
  1098.         return TRUE;
  1099.  
  1100. #ifdef PSN_HASHELP
  1101.       case PSN_HASHELP:
  1102. #endif
  1103.       case PSN_HELP:
  1104.  
  1105.         return TRUE;
  1106.     }
  1107.  
  1108.     return FALSE;
  1109. }
  1110.  
  1111.  
  1112. /*
  1113.  *  GeneralPage_COMMAND()
  1114.  *
  1115.  *  Purpose:
  1116.  *
  1117.  *      Handles the WM_COMMAND message for the filter description dialog
  1118.  *
  1119.  *      IMPORTANT: This function relies on the dialog control IDs as
  1120.  *      defined in _SMH.RH.  The yearly archive checkboxes must have an
  1121.  *      ID that is one greater than the companion checkbox.
  1122.  */
  1123. BOOL
  1124. GeneralPage_COMMAND (HWND hdlg, UINT id, HWND hwndCtl, UINT codeNotify)
  1125. {
  1126.     switch (id)
  1127.     {
  1128.       case ID_SentMail:
  1129.       case ID_Deleted:
  1130.  
  1131.         EnableWindow (GetDlgItem (hdlg, id + 1),
  1132.                     !!IsDlgButtonChecked (hdlg, ID_SentMail));
  1133.         break;
  1134.  
  1135.       case ID_SentMailYr:
  1136.       case ID_DeletedYr:
  1137.       case ID_Inbound:
  1138.       case ID_Unread:
  1139.  
  1140.         break;
  1141.  
  1142.       default:
  1143.  
  1144.         return TRUE;
  1145.     }
  1146.     PropSheet_Changed (GetParent (hdlg), hdlg);
  1147.     return TRUE;
  1148. }
  1149.  
  1150.  
  1151. /*
  1152.  *  GeneralPageProc()
  1153.  *
  1154.  *  Purpose:
  1155.  *
  1156.  *      Dispatches window messages to the proper function for processing
  1157.  */
  1158. BOOL CALLBACK
  1159. GeneralPageProc (HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  1160. {
  1161.     switch (msg)
  1162.     {
  1163.       case WM_INITDIALOG:
  1164.  
  1165.         FHandleWm (GeneralPage, hdlg, INITDIALOG, wParam, lParam);
  1166.         return TRUE;
  1167.  
  1168.       case WM_COMMAND:
  1169.  
  1170.         FHandleWm (GeneralPage, hdlg, COMMAND, wParam, lParam);
  1171.         break;
  1172.  
  1173.       case WM_DRAWITEM:
  1174.  
  1175.         break;
  1176.  
  1177.       case WM_DESTROY:
  1178.  
  1179.         break;
  1180.  
  1181.       case WM_NOTIFY:
  1182.  
  1183.         return FHandleWm (GeneralPage, hdlg, NOTIFY, wParam, lParam);
  1184.     }
  1185.  
  1186.     return FALSE;
  1187. }
  1188.  
  1189.  
  1190. /*
  1191.  *  ExclusionEdit_INITDIALOG()
  1192.  *
  1193.  *  Purpose:
  1194.  *
  1195.  *      Handles the WM_INITDIALOG message for the filter description dialog
  1196.  */
  1197. BOOL
  1198. ExclusionEdit_INITDIALOG (HWND hdlg, HWND hwndFocus, LPARAM lParam)
  1199. {
  1200.     MakeDlg3D (hdlg);
  1201.     SetWindowLong (hdlg, DWL_USER, lParam);
  1202.  
  1203.     /* Enable/limit the exclusion edit */
  1204.  
  1205.     Edit_LimitText (GetDlgItem (hdlg, ID_ExclusionClass), cchRuleMax);
  1206.     Button_Enable (GetDlgItem (hdlg, IDOK), FALSE);
  1207.     return TRUE;
  1208. }
  1209.  
  1210.  
  1211. /*
  1212.  *  ExclusionEdit_COMMAND()
  1213.  *
  1214.  *  Purpose:
  1215.  *
  1216.  *      Handles the WM_COMMAND message for the filter description dialog
  1217.  */
  1218. BOOL ExclusionEdit_COMMAND (HWND hdlg, UINT id, HWND hwndCtl, UINT codeNotify)
  1219. {
  1220.     LPSMHDLG lpsmhdlg = (LPSMHDLG)GetWindowLong (hdlg, DWL_USER);
  1221.     HWND hctrl = GetDlgItem (hdlg, ID_ExclusionClass);
  1222.  
  1223.     switch (id)
  1224.     {
  1225.       case IDOK:
  1226.  
  1227.         Edit_GetText (hctrl, lpsmhdlg->rgchT, cchRuleMax);
  1228.         break;
  1229.  
  1230.       case IDCANCEL:
  1231.  
  1232.         break;
  1233.  
  1234.       default:
  1235.  
  1236.         return FALSE;
  1237.     }
  1238.  
  1239.     EndDialog (hdlg, id);
  1240.     return TRUE;
  1241. }
  1242.  
  1243.  
  1244. /*
  1245.  *  ExclusionEditProc()
  1246.  *
  1247.  *  Purpose:
  1248.  *
  1249.  *      Dispatches window messages to the proper function for processing
  1250.  */
  1251. BOOL CALLBACK
  1252. ExclusionEditProc (HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  1253. {
  1254.     HWND hctrl = GetDlgItem (hdlg, ID_ExclusionClass);
  1255.  
  1256.     switch (msg)
  1257.     {
  1258.       case WM_INITDIALOG:
  1259.  
  1260.         FHandleWm (ExclusionEdit, hdlg, INITDIALOG, wParam, lParam);
  1261.         return TRUE;
  1262.  
  1263.       case WM_COMMAND:
  1264.  
  1265.         FHandleWm (ExclusionEdit, hdlg, COMMAND, wParam, lParam);
  1266.         break;
  1267.  
  1268.       case WM_DRAWITEM:
  1269.  
  1270.         break;
  1271.  
  1272.       case WM_DESTROY:
  1273.  
  1274.         break;
  1275.     }
  1276.     Button_Enable (GetDlgItem (hdlg, IDOK), !!Edit_GetTextLength (hctrl));
  1277.     return FALSE;
  1278. }
  1279.  
  1280.  
  1281. /*
  1282.  *  ExclusionPage_INITDIALOG()
  1283.  *
  1284.  *  Purpose:
  1285.  *
  1286.  *      Handles the WM_INITDIALOG message for the filter description dialog
  1287.  */
  1288. BOOL
  1289. ExclusionPage_INITDIALOG (HWND hdlg, HWND hwndFocus, LPARAM lParam)
  1290. {
  1291.     LPSMHDLG lpsmhdlg = (LPSMHDLG)(((PROPSHEETPAGE *)lParam)->lParam);
  1292.     HWND hctrl = GetDlgItem (hdlg, ID_ExclusionLB);
  1293.     UINT isz;
  1294.  
  1295.     MakeDlg3D (hdlg);
  1296.     SetWindowLong (hdlg, DWL_USER, ((PROPSHEETPAGE *)lParam)->lParam);
  1297.  
  1298.     /* Populate the exclusion listbox */
  1299.  
  1300.     if (lpsmhdlg->lpvalSMH[ipExc].ulPropTag == PR_SMH_EXCLUSIONS)
  1301.         for (isz = 0; isz < lpsmhdlg->lpvalSMH[ipExc].Value.MVSZ.cValues; isz++)
  1302.             ListBox_AddString (hctrl, lpsmhdlg->lpvalSMH[ipExc].Value.MVSZ.LPPSZ[isz]);
  1303.  
  1304.     return TRUE;
  1305. }
  1306.  
  1307.  
  1308. /*
  1309.  *  ExclusionPage_NOTIFY()
  1310.  *
  1311.  *  Purpose:
  1312.  *
  1313.  *      Handles the WM_NOTIFY message for the filter description dialog
  1314.  */
  1315. BOOL
  1316. ExclusionPage_NOTIFY (HWND hdlg, UINT id, NMHDR FAR * lpnmhdr)
  1317. {
  1318.     SCODE sc;
  1319.     LPSMHDLG lpsmhdlg = (LPSMHDLG)GetWindowLong (hdlg, DWL_USER);
  1320.     HWND hctrl = GetDlgItem (hdlg, ID_ExclusionLB);
  1321.     LPTSTR FAR * lppsz = NULL;
  1322.     UINT cex;
  1323.     UINT iex;
  1324.  
  1325.     switch (lpnmhdr->code)
  1326.     {
  1327.       case PSN_KILLACTIVE:
  1328.       case PSN_RESET:
  1329.       case PSN_SETACTIVE:
  1330.       default:
  1331.  
  1332.         break;
  1333.  
  1334.       case PSN_APPLY:
  1335.  
  1336.         /* Assemble a new PR_SMH_EXCLUSIONS property value */
  1337.  
  1338.         cex = ListBox_GetCount (hctrl);
  1339.         if (cex)
  1340.         {
  1341.             sc = (*lpsmhdlg->lpfnAllocMore) (cex * sizeof(LPTSTR),
  1342.                                     lpsmhdlg->lpvalSMH,
  1343.                                     (LPVOID FAR *)&lppsz);
  1344.             if (!FAILED (sc))
  1345.             {
  1346.                 lpsmhdlg->lpvalSMH[ipExc].ulPropTag = PR_SMH_EXCLUSIONS;
  1347.                 lpsmhdlg->lpvalSMH[ipExc].Value.MVSZ.LPPSZ = lppsz;
  1348.                 for (iex = 0; iex < cex; iex++, lppsz++)
  1349.                 {
  1350.                     sc = (*lpsmhdlg->lpfnAllocMore) (ListBox_GetTextLen (hctrl, iex) + 1,
  1351.                                     lpsmhdlg->lpvalSMH,
  1352.                                     lppsz);
  1353.                     if (FAILED (sc))
  1354.                         break;
  1355.  
  1356.                     ListBox_GetText (hctrl, iex, *lppsz);
  1357.                 }
  1358.                 lpsmhdlg->lpvalSMH[ipExc].Value.MVSZ.cValues = iex;
  1359.  
  1360.                 /* Set the new value */
  1361.  
  1362.                 sc = GetScode (lpsmhdlg->lpsec->lpVtbl->SetProps (lpsmhdlg->lpsec,
  1363.                         cpMax, lpsmhdlg->lpvalSMH, NULL));
  1364.  
  1365.                 lpsmhdlg->fDirty = (!FAILED (sc));
  1366.             }
  1367.             lpsmhdlg->sc = sc;
  1368.         }
  1369.         else
  1370.         {
  1371.             lpsmhdlg->lpvalSMH[ipExc].ulPropTag = PR_NULL;
  1372.             HrDeleteOneProp ((LPMAPIPROP)lpsmhdlg->lpsec, PR_SMH_EXCLUSIONS);
  1373.         }
  1374.         return TRUE;
  1375.  
  1376. #ifdef PSN_HASHELP
  1377.       case PSN_HASHELP:
  1378. #endif
  1379.       case PSN_HELP:
  1380.  
  1381.         return TRUE;
  1382.     }
  1383.  
  1384.     return FALSE;
  1385. }
  1386.  
  1387.  
  1388. /*
  1389.  *  ExclusionPage_COMMAND()
  1390.  *
  1391.  *  Purpose:
  1392.  *
  1393.  *      Handles the WM_COMMAND message for the filter description dialog
  1394.  */
  1395. BOOL
  1396. ExclusionPage_COMMAND (HWND hdlg, UINT id, HWND hwndCtl, UINT codeNotify)
  1397. {
  1398.     LPSMHDLG lpsmhdlg = (LPSMHDLG)GetWindowLong (hdlg, DWL_USER);
  1399.     HWND hctrl = GetDlgItem (hdlg, ID_ExclusionLB);
  1400.     UINT iex;
  1401.  
  1402.     switch (id)
  1403.     {
  1404.       case ID_NewExclusion:
  1405.  
  1406.         id = DialogBoxParam (lpsmhdlg->hinst,
  1407.                     MAKEINTRESOURCE (SMH_ExclusionEdit),
  1408.                     GetParent(hdlg),
  1409.                     ExclusionEditProc,
  1410.                     (LPARAM)lpsmhdlg);
  1411.         if (id == IDOK)
  1412.             ListBox_SetCurSel (hctrl, ListBox_AddString (hctrl, lpsmhdlg->rgchT));
  1413.  
  1414.         PropSheet_Changed (GetParent (hdlg), hdlg);
  1415.         break;
  1416.  
  1417.       case ID_RmvExclusion:
  1418.  
  1419.         iex = ListBox_GetCurSel (hctrl);
  1420.         ListBox_DeleteString (hctrl, iex);
  1421.         ListBox_SetCurSel (hctrl, iex);
  1422.         PropSheet_Changed (GetParent (hdlg), hdlg);
  1423.         break;
  1424.  
  1425.       default:
  1426.  
  1427.         break;
  1428.     }
  1429.     return TRUE;
  1430. }
  1431.  
  1432.  
  1433. /*
  1434.  *  ExclusionPageProc()
  1435.  *
  1436.  *  Purpose:
  1437.  *
  1438.  *      Dispatches window messages to the proper function for processing
  1439.  */
  1440. BOOL CALLBACK
  1441. ExclusionPageProc (HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  1442. {
  1443.     switch (msg)
  1444.     {
  1445.       case WM_INITDIALOG:
  1446.  
  1447.         FHandleWm (ExclusionPage, hdlg, INITDIALOG, wParam, lParam);
  1448.         return TRUE;
  1449.  
  1450.       case WM_COMMAND:
  1451.  
  1452.         FHandleWm (ExclusionPage, hdlg, COMMAND, wParam, lParam);
  1453.         return TRUE;
  1454.  
  1455.       case WM_DESTROY:
  1456.  
  1457.         break;
  1458.  
  1459.       case WM_NOTIFY:
  1460.  
  1461.         return FHandleWm (ExclusionPage, hdlg, NOTIFY, wParam, lParam);
  1462.     }
  1463.  
  1464.     return FALSE;
  1465. }
  1466.  
  1467.  
  1468. /*
  1469.  *  HrDisplayPropSheets()
  1470.  *
  1471.  *  Purpose:
  1472.  *
  1473.  *      Brings up the SMH property sheets.
  1474.  *
  1475.  *  Returns:
  1476.  *
  1477.  *      (HRESULT)
  1478.  */
  1479. HRESULT
  1480. HrDisplayPropSheets (HINSTANCE hinst,
  1481.     HWND hwnd,
  1482.     LPSMHDLG lpsmhdlg)
  1483. {
  1484.     UINT ipg;
  1485.     HRESULT hr = hrSuccess;
  1486.     CHAR rgch[60] = {0};
  1487.     PROPSHEETPAGE psp[] =
  1488.     {
  1489.         {
  1490.             sizeof(PROPSHEETPAGE),
  1491.             PSP_USETITLE,
  1492.             hinst,
  1493.             MAKEINTRESOURCE(SMH_GeneralPage),
  1494.             NULL,
  1495.             MAKEINTRESOURCE(SMH_GeneralTab),
  1496.             GeneralPageProc,
  1497.             0,
  1498.             NULL,
  1499.             NULL
  1500.         },
  1501.         {
  1502.             sizeof(PROPSHEETPAGE),
  1503.             PSP_USETITLE,
  1504.             hinst,
  1505.             MAKEINTRESOURCE(SMH_FilterPage),
  1506.             NULL,
  1507.             MAKEINTRESOURCE(SMH_FilterTab),
  1508.             FilterPageProc,
  1509.             0,
  1510.             NULL,
  1511.             NULL
  1512.         },
  1513.         {
  1514.             sizeof(PROPSHEETPAGE),
  1515.             PSP_USETITLE,
  1516.             hinst,
  1517.             MAKEINTRESOURCE(SMH_ExclusionPage),
  1518.             NULL,
  1519.             MAKEINTRESOURCE(SMH_ExclusionTab),
  1520.             ExclusionPageProc,
  1521.             0,
  1522.             NULL,
  1523.             NULL
  1524.         },
  1525.     };
  1526.     PROPSHEETHEADER psh =
  1527.     {
  1528.         sizeof(PROPSHEETHEADER),
  1529.         PSH_PROPSHEETPAGE | PSH_PROPTITLE,
  1530.         hwnd,
  1531.         hinst,
  1532.         NULL,
  1533.         NULL,
  1534.         sizeof(psp) / sizeof(PROPSHEETPAGE),
  1535.         0,
  1536.         (LPCPROPSHEETPAGE)&psp
  1537.     };
  1538.  
  1539.     /* set property sheet data */
  1540.  
  1541.     for (ipg = 0; ipg < psh.nPages; ipg++)
  1542.         psp[ipg].lParam = (LPARAM)lpsmhdlg;
  1543.  
  1544.     if (LoadString (hinst, SMH_ProviderName, rgch, sizeof(rgch)))
  1545.     {
  1546.         RegDlg3D (hinst);
  1547.         psh.pszCaption = rgch;
  1548.         switch (PropertySheet (&psh))
  1549.         {
  1550.           case -1:
  1551.  
  1552.             hr = ResultFromScode (MAPI_E_CALL_FAILED);
  1553.             break;
  1554.  
  1555.           case 0:
  1556.  
  1557.             hr = ResultFromScode (MAPI_E_USER_CANCEL);
  1558.             break;
  1559.         }
  1560.         UnregDlg3D (hinst);
  1561.     }
  1562.     else
  1563.         hr = ResultFromScode (MAPI_E_CALL_FAILED);
  1564.  
  1565.     (*lpsmhdlg->lpfnFree) (lpsmhdlg->lpmuid);
  1566.     DebugTraceResult (HrDisplayPropSheets(), hr);
  1567.     return hr;
  1568. }
  1569.