home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / mapi / manager.sh / smharc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-11  |  22.5 KB  |  816 lines

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