Leaked source code of windows server 2003
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.
 
 
 
 
 
 

550 lines
16 KiB

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <pdh.h>
#include <pdhp.h>
#include <pdhmsg.h>
#include <winperf.h>
#include <tchar.h>
#include <varg.h>
#include "rpdh.h"
const DWORD dwFileHeaderLength = 13;
const DWORD dwTypeLoc = 2;
const DWORD dwFieldLength = 7;
const DWORD dwPerfmonTypeLength = 5;
LPCSTR szTsvType = "PDH-TSV";
LPCSTR szCsvType = "PDH-CSV";
LPCSTR szBinaryType = "PDH-BIN";
LPCWSTR cszPerfmonLogSig = (LPCWSTR)L"Loges";
#define MemoryAllocate(x) \
((LPVOID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, x))
#define MemoryFree(x) \
if( x ){ ((VOID) HeapFree(GetProcessHeap(), 0, x)); x = NULL; }
#define MemoryResize(x,y) \
((LPVOID) HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, x, y));
#define MAKEULONGLONG(low, high) \
((ULONGLONG) (((DWORD) (low)) | ((ULONGLONG) ((DWORD) (high))) << 32))
#define PDH_BLG_HEADER_SIZE 24
#define PDH_MAX_BUFFER 0x01000000
#define PDH_HEADER_BUFFER 65536
typedef struct _PDHI_BINARY_LOG_RECORD_HEADER {
DWORD dwType;
DWORD dwLength;
} PDHI_BINARY_LOG_RECORD_HEADER, *PPDHI_BINARY_LOG_RECORD_HEADER;
PDH_STATUS
R_PdhRelog( LPTSTR szSource, HQUERY hQuery, PPDH_RELOG_INFO_W pRelogInfo )
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HLOG hLogOut;
ULONG nSampleCount = 0;
ULONG nSamplesWritten = 0;
ULONG nRecordSkip;
pdhStatus = PdhOpenLogW(
pRelogInfo->strLog,
pRelogInfo->dwFlags,
&pRelogInfo->dwFileFormat,
hQuery,
0,
NULL,
&hLogOut
);
if( pdhStatus == ERROR_SUCCESS ){
DWORD dwNumEntries = 1;
DWORD dwBufferSize = sizeof(PDH_TIME_INFO);
PDH_TIME_INFO TimeInfo;
ZeroMemory( &TimeInfo, sizeof( PDH_TIME_INFO ) );
pdhStatus = PdhGetDataSourceTimeRange(
szSource,
&dwNumEntries,
&TimeInfo,
&dwBufferSize
);
if( pRelogInfo->TimeInfo.StartTime > TimeInfo.StartTime &&
pRelogInfo->TimeInfo.StartTime < TimeInfo.EndTime ){
TimeInfo.StartTime = pRelogInfo->TimeInfo.StartTime;
}
if( pRelogInfo->TimeInfo.EndTime < TimeInfo.EndTime &&
pRelogInfo->TimeInfo.EndTime > TimeInfo.StartTime ){
TimeInfo.EndTime = pRelogInfo->TimeInfo.EndTime;
}
if( TimeInfo.EndTime > TimeInfo.StartTime ){
pdhStatus = PdhSetQueryTimeRange( hQuery, &TimeInfo );
}
nRecordSkip = pRelogInfo->TimeInfo.SampleCount >= 1 ? pRelogInfo->TimeInfo.SampleCount : 1;
while( ERROR_SUCCESS == pdhStatus ){
if( nSampleCount++ % nRecordSkip ){
pdhStatus = PdhCollectQueryData( hQuery );
continue;
}
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PdhUpdateLog( hLogOut, NULL );
nSamplesWritten++;
}
}
if( PDH_NO_MORE_DATA == pdhStatus ||
(PDH_ENTRY_NOT_IN_LOG_FILE == pdhStatus && pRelogInfo->dwFileFormat == PDH_LOG_TYPE_BINARY) ){
pdhStatus = PdhCloseLog( hLogOut, 0 );
if( ERROR_SUCCESS == pdhStatus ){
PdhGetDataSourceTimeRange( pRelogInfo->strLog, &dwNumEntries, &pRelogInfo->TimeInfo, &dwBufferSize );
}
}
}
pRelogInfo->TimeInfo.SampleCount = nSamplesWritten;
return pdhStatus;
}
DWORD
GetLogFileType (
IN HANDLE hLogFile
)
{
CHAR cBuffer[MAX_PATH];
CHAR cType[MAX_PATH];
WCHAR wcType[MAX_PATH];
BOOL bStatus;
DWORD dwResult;
DWORD dwBytesRead;
memset (&cBuffer[0], 0, sizeof(cBuffer));
memset (&cType[0], 0, sizeof(cType));
memset (&wcType[0], 0, sizeof(wcType));
// read first log file record
SetFilePointer (hLogFile, 0, NULL, FILE_BEGIN);
bStatus = ReadFile (hLogFile,
(LPVOID)cBuffer,
dwFileHeaderLength,
&dwBytesRead,
NULL);
if (bStatus) {
// read header record to get type
lstrcpynA (cType, (LPSTR)(cBuffer+dwTypeLoc), dwFieldLength+1);
if (lstrcmpA(cType, szTsvType) == 0) {
dwResult = PDH_LOG_TYPE_TSV;
} else if (lstrcmpA(cType, szCsvType) == 0) {
dwResult = PDH_LOG_TYPE_CSV;
} else if (lstrcmpA(cType, szBinaryType) == 0) {
dwResult = PDH_LOG_TYPE_RETIRED_BIN_;
} else {
// perfmon log file type string is in a different
// location than sysmon logs and used wide chars.
lstrcpynW (wcType, (LPWSTR)cBuffer, dwPerfmonTypeLength+1);
if (lstrcmpW(wcType, cszPerfmonLogSig) == 0) {
dwResult = PDH_LOG_TYPE_PERFMON;
} else {
dwResult = PDH_LOG_TYPE_UNDEFINED;
}
}
} else {
// unable to read file
dwResult = PDH_LOG_TYPE_UNDEFINED;
}
return dwResult;
}
PDH_STATUS
R_PdhBlgLogFileHeader(LPCWSTR szFile1, LPCWSTR szFile2)
{
BOOL bReturn = FALSE;
PDH_STATUS Status = ERROR_SUCCESS;
LPWSTR szHeaderList1 = NULL;
LPWSTR szHeaderList2 = NULL;
DWORD dwHeader1 = 0;
DWORD dwHeader2 = 0;
LPWSTR szName1;
LPWSTR szName2;
Status = PdhListLogFileHeaderW(szFile1, szHeaderList1, &dwHeader1);
if (Status != ERROR_SUCCESS && Status != PDH_MORE_DATA && Status != PDH_INSUFFICIENT_BUFFER){
goto Cleanup;
}
szHeaderList1 = (LPWSTR)MemoryAllocate( (dwHeader1+1)*sizeof(WCHAR) );
Status = PdhListLogFileHeaderW(szFile1, szHeaderList1, &dwHeader1);
if (Status != ERROR_SUCCESS ){
goto Cleanup;
}
Status = PdhListLogFileHeaderW(szFile2, szHeaderList2, &dwHeader2);
if (Status != ERROR_SUCCESS && Status != PDH_MORE_DATA && Status != PDH_INSUFFICIENT_BUFFER){
goto Cleanup;
}
szHeaderList2 = (LPWSTR)MemoryAllocate( (dwHeader2+1)*sizeof(WCHAR) );
Status = PdhListLogFileHeaderW(szFile2, szHeaderList2, &dwHeader2);
if (Status != ERROR_SUCCESS ){
goto Cleanup;
}
for (szName1 = szHeaderList1, szName2 = szHeaderList2;
szName1[0] != L'\0' && szName2[0] != L'\0';
szName1 += (lstrlenW(szName1) + 1),
szName2 += (lstrlenW(szName2) + 1)) {
if (lstrcmpiW(szName1, szName2) != 0) {
varg_printf( g_debug, _T("(%s) != (%s)\n"), szName1, szName2);
break;
}
}
if (szName1[0] != L'\0' || szName2[0] != L'\0'){
Status = PDH_HEADER_MISMATCH;
}
Cleanup:
MemoryFree( szHeaderList1 );
MemoryFree( szHeaderList2 );
return Status;
}
PDH_STATUS
R_PdhGetLogFileType(
IN LPCWSTR LogFileName,
IN LPDWORD LogFileType)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HANDLE hFile;
DWORD dwLogFormat;
if (LogFileName == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
dwLogFormat = * LogFileType;
* LogFileType = dwLogFormat;
if (* LogFileName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
hFile = CreateFileW(LogFileName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
}
}
if (pdhStatus == ERROR_SUCCESS) {
dwLogFormat = GetLogFileType(hFile);
CloseHandle(hFile);
}
if (pdhStatus == ERROR_SUCCESS) {
* LogFileType = dwLogFormat;
}
return pdhStatus;
}
PDH_STATUS
R_PdhRelogCopyFile(
HANDLE hOutFile,
HANDLE hInFile,
BOOL bCopyHeader
)
{
BOOL bResult = TRUE;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwSizeLow = 0;
DWORD dwSizeHigh = 0;
DWORD dwBuffer = PDH_MAX_BUFFER;
ULONGLONG lFileSize = 0;
ULONGLONG lCurrent = 0;
LPBYTE pBuffer = NULL;
LPBYTE pCurrent = NULL;
PPDHI_BINARY_LOG_RECORD_HEADER pPdhBlgHeader = NULL;
dwSizeLow = GetFileSize(hInFile, & dwSizeHigh);
lFileSize = MAKEULONGLONG(dwSizeLow, dwSizeHigh);
lCurrent = PDH_BLG_HEADER_SIZE + sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
if (lCurrent > lFileSize) {
pdhStatus = PDH_INVALID_HANDLE;
goto Cleanup;
}
pBuffer = (LPBYTE)MemoryAllocate(dwBuffer);
if (pBuffer == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
dwSizeLow = (DWORD) lCurrent;
dwSizeHigh = 0;
bResult = ReadFile(hInFile, pBuffer, dwSizeLow, & dwSizeHigh, NULL);
if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
pdhStatus = PDH_INVALID_DATA;
goto Cleanup;
}
pPdhBlgHeader = (PPDHI_BINARY_LOG_RECORD_HEADER)
(pBuffer + PDH_BLG_HEADER_SIZE);
if (pPdhBlgHeader->dwType != 0x01024C42) {
pdhStatus = PDH_INVALID_ARGUMENT;
goto Cleanup;
}
if (pPdhBlgHeader->dwLength + PDH_BLG_HEADER_SIZE > dwBuffer) {
LPBYTE pTemp = pBuffer;
pBuffer = (LPBYTE)MemoryResize(pBuffer, pPdhBlgHeader->dwLength);
if (pBuffer == NULL) {
MemoryFree(pTemp);
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
}
if ((lCurrent + dwSizeLow) > lFileSize) {
pdhStatus = PDH_INVALID_HANDLE;
goto Cleanup;
}
pCurrent = (LPBYTE) (pBuffer + dwSizeLow);
dwSizeLow = pPdhBlgHeader->dwLength
- sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
dwSizeHigh = 0;
bResult = ReadFile(hInFile, pCurrent, dwSizeLow, & dwSizeHigh, NULL);
if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
pdhStatus = PDH_INVALID_DATA;
goto Cleanup;
}
lCurrent += dwSizeLow;
if (bCopyHeader) {
dwSizeLow = dwSizeHigh = (DWORD) lCurrent;
bResult = WriteFile(hOutFile, pBuffer, dwSizeLow, & dwSizeHigh, NULL);
if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
pdhStatus = PDH_INVALID_DATA;
goto Cleanup;
}
}
while (lCurrent + sizeof(PDHI_BINARY_LOG_RECORD_HEADER) < lFileSize) {
ZeroMemory(pBuffer, dwBuffer);
dwSizeLow = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
dwSizeHigh = 0;
bResult = ReadFile(hInFile, pBuffer, dwSizeLow, & dwSizeHigh, NULL);
if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
pdhStatus = PDH_INVALID_DATA;
goto Cleanup;
}
pPdhBlgHeader = (PPDHI_BINARY_LOG_RECORD_HEADER) pBuffer;
if ((pPdhBlgHeader->dwType & 0x0000FFFF) != 0x00004C42) {
pdhStatus = PDH_INVALID_ARGUMENT;
goto Cleanup;
}
if (pPdhBlgHeader->dwLength > dwBuffer) {
LPBYTE pTemp = pBuffer;
pBuffer = (LPBYTE)MemoryResize(pBuffer, pPdhBlgHeader->dwLength);
if (pBuffer == NULL) {
MemoryFree(pTemp);
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
}
if ((lCurrent + pPdhBlgHeader->dwLength) > lFileSize) {
pdhStatus = PDH_INVALID_HANDLE;
bResult = FALSE;
goto Cleanup;
}
pCurrent = (LPBYTE) (pBuffer + dwSizeLow);
dwSizeLow = pPdhBlgHeader->dwLength
- sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
dwSizeHigh = 0;
bResult = ReadFile(hInFile, pCurrent, dwSizeLow, & dwSizeHigh, NULL);
if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
pdhStatus = PDH_INVALID_DATA;
goto Cleanup;
}
if ((pPdhBlgHeader->dwType & 0x00FF0000) == 0x00030000) {
dwSizeLow = dwSizeHigh = pPdhBlgHeader->dwLength;
bResult = WriteFile(
hOutFile, pBuffer, dwSizeLow, & dwSizeHigh, NULL);
if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
pdhStatus = PDH_INVALID_DATA;
goto Cleanup;
}
}
lCurrent += pPdhBlgHeader->dwLength;
}
Cleanup:
if (pBuffer != NULL){
MemoryFree(pBuffer);
}
return pdhStatus;
}
PDH_STATUS
R_PdhAppendLog( LPTSTR szSource, LPTSTR szAppend )
{
HANDLE hSource = INVALID_HANDLE_VALUE;
HANDLE hAppend = INVALID_HANDLE_VALUE;
BOOL bResult = TRUE;
PDH_STATUS pdhStatus;
DWORD dwFormat;
PDH_TIME_INFO TimeSource;
PDH_TIME_INFO TimeAppend;
LPTSTR mszSourceHeader = NULL;
LPTSTR mszAppendHeader = NULL;
DWORD dwSourceSize = 0;
DWORD dwAppendSize = 0;
DWORD dwNumEntries = 1;
DWORD dwBufferSize = sizeof(PDH_TIME_INFO);
//
// Compare the log types, both must be Windows 2000 binary
//
pdhStatus = R_PdhGetLogFileType( szSource, &dwFormat );
if( ERROR_SUCCESS != pdhStatus || PDH_LOG_TYPE_RETIRED_BIN_ != dwFormat ){
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PDH_TYPE_MISMATCH;
}
goto cleanup;
}
pdhStatus = R_PdhGetLogFileType( szAppend, &dwFormat );
if( ERROR_SUCCESS != pdhStatus || PDH_LOG_TYPE_RETIRED_BIN_ != dwFormat ){
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PDH_TYPE_MISMATCH;
}
goto cleanup;
}
//
// Compare the time ranges, source file must start after append end
//
ZeroMemory( &TimeSource, sizeof( PDH_TIME_INFO ) );
ZeroMemory( &TimeAppend, sizeof( PDH_TIME_INFO ) );
pdhStatus = PdhGetDataSourceTimeRange(
szSource,
&dwNumEntries,
&TimeSource,
&dwBufferSize
);
if( ERROR_SUCCESS != pdhStatus ){
goto cleanup;
}
pdhStatus = PdhGetDataSourceTimeRange(
szAppend,
&dwNumEntries,
&TimeAppend,
&dwBufferSize
);
if( ERROR_SUCCESS != pdhStatus ){
goto cleanup;
}
if( TimeSource.EndTime > TimeAppend.StartTime ){
pdhStatus = PDH_TIME_MISMATCH;
goto cleanup;
}
//
// Compare the headers, must be exact match
//
pdhStatus = R_PdhBlgLogFileHeader( szSource, szAppend );
if( ERROR_SUCCESS != pdhStatus ){
goto cleanup;
}
//
// All good, now do the actual append
//
hSource = CreateFileW(
szSource,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
hAppend = CreateFileW(
szAppend,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if ( INVALID_HANDLE_VALUE == hSource || INVALID_HANDLE_VALUE == hAppend ){
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
goto cleanup;
}
SetFilePointer( hSource, NULL, NULL, FILE_END );
pdhStatus = R_PdhRelogCopyFile( hSource, hAppend, FALSE);
cleanup:
MemoryFree( mszSourceHeader );
MemoryFree( mszAppendHeader );
if ( INVALID_HANDLE_VALUE != hAppend ) {
CloseHandle(hAppend);
}
if ( INVALID_HANDLE_VALUE != hSource ) {
CloseHandle(hSource);
}
return pdhStatus;
}