Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

914 lines
26 KiB

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <pdh.h>
#include <pdhmsg.h>
#include <common.h>
#include "pdlsvc.h"
#include "logutils.h"
// local definitions
typedef struct _LOG_INFO {
DWORD dwLength; // the size of this structure
LPWSTR szLogFileName; // full file name for this log file
HANDLE hLogFileHandle; // handle to open log file
HANDLE hMappedLogFile; // handle for memory mapped files
LPVOID lpMappedFileBase; // starting address for mapped log file
FILE *StreamFile; // stream pointer for text files
DWORD dwLastRecordRead; // index of last record read from the file
LPSTR szLastRecordRead; // pointer to buffer containing the last record
LPWSTR szCatFileName; // catalog file name
HANDLE hCatFileHandle; // handle to the open catalog file
HQUERY hQuery; // query handle associated with the log
DWORD dwMaxRecords; // max size of a circular log file
DWORD dwLogFormat; // log type and access flags
} LOG_INFO, *PLOG_INFO;
// note that when the text format headers are written
// they will be prefixed with a double quote character
// the binary header will not. That's why there's a space
// in the binary string so the offset in the file will be
// the same.
#define VALUE_BUFFER_SIZE 32
//
// local static variables
//
static LOG_INFO LogEntry = {0,NULL,NULL,
NULL,NULL,NULL,0,
NULL,NULL,NULL,NULL,
0,0};
#define TAB_DELIMITER '\t'
#define COMMA_DELIMITER ','
#define DOUBLE_QUOTE '\"'
#define VALUE_BUFFER_SIZE 32
const CHAR szFmtTimeStamp[] = {"\"%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d.%3.3d\""};
const CHAR szFmtRealValue[] = {"%c\"%.20g\""};
const CHAR szRecordTerminator[] = {"\r\n"};
const DWORD dwRecordTerminatorLength = 2;
const CHAR szTimeStampLabel[] = {" Sample Time\""};
const DWORD dwTimeStampLabelLength = 13;
#define TEXTLOG_TYPE_ID_RECORD 1
#define TEXTLOG_HEADER_RECORD 1
#define TEXTLOG_FIRST_DATA_RECORD 2
#define TIME_FIELD_COUNT 7
#define TIME_FIELD_BUFF_SIZE 24
DWORD dwTimeFieldOffsetList[TIME_FIELD_COUNT] = {2, 5, 10, 13, 16, 19, 23};
BOOL
GetLocalFileTime (
SYSTEMTIME *pST,
LONGLONG *pFileTime
)
{
BOOL bResult;
GetLocalTime (pST);
if (pFileTime != NULL) {
bResult = SystemTimeToFileTime (pST, (LPFILETIME)pFileTime);
} else {
bResult = TRUE;
}
return bResult;
}
static
BOOL
DateStringToFileTimeA (
IN LPSTR szDateTimeString,
IN LPFILETIME pFileTime
)
{
CHAR mszTimeFields[TIME_FIELD_BUFF_SIZE];
DWORD dwThisField;
LONG lValue;
SYSTEMTIME st;
// make string into msz
lstrcpynA (mszTimeFields, szDateTimeString, TIME_FIELD_BUFF_SIZE);
for (dwThisField = 0; dwThisField < TIME_FIELD_COUNT; dwThisField++) {
mszTimeFields[dwTimeFieldOffsetList[dwThisField]] = 0;
}
// read string into system time structure
dwThisField = 0;
st.wDayOfWeek = 0;
lValue = atol(&mszTimeFields[0]);
st.wMonth = LOWORD(lValue);
lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
st.wDay = LOWORD(lValue);
lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
st.wYear = LOWORD(lValue);
lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
st.wHour = LOWORD(lValue);
lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
st.wMinute = LOWORD(lValue);
lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
st.wSecond = LOWORD(lValue);
lValue = atol(&mszTimeFields[dwTimeFieldOffsetList[dwThisField++]+1]);
st.wMilliseconds = LOWORD(lValue);
return SystemTimeToFileTime (&st, pFileTime);
}
#define GSFDL_REMOVE_QUOTES 0x00000001
static
DWORD
GetStringFromDelimitedListA (
IN LPSTR szInputString,
IN DWORD dwItemIndex,
IN CHAR cDelimiter,
IN DWORD dwFlags,
IN LPSTR szOutputString,
IN DWORD cchBufferLength
)
{
DWORD dwCurrentIndex = 0;
LPSTR szCurrentItem;
LPSTR szSrcPtr, szDestPtr;
DWORD dwReturn = 0;
// go to desired entry in string, 0 = first entry
szCurrentItem = szInputString;
while (dwCurrentIndex < dwItemIndex) {
// goto next delimiter or terminator
while (*szCurrentItem++ != cDelimiter) {
if (*szCurrentItem == 0) break;
}
dwCurrentIndex++;
}
if (*szCurrentItem != 0) {
// then copy to the user's buffer, as long as it fits
szSrcPtr = szCurrentItem;
szDestPtr = szOutputString;
dwReturn = 0;
while (((*szSrcPtr != cDelimiter) && (*szSrcPtr != 0)) &&
(dwReturn < cchBufferLength)) {
if (dwFlags & GSFDL_REMOVE_QUOTES) {
if (*szSrcPtr == '\"') {
// skip the quote
szSrcPtr++;
continue;
}
}
*szDestPtr++ = *szSrcPtr++; // copy character
dwReturn++; // increment length
}
if (dwReturn > 0) {
*szDestPtr = 0; // add terminator char
}
}
return dwReturn;
}
static
DWORD
AddUniqueStringToMultiSz (
IN LPVOID mszDest,
IN LPSTR szSource,
IN BOOL bUnicodeDest
)
/*++
Routine Description:
searches the Multi-SZ list, mszDest for szSource and appends it
to mszDest if it wasn't found
Arguments:
OUT LPVOID mszDest Multi-SZ list to get new string
IN LPSTR szSource string to add if it's not already in list
ReturnValue:
The new length of the destination string including both
trailing NULL characters if the string was added, or 0 if the
string is already in the list.
--*/
{
LPVOID szDestElem;
DWORD dwReturnLength;
LPWSTR wszSource = NULL;
DWORD dwLength;
// check arguments
if ((mszDest == NULL) || (szSource == NULL)) return 0; // invalid buffers
if (*szSource == '\0') return 0; // no source string to add
// if unicode list, make a unicode copy of the string to compare
// and ultimately copy if it's not already in the list
if (bUnicodeDest) {
dwLength = lstrlenA(szSource) + 1;
wszSource = G_ALLOC (dwLength * sizeof(WCHAR));
if (wszSource != NULL) {
dwReturnLength = mbstowcs (wszSource, szSource, dwLength);
} else {
// unable to allocate memory for the temp string
dwReturnLength = 0;
}
} else {
// just use the ANSI version of the source file name
dwReturnLength = 1;
}
if (dwReturnLength > 0) {
// go to end of dest string
//
for (szDestElem = mszDest;
(bUnicodeDest ? (*(LPWSTR)szDestElem != 0) :
(*(LPSTR)szDestElem != 0));
) {
if (bUnicodeDest) {
// bail out if string already in lsit
if (lstrcmpiW((LPCWSTR)szDestElem, wszSource) == 0) {
return 0;
} else {
// goto the next item
szDestElem = (LPVOID)((LPWSTR)szDestElem +
(lstrlenW((LPCWSTR)szDestElem)+1));
}
} else {
// bail out if string already in lsit
if (lstrcmpiA((LPSTR)szDestElem, szSource) == 0) {
return 0;
} else {
// goto the next item
szDestElem = (LPVOID)((LPSTR)szDestElem +
(lstrlenA((LPCSTR)szDestElem)+1));
}
}
}
// if here, then add string
// szDestElem is at end of list
if (bUnicodeDest) {
lstrcpyW ((LPWSTR)szDestElem, wszSource);
szDestElem = (LPVOID)((LPWSTR)szDestElem + lstrlenW(wszSource) + 1);
*((LPWSTR)szDestElem)++ = L'\0';
dwReturnLength = (DWORD)((LPWSTR)szDestElem - (LPWSTR)mszDest);
} else {
lstrcpyA ((LPSTR)szDestElem, szSource);
szDestElem = (LPVOID)((LPSTR)szDestElem + lstrlenA(szDestElem) + 1);
*((LPSTR)szDestElem)++ = '\0'; // add second NULL
dwReturnLength = (DWORD)((LPSTR)szDestElem - (LPSTR)mszDest);
}
}
return dwReturnLength;
}
PDH_FUNCTION
OpenOutputTextLog (
IN PLOG_INFO pLog
)
{
LONG pdhStatus;
pLog->StreamFile = (FILE *)-1;
pdhStatus = ERROR_SUCCESS;
return pdhStatus;
}
PDH_FUNCTION
CloseTextLog (
IN PLOG_INFO pLog
)
{
LONG pdhStatus;
if (pLog->StreamFile != (FILE *)-1) {
fclose (pLog->StreamFile);
}
pdhStatus = ERROR_SUCCESS;
return pdhStatus;
}
PDH_FUNCTION
WriteTextLogHeader (
IN PLOG_INFO pLog
)
{
LONG pdhStatus = ERROR_SUCCESS;
PLOG_COUNTER_INFO pThisCounter;
CHAR cDelim;
CHAR szLeadDelim[4];
DWORD dwLeadSize;
CHAR szTrailDelim[4];
DWORD dwTrailSize;
DWORD dwBytesWritten;
PPDH_COUNTER_INFO_A pCtrInfo;
DWORD dwCtrInfoSize;
BOOL bResult;
pCtrInfo = G_ALLOC (8192);
if (pCtrInfo == NULL) {
return PDH_MEMORY_ALLOCATION_FAILURE;
}
cDelim = (LOWORD(pLog->dwLogFormat) == OPD_CSV_FILE) ? COMMA_DELIMITER :
TAB_DELIMITER;
szLeadDelim[0] = cDelim;
szLeadDelim[1] = DOUBLE_QUOTE;
szLeadDelim[2] = 0;
szLeadDelim[3] = 0;
dwLeadSize = 2;
szTrailDelim[0] = DOUBLE_QUOTE;
szTrailDelim[1] = 0;
szTrailDelim[2] = 0;
szTrailDelim[3] = 0;
dwTrailSize = 1;
// write the logfile header record
bResult = WriteFile (pLog->hLogFileHandle,
(LPCVOID)&szTrailDelim[0],
1,
&dwBytesWritten,
NULL);
if (!bResult) {
pdhStatus = GetLastError();
}
if (pdhStatus == ERROR_SUCCESS) {
// write the time stamp title
bResult = WriteFile (pLog->hLogFileHandle,
(LPCVOID)szTimeStampLabel,
dwTimeStampLabelLength,
&dwBytesWritten,
NULL);
if (!bResult) {
pdhStatus = GetLastError();
}
}
if (pdhStatus == ERROR_SUCCESS) {
// check each counter in the list of counters for this query and
// write them to the file
// output the path names
pThisCounter = pFirstCounter;
if (pThisCounter != NULL) {
do {
// write the leading delimiter
bResult = WriteFile (pLog->hLogFileHandle,
(LPCVOID)szLeadDelim,
dwLeadSize,
&dwBytesWritten,
NULL);
if (!bResult) {
pdhStatus = GetLastError();
break; // out of the Do Loop
}
// get the counter path information from the counter
dwCtrInfoSize = 8192;
pdhStatus = PdhGetCounterInfoA (
pThisCounter->hCounter,
FALSE,
&dwCtrInfoSize,
pCtrInfo);
if (pdhStatus == ERROR_SUCCESS) {
// write the counter name
bResult = WriteFile (pLog->hLogFileHandle,
(LPCVOID)pCtrInfo->szFullPath,
lstrlen(pCtrInfo->szFullPath),
&dwBytesWritten,
NULL);
if (!bResult) {
pdhStatus = GetLastError();
break; // out of the Do Loop
}
} else {
// unable to get counter information so bail here
break;
}
// write the trailing delimiter
bResult = WriteFile (pLog->hLogFileHandle,
(LPCVOID)szTrailDelim,
dwTrailSize,
&dwBytesWritten,
NULL);
if (!bResult) {
pdhStatus = GetLastError();
break; // out of the Do Loop
}
pThisCounter = pThisCounter->next;
} while (pThisCounter != NULL);
}
}
if (pdhStatus == ERROR_SUCCESS) {
// write the record terminator
bResult = WriteFile (pLog->hLogFileHandle,
(LPCVOID)szRecordTerminator,
dwRecordTerminatorLength,
&dwBytesWritten,
NULL);
if (!bResult) {
pdhStatus = GetLastError();
}
}
G_FREE (pCtrInfo);
return pdhStatus;
}
PDH_FUNCTION
WriteTextLogRecord (
IN PLOG_INFO pLog,
IN SYSTEMTIME *stTimeStamp
)
{
LONG pdhStatus = ERROR_SUCCESS;
PLOG_COUNTER_INFO pThisCounter;
CHAR cDelim;
DWORD dwBytesWritten;
DWORD dwBufferSize;
CHAR szValueBuffer[VALUE_BUFFER_SIZE];
PDH_FMT_COUNTERVALUE pdhValue;
BOOL bResult;
cDelim = (LOWORD(pLog->dwLogFormat) == OPD_CSV_FILE) ? COMMA_DELIMITER :
TAB_DELIMITER;
// format and write the time stamp title
dwBufferSize = sprintf (szValueBuffer, szFmtTimeStamp,
stTimeStamp->wMonth, stTimeStamp->wDay, stTimeStamp->wYear,
stTimeStamp->wHour, stTimeStamp->wMinute, stTimeStamp->wSecond, stTimeStamp->wMilliseconds);
bResult = WriteFile (pLog->hLogFileHandle,
szValueBuffer,
dwBufferSize,
&dwBytesWritten,
NULL);
if (!bResult) {
pdhStatus = GetLastError();
} else {
// check each counter in the list of counters for this query and
// write them to the file
pThisCounter = pFirstCounter;
if (pThisCounter != NULL) {
do {
// get the formatted value from the counter
// compute and format current value
pdhStatus = PdhGetFormattedCounterValue (
pThisCounter->hCounter,
PDH_FMT_DOUBLE,
NULL,
&pdhValue);
if ((pdhStatus == ERROR_SUCCESS) &&
((pdhValue.CStatus == PDH_CSTATUS_VALID_DATA) ||
(pdhValue.CStatus == PDH_CSTATUS_NEW_DATA))) {
// then this is a valid data value so print it
dwBufferSize = sprintf (szValueBuffer,
szFmtRealValue, cDelim, pdhValue.doubleValue);
} else {
// invalid data so show a blank
dwBufferSize = sprintf (szValueBuffer, " ");
// reset error value
pdhStatus = ERROR_SUCCESS;
}
// write this value to the file
bResult = WriteFile (pLog->hLogFileHandle,
szValueBuffer,
dwBufferSize,
&dwBytesWritten,
NULL);
if (!bResult) {
pdhStatus = GetLastError();
break; // out of the loop
}
// goto the next counter in the list
pThisCounter = pThisCounter->next;
} while (pThisCounter != NULL);
}
if (pdhStatus == ERROR_SUCCESS) {
// write the record terminator
bResult = WriteFile (pLog->hLogFileHandle,
(LPCVOID)szRecordTerminator,
dwRecordTerminatorLength,
&dwBytesWritten,
NULL);
if (!bResult) {
pdhStatus = GetLastError();
}
}
}
return pdhStatus;
}
static
LONG
CreateNewLogEntry (
IN LPCWSTR szLogFileName,
IN DWORD dwLogFileNameSize, // in chars, including term char
IN HQUERY hQuery,
IN DWORD dwMaxRecords
)
/*++
creates a new log entry and inserts it in the list of open log files
--*/
{
PLOG_INFO pNewLog;
DWORD dwSize;
LONG pdhStatus = ERROR_SUCCESS;
dwSize = dwLogFileNameSize;
dwSize *= sizeof (WCHAR);
dwSize *= 2; // double to make room for cat file name
dwSize = DWORD_MULTIPLE (dwSize); // ... rounded to the next DWORD
dwSize += sizeof (LOG_INFO); // + room for the data block
pNewLog = &LogEntry;
// set length field (this is used more for validation
// than anything else
pNewLog->dwLength = sizeof (LOG_INFO);
// append filename strings immediately after this block
pNewLog->szLogFileName = (LPWSTR)(&pNewLog[1]);
lstrcpyW (pNewLog->szLogFileName, szLogFileName);
// locate catalog name immediately after log file name
pNewLog->szCatFileName = pNewLog->szLogFileName + dwLogFileNameSize;
// FIXFIX: for now they are the same, later the log file extension
// will be replaced with the catalog file extenstion
lstrcpyW (pNewLog->szCatFileName, szLogFileName);
// initialize the file handles
pNewLog->hLogFileHandle = INVALID_HANDLE_VALUE;
pNewLog->hCatFileHandle = INVALID_HANDLE_VALUE;
// assign the query
pNewLog->hQuery = hQuery;
pNewLog->dwMaxRecords = dwMaxRecords;
pNewLog->dwLogFormat = 0; // for now
return pdhStatus;
}
static
LONG
OpenOutputLogFile (
IN PLOG_INFO pLog,
IN DWORD dwAccessFlags,
IN LPDWORD lpdwLogType
)
{
LONG Win32Error;
LONG pdhStatus = ERROR_SUCCESS;
DWORD dwFileCreate;
// open file for output based on the specified access flags
if (pdhStatus == ERROR_SUCCESS) {
switch (dwAccessFlags & LOG_CREATE_MASK) {
case LOG_CREATE_NEW:
dwFileCreate = CREATE_NEW;
break;
case LOG_CREATE_ALWAYS:
dwFileCreate = CREATE_ALWAYS;
break;
case LOG_OPEN_EXISTING:
dwFileCreate = OPEN_EXISTING;
break;
case LOG_OPEN_ALWAYS:
dwFileCreate = OPEN_ALWAYS;
break;
default:
// unrecognized value
pdhStatus = PDH_INVALID_ARGUMENT;
break;
}
}
if (pdhStatus == ERROR_SUCCESS) {
pLog->hLogFileHandle = CreateFileW (
pLog->szLogFileName,
GENERIC_WRITE, // write access for output
FILE_SHARE_READ, // allow read sharing
NULL, // default security
dwFileCreate,
FILE_ATTRIBUTE_NORMAL,
NULL); // no template file
if (pLog->hLogFileHandle == INVALID_HANDLE_VALUE) {
Win32Error = GetLastError();
}
}
if (pdhStatus == ERROR_SUCCESS) {
// the file opened successfully so update the data structure
// this assumes the access flags are in the HIWORD and the...
pLog->dwLogFormat = dwAccessFlags & LOG_ACCESS_MASK;
// the type id is in the LOWORD
pLog->dwLogFormat |= *lpdwLogType;
// call any type-specific open functions
switch (LOWORD(pLog->dwLogFormat)) {
case OPD_CSV_FILE:
case OPD_TSV_FILE:
pdhStatus = OpenOutputTextLog(pLog);
break;
default:
pdhStatus = ERROR_NOT_SUPPORTED;
break;
}
}
return pdhStatus;
}
static
LONG
WriteLogHeader (
IN PLOG_INFO pLog
)
{
LONG pdhStatus;
switch (LOWORD(pLog->dwLogFormat)) {
case OPD_CSV_FILE:
case OPD_TSV_FILE:
pdhStatus = WriteTextLogHeader (pLog);
break;
default:
pdhStatus = ERROR_NOT_SUPPORTED;
break;
}
return pdhStatus;
}
static
LONG
CloseAndDeleteLogEntry (
IN PLOG_INFO pLog,
IN DWORD dwFlags
)
{
LONG pdhStatus = ERROR_SUCCESS;
// call any type-specific open functions
switch (LOWORD(pLog->dwLogFormat)) {
case OPD_CSV_FILE:
case OPD_TSV_FILE:
pdhStatus = CloseTextLog(pLog);
break;
default:
pdhStatus = ERROR_NOT_SUPPORTED;
break;
}
if (pdhStatus == ERROR_SUCCESS) {
if (pLog->lpMappedFileBase != NULL) {
UnmapViewOfFile (pLog->lpMappedFileBase);
}
if (pLog->hMappedLogFile != NULL) {
CloseHandle (pLog->hMappedLogFile);
}
if (pLog->hLogFileHandle != INVALID_HANDLE_VALUE) {
CloseHandle (pLog->hLogFileHandle);
}
if (pLog->hCatFileHandle != INVALID_HANDLE_VALUE) {
CloseHandle (pLog->hCatFileHandle);
}
if ((dwFlags & FLAGS_CLOSE_QUERY) == FLAGS_CLOSE_QUERY) {
pdhStatus = PdhCloseQuery (pLog->hQuery);
}
}
return pdhStatus;
}
//
// Local utility functions
//
LONG __stdcall
OpenLogW (
IN LPCWSTR szLogFileName,
IN DWORD dwAccessFlags,
IN LPDWORD lpdwLogType,
IN HQUERY hQuery,
IN DWORD dwMaxRecords
)
{
DWORD dwFileNameSize;
LONG pdhStatus = ERROR_SUCCESS;
DWORD dwLocalLogType;
PLOG_INFO pLog = &LogEntry;
try {
// test the parameters before continuing
if (szLogFileName != NULL) {
dwFileNameSize = lstrlenW (szLogFileName) + 1;
if (dwFileNameSize > 1) {
if (lpdwLogType != NULL) {
dwLocalLogType = *lpdwLogType; // test read
*lpdwLogType = 0; // test write to buffer
*lpdwLogType = dwLocalLogType; // restore value
} else {
// required parameter is missing
pdhStatus = PDH_INVALID_ARGUMENT;
}
} else {
// empty file name
pdhStatus = PDH_INVALID_ARGUMENT;
}
} else {
// required parameter is missing
pdhStatus = PDH_INVALID_ARGUMENT;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
// something failed so give up here
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
// create a log entry
pdhStatus = CreateNewLogEntry (
szLogFileName,
dwFileNameSize,
hQuery,
dwMaxRecords);
// open the file
if (pdhStatus == ERROR_SUCCESS) {
// dispatch based on read/write attribute
if ((dwAccessFlags & LOG_READ_ACCESS) ==
LOG_READ_ACCESS) {
pdhStatus = ERROR_NOT_SUPPORTED;
} else if ((dwAccessFlags & LOG_WRITE_ACCESS) ==
LOG_WRITE_ACCESS) {
pdhStatus = OpenOutputLogFile (pLog,
dwAccessFlags, &dwLocalLogType);
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = WriteLogHeader (pLog);
}
} else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
// return handle to caller
*lpdwLogType = dwLocalLogType;
}
}
}
return pdhStatus;
}
LONG __stdcall
UpdateLog (
IN LPDWORD pdwSampleTime)
{
LONG pdhStatus;
SYSTEMTIME st;
LONGLONG llStartTime = 0;
LONGLONG llFinishTime = 0;
PLOG_INFO pLog = &LogEntry;
*pdwSampleTime = 0;
if (TRUE) {
// get the timestamp and update the log's query, then write the data
// to the log file in the appropriate format
GetLocalFileTime (&st, &llStartTime);
// update data samples
pdhStatus = PdhCollectQueryData (pLog->hQuery);
// write data to log file
pdhStatus = WriteTextLogRecord (pLog, &st);
GetLocalFileTime (&st, &llFinishTime);
*pdwSampleTime = (DWORD)((llFinishTime - llStartTime) / 10000L);
}
return pdhStatus;
}
LONG __stdcall
CloseLog(
IN DWORD dwFlags
)
{
LONG pdhStatus;
PLOG_INFO pLog;
pLog = &LogEntry;
pdhStatus = CloseAndDeleteLogEntry (pLog, dwFlags);
memset (pLog, 0, sizeof(LOG_INFO));
return pdhStatus;
}
LONG __stdcall
GetLogFileSize (
IN LONGLONG *llSize
)
{
LONG pdhStatus = ERROR_SUCCESS;
PLOG_INFO pLog;
UINT nErrorMode;
DWORD dwFileSizeLow = 0;
DWORD dwFileSizeHigh = 0;
LONGLONG llFileLength;
DWORD dwError;
// test return argument
try {
// test access to the user's buffer.
llFileLength = *llSize;
*llSize = 0;
*llSize = llFileLength;
} except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
return pdhStatus;
}
if (TRUE) {
pLog = &LogEntry;
// disable windows error message popup
nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
if (pLog->hLogFileHandle != INVALID_HANDLE_VALUE) {
dwFileSizeLow = GetFileSize (pLog->hLogFileHandle, &dwFileSizeHigh);
// test for error
if ((dwFileSizeLow == 0xFFFFFFFF) &&
((dwError = GetLastError()) != NO_ERROR)) {
// then we couldn't get the file size
pdhStatus = ERROR_OPEN_FAILED;
} else {
if (dwFileSizeHigh > 0) {
llFileLength = dwFileSizeHigh << (sizeof(DWORD) * 8);
} else {
llFileLength = 0;
}
llFileLength += dwFileSizeLow;
// write to the caller' buffer
*llSize = llFileLength;
}
} else {
pdhStatus = ERROR_OPEN_FAILED;
}
SetErrorMode (nErrorMode); // restore old error mode
} else {
pdhStatus = PDH_INVALID_HANDLE;
}
return pdhStatus;
}