<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://forums.iis.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:cs="http://blogs.iis.net/"><channel><title>Advanced Topics</title><link>http://forums.iis.net/1143.aspx</link><description>Advanced topics such as COM Programming, Log file format conversions, and Multiplex features.</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>Minor Enhancement to Microsoft's STS-to-CSV Parser C++ Console App</title><link>http://forums.iis.net/thread/1850559.aspx</link><pubDate>Thu, 05 Jan 2006 20:54:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:1850559</guid><dc:creator>Anonymous</dc:creator><slash:comments>0</slash:comments><comments>http://forums.iis.net/thread/1850559.aspx</comments><wfw:commentRss>http://forums.iis.net/commentrss.aspx?SectionID=1143&amp;PostID=1850559</wfw:commentRss><description>&lt;P&gt;Greetings all, &lt;/P&gt;&lt;P&gt;I recently started working with Logparser 2.2, and needed it to process both IIS logs and STS logs. As many of you might have guessed, the IIS logs processed quite nicely, using Logparser 2.2's IISW3C plugin to parse them. &lt;/P&gt;&lt;P&gt;The STS logs were another matter - no obvious Logparser plugin to aid me... but I did come across a semi-popular article at Microsoft: &lt;/P&gt;&lt;P&gt;&lt;a target=_blank href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odc_SP2003_ta/html/ODC_WSSUsageEventLogging.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odc_SP2003_ta/html/ODC_WSSUsageEventLogging.asp&lt;/A&gt;&lt;/P&gt;&lt;P&gt;The author - Radu Rusu - does a fine job of providing bulletproof C++ sample code and excellent instructions. His STSlog-to-CSV Transformer console application compiled, built and worked precisely as he described...&lt;/P&gt;&lt;P&gt;But his output file had no header line of column names in it - something CSV files really benefit from in order to be completely useful. &lt;/P&gt;&lt;P&gt;I added that extra code to his snippet, and offer it here for everyone to use. Your end result will be a Windows Console App that can be added to a BAT file used to automate processing of both IIS logs and STS logs. &lt;/P&gt;&lt;P&gt;Cheers, and thanks again to Radu for an excellent article...&lt;/P&gt;&lt;P&gt;- MV&lt;/P&gt;&lt;PRE class=code&gt;BEGIN CODE ===============v&lt;/PRE&gt;&lt;PRE class=code&gt;#include "stdafx.h"&lt;BR&gt;#include "windows.h"&lt;BR&gt;#include "assert.h"&lt;BR&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/PRE&gt;&lt;PRE class=code&gt;typedef struct _VLogFileEntry&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Point to previous entry&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; struct _VLogFileEntry *pPrev;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned char&amp;nbsp; bitFlags;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Number of bytes to skip ahead to next entry&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned short cbEntry;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned short cbSiteUrl;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned short cbWeb;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned short cbDoc;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Bandwidth consumed (bytes in + bytes out)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned long cBytes;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned short httpStatus;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned short cbUser;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned short cbQS;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned short cbRef;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; signed short&amp;nbsp; cbUAS;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; signed long&amp;nbsp; reserved;&lt;BR&gt;} VLogFileEntry;&lt;/PRE&gt;&lt;PRE class=code&gt;int main(int argc, char* argv[])&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool fError = FALSE;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (argc &amp;lt; 3)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "\nUsage: %s wsslogfile csvfile optionalField1 optionalField2",&amp;nbsp; argv[0]);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *szFile = argv[1];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *szCsvFile = argv[2];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *szOptionalField1 = argc &amp;gt; 3 ? argv[3] : NULL;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *szOptionalField2 = argc &amp;gt; 4 ? argv[4] : NULL;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *szGuid = NULL;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *szReplace = NULL;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Format of each CSV line. Include optional fields&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; passed as command line arguments, if any*/&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *szFormat = "%s,%s,%s,%s,%s,%s,%s,%s\r\n";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL == szOptionalField1)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; szFormat += 3;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL == szOptionalField2)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; szFormat += 3;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FILE *csvFile = fopen( szCsvFile, "a");&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Bytes (with no braces)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static const unsigned long cbSiteGuid&amp;nbsp; = 36; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static const unsigned short cbTimeStamp = 8;&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("\r\nParsing %s to %s \r\n",&amp;nbsp; szFile, szCsvFile);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *pBase, *pEnd;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HANDLE hF, hFM;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((hF = CreateFileA(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; szFile,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GENERIC_READ, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NULL, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OPEN_EXISTING, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NULL)) == INVALID_HANDLE_VALUE)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Can't open file %s (perhaps because it doesn't exist)",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; szFile);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DWORD dwFileSize, dwFileSizeHigh = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dwFileSize = GetFileSize(hF, &amp;amp;dwFileSizeHigh);&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* We should never encounter a file larger than about 1 GB */&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (dwFileSizeHigh || dwFileSize &amp;gt; 1000000000)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(" File too large %s", szFile);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CloseHandle(hF);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (dwFileSize == 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(" Skipping empty file %s", szFile);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CloseHandle(hF);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hFM = CreateFileMapping(hF, NULL, PAGE_WRITECOPY, 0, 0, NULL);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (NULL == hFM ||&lt;BR&gt;NULL == (pBase = (char *)MapViewOfFile(hFM, FILE_MAP_COPY, 0, 0, 0)))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(" Can't map file %s", szFile);&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (hFM)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CloseHandle(hFM);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CloseHandle(hF);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pEnd = pBase + dwFileSize - sizeof(VLogFileEntry);&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *pCur, *pszSite, *pszSiteGuid, *pszTS;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *pszWeb, *pszDoc, *pszUser;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; VLogFileEntry *pLFE;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned long cItemsProcessed = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned long cbEntrySize = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; const unsigned long maxCbEntrySize = 2048;&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;FONT style="BACKGROUND-COLOR: #dddd77"&gt;&amp;nbsp; //MV: Start output CSV file with header (column) labels - very useful in future...&lt;BR&gt;&amp;nbsp;fprintf(csvFile, szFormat,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Timestamp",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "SiteGUID",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "SiteURL",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Subsite",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Document",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "User",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Optional1",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Optional2");&lt;/FONT&gt;&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;FONT style="BACKGROUND-COLOR: #dddd77"&gt;&amp;nbsp;//MV: Now begin looping through all the logfile entries, entering them into the output file...&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(pCur = pBase;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCur &amp;lt; pEnd;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCur += cbEntrySize)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pLFE = (VLogFileEntry *)pCur;&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cbEntrySize = sizeof(VLogFileEntry) \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + cbSiteGuid + cbTimeStamp + 2 \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + pLFE-&amp;gt;cbSiteUrl +&amp;nbsp; pLFE-&amp;gt;cbWeb +&amp;nbsp; pLFE-&amp;gt;cbDoc \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + pLFE-&amp;gt;cbUser +&amp;nbsp; pLFE-&amp;gt;cbQS&amp;nbsp; +&amp;nbsp; pLFE-&amp;gt;cbRef \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + pLFE-&amp;gt;cbUAS&amp;nbsp; + 9;&amp;nbsp;&amp;nbsp; //7 NULLs and 2 bytes for \r\n&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Check for corrupt log files&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fError&amp;nbsp; = (cbEntrySize &amp;gt; maxCbEntrySize ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; !(*(pCur + sizeof(VLogFileEntry)) == '\r') ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; !(*(pCur +&amp;nbsp; sizeof(VLogFileEntry) + 1) == '\n') ||&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; !(pLFE-&amp;gt;cbEntry == cbEntrySize));&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (fError)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("Error reading Wss log file, aborting.\n");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto cleanup;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Skip&amp;nbsp; 2 bytes for \r\n&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszSiteGuid = pCur + sizeof(VLogFileEntry) + 2;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Skip 1 byte for the NULL separator&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszTS = pszSiteGuid + cbSiteGuid + 1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszSite = pszTS + cbTimeStamp + 1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Stop at the end of the site url &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *(pszSite + pLFE-&amp;gt;cbSiteUrl) = '\0';&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Skip 1 byte for the NULL separator&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszWeb = pszSite + pLFE-&amp;gt;cbSiteUrl + 1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszDoc&amp;nbsp; = pszWeb + pLFE-&amp;gt;cbWeb + 1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszUser = pszDoc + pLFE-&amp;gt;cbDoc + 1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* Output is in the format: timestamp, site guid, siteUrl, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; subsite, document, user, optional1, optional2*/&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fprintf(csvFile, szFormat,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszTS,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszSiteGuid,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszSite,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszWeb,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszDoc,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pszUser,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; szOptionalField1,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; szOptionalField2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/PRE&gt;&lt;PRE class=code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cleanup:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; UnmapViewOfFile(pBase);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CloseHandle(hFM);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CloseHandle(hF);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fclose(csvFile);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return fError;&lt;BR&gt;}&lt;/PRE&gt;&lt;PRE class=code&gt;END CODE =================^&lt;/PRE&gt;</description></item></channel></rss>