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 / peer.xp / xplogger.c < prev    next >
C/C++ Source or Header  |  1996-04-11  |  11KB  |  390 lines

  1. /*
  2.  -  X P L O G G E R . C
  3.  -
  4.  *  Purpose:
  5.  *      Code to support the Log File for the Sample Transport Provider.
  6.  *
  7.  *  Copyright 1992-1995 Microsoft Corporation.  All Rights Reserved.
  8.  */
  9.  
  10. #include "xppch.h"
  11.  
  12. static HANDLE hLogHandle = INVALID_HANDLE_VALUE;
  13. static DWORD dwLogLowWater = 0;
  14. static DWORD dwLogHiWater = (DWORD) -1;
  15. static TCHAR chLogFileName[MAX_PATH];
  16.  
  17. #define BUFSIZE 255             /* Size of buffer to use for LogPrintf */
  18. static TCHAR _xpbuf[BUFSIZE];
  19.  
  20.  
  21. /*
  22.  -  InitTransportLog
  23.  -
  24.  *  Purpose:
  25.  *      Called by TransportLogon() logic to start logging.
  26.  *
  27.  *  Parameters:
  28.  *      lpxpl               Session object. We'll need it
  29.  *                          to get the logfile name and
  30.  *                          size constraints.
  31.  *      ulFlags             Flags. Not used at present.
  32.  *
  33.  *  Returns:
  34.  *      hLogHandle          Handle of open Log File.
  35.  *      dwLogLowWater       "Low Water Mark" of Log File.
  36.  *      dwLogHiWater        "High Water Mark" of Log File.
  37.  *      chLogFileName       Filename of open Log File.
  38.  *
  39.  *  Operation:
  40.  *      If a file is already open, this transport session doesn't want to log
  41.  *      events, or the filename given is null, return to caller.  Open the 
  42.  *      file and save the filename into chLogFileName. Store water marks into 
  43.  *      the appropriate variables. Save the handle.  We grab the Critical
  44.  *      Section here because it is possible to Init the logging at times
  45.  *      other than TransportLogon.  This makes it necessary to protect this
  46.  *      section of code.
  47.  */
  48.  
  49. void
  50. InitTransportLog(LPXPL lpxpl, ULONG ulFlags)
  51. {
  52.     LPSPropValue lpPropArray = lpxpl->lpPropArray;
  53.     ULONG ulSessFlags;
  54.     LPTSTR lpszFileName;
  55.     HANDLE hTempHandle;
  56.     DWORD dwOffset;
  57.     ULONG ulLow, ulHigh;
  58.  
  59.     /*  Use the critical section here */
  60.  
  61.     EnterCriticalSection(&(lpxpl->lpxppParent->csTransport));
  62.  
  63.     /*  Are we already logging? If so there's nothing to do here. */
  64.  
  65.     if (hLogHandle != INVALID_HANDLE_VALUE)
  66.     {
  67.         DebugTrace("Already logging to %s\n", chLogFileName);
  68.         goto ret;
  69.     }
  70.  
  71.     /*  Logging isn't on. Would this session like it turned on? */
  72.  
  73.     ulSessFlags = (ArrayIndex(PR_SAMPLE_FLAGS, lpPropArray)).Value.ul;
  74.     if (!(ulSessFlags & PR_SAMPLE_FLAG_LOG_EVENTS))
  75.     {
  76.         DebugTrace("Log flag isn't on, logfile won't be opened\n");
  77.         goto ret;
  78.     }
  79.  
  80.     /*  We're going to log if we can. Get the filename and see if it
  81.         makes any sense. If so, try to open it. */
  82.  
  83.     lpszFileName = (ArrayIndex(PR_SAMPLE_LOGFILE, lpPropArray)).Value.LPSZ;
  84.     if (!lpszFileName || !*lpszFileName)
  85.     {
  86.         DebugTrace("LogFile name wasn't given, logfile won't be opened\n");
  87.         goto ret;
  88.     }
  89.  
  90.     hTempHandle = CreateFile(lpszFileName,
  91.         GENERIC_READ | GENERIC_WRITE,
  92.         FILE_SHARE_READ,
  93.         NULL,
  94.         OPEN_ALWAYS,
  95.         FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS,
  96.         NULL);
  97.  
  98.     if (hTempHandle == INVALID_HANDLE_VALUE)
  99.     {
  100.         DebugTrace("Error %x opening logfile\n", GetLastError());
  101.         goto ret;
  102.     }
  103.  
  104.     /*  The log file is open. Seek to the end so we can resume logging. */
  105.  
  106.     dwOffset = SetFilePointer(hTempHandle, 0L, NULL, FILE_END);
  107.     if (dwOffset == -1)
  108.     {
  109.         DebugTrace("Error %x seeking to end of logfile\n", GetLastError());
  110.         CloseHandle(hTempHandle);
  111.         goto ret;
  112.     }
  113.  
  114.     /*  Get the relevant data into the local structures. */
  115.  
  116.     lstrcpy(chLogFileName, lpszFileName);
  117.     hLogHandle = hTempHandle;
  118.  
  119.     ulLow = (ArrayIndex(PR_SAMPLE_LOGLOWWATER, lpPropArray)).Value.ul;
  120.     ulHigh = (ArrayIndex(PR_SAMPLE_LOGHIGHWATER, lpPropArray)).Value.ul;
  121.     if (ulHigh)
  122.     {
  123.         dwLogHiWater = ulHigh * 1024;
  124.         dwLogLowWater = ulLow * 1024;
  125.     }
  126.  
  127. ret:
  128.  
  129.     /*  Release the critical section */
  130.  
  131.     LeaveCriticalSection(&(lpxpl->lpxppParent->csTransport));
  132.  
  133.     return;
  134. }
  135.  
  136.  
  137. /*
  138.  -  DeInitTransportLog
  139.  -
  140.  *  Purpose:
  141.  *      Called by DeinitTransport() to turn off all session logging.
  142.  *
  143.  *  Parameters:
  144.  *      ulFlags             Flags. Not used at present.
  145.  *
  146.  *  Returns:
  147.  *      none.
  148.  *
  149.  *  Operation:
  150.  *      If we have a file open, try to close it. Reinitialize structures
  151.  *      whether we succeeded or not.
  152.  */
  153.  
  154. void
  155. DeInitTransportLog(ULONG ulFlags)
  156. {
  157.     if (hLogHandle != INVALID_HANDLE_VALUE)
  158.     {
  159.         if (!CloseHandle(hLogHandle))
  160.             DebugTrace("Unable to close logfile %s\n", chLogFileName);
  161.  
  162.         hLogHandle = INVALID_HANDLE_VALUE;
  163.         dwLogHiWater = (DWORD) -1L;
  164.         dwLogLowWater = 0;
  165.         *chLogFileName = '\0';
  166.     }
  167. }
  168.  
  169.  
  170. /*
  171.  -  PrintfTransportLog
  172.  -
  173.  *  Purpose:
  174.  *      Called by various parts of the Transport to log information (if
  175.  *      logging is currently active).
  176.  *
  177.  *  Parameters:
  178.  *      fmt                 Start of variable argument list.
  179.  *
  180.  *  Returns:
  181.  *      none.
  182.  *
  183.  *  Operation:
  184.  *      Format the input data and call PutsTransportLog to write to logfile.
  185.  *      Current maximum length permitted is 255 characters (and is NOT
  186.  *      protected!).
  187.  */
  188.  
  189. void __cdecl
  190. PrintfTransportLog(LPTSTR fmt,...)
  191. {
  192.     va_list marker;
  193.  
  194.     va_start(marker, fmt);
  195.  
  196.     if (hLogHandle != INVALID_HANDLE_VALUE)
  197.     {
  198.         if (wvsprintf((LPTSTR) _xpbuf, fmt, marker))
  199.             PutsTransportLog((LPTSTR) _xpbuf);
  200.     }
  201.  
  202.     va_end(marker);
  203. }
  204.  
  205.  
  206. /*
  207.  -  PutsTransportLog
  208.  -
  209.  *  Purpose:
  210.  *      Called mostly by PrintfTransportLog. Writes a single line to the
  211.  *      logfile if it's open.
  212.  *
  213.  *  Parameters:
  214.  *      str                 String that wants to be written.
  215.  *
  216.  *  Returns:
  217.  *      none.
  218.  *
  219.  *  Operation:
  220.  *      If we have set a high water mark, get the current logfile size. If it
  221.  *      exceeds the high water mark, move back by the amount of the low water
  222.  *      mark, find a line ending, read everything to the end, write to the
  223.  *      front of the file, and truncate to that location.
  224.  *
  225.  *      Create a line consisting of the date and time, the input string, and
  226.  *      line ending characters. Write this line to the logfile.
  227.  */
  228.  
  229. void
  230. PutsTransportLog(LPTSTR str)
  231. {
  232.     DWORD cWritten;
  233.     SYSTEMTIME stOurTime;
  234.     TCHAR tchData[512];
  235.     HGLOBAL hGlobal = (HGLOBAL) 0L;
  236.     LPVOID lpvBuf = NULL;
  237.  
  238.     if (hLogHandle == INVALID_HANDLE_VALUE)
  239.         return;
  240.  
  241.     /*  See if we want to be adjusting the file size. */
  242.  
  243.     if (dwLogHiWater != -1)
  244.     {
  245.         DWORD finfo;
  246.  
  247.         /*  Get the current file size */
  248.  
  249.         finfo = GetFileSize(hLogHandle, NULL);
  250.  
  251.         if (finfo == 0xFFFFFFFF)
  252.         {
  253.             DebugTrace("Error %x getting logfile info\n", GetLastError());
  254.             DeInitTransportLog(LOG_DEINIT_HURRY);
  255.             return;
  256.         }
  257.  
  258.         /*  Is it time to trim back? If so, let's do it. */
  259.  
  260.         if (finfo > dwLogHiWater)
  261.         {
  262.             DWORD dwOffset;
  263.             ULONG ulT, ulLowWater;
  264.             char *lpbT;
  265.  
  266.             /*  Allocate a buffer to read dwLogLowWater bytes. If
  267.                 dwLogLowWater > 32K, use 32K. */
  268.  
  269.             ulLowWater = (dwLogLowWater > 32000L ? 32000L : dwLogLowWater);
  270.             if (ulLowWater == 0L)
  271.                 goto Truncate;
  272.  
  273.             hGlobal = GlobalAlloc(GPTR, (UINT) ulLowWater);
  274.             if (hGlobal == NULL)
  275.             {
  276.                 DebugTrace("Attempt to GlobalAlloc %l bytes for lowwater buffer failed\n", ulLowWater);
  277.                 goto Truncate;
  278.             }
  279.  
  280.             lpvBuf = (LPVOID) GlobalLock(hGlobal);
  281.             if (lpvBuf == NULL)
  282.             {
  283.                 DebugTrace("Attempt to Lock allocated memory buffer failed\n");
  284.                 goto Truncate;
  285.             }
  286.  
  287.             /*  Reposition the pointer back by the size of ulLowWater. */
  288.  
  289.             dwOffset = SetFilePointer(hLogHandle, 0L - ulLowWater, NULL, FILE_CURRENT);
  290.             if (dwOffset == -1)
  291.             {
  292.                 DebugTrace("Error %x seeking to low water mark\n", GetLastError());
  293.                 DeInitTransportLog(LOG_DEINIT_HURRY);
  294.                 return;
  295.             }
  296.  
  297.             /*  Read (ulLowWater) bytes from that position. */
  298.  
  299.             if (!ReadFile(hLogHandle, lpvBuf, ulLowWater, &cWritten, NULL))
  300.             {
  301.                 DebugTrace("Attempt to read %l bytes for low water copy failed, error = %lx\n", ulLowWater, GetLastError());
  302.                 goto Truncate;
  303.             }
  304.  
  305.             Assert(cWritten == ulLowWater);
  306.  
  307.             /*  Find the first newline from that point */
  308.  
  309.             for (ulT = 0, lpbT = (char *)lpvBuf; ulT < ulLowWater; lpbT++, ulT++)
  310.             {
  311.                 if (*lpbT == '\n')
  312.                     break;
  313.             }
  314.  
  315.             /* Did the search fail? If so, truncate the file to zero. */
  316.  
  317.             if (ulT == ulLowWater)
  318.             {
  319.                 ulLowWater = 0L;
  320. Truncate:
  321.                 /*  We failed for some reason. Deallocate the buffer if
  322.                     any and truncate the file to ulLowWater. */
  323.  
  324.                 if (lpvBuf)
  325.                     GlobalUnlock(hGlobal);
  326.                 if (hGlobal)
  327.                     (void)GlobalFree(hGlobal);
  328.  
  329.                 dwOffset = SetFilePointer(hLogHandle, ulLowWater, NULL, FILE_BEGIN);
  330.                 if (dwOffset == -1)
  331.                 {
  332.                     DebugTrace("Error %x seeking to low water mark\n", GetLastError());
  333.                     DeInitTransportLog(LOG_DEINIT_HURRY);
  334.                     return;
  335.                 }
  336.                 goto Adjusted;
  337.             }
  338.  
  339.             /*  We found a newline. Skip over it and write the remaining
  340.                 data from the file start, if any. */
  341.  
  342.             ulT++;
  343.             lpbT++;
  344.  
  345.             dwOffset = SetFilePointer(hLogHandle, 0L, NULL, FILE_BEGIN);
  346.             if (dwOffset == -1)
  347.             {
  348.                 if (lpvBuf)
  349.                     GlobalUnlock(hGlobal);
  350.                 if (hGlobal)
  351.                     (void)GlobalFree(hGlobal);
  352.  
  353.                 DebugTrace("Error %x seeking to file start\n", GetLastError());
  354.                 DeInitTransportLog(LOG_DEINIT_HURRY);
  355.                 return;
  356.             }
  357.  
  358.             if (ulT < ulLowWater)
  359.             {
  360.                 cWritten = 0;
  361.                 WriteFile(hLogHandle, (LPVOID) lpbT, (DWORD) (ulLowWater - ulT), &cWritten, NULL);
  362.                 Assert((cWritten + ulT) == ulLowWater);
  363.             }
  364.  
  365.             GlobalUnlock(hGlobal);
  366.             GlobalFree(hGlobal);
  367.  
  368. Adjusted:
  369.             if (!SetEndOfFile(hLogHandle))
  370.             {
  371.                 DebugTrace("Error %x setting EOF\n", GetLastError());
  372.                 DeInitTransportLog(LOG_DEINIT_HURRY);
  373.                 return;
  374.             }
  375.         }
  376.     }
  377.  
  378.     /* We can't handle more than 490 characters on a input line. */
  379.  
  380.     Assert(lstrlen(str) < 490L);
  381.  
  382.     GetLocalTime(&stOurTime);
  383.     wsprintf(tchData, TEXT("%04d/%02d/%02d %02d:%02d:%02d %s\r\n"),
  384.         stOurTime.wYear, stOurTime.wMonth, stOurTime.wDay,
  385.         stOurTime.wHour, stOurTime.wMinute, stOurTime.wSecond,
  386.         str);
  387.  
  388.     WriteFile(hLogHandle, tchData, (DWORD) (lstrlen(tchData) * sizeof(TCHAR)), &cWritten, NULL);
  389. }
  390.