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

Windows编程

开发平台:

Visual C++

  1. /*
  2.  *  CINDEX.C
  3.  *  
  4.  *  Create and extend PR_CONVERSATION_INDEX
  5.  */
  6. #include <windows.h>
  7. #include <mapiwin.h>
  8. #include <mapix.h>
  9. #include <mapiutil.h>
  10. #include <mapidbg.h>
  11. #include <memory.h>
  12. #define cbConvIndexHdr          22
  13. #define cbConvIndexComponent    5
  14. #define bConvIndexRes           (BYTE)1
  15. /*
  16.  *  ExtractLastFileTime()
  17.  *  
  18.  *  Purpose:
  19.  *  
  20.  *      Parses an existing covnersation index and extracts the last
  21.  *      FILETIME value contained in the index.
  22.  */
  23. VOID
  24. ExtractLastFileTime (LPBYTE lpb, ULONG cb, FILETIME FAR * lpft)
  25. {
  26.     FILETIME ft;
  27.     FILETIME ftCur;
  28.     LPBYTE lpbEnd;
  29.     //  Lets do some verification on the key
  30.     //
  31.     Assert (!IsBadReadPtr (lpb, (UINT)cb));
  32.     Assert (!IsBadWritePtr (lpft, sizeof(FILETIME)));
  33.     Assert (*lpb == bConvIndexRes);
  34.     Assert (cb >= cbConvIndexHdr);
  35.     Assert (!((cb - cbConvIndexHdr) % cbConvIndexComponent));
  36.     //  Rebuild the header timedate into FILETIME format
  37.     //
  38.     ft.dwHighDateTime = (((DWORD)(lpb[1])) << 16) |
  39.                         (((DWORD)(lpb[2])) << 8) |
  40.                         ((DWORD)(lpb[3]));
  41.     ft.dwLowDateTime = (((DWORD)(lpb[4])) << 24) |
  42.                        (((DWORD)(lpb[5])) << 16);
  43.     //  See where the last child chunk ends
  44.     //
  45.     lpbEnd = lpb + cb;
  46.     lpb += cbConvIndexHdr;
  47.     //  Now go through the child chunks to compute
  48.     //  for the last FILETIME using the delta
  49.     //
  50.     while (lpb < lpbEnd)
  51.     {
  52.         //  Convert the delta of the current child
  53.         //  chunk into the FILETIME format.  Use the
  54.         //  delta code in the first bit to get the
  55.         //  real delta.
  56.         //
  57.         //  Delta code : 1 = mask 10000000 = 0x80
  58.         //
  59.         if ((*lpb & 0x80) == 0x80)
  60.         {
  61.             //  Mask out the first bit used for the delta code
  62.             //  *lpb | 0x7F;
  63.             //
  64.             ftCur.dwHighDateTime = (((DWORD)(lpb[0] & 0x7F)) << 15) |
  65.                                    (((DWORD)(lpb[1])) << 7) |
  66.                                    (((DWORD)(lpb[2])) >> 1);
  67.             ftCur.dwLowDateTime = (((DWORD)(lpb[2])) << 31) |
  68.                                   (((DWORD)(lpb[3])) << 23);
  69.             ft = FtAddFt (ft, ftCur);
  70.         }
  71.         else
  72.         {
  73.             ftCur.dwHighDateTime = (((DWORD)(lpb[0] & 0x7F)) << 10) |
  74.                                    (((DWORD)(lpb[1])) << 2) |
  75.                                    (((DWORD)(lpb[2])) >> 6);
  76.             ftCur.dwLowDateTime = (((DWORD)(lpb[2])) << 26) |
  77.                                   (((DWORD)(lpb[3])) << 18);
  78.             ft = FtAddFt (ft, ftCur);
  79.         }
  80.         // Advance to next child
  81.         //
  82.         lpb += cbConvIndexComponent;
  83.     }
  84.     //  If all went well, we sould have ended up at
  85.     //  lpbEnd
  86.     //
  87.     Assert (lpb == lpbEnd);
  88.     *lpft = ft;
  89.     return;
  90. }
  91. /*
  92.  *  ScFillConvHeader()
  93.  *  
  94.  *  Purpose:
  95.  *  
  96.  *      Fills in the header of a conversation index.  This function is
  97.  *      called when a new conversation index is created.
  98.  *  
  99.  *  Assumptions:
  100.  *  
  101.  *      The buffer passed in should be big enough to hold cbConvIndexHdr
  102.  *      bytes (22 bytes).
  103.  */
  104. SCODE
  105. ScFillConvHeader (LPBYTE rgb, ULONG cb)
  106. {
  107.     SCODE sc = S_OK;
  108.     SYSTEMTIME st;
  109.     FILETIME ft;
  110.     GUID guid;
  111.     Assert (cb >= cbConvIndexHdr);
  112.     Assert (!IsBadWritePtr (rgb, cbConvIndexHdr));
  113.     //  (Ha). Put the reserved byte
  114.     //
  115.     rgb[0] = bConvIndexRes;
  116.         
  117.     //  (Hb). Put the current time
  118.     //
  119.     GetSystemTime (&st);
  120.     SystemTimeToFileTime (&st, &ft);
  121.     //  Construct the datetime one byte at a time
  122.     //
  123.     rgb[1] = (BYTE) ((ft.dwHighDateTime & 0x00FF0000) >> 16);
  124.     rgb[2] = (BYTE) ((ft.dwHighDateTime & 0x0000FF00) >> 8);
  125.     rgb[3] = (BYTE) (ft.dwHighDateTime & 0x000000FF);
  126.     //  Drop the rightmost least significant 2 bytes
  127.     //
  128.     rgb[4] = (BYTE) ((ft.dwLowDateTime & 0xFF000000) >> 24);
  129.     rgb[5] = (BYTE) ((ft.dwLowDateTime & 0x00FF0000) >> 16);
  130.     //  (Hc). Now put the GUID
  131.     //      {
  132.     //          DWORD Data1;
  133.     //          WORD  Data2;
  134.     //          WORD  Data3;
  135.     //          BYTE  Data4[8];
  136.     //      } GUID;
  137.     //
  138.     sc = GetScode (CoCreateGuid (&guid));
  139.     if (!FAILED (sc))
  140.     {       
  141.         //  Again, lets do it one byte at a time
  142.         //
  143.         rgb[6] = (BYTE) ((guid.Data1 & 0xFF000000) >> 24);
  144.         rgb[7] = (BYTE) ((guid.Data1 & 0x00FF0000) >> 16);
  145.         rgb[8] = (BYTE) ((guid.Data1 & 0x0000FF00) >> 8);
  146.         rgb[9] = (BYTE) ((guid.Data1 & 0x000000FF));
  147.         rgb[10] = (BYTE) ((guid.Data2 & 0xFF00) >> 8);
  148.         rgb[11] = (BYTE) ((guid.Data2 & 0x00FF));
  149.         rgb[12] = (BYTE) ((guid.Data3 & 0xFF00) >> 8);
  150.         rgb[13] = (BYTE) ((guid.Data3 & 0x00FF));
  151.     }
  152.     //  Slurp the rest across
  153.     //
  154.     CopyMemory (&rgb[14], &guid.Data4, 8);
  155.     DebugTraceSc (ScFillConvHeader(), sc);
  156.     return sc;
  157. }
  158. /*
  159.  *  ScAddConversationIndex()
  160.  *  
  161.  *  Purpose:
  162.  *  
  163.  *      Given the conversation index to a message, this function will
  164.  *      create the conversation of a child message to the original.  If
  165.  *      the no original is suplied, then an index is created that would
  166.  *      signify the start of a new thread.
  167.  */
  168. SCODE
  169. ScAddConversationIndex (ULONG cbParent,
  170.     LPBYTE lpbParent,
  171.     ULONG FAR * lpcb,
  172.     LPBYTE FAR * lppb)
  173. {
  174.     SCODE sc;
  175.     DWORD dwTemp;
  176.     SYSTEMTIME st;
  177.     FILETIME ft;
  178.     FILETIME ftLast;
  179.     FILETIME ftDelta;
  180.     HMODULE hMAPIDll = NULL;
  181.     typedef SCODE (STDAPICALLTYPE FAR *MAPICONVIDX)(ULONG, LPBYTE, ULONG FAR *, LPBYTE FAR *);
  182.     MAPICONVIDX lpfnMAPIConvIdx = NULL;
  183. #if defined (WIN16)
  184. #define szScCreateConversationIndex "ScCreateConversationIndex"
  185. #elif defined (_WIN32) && defined (_X86_)
  186. #ifndef szScCreateConversationIndex
  187. #define szScCreateConversationIndex "ScCreateConversationIndex@16"
  188. #endif
  189. #elif defined (_ALPHA_) || defined (_MIPS_) || defined (_PPC_)
  190. #define szScCreateConversationIndex "ScCreateConversationIndex"
  191. #endif
  192. #ifdef _WIN32
  193.     #define szMAPIDll "mapi32.dll"
  194. #else
  195.     #define szMAPIDll "mapi.dll"
  196. #endif
  197.     /*
  198.      * MAPI is going to export a function that is doing the same thing as this one.
  199.      * So if the function is present we'll use it.
  200.      */
  201.     hMAPIDll = GetModuleHandle(szMAPIDll);
  202.     if(hMAPIDll)
  203.     {
  204.         lpfnMAPIConvIdx = (MAPICONVIDX)GetProcAddress(hMAPIDll,
  205.                                             szScCreateConversationIndex);
  206.         if(lpfnMAPIConvIdx)
  207.         {
  208.             return (*lpfnMAPIConvIdx)(cbParent, lpbParent, lpcb, lppb);
  209.         }
  210.     }
  211.     //  Ensure that the parent is what we think
  212.     //  it should be
  213.     //
  214.     if ((cbParent < cbConvIndexHdr) ||
  215.         ((cbParent - cbConvIndexHdr) % cbConvIndexComponent) ||
  216.         (lpbParent[0] != bConvIndexRes))
  217.     {
  218.         cbParent = 0;
  219.         *lpcb = cbConvIndexHdr;
  220.     }
  221.     else
  222.         *lpcb = cbParent + cbConvIndexComponent;
  223.     sc = MAPIAllocateBuffer (*lpcb, (LPVOID FAR *)lppb);
  224.     if (!FAILED (sc))
  225.     {
  226.         if (cbParent == 0)
  227.         {
  228.             //  This is a new key, so all it ever contains
  229.             //  is a header.  Fill it in and we are done
  230.             //
  231.             sc = ScFillConvHeader (*lppb, *lpcb);
  232.             if (FAILED (sc))
  233.             {
  234.                 MAPIFreeBuffer (*lppb);
  235.                 *lppb = NULL;
  236.             }
  237.         }
  238.         else
  239.         {
  240.             //  First copy the old key across
  241.             //
  242.             CopyMemory (*lppb, lpbParent, (UINT)cbParent);
  243.             //  (Cb).  First get the current time (we'll then get
  244.             //  the absolute distance between the current time and
  245.             //  the time in the last chunk)
  246.             //
  247.             GetSystemTime (&st);
  248.             SystemTimeToFileTime (&st, &ft);
  249.             //  Now get the time of the last chunk
  250.             //  
  251.             ExtractLastFileTime (lpbParent, cbParent, &ftLast);
  252.             //  Now mask out the bits we don't want from the
  253.             //  current time
  254.             //
  255.             ft.dwHighDateTime &= 0x00FFFFFF;
  256.             ft.dwLowDateTime &= 0xFFFF0000;
  257.             //  This assert is here to catch how often the
  258.             //  5-byte time can collide and under what scenario,
  259.             //  to see if 5 bytes + the next byte suffices to
  260.             //  make this child chunk unique.
  261.             //  
  262.             Assert (!((ftLast.dwHighDateTime == ft.dwHighDateTime) &&
  263.                 (ftLast.dwLowDateTime == ft.dwLowDateTime)));
  264.             //  Get the change in time
  265.             //
  266.             if ((ft.dwHighDateTime > ftLast.dwHighDateTime) ||
  267.                 ((ft.dwHighDateTime == ftLast.dwHighDateTime) &&
  268.                  (ft.dwLowDateTime > ftLast.dwLowDateTime)))
  269.             {
  270.                 ftDelta = FtSubFt (ft, ftLast);
  271.             }
  272.             else
  273.                 ftDelta = FtSubFt (ftLast, ft);
  274.             //  If the delta is less than 1.7 yrs, use 0
  275.             //
  276.             if (!(ftDelta.dwHighDateTime & 0x00FE0000))
  277.             {
  278.                 //  Just mask out the 31 bits that we
  279.                 //  want from the ftDelta
  280.                 //
  281.                 dwTemp = ((DWORD)(ftDelta.dwHighDateTime & 0x0001FFFF)) << 14 |
  282.                          ((DWORD)(ftDelta.dwLowDateTime & 0xFFFC0000)) >> 18;
  283.                 //  Only the first byte is different
  284.                 //
  285.                 (*lppb)[cbParent] = (BYTE)((dwTemp & 0xFF000000) >> 24 );
  286.             }
  287.             else
  288.             {
  289.                 //  Just mask out the 31 bits that we
  290.                 //  want from the ftDelta
  291.                 //
  292.                 dwTemp = ((DWORD)(ftDelta.dwHighDateTime & 0x003FFFFF)) << 9 |
  293.                          ((DWORD)(ftDelta.dwLowDateTime & 0xFF800000)) >> 23;
  294.                 // Only the first byte is different
  295.                 //
  296.                 (*lppb)[cbParent] = (BYTE)(HIBYTE(HIWORD(dwTemp)) | 0x080);
  297.             }
  298.             //  The remaining delta bytes are the same
  299.             //
  300.             (*lppb)[cbParent + 1] = (BYTE) ((dwTemp & 0x00FF0000) >> 16);
  301.             (*lppb)[cbParent + 2] = (BYTE) ((dwTemp & 0x0000FF00) >> 8);
  302.             (*lppb)[cbParent + 3] = (BYTE) ((dwTemp & 0x000000FF) );
  303.             //  (Cc). Next get the random number
  304.             //  (Cd). Next get the sequence count
  305.             //  -- we are going to use part of the tick count
  306.             //
  307.             (*lppb)[cbParent + 4] = (BYTE) (GetTickCount() & 0x000000FF);
  308.         }
  309.     }
  310.     DebugTraceSc (ScAddConversationIndex(), sc);
  311.     return sc;
  312. }