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

Windows编程

开发平台:

Visual C++

  1. /*
  2.  *  S M H A R C . C
  3.  *
  4.  *  Sample mail handling message archiving
  5.  *  Copyright 1992-95 Microsoft Corporation.  All Rights Reserved.
  6.  */
  7. #include "_pch.h"
  8. /*
  9.  *  FIsLeapYear()
  10.  *
  11.  *  Used to calculate leap years when determining month ranges for
  12.  *  archive folders.
  13.  */
  14. #define FIsLeapYear(_yr) ((!((_yr) % 400) || ((_yr) % 100) && !((_yr) % 4)) ? TRUE : FALSE)
  15. /*
  16.  *  sptMsgDates
  17.  *
  18.  *  The list of properties that are used for archiving.  If
  19.  *  PR_MESSAGE_DELIVERY_TIME is not available, then SMH will use
  20.  *  PR_CLIENT_SUBMIT_TIME.
  21.  */
  22. const static SizedSPropTagArray(2, sptMsgDates) =
  23. {
  24.     2,
  25.     {
  26.         PR_MESSAGE_DELIVERY_TIME,
  27.         PR_CLIENT_SUBMIT_TIME
  28.     }
  29. };
  30. /*
  31.  *  sptFldrDates
  32.  *
  33.  *  Theses properties describe the range of dates that an archive folder
  34.  *  with the returned EntryID will support.  This is used in the call to
  35.  *  find a supporting sub-folder.
  36.  */
  37. const static SizedSPropTagArray (3, sptFldrDates) =
  38. {
  39.     3,
  40.     {
  41.         PR_START_DATE,
  42.         PR_END_DATE,
  43.         PR_ENTRYID
  44.     }
  45. };
  46. /*
  47.  *  rgtstrMonth
  48.  *  rgtstrMonthFull
  49.  *  rgwDaysPerMonth
  50.  *
  51.  *  These arrays are used in the calculation and creation of supporting
  52.  *  archive folders.
  53.  */
  54. const static TCHAR FAR * rgtstrMonth[] =
  55. {
  56.     TEXT ("Jan"),
  57.     TEXT ("Feb"),
  58.     TEXT ("Mar"),
  59.     TEXT ("Apr"),
  60.     TEXT ("May"),
  61.     TEXT ("Jun"),
  62.     TEXT ("Jul"),
  63.     TEXT ("Aug"),
  64.     TEXT ("Sep"),
  65.     TEXT ("Oct"),
  66.     TEXT ("Nov"),
  67.     TEXT ("Dec")
  68. };
  69. const TCHAR FAR * rgtstrMonthFull[] =
  70. {
  71.     TEXT ("January"),
  72.     TEXT ("February"),
  73.     TEXT ("March"),
  74.     TEXT ("April"),
  75.     TEXT ("May"),
  76.     TEXT ("June"),
  77.     TEXT ("July"),
  78.     TEXT ("August"),
  79.     TEXT ("September"),
  80.     TEXT ("October"),
  81.     TEXT ("November"),
  82.     TEXT ("December")
  83. };
  84. const static WORD rgwDaysPerMonth[] =
  85. {
  86.     31, //  JAN
  87.     28, //  FEB
  88.     31, //  MAR
  89.     30, //  APR
  90.     31, //  MAY
  91.     30, //  JUN
  92.     31, //  JUL
  93.     31, //  AUG
  94.     30, //  SEP
  95.     31, //  OCT
  96.     30, //  NOV
  97.     31  //  DEC
  98. };
  99. /*
  100.  *  HrCacheFolder()
  101.  *
  102.  *  Purpose:
  103.  *
  104.  *      Caches the passed in entryid along with a matching folder
  105.  *
  106.  *  Arguments:
  107.  *
  108.  *      lpsmh       pointer to the sentmail handler
  109.  *      cbeid       count of bytes for the entryid to check
  110.  *      lpeid       data for the entryid to check
  111.  *      lpcbeid     points to the cached entryid size
  112.  *      lppeid      points to the cached entryid data
  113.  *      lppfldr     points to the cached mapi folder object
  114.  *      lpfUpdated  points to cache update flag
  115.  *
  116.  *  Returns:
  117.  *
  118.  *      (HRESULT)
  119.  *      lpcbeid     [OUT] size of newly cached entryid
  120.  *      lppeid      [OUT] data of newly cached entryid
  121.  *      lppfldr     [OUT] folder corresponding to cached entryid
  122.  *      lpfUpdated  [OUT] TRUE iff the out folder is not the
  123.  *                          previously cached folder
  124.  */
  125. HRESULT
  126. HrCacheFolder (LPSMH lpsmh,
  127.     LPMDB lpmdbPref,
  128.     ULONG cbeid,
  129.     LPENTRYID lpeid,
  130.     ULONG FAR * lpcbeid,
  131.     LPENTRYID FAR * lppeid,
  132.     LPMAPIFOLDER FAR * lppfldr,
  133.     BOOL far * lpfUpdated)
  134. {
  135.     HRESULT hr;
  136.     ULONG ulType;
  137.     ULONG ulMatch;
  138.     LPMAPIPROP lpmp = NULL;
  139.     /* Init the update flag */
  140.     *lpfUpdated = FALSE;
  141.     /*  Is the topmost sent mail folder the same folder
  142.      *  as the last filtered message?
  143.      */
  144.     hr = lpsmh->lpsess->lpVtbl->CompareEntryIDs (lpsmh->lpsess,
  145.                                         cbeid,
  146.                                         lpeid,
  147.                                         *lpcbeid,
  148.                                         *lppeid,
  149.                                         0,
  150.                                         &ulMatch);
  151.     if (HR_FAILED (hr) || !ulMatch)
  152.     {
  153.         /* Different folder, guess we better toss the cached one */
  154.         (*lpsmh->lpfnFree) (*lppeid);
  155.         *lppeid = NULL;
  156.         *lpcbeid = 0;
  157.         /* Cache the SentMail */
  158.         hr = ResultFromScode ((*lpsmh->lpfnAlloc) (cbeid, lppeid));
  159.         if (HR_FAILED (hr))
  160.             goto ret;
  161.         memcpy (*lppeid, lpeid, (UINT)cbeid);
  162.         *lpcbeid = cbeid;
  163.         *lpfUpdated = TRUE;
  164.     }
  165.     else if (*lppfldr)
  166.         return hrSuccess;
  167.     /* Open the new folder, but try the preferred store first */
  168.     hr = lpmdbPref->lpVtbl->OpenEntry (lpmdbPref,
  169.                                         cbeid,
  170.                                         lpeid,
  171.                                         NULL,
  172.                                         MAPI_BEST_ACCESS,
  173.                                         &ulType,
  174.                                         (LPUNKNOWN FAR *)&lpmp);
  175.     if (HR_FAILED (hr))
  176.     {
  177.         /* Try the MAPI session now and see if we can get the folder */
  178.         
  179.         hr = lpsmh->lpsess->lpVtbl->OpenEntry (lpsmh->lpsess,
  180.                                         cbeid,
  181.                                         lpeid,
  182.                                         NULL,
  183.                                         MAPI_BEST_ACCESS,
  184.                                         &ulType,
  185.                                         (LPUNKNOWN FAR *)&lpmp);
  186.     }
  187.     if (HR_FAILED (hr))
  188.         goto ret;
  189.     if (ulType != MAPI_FOLDER)
  190.     {
  191.         hr = ResultFromScode (MAPI_E_UNEXPECTED_TYPE);
  192.         goto ret;
  193.     }
  194. ret:
  195.     if (HR_FAILED (hr))
  196.     {
  197.         UlRelease (lpmp);
  198.         (*lpsmh->lpfnFree) (*lppeid);
  199.         *lppeid = NULL;
  200.         *lpcbeid = 0;
  201.         lpmp = NULL;
  202.     }
  203.     UlRelease (*lppfldr);
  204.     *lppfldr = (LPMAPIFOLDER)lpmp;
  205.     DebugTraceResult (HrCacheFolder(), hr);
  206.     return hr;
  207. }
  208. /*
  209.  *  HrCreateHashedFolder()
  210.  *
  211.  *  Purpose:
  212.  *
  213.  *      Create/Caches the a folder that satisfies the hash value
  214.  *
  215.  *  Arguments:
  216.  *
  217.  *      lpsmh       pointer to the sentmail handler
  218.  *      lpdft       pointer the the hash interval
  219.  *      lpfldrPar   parnet folder
  220.  *      lpszName    name for folder
  221.  *      lpszComment comment for folder
  222.  *      lpcbeid     points to the cached entryid size
  223.  *      lppeid      points to the cached entryid data
  224.  *      lppfldr     points to the cached mapi folder object
  225.  *
  226.  *  Returns:
  227.  *
  228.  *      (HRESULT)
  229.  *      lpcbeid     [OUT] size of newly cached entryid
  230.  *      lppeid      [OUT] data of newly cached entryid
  231.  *      lppfldr     [OUT] folder corresponding to cached entryid
  232.  */
  233. HRESULT
  234. HrCreateHashedFolder (LPSMH lpsmh,
  235.     LPDFT lpdft,
  236.     LPMAPIFOLDER lpfldrPar,
  237.     LPTSTR lpszName,
  238.     LPTSTR lpszComment,
  239.     ULONG FAR * lpcbeid,
  240.     LPENTRYID FAR * lppeid,
  241.     LPMAPIFOLDER FAR * lppfldr)
  242. {
  243.     HRESULT hr;
  244.     LPMAPIFOLDER lpfldr = NULL;
  245.     LPSPropValue lpval = NULL;
  246.     SPropValue rgval[2] = {0};
  247.     ULONG cval;
  248.     /* Toss the current cache info */
  249.     (*lpsmh->lpfnFree) (*lppeid);
  250.     *lppeid = NULL;
  251.     *lpcbeid = 0;
  252.     /* Create the new folder */
  253.     hr = lpfldrPar->lpVtbl->CreateFolder (lpfldrPar,
  254.                             FOLDER_GENERIC,
  255.                             lpszName,
  256.                             lpszComment,
  257.                             NULL,
  258.                             OPEN_IF_EXISTS,
  259.                             &lpfldr);
  260.     if (HR_FAILED (hr))
  261.         goto ret;
  262.     /* Set the hashing interval properties */
  263.     rgval[0].ulPropTag = PR_START_DATE;
  264.     rgval[0].Value.ft = lpdft->ftStart;
  265.     rgval[1].ulPropTag = PR_END_DATE;
  266.     rgval[1].Value.ft = lpdft->ftEnd;
  267.     hr = lpfldr->lpVtbl->SetProps (lpfldr, 2, rgval, NULL);
  268.     if (HR_FAILED (hr))
  269.         goto ret;
  270.     /* Cache the folder info */
  271.     hr = lpfldr->lpVtbl->GetProps (lpfldr,
  272.                             (LPSPropTagArray)&sptFldrDates,
  273.                             FALSE,
  274.                             &cval,
  275.                             &lpval);
  276.     if (HR_FAILED (hr))
  277.         goto ret;
  278.     /* Make sure we have all the info we need */
  279.     if ((lpval[0].ulPropTag != PR_START_DATE) ||
  280.         (lpval[1].ulPropTag != PR_END_DATE) ||
  281.         (lpval[2].ulPropTag != PR_ENTRYID))
  282.     {
  283.         hr = ResultFromScode (MAPI_E_BAD_VALUE);
  284.         goto ret;
  285.     }
  286.     /* Cache the entryid */
  287.     hr = ResultFromScode ((*lpsmh->lpfnAlloc) (lpval[2].Value.bin.cb, lppeid));
  288.     if (HR_FAILED (hr))
  289.         goto ret;
  290.     memcpy (*lppeid, lpval[2].Value.bin.lpb, (UINT)lpval[2].Value.bin.cb);
  291.     *lpcbeid = lpval[2].Value.bin.cb;
  292. ret:
  293.     (*lpsmh->lpfnFree) (lpval);
  294.     if (HR_FAILED (hr))
  295.     {
  296.         UlRelease (lpfldr);
  297.         lpfldr = NULL;
  298.     }
  299.     UlRelease (*lppfldr);
  300.     *lppfldr = lpfldr;
  301.     DebugTraceResult (HrCreateHashedFolder(), hr);
  302.     return hr;
  303. }
  304. /*
  305.  *  HrCacheHashedFolder()
  306.  *
  307.  *  Purpose:
  308.  *
  309.  *      Caches the folder that matches the hash value (file time)
  310.  *
  311.  *  Arguments:
  312.  *
  313.  *      lpsmh       pointer to the sentmail handler
  314.  *      ft          hash filetime
  315.  *      lpdft       pointer the the hash interval
  316.  *      lpcbeid     points to the cached entryid size
  317.  *      lppeid      points to the cached entryid data
  318.  *      lppfldr     points to the cached mapi folder object
  319.  *      lpfUpdated  points to cache update flag
  320.  *
  321.  *  Returns:
  322.  *
  323.  *      (HRESULT)
  324.  *      lpcbeid     [OUT] size of newly cached entryid
  325.  *      lppeid      [OUT] data of newly cached entryid
  326.  *      lppfldr     [OUT] folder corresponding to cached entryid
  327.  *      lpfUpdated  [OUT] TRUE iff the out folder is not the
  328.  *                          previously cached folder
  329.  */
  330. HRESULT
  331. HrCacheHashedFolder (LPSMH lpsmh,
  332.     LPMDB lpmdbPref,
  333.     FILETIME ft,
  334.     LPDFT lpdft,
  335.     LPMAPIFOLDER lpfldr,
  336.     ULONG FAR * lpcbeid,
  337.     LPENTRYID FAR * lppeid,
  338.     LPMAPIFOLDER FAR * lppfldr,
  339.     BOOL far * lpfUpdated)
  340. {
  341.     HRESULT hr;
  342.     LPMAPIPROP lpmp = NULL;
  343.     LPMAPITABLE lptbl = NULL;
  344.     LPSRow lprw = NULL;
  345.     LPSRowSet lprws = NULL;
  346.     ULONG ulType;
  347.     UINT i;
  348.     /*  Check to see if the new hash fits the
  349.      *  the current hashed folder, if the hash
  350.      *  value does not work, find one that does
  351.      */
  352.     if (!*lpfUpdated &&
  353.         (CompareFileTime (&lpdft->ftStart, &ft) != 1) &&
  354.         (CompareFileTime (&lpdft->ftEnd, &ft) != -1))
  355.     {
  356.         /* The hash works, but do we have a folder? */
  357.         if (*lppfldr)
  358.             return hrSuccess;
  359.         hr = lpsmh->lpsess->lpVtbl->OpenEntry (lpsmh->lpsess,
  360.                                         *lpcbeid,
  361.                                         *lppeid,
  362.                                         NULL,
  363.                                         MAPI_BEST_ACCESS,
  364.                                         &ulType,
  365.                                         (LPUNKNOWN FAR *)&lpmp);
  366.         if (!HR_FAILED (hr) && (ulType != MAPI_FOLDER))
  367.         {
  368.             hr = ResultFromScode (MAPI_E_UNEXPECTED_TYPE);
  369.             UlRelease (lpmp);
  370.             lpmp = NULL;
  371.         }
  372.         goto ret;
  373.     }
  374.     /* Toss the cached info */
  375.     (*lpsmh->lpfnFree) (*lppeid);
  376.     *lppeid = NULL;
  377.     *lpcbeid = 0;
  378.     /* Get the hierachy and set it up to find the target folder */
  379.     hr = lpfldr->lpVtbl->GetHierarchyTable (lpfldr, 0, &lptbl);
  380.     if (HR_FAILED (hr))
  381.         goto ret;
  382.     hr = lptbl->lpVtbl->SetColumns (lptbl, (LPSPropTagArray)&sptFldrDates, 0);
  383.     if (HR_FAILED (hr))
  384.         goto ret;
  385.     hr = lptbl->lpVtbl->QueryRows (lptbl, 12, 0L, &lprws);
  386.     if (HR_FAILED (hr))
  387.         goto ret;
  388.     while (lprws->cRows)
  389.     {
  390.         for (i = 0; i < lprws->cRows; i++)
  391.         {
  392.             lprw = &lprws->aRow[i];
  393.             if (!lpmp &&
  394.                 (lprw->lpProps[0].ulPropTag == PR_START_DATE) &&
  395.                 (lprw->lpProps[1].ulPropTag == PR_END_DATE) &&
  396.                 (CompareFileTime (&lprw->lpProps[0].Value.ft, &ft) != 1) &&
  397.                 (CompareFileTime (&lprw->lpProps[1].Value.ft, &ft) != -1))
  398.             {
  399.                 /* Hey, this looks like the folder we want */
  400.                 hr = HrCacheFolder (lpsmh,
  401.                         lpmdbPref,
  402.                         lprw->lpProps[2].Value.bin.cb,
  403.                         (LPENTRYID)lprw->lpProps[2].Value.bin.lpb,
  404.                         lpcbeid,
  405.                         lppeid,
  406.                         (LPMAPIFOLDER FAR *)&lpmp,
  407.                         lpfUpdated);
  408.                 if (!HR_FAILED (hr))
  409.                 {
  410.                     lpdft->ftStart = lprw->lpProps[0].Value.ft;
  411.                     lpdft->ftEnd = lprw->lpProps[1].Value.ft;
  412.                 }
  413.             }
  414.         }
  415.         /* Clean up the row properies */
  416.         for (i = 0; i < lprws->cRows; i++)
  417.             (*lpsmh->lpfnFree) (lprws->aRow[i].lpProps);
  418.         /* We either found the folder or we had an error */
  419.         if (lpmp || HR_FAILED (hr))
  420.             break;
  421.         /* Clean up the row set */
  422.         (*lpsmh->lpfnFree) (lprws);
  423.         hr = lptbl->lpVtbl->QueryRows (lptbl, 12, 0L, &lprws);
  424.         if (HR_FAILED (hr))
  425.             goto ret;
  426.     }
  427.     /* Clean up the final row set */
  428.     (*lpsmh->lpfnFree) (lprws);
  429. ret:
  430.     UlRelease (lptbl);
  431.     UlRelease (*lppfldr);
  432.     *lppfldr = (LPMAPIFOLDER)lpmp;
  433.     DebugTraceResult (HrCacheHashedFolder(), hr);
  434.     return hr ? hr : (lpmp ? hrSuccess : ResultFromScode (MAPI_E_NOT_FOUND));
  435. }
  436. /*
  437.  *  HrArchiveByDate()
  438.  *
  439.  *  Purpose:
  440.  *
  441.  *      The purpose of this function is to "hash" a single message by
  442.  *      processing based on date.  The most obvious bucket size is
  443.  *      monthly but there is no reason not to make this an option the
  444.  *      user could confiigure.
  445.  *
  446.  *  Arguments:
  447.  *
  448.  *      lpsmh           this filter hook obj
  449.  *      lpft            the date to be filtered against
  450.  *      lpfldrDef       the owning folder of the message
  451.  *      lpmdbDef        the owning store of the message
  452.  *      lpbkit          the cached bucket structure
  453.  *      fCatByYear      uses yearly subfolders iff TRUE
  454.  *      cbeid           cb for entryid of default target for message
  455.  *      lpbeid          pb for entryid of default target for message
  456.  *
  457.  *  Operation:
  458.  *
  459.  *      Opens the suggested folder (if needed) and checks for the
  460.  *      existence of the appropriate "bucket" folder.  If it does exist,
  461.  *      then the  folder is created and cached.  The entryid is grabbed
  462.  *      and passed back in to the spooler.
  463.  *
  464.  *  Returns:
  465.  *
  466.  *      (HRESULT)
  467.  */
  468. HRESULT
  469. HrArchiveByDate (LPSMH lpsmh,
  470.     FILETIME FAR * lpft,
  471.     LPMAPIFOLDER lpfldrDef,
  472.     LPMDB lpmdbDef,
  473.     LPBKIT lpbkit,
  474.     BOOL fCatByYear,
  475.     ULONG cbeid,
  476.     LPBYTE lpeid)
  477. {
  478.     HRESULT hr = hrSuccess;
  479.     BOOL fUpdated = FALSE;
  480.     LPMAPIFOLDER lpfldr;
  481.     SYSTEMTIME st;
  482.     SYSTEMTIME sty;
  483.     TCHAR rgchName[64] = {0};
  484.     
  485.     if (!FileTimeToSystemTime (lpft, &st))
  486.     {
  487.         hr = ResultFromScode (MAPI_E_BAD_VALUE);
  488.         goto ret;
  489.     }
  490.     /* Cache the parent folder */
  491.     hr = HrCacheFolder (lpsmh,
  492.                     lpmdbDef,
  493.                     cbeid,
  494.                     (LPENTRYID)lpeid,
  495.                     &lpbkit->cbeidParent,
  496.                     &lpbkit->lpeidParent,
  497.                     &lpbkit->lpfldrParent,
  498.                     &fUpdated);
  499.     if (HR_FAILED (hr))
  500.         goto ret;
  501.     if (fCatByYear)
  502.     {
  503.         /* Cache the year folder */
  504.         hr = HrCacheHashedFolder (lpsmh,
  505.                     lpmdbDef,
  506.                     *lpft,
  507.                     &lpbkit->dftYr,
  508.                     lpbkit->lpfldrParent,
  509.                     &lpbkit->cbeidYr,
  510.                     &lpbkit->lpeidYr,
  511.                     &lpbkit->lpfldrYr,
  512.                     &fUpdated);
  513.         if (HR_FAILED (hr) && (GetScode (hr) == MAPI_E_NOT_FOUND))
  514.         {
  515.             wsprintf (rgchName, "%04hu", st.wYear);
  516.             sty.wYear = st.wYear;
  517.             sty.wMonth = 1;
  518.             sty.wDayOfWeek = 0;
  519.             sty.wDay = 1;
  520.             sty.wHour = 0;
  521.             sty.wMinute = 0;
  522.             sty.wSecond = 0;
  523.             sty.wMilliseconds = 0;
  524.             if (!SystemTimeToFileTime (&sty, &lpbkit->dftYr.ftStart))
  525.             {
  526.                 hr = ResultFromScode (MAPI_E_BAD_VALUE);
  527.                 goto ret;
  528.             }
  529.             sty.wMonth = 12;
  530.             sty.wDay = rgwDaysPerMonth[sty.wMonth - 1];
  531.             sty.wDayOfWeek = 0;
  532.             sty.wDay = 31;
  533.             sty.wHour = 23;
  534.             sty.wMinute = 59;
  535.             sty.wSecond = 59;
  536.             sty.wMilliseconds = 999;
  537.             if (!SystemTimeToFileTime (&sty, &lpbkit->dftYr.ftEnd))
  538.             {
  539.                 hr = ResultFromScode (MAPI_E_BAD_VALUE);
  540.                 goto ret;
  541.             }
  542.             hr = HrCreateHashedFolder (lpsmh,
  543.                             &lpbkit->dftYr,
  544.                             lpbkit->lpfldrParent,
  545.                             rgchName,
  546.                             NULL,
  547.                             &lpbkit->cbeidYr,
  548.                             &lpbkit->lpeidYr,
  549.                             &lpbkit->lpfldrYr);
  550.             if (HR_FAILED (hr))
  551.                 goto ret;
  552.         }
  553.         else if (HR_FAILED (hr))
  554.             goto ret;
  555.         lpfldr = lpbkit->lpfldrYr;
  556.     }
  557.     else
  558.         lpfldr = lpbkit->lpfldrParent;
  559.     /* Cache the hashed target folder */
  560.     hr = HrCacheHashedFolder (lpsmh,
  561.                     lpmdbDef,
  562.                     *lpft,
  563.                     &lpbkit->dft,
  564.                     lpfldr,
  565.                     &lpbkit->cbeid,
  566.                     &lpbkit->lpeid,
  567.                     &lpbkit->lpfldr,
  568.                     &fUpdated);
  569.     if (HR_FAILED (hr) && (GetScode (hr) == MAPI_E_NOT_FOUND))
  570.     {
  571.         if (fCatByYear)
  572.         {
  573.             wsprintf (rgchName,
  574.                 "%02hu %s",
  575.                 st.wMonth,
  576.                 rgtstrMonthFull[st.wMonth - 1]);
  577.         }
  578.         else
  579.         {
  580.             wsprintf (rgchName,
  581.                 TEXT("'%02hu/%02hu %s"),
  582.                 st.wYear % 100,
  583.                 st.wMonth,
  584.                 rgtstrMonthFull[st.wMonth - 1]);
  585.         }
  586.         st.wDayOfWeek = (st.wDay - st.wDayOfWeek - 1) % 7;
  587.         st.wDay = 1;
  588.         st.wHour = 0;
  589.         st.wMinute = 0;
  590.         st.wSecond = 0;
  591.         st.wMilliseconds = 0;
  592.         if (!SystemTimeToFileTime (&st, &lpbkit->dft.ftStart))
  593.         {
  594.             hr = ResultFromScode (MAPI_E_BAD_VALUE);
  595.             goto ret;
  596.         }
  597.         st.wDay = rgwDaysPerMonth[st.wMonth - 1];
  598.         if ((st.wMonth == 2) && FIsLeapYear (st.wYear))
  599.             st.wDay += 1;
  600.         st.wDayOfWeek = (st.wDayOfWeek + st.wDay - 1) % 7;
  601.         st.wHour = 23;
  602.         st.wMinute = 59;
  603.         st.wSecond = 59;
  604.         st.wMilliseconds = 999;
  605.         if (!SystemTimeToFileTime (&st, &lpbkit->dft.ftEnd))
  606.         {
  607.             hr = ResultFromScode (MAPI_E_BAD_VALUE);
  608.             goto ret;
  609.         }
  610.         hr = HrCreateHashedFolder (lpsmh,
  611.                             &lpbkit->dft,
  612.                             lpfldr,
  613.                             rgchName,
  614.                             NULL,
  615.                             &lpbkit->cbeid,
  616.                             &lpbkit->lpeid,
  617.                             &lpbkit->lpfldr);
  618.     }
  619. ret:
  620.     DebugTraceResult (HrArchiveMessage(), hr);
  621.     return hr;
  622. }
  623. /*
  624.  *  HrArchiveMessage()
  625.  *
  626.  *  Purpose:
  627.  *
  628.  *      The purpose of this function is to "hash" a single message by
  629.  *      processing based on date.  The most obvious bucket size is
  630.  *      monthly but there is no reason not to make this an option the
  631.  *      user could confiigure.
  632.  *
  633.  *  Arguments:
  634.  *
  635.  *      lpsmh           this filter hook obj
  636.  *      lpmsg           the message to be filtered
  637.  *      lpfldrDef       the owning folder of the message
  638.  *      lpmdbDef        the owning store of the message
  639.  *      lpbkit          the cached bucket structure
  640.  *      fCatByYear      uses yearly subfolders iff TRUE
  641.  *      lpcbeid         cb for entryid of default target for message
  642.  *      lppbeid         pb for entryid of default target for message
  643.  *
  644.  *  Operation:
  645.  *
  646.  *      Extracts the date of the message that is to be used in the
  647.  *      archiving, and calls off to HrArchiveByDate().
  648.  *
  649.  *      IMPORTANT: the entryid passed in will be swapped out by this
  650.  *      call.  Therefore the *lppeid buffer must be allocated with the
  651.  *      MAPIAllocateBuffer provider to the filter.
  652.  *
  653.  *  Returns:
  654.  *
  655.  *      (HRESULT)
  656.  *      lpcbeid [out]   the size of the returned EntryID
  657.  *      lppbeid [out]   the data of the returned EntryID
  658.  */
  659. HRESULT
  660. HrArchiveMessage (LPSMH lpsmh,
  661.     LPMESSAGE lpmsg,
  662.     LPMAPIFOLDER lpfldrDef,
  663.     LPMDB lpmdbDef,
  664.     LPBKIT lpbkit,
  665.     BOOL fCatByYear,
  666.     ULONG FAR * lpcbeid,
  667.     LPBYTE FAR * lppeid)
  668. {
  669.     HRESULT hr = hrSuccess;
  670.     FILETIME ft;
  671.     LPSPropValue lpval = NULL;
  672.     ULONG cval;
  673.     /* Quick and dirty parameter check */
  674.     if (IsBadWritePtr (lpsmh, sizeof(SMH)) ||
  675.         IsBadWritePtr (lpcbeid, sizeof(ULONG)) ||
  676.         IsBadWritePtr (lppeid, sizeof(LPBYTE)) ||
  677.         IsBadWritePtr (*lppeid, (UINT)(*lpcbeid)))
  678.         return ResultFromScode (MAPI_E_INVALID_PARAMETER);
  679.     /* Get the date used by the hash */
  680.     hr = lpmsg->lpVtbl->GetProps (lpmsg,
  681.                             (LPSPropTagArray)&sptMsgDates,
  682.                             FALSE,
  683.                             &cval,
  684.                             &lpval);
  685.     if (HR_FAILED (hr))
  686.         goto ret;
  687.     /* Make sure what we end up with is usable */
  688.     if (lpval[0].ulPropTag == PR_MESSAGE_DELIVERY_TIME)
  689.     {
  690.         DebugTrace ("SMH: filtering on PR_MESSAGE_DELIVERY_TIMEn");
  691.         ft = lpval[0].Value.ft;
  692.     }
  693.     else if (lpval[1].ulPropTag == PR_CLIENT_SUBMIT_TIME)
  694.     {
  695.         DebugTrace ("SMH: filtering on PR_CLIENT_SUBMIT_TIMEn");
  696.         ft = lpval[1].Value.ft;
  697.     }
  698.     else
  699.     {
  700.         DebugTrace ("SMH: cannot filter on provided time propsn");
  701.         hr = ResultFromScode (MAPI_E_BAD_VALUE);
  702.         goto ret;
  703.     }
  704.     hr = HrArchiveByDate (lpsmh,
  705.                     &ft,
  706.                     lpfldrDef,
  707.                     lpmdbDef,
  708.                     lpbkit,
  709.                     fCatByYear,
  710.                     *lpcbeid,
  711.                     *lppeid);
  712. ret:
  713.     
  714.     if (!HR_FAILED (hr))
  715.     {
  716.         LPBYTE lpeid;
  717.         /* OK, If we get this far we are moving the message */
  718.         hr = ResultFromScode ((*lpsmh->lpfnAlloc) (lpbkit->cbeid, &lpeid));
  719.         if (HR_FAILED (hr))
  720.             goto ret;
  721.         memcpy (lpeid, lpbkit->lpeid, (UINT)lpbkit->cbeid);
  722.         (*lpsmh->lpfnFree) (*lppeid);
  723.         *lpcbeid = lpbkit->cbeid;
  724.         *lppeid = lpeid;
  725.     }
  726.     (*lpsmh->lpfnFree) (lpval);
  727.     
  728.     DebugTraceResult (HrArchiveMessage(), hr);
  729.     return hr;
  730. }