5268 lines
180 KiB
C
5268 lines
180 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (C) 1996-1999 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
log_SQL.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
<abstract>
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <assert.h>
|
||
|
#include <mbctype.h>
|
||
|
#include <pdh.h>
|
||
|
#include "strings.h"
|
||
|
#include <pdhmsg.h>
|
||
|
#include "pdhidef.h"
|
||
|
|
||
|
#include <sql.h>
|
||
|
#include <odbcss.h>
|
||
|
// pragma to supress /W4 errors
|
||
|
#pragma warning ( disable : 4201 )
|
||
|
#include <sqlext.h>
|
||
|
#pragma warning ( default : 4201 )
|
||
|
|
||
|
#include "log_SQL.h"
|
||
|
#include "log_bin.h" // to get the binary log file record formatting
|
||
|
#include "log_pm.h" // to get PDH_LOG_... structure definition.
|
||
|
|
||
|
#pragma warning ( disable : 4213)
|
||
|
|
||
|
#define TIME_FIELD_BUFF_SIZE 24
|
||
|
#define PDH_SQL_BULK_COPY_REC 2048
|
||
|
#define PDH_SQL_STRING_SIZE 1024
|
||
|
#define MULTI_COUNT_DOUBLE_RAW 0xFFFFFFFF
|
||
|
#define SQLSTMTSIZE 1024
|
||
|
#define INITIAL_MSZ_SIZE 1024
|
||
|
#define MSZ_SIZE_ADDON 1024
|
||
|
|
||
|
#define ALLOC_CHECK(pB) if(NULL == pB){assert(GetLastError() == ERROR_SUCCESS);return PDH_MEMORY_ALLOCATION_FAILURE;}
|
||
|
#define ALLOC_CHECK_HSTMT(pB) if(NULL == pB) {SQLFreeStmt(hstmt, SQL_DROP);assert(GetLastError() == ERROR_SUCCESS);return PDH_MEMORY_ALLOCATION_FAILURE;}
|
||
|
|
||
|
#define SQLSUCCEEDED(rc) (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO || rc == SQL_NO_DATA)
|
||
|
|
||
|
typedef struct _PDH_SQL_BULK_COPY {
|
||
|
GUID dbGuid;
|
||
|
INT dbCounterId;
|
||
|
INT dbRecordIndex;
|
||
|
CHAR dbDateTime[24];
|
||
|
double dbCounterValue;
|
||
|
INT dbFirstValueA;
|
||
|
INT dbFirstValueB;
|
||
|
INT dbSecondValueA;
|
||
|
INT dbSecondValueB;
|
||
|
INT dbMultiCount;
|
||
|
DWORD dwRecordCount;
|
||
|
} PDH_SQL_BULK_COPY, * PPDH_SQL_BULK_COPY;
|
||
|
|
||
|
typedef struct _PDHI_SQL_LOG_INFO PDHI_SQL_LOG_INFO, * PPDHI_SQL_LOG_INFO;
|
||
|
|
||
|
struct _PDHI_SQL_LOG_INFO {
|
||
|
PPDHI_LOG_MACHINE MachineList;
|
||
|
//PPDHI_SQL_LOG_DATA LogData;
|
||
|
FILETIME RecordTime;
|
||
|
DWORD dwRunId;
|
||
|
};
|
||
|
|
||
|
int
|
||
|
PdhiCompareLogCounterInstance(
|
||
|
IN PPDHI_LOG_COUNTER pCounter,
|
||
|
IN LPWSTR szCounter,
|
||
|
IN LPWSTR szInstance,
|
||
|
IN DWORD dwInstance,
|
||
|
IN LPWSTR szParent
|
||
|
)
|
||
|
{
|
||
|
int iResult;
|
||
|
WCHAR szTmp[PDH_SQL_STRING_SIZE + 1];
|
||
|
|
||
|
ZeroMemory(szTmp, sizeof(szTmp));
|
||
|
lstrcpynW(szTmp, szCounter, PDH_SQL_STRING_SIZE);
|
||
|
iResult = lstrcmpiW(szTmp, pCounter->szCounter);
|
||
|
if (iResult != 0) goto Cleanup;
|
||
|
|
||
|
if ( (pCounter->szInstance != NULL && pCounter->szInstance[0] != L'\0')
|
||
|
&& (szInstance != NULL && szInstance[0] != L'\0')) {
|
||
|
ZeroMemory(szTmp, sizeof(szTmp));
|
||
|
lstrcpynW(szTmp, szInstance, PDH_SQL_STRING_SIZE);
|
||
|
iResult = lstrcmpiW(szTmp, pCounter->szInstance);
|
||
|
}
|
||
|
else if ((pCounter->szInstance != NULL && pCounter->szInstance[0] != L'\0')
|
||
|
&& (szInstance == NULL || szInstance[0] == L'\0')) {
|
||
|
iResult = -1;
|
||
|
}
|
||
|
else if ((pCounter->szInstance == NULL || pCounter->szInstance[0] == L'\0')
|
||
|
&& (szInstance != NULL && szInstance[0] != L'\0')) {
|
||
|
iResult = 1;
|
||
|
}
|
||
|
if (iResult != 0) goto Cleanup;
|
||
|
|
||
|
iResult = (dwInstance < pCounter->dwInstance)
|
||
|
? (-1)
|
||
|
: ((dwInstance > pCounter->dwInstance) ? (1) : (0));
|
||
|
if (iResult != 0) goto Cleanup;
|
||
|
|
||
|
if ( (pCounter->szParent != NULL && pCounter->szParent[0] != L'\0')
|
||
|
&& (szParent != NULL && szParent[0] != L'\0')) {
|
||
|
ZeroMemory(szTmp, sizeof(szTmp));
|
||
|
lstrcpynW(szTmp, szParent, PDH_SQL_STRING_SIZE);
|
||
|
iResult = lstrcmpiW(szTmp, pCounter->szParent);
|
||
|
}
|
||
|
else if ((pCounter->szParent != NULL && pCounter->szParent[0] != L'\0')
|
||
|
&& (szParent == NULL || szParent[0] == L'\0')) {
|
||
|
iResult = -1;
|
||
|
}
|
||
|
else if ((pCounter->szParent == NULL || pCounter->szParent[0] == L'\0')
|
||
|
&& (szParent != NULL && szParent[0] != L'\0')) {
|
||
|
iResult = 1;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
return iResult;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
PdhiFreeLogCounterNode(
|
||
|
IN PPDHI_LOG_COUNTER pCounter,
|
||
|
IN DWORD dwLevel
|
||
|
)
|
||
|
{
|
||
|
if (pCounter == NULL) return;
|
||
|
|
||
|
if (pCounter->left != NULL) {
|
||
|
PdhiFreeLogCounterNode(pCounter->left, dwLevel + 1);
|
||
|
}
|
||
|
if (pCounter->right != NULL) {
|
||
|
PdhiFreeLogCounterNode(pCounter->right, dwLevel + 1);
|
||
|
}
|
||
|
|
||
|
G_FREE(pCounter);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
PdhiFreeLogObjectNode(
|
||
|
IN PPDHI_LOG_OBJECT pObject,
|
||
|
IN DWORD dwLevel
|
||
|
)
|
||
|
{
|
||
|
if (pObject == NULL) return;
|
||
|
|
||
|
if (pObject->left != NULL) {
|
||
|
PdhiFreeLogObjectNode(pObject->left, dwLevel + 1);
|
||
|
}
|
||
|
|
||
|
PdhiFreeLogCounterNode(pObject->CtrTable, 0);
|
||
|
|
||
|
if (pObject->right != NULL) {
|
||
|
PdhiFreeLogObjectNode(pObject->right, dwLevel + 1);
|
||
|
}
|
||
|
|
||
|
G_FREE(pObject);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
PdhiFreeLogMachineTable(
|
||
|
IN PPDHI_LOG_MACHINE * MachineTable
|
||
|
)
|
||
|
{
|
||
|
PPDHI_LOG_MACHINE pMachine;
|
||
|
PPDHI_LOG_OBJECT pObject;
|
||
|
PPDHI_LOG_COUNTER pCounter;
|
||
|
|
||
|
if (MachineTable == NULL) return;
|
||
|
|
||
|
pMachine = * MachineTable;
|
||
|
while (pMachine != NULL) {
|
||
|
PPDHI_LOG_MACHINE pDelMachine = pMachine;
|
||
|
pMachine = pMachine->next;
|
||
|
PdhiFreeLogObjectNode(pDelMachine->ObjTable, 0);
|
||
|
G_FREE(pDelMachine);
|
||
|
}
|
||
|
|
||
|
* MachineTable = NULL;
|
||
|
}
|
||
|
|
||
|
PPDHI_LOG_MACHINE
|
||
|
PdhiFindLogMachine(
|
||
|
IN PPDHI_LOG_MACHINE * MachineTable,
|
||
|
IN LPWSTR szMachine,
|
||
|
IN BOOL bInsert
|
||
|
)
|
||
|
{
|
||
|
PPDHI_LOG_MACHINE pMachine = NULL;
|
||
|
WCHAR szTmp[PDH_SQL_STRING_SIZE + 1];
|
||
|
|
||
|
if (MachineTable != NULL) {
|
||
|
ZeroMemory(szTmp, sizeof(szTmp));
|
||
|
lstrcpynW(szTmp, szMachine, PDH_SQL_STRING_SIZE);
|
||
|
for (pMachine = (* MachineTable);
|
||
|
pMachine && lstrcmpiW(pMachine->szMachine, szTmp) != 0;
|
||
|
pMachine = pMachine->next);
|
||
|
|
||
|
if (bInsert && pMachine == NULL) {
|
||
|
pMachine = G_ALLOC(sizeof(PDHI_LOG_MACHINE) + (PDH_SQL_STRING_SIZE + 1) * sizeof(WCHAR));
|
||
|
if (pMachine != NULL) {
|
||
|
pMachine->szMachine = (LPWSTR) (((PCHAR) pMachine) + sizeof(PDHI_LOG_MACHINE));
|
||
|
lstrcpynW(pMachine->szMachine, szMachine, PDH_SQL_STRING_SIZE);
|
||
|
pMachine->ObjTable = NULL;
|
||
|
pMachine->next = (* MachineTable);
|
||
|
* MachineTable = pMachine;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return pMachine;
|
||
|
}
|
||
|
|
||
|
PPDHI_LOG_OBJECT
|
||
|
PdhiFindLogObject(
|
||
|
IN PPDHI_LOG_MACHINE pMachine,
|
||
|
IN PPDHI_LOG_OBJECT * ObjectTable,
|
||
|
IN LPWSTR szObject,
|
||
|
IN BOOL bInsert
|
||
|
)
|
||
|
{
|
||
|
PPDHI_LOG_OBJECT * pStack[MAX_BTREE_DEPTH];
|
||
|
PPDHI_LOG_OBJECT * pLink;
|
||
|
int dwStack = 0;
|
||
|
PPDHI_LOG_OBJECT pNode = * ObjectTable;
|
||
|
PPDHI_LOG_OBJECT pObject;
|
||
|
PPDHI_LOG_OBJECT pParent;
|
||
|
PPDHI_LOG_OBJECT pSibling;
|
||
|
PPDHI_LOG_OBJECT pChild;
|
||
|
int iCompare;
|
||
|
WCHAR szTmp[PDH_SQL_STRING_SIZE + 1];
|
||
|
|
||
|
ZeroMemory(szTmp, sizeof(szTmp));
|
||
|
lstrcpynW(szTmp, szObject, PDH_SQL_STRING_SIZE);
|
||
|
|
||
|
pStack[dwStack ++] = ObjectTable;
|
||
|
while (pNode != NULL) {
|
||
|
iCompare = lstrcmpiW(szTmp, pNode->szObject);
|
||
|
if (iCompare < 0) {
|
||
|
pStack[dwStack ++] = & (pNode->left);
|
||
|
pNode = pNode->left;
|
||
|
}
|
||
|
else if (iCompare > 0) {
|
||
|
pStack[dwStack ++] = & (pNode->right);
|
||
|
pNode = pNode->right;
|
||
|
}
|
||
|
else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pNode != NULL) {
|
||
|
pObject = pNode;
|
||
|
}
|
||
|
else if (bInsert) {
|
||
|
pObject = G_ALLOC(sizeof(PDHI_LOG_OBJECT) + (PDH_SQL_STRING_SIZE + 1) * sizeof(WCHAR));
|
||
|
if (pObject == NULL) goto Cleanup;
|
||
|
|
||
|
pObject->next = pMachine->ObjList;
|
||
|
pMachine->ObjList = pObject;
|
||
|
|
||
|
pObject->bIsRed = TRUE;
|
||
|
pObject->left = NULL;
|
||
|
pObject->right = NULL;
|
||
|
pObject->CtrTable = NULL;
|
||
|
pObject->szObject = (LPWSTR) (((PCHAR) pObject) + sizeof(PDHI_LOG_OBJECT));
|
||
|
lstrcpynW(pObject->szObject, szObject, PDH_SQL_STRING_SIZE);
|
||
|
|
||
|
pLink = pStack[-- dwStack];
|
||
|
* pLink = pObject;
|
||
|
|
||
|
pChild = NULL;
|
||
|
pNode = pObject;
|
||
|
while (dwStack > 0) {
|
||
|
pLink = pStack[-- dwStack];
|
||
|
pParent = * pLink;
|
||
|
if (! pParent->bIsRed) {
|
||
|
pSibling = (pParent->left == pNode)
|
||
|
? pParent->right : pParent->left;
|
||
|
if (pSibling && pSibling->bIsRed) {
|
||
|
pNode->bIsRed = FALSE;
|
||
|
pSibling->bIsRed = FALSE;
|
||
|
pParent->bIsRed = TRUE;
|
||
|
}
|
||
|
else {
|
||
|
if (pChild && pChild->bIsRed) {
|
||
|
if (pChild == pNode->left) {
|
||
|
if (pNode == pParent->left) {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->left = pNode->right;
|
||
|
pNode->right = pParent;
|
||
|
pNode->bIsRed = FALSE;
|
||
|
* pLink = pNode;
|
||
|
}
|
||
|
else {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->right = pChild->left;
|
||
|
pChild->left = pParent;
|
||
|
pNode->left = pChild->right;
|
||
|
pChild->right = pNode;
|
||
|
pChild->bIsRed = FALSE;
|
||
|
* pLink = pChild;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (pNode == pParent->right) {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->right = pNode->left;
|
||
|
pNode->left = pParent;
|
||
|
pNode->bIsRed = FALSE;
|
||
|
* pLink = pNode;
|
||
|
}
|
||
|
else {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->left = pChild->right;
|
||
|
pChild->right = pParent;
|
||
|
pNode->right = pChild->left;
|
||
|
pChild->left = pNode;
|
||
|
pChild->bIsRed = FALSE;
|
||
|
* pLink = pChild;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
pChild = pNode;
|
||
|
pNode = pParent;
|
||
|
}
|
||
|
|
||
|
(* ObjectTable)->bIsRed = FALSE;
|
||
|
}
|
||
|
else {
|
||
|
pObject = NULL;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
return pObject;
|
||
|
}
|
||
|
|
||
|
PPDHI_LOG_COUNTER
|
||
|
PdhiFindLogCounter(
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN PPDHI_LOG_MACHINE * MachineTable,
|
||
|
IN LPWSTR szMachine,
|
||
|
IN LPWSTR szObject,
|
||
|
IN LPWSTR szCounter,
|
||
|
IN DWORD dwCounterType,
|
||
|
IN DWORD dwDefaultScale,
|
||
|
IN LPWSTR szInstance,
|
||
|
IN DWORD dwInstance,
|
||
|
IN LPWSTR szParent,
|
||
|
IN DWORD dwParent,
|
||
|
IN LPDWORD pdwIndex,
|
||
|
IN BOOL bInsert
|
||
|
)
|
||
|
{
|
||
|
PPDHI_LOG_MACHINE pMachine = NULL;
|
||
|
PPDHI_LOG_OBJECT pObject = NULL;
|
||
|
PPDHI_LOG_COUNTER pCounter = NULL;
|
||
|
PPDHI_LOG_COUNTER pNode = NULL;
|
||
|
|
||
|
PPDHI_LOG_COUNTER * pStack[MAX_BTREE_DEPTH];
|
||
|
PPDHI_LOG_COUNTER * pLink;
|
||
|
int dwStack = 0;
|
||
|
PPDHI_LOG_COUNTER pParent;
|
||
|
PPDHI_LOG_COUNTER pSibling;
|
||
|
PPDHI_LOG_COUNTER pChild;
|
||
|
int iCompare;
|
||
|
|
||
|
pMachine = PdhiFindLogMachine(MachineTable, szMachine, bInsert);
|
||
|
if (pMachine == NULL) goto Cleanup;
|
||
|
|
||
|
pObject = PdhiFindLogObject(pMachine, & (pMachine->ObjTable), szObject, bInsert);
|
||
|
if (pObject == NULL) goto Cleanup;
|
||
|
|
||
|
pStack[dwStack ++] = & (pObject->CtrTable);
|
||
|
pCounter = pObject->CtrTable;
|
||
|
while (pCounter != NULL) {
|
||
|
iCompare = PdhiCompareLogCounterInstance(pCounter, szCounter, szInstance, dwInstance, szParent);
|
||
|
#if 0
|
||
|
if (iCompare == 0) {
|
||
|
if (dwCounterType < pCounter->dwCounterType) {
|
||
|
iCompare = -1;
|
||
|
}
|
||
|
else if (dwCounterType > pCounter->dwCounterType) {
|
||
|
iCompare = 1;
|
||
|
}
|
||
|
else {
|
||
|
iCompare = 0;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
if (iCompare < 0) {
|
||
|
pStack[dwStack ++] = & (pCounter->left);
|
||
|
pCounter = pCounter->left;
|
||
|
}
|
||
|
else if (iCompare > 0) {
|
||
|
pStack[dwStack ++] = & (pCounter->right);
|
||
|
pCounter = pCounter->right;
|
||
|
}
|
||
|
else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bInsert) {
|
||
|
if (pCounter == NULL) {
|
||
|
DWORD dwBufSize = sizeof(PDHI_LOG_COUNTER) + 3 * sizeof(WCHAR) * (PDH_SQL_STRING_SIZE + 1);
|
||
|
pCounter = G_ALLOC(dwBufSize);
|
||
|
if (pCounter == NULL) goto Cleanup;
|
||
|
|
||
|
pCounter->next = pObject->CtrList;
|
||
|
pObject->CtrList = pCounter;
|
||
|
|
||
|
pCounter->bIsRed = TRUE;
|
||
|
pCounter->left = NULL;
|
||
|
pCounter->right = NULL;
|
||
|
pCounter->dwCounterID = * pdwIndex;
|
||
|
pCounter->dwCounterType = dwCounterType;
|
||
|
pCounter->dwDefaultScale = dwDefaultScale;
|
||
|
pCounter->dwInstance = dwInstance;
|
||
|
pCounter->dwParent = dwParent;
|
||
|
pCounter->TimeStamp = 0;
|
||
|
|
||
|
pCounter->szCounter = (LPWSTR) (((PCHAR) pCounter) + sizeof(PDHI_LOG_COUNTER));
|
||
|
lstrcpynW(pCounter->szCounter, szCounter, PDH_SQL_STRING_SIZE);
|
||
|
if (szInstance == NULL || szInstance[0] == L'\0') {
|
||
|
pCounter->szInstance = NULL;
|
||
|
}
|
||
|
else {
|
||
|
pCounter->szInstance = (LPWSTR) (((PCHAR) pCounter) + sizeof(PDHI_LOG_COUNTER)
|
||
|
+ sizeof(WCHAR) * (PDH_SQL_STRING_SIZE + 1));
|
||
|
lstrcpynW(pCounter->szInstance, szInstance, PDH_SQL_STRING_SIZE);
|
||
|
}
|
||
|
|
||
|
if (szParent == NULL || szParent[0] == L'\0') {
|
||
|
pCounter->szParent = NULL;
|
||
|
}
|
||
|
else {
|
||
|
pCounter->szParent = (LPWSTR) (((PCHAR) pCounter) + sizeof(PDHI_LOG_COUNTER)
|
||
|
+ 2 * sizeof(WCHAR) * (PDH_SQL_STRING_SIZE + 1));
|
||
|
lstrcpynW(pCounter->szParent, szParent, PDH_SQL_STRING_SIZE);
|
||
|
}
|
||
|
|
||
|
pLink = pStack[-- dwStack];
|
||
|
* pLink = pCounter;
|
||
|
|
||
|
pChild = NULL;
|
||
|
pNode = pCounter;
|
||
|
while (dwStack > 0) {
|
||
|
pLink = pStack[-- dwStack];
|
||
|
pParent = * pLink;
|
||
|
if (! pParent->bIsRed) {
|
||
|
pSibling = (pParent->left == pNode)
|
||
|
? pParent->right : pParent->left;
|
||
|
if (pSibling && pSibling->bIsRed) {
|
||
|
pNode->bIsRed = FALSE;
|
||
|
pSibling->bIsRed = FALSE;
|
||
|
pParent->bIsRed = TRUE;
|
||
|
}
|
||
|
else {
|
||
|
if (pChild && pChild->bIsRed) {
|
||
|
if (pChild == pNode->left) {
|
||
|
if (pNode == pParent->left) {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->left = pNode->right;
|
||
|
pNode->right = pParent;
|
||
|
pNode->bIsRed = FALSE;
|
||
|
* pLink = pNode;
|
||
|
}
|
||
|
else {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->right = pChild->left;
|
||
|
pChild->left = pParent;
|
||
|
pNode->left = pChild->right;
|
||
|
pChild->right = pNode;
|
||
|
pChild->bIsRed = FALSE;
|
||
|
* pLink = pChild;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (pNode == pParent->right) {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->right = pNode->left;
|
||
|
pNode->left = pParent;
|
||
|
pNode->bIsRed = FALSE;
|
||
|
* pLink = pNode;
|
||
|
}
|
||
|
else {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->left = pChild->right;
|
||
|
pChild->right = pParent;
|
||
|
pNode->right = pChild->left;
|
||
|
pChild->left = pNode;
|
||
|
pChild->bIsRed = FALSE;
|
||
|
* pLink = pChild;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
pChild = pNode;
|
||
|
pNode = pParent;
|
||
|
}
|
||
|
|
||
|
pObject->CtrTable->bIsRed = FALSE;
|
||
|
}
|
||
|
}
|
||
|
else if (pCounter != NULL) {
|
||
|
* pdwIndex = pCounter->dwCounterID;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
return pCounter;
|
||
|
}
|
||
|
|
||
|
/* external functions */
|
||
|
BOOL __stdcall
|
||
|
IsValidLogHandle (
|
||
|
IN HLOG hLog
|
||
|
);
|
||
|
|
||
|
/* forward declares */
|
||
|
PDH_FUNCTION
|
||
|
PdhpGetSQLLogHeader (
|
||
|
IN PPDHI_LOG pLog);
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhpWriteSQLCounters(
|
||
|
IN PPDHI_LOG pLog);
|
||
|
|
||
|
BOOL __stdcall
|
||
|
PdhpConvertFileTimeToSQLString(
|
||
|
FILETIME *pFileTime,
|
||
|
WCHAR *szStartDate
|
||
|
)
|
||
|
{
|
||
|
//1998-01-02 12:00:00.000
|
||
|
SYSTEMTIME st;
|
||
|
|
||
|
if (0 == FileTimeToSystemTime(pFileTime,&st)) return 0;
|
||
|
|
||
|
swprintf(szStartDate, L"%04d-%02d-%02d %02d:%02d:%02d.%03d",
|
||
|
st.wYear, st.wMonth, st.wDay, st.wHour,
|
||
|
st.wMinute, st.wSecond, st.wMilliseconds);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
BOOL __stdcall
|
||
|
PdhpConvertSQLStringToFileTime(
|
||
|
WCHAR *szStartDate,
|
||
|
FILETIME *pFileTime
|
||
|
) // 1111111111222
|
||
|
{ //01234567890123456789012
|
||
|
//1998-01-02 12:00:00.000
|
||
|
|
||
|
SYSTEMTIME st;
|
||
|
|
||
|
WCHAR buffer[TIME_FIELD_BUFF_SIZE];
|
||
|
WCHAR *pwchar;
|
||
|
|
||
|
lstrcpyW(buffer,szStartDate);
|
||
|
|
||
|
buffer[4] = 0;
|
||
|
st.wYear = (WORD) _wtoi(buffer);
|
||
|
pwchar = &(buffer[5]);
|
||
|
buffer[7] = 0;
|
||
|
st.wMonth = (WORD) _wtoi(pwchar);
|
||
|
pwchar = &(buffer[8]);
|
||
|
buffer[10] = 0;
|
||
|
st.wDay = (WORD) _wtoi(pwchar);
|
||
|
pwchar = &(buffer[11]);
|
||
|
buffer[13] = 0;
|
||
|
st.wHour = (WORD) _wtoi(pwchar);
|
||
|
pwchar = &(buffer[14]);
|
||
|
buffer[16] = 0;
|
||
|
st.wMinute = (WORD) _wtoi(pwchar);
|
||
|
pwchar = &(buffer[17]);
|
||
|
buffer[19] = 0;
|
||
|
st.wSecond = (WORD) _wtoi(pwchar);
|
||
|
pwchar = &(buffer[20]);
|
||
|
st.wMilliseconds = (WORD) _wtoi(pwchar);
|
||
|
|
||
|
|
||
|
return SystemTimeToFileTime (&st, pFileTime);
|
||
|
}
|
||
|
|
||
|
LPWSTR __stdcall
|
||
|
PdhpGetNextMultisz(
|
||
|
IN LPWSTR mszSource
|
||
|
)
|
||
|
{
|
||
|
// get the next string in a multisz
|
||
|
LPVOID szDestElem;
|
||
|
|
||
|
szDestElem=mszSource;
|
||
|
|
||
|
szDestElem = (LPVOID)((LPWSTR)szDestElem +
|
||
|
(lstrlenW((LPCWSTR)szDestElem)+1));
|
||
|
|
||
|
return ((LPWSTR)szDestElem);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
PdhpAddUniqueUnicodeStringToMultiSz (
|
||
|
IN LPVOID mszDest,
|
||
|
IN LPWSTR wszSource,
|
||
|
IN BOOL bUnicodeDest
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
searches the Multi-SZ list, mszDest for wszSource and appends it
|
||
|
to mszDest if it wasn't found.
|
||
|
Assumes wszSource is UNICODE - and may have to be converted to ASCII
|
||
|
for an ascii destination
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OUT LPVOID mszDest Multi-SZ list to get new string
|
||
|
IN LPSTR wszSource 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_PTR dwReturnLength;
|
||
|
LPSTR aszSource = NULL;
|
||
|
DWORD dwLength;
|
||
|
|
||
|
// check arguments
|
||
|
|
||
|
if ((mszDest == NULL) || (wszSource == NULL)) return 0; // invalid buffers
|
||
|
if (*wszSource == '\0') return 0; // no source string to add
|
||
|
|
||
|
// if ascii list, make an ascii copy of the source string to compare
|
||
|
// and ultimately copy if it's not already in the list
|
||
|
|
||
|
if (!bUnicodeDest) {
|
||
|
dwLength = lstrlenW(wszSource) + 1;
|
||
|
aszSource = G_ALLOC ((dwLength * 3 * sizeof(CHAR))); // DBCS concern
|
||
|
if (aszSource != NULL) {
|
||
|
dwReturnLength = WideCharToMultiByte(_getmbcp(),
|
||
|
0,
|
||
|
wszSource,
|
||
|
lstrlenW(wszSource),
|
||
|
aszSource,
|
||
|
dwLength * 3 * sizeof(CHAR),
|
||
|
NULL,
|
||
|
NULL);
|
||
|
} else {
|
||
|
// unable to allocate memory for the temp string
|
||
|
dwReturnLength = 0;
|
||
|
}
|
||
|
} else {
|
||
|
// just use the Unicode 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 list
|
||
|
if (lstrcmpiW((LPCWSTR)szDestElem, wszSource) == 0) {
|
||
|
dwReturnLength = 0;
|
||
|
goto AddString_Bailout;
|
||
|
} else {
|
||
|
// goto the next item
|
||
|
szDestElem = (LPVOID)((LPWSTR)szDestElem +
|
||
|
(lstrlenW((LPCWSTR)szDestElem)+1));
|
||
|
}
|
||
|
} else {
|
||
|
// bail out if string already in list
|
||
|
if (lstrcmpiA((LPSTR)szDestElem, aszSource) == 0) {
|
||
|
dwReturnLength = 0;
|
||
|
goto AddString_Bailout;
|
||
|
} 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);
|
||
|
// return len is in wide char
|
||
|
|
||
|
} else {
|
||
|
lstrcpyA ((LPSTR)szDestElem, aszSource);
|
||
|
szDestElem = (LPVOID)((LPSTR)szDestElem + lstrlenA(szDestElem) + 1);
|
||
|
*((LPSTR)szDestElem)++ = '\0'; // add second NULL
|
||
|
dwReturnLength = (DWORD)((LPSTR)szDestElem - (LPSTR)mszDest);
|
||
|
// return len is in bytes
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AddString_Bailout:
|
||
|
if (aszSource != NULL) {
|
||
|
G_FREE (aszSource);
|
||
|
}
|
||
|
|
||
|
return (DWORD)dwReturnLength;
|
||
|
}
|
||
|
|
||
|
DWORD __stdcall
|
||
|
PdhpSQLAddUniqueStringToMultiSz (
|
||
|
IN LPVOID mszDest,
|
||
|
IN LPWSTR wszSource
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
searches the Multi-SZ list, mszDest for szSource and appends it
|
||
|
to mszDest if it wasn't found (source & dest assumed to be both
|
||
|
UNICODE)
|
||
|
|
||
|
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;
|
||
|
|
||
|
// check arguments
|
||
|
|
||
|
if ((mszDest == NULL) || (wszSource == NULL)) return 0; // invalid buffers
|
||
|
if (*wszSource == '\0') return 0; // no source string to add
|
||
|
|
||
|
|
||
|
// go to end of dest string
|
||
|
//
|
||
|
for (szDestElem = mszDest;(*(LPWSTR)szDestElem != 0); )
|
||
|
{
|
||
|
// bail out if string already in lsit
|
||
|
if (lstrcmpiW((LPCWSTR)szDestElem, wszSource) == 0)
|
||
|
{
|
||
|
dwReturnLength = 0;
|
||
|
goto Bailout;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// goto the next item
|
||
|
szDestElem = (LPVOID)((LPWSTR)szDestElem +
|
||
|
(lstrlenW((LPCWSTR)szDestElem)+1));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// if here (at end of multi sz), then add string
|
||
|
// szDestElem is at end of list
|
||
|
|
||
|
lstrcpyW ((LPWSTR)szDestElem, wszSource);
|
||
|
szDestElem = (LPVOID)((LPWSTR)szDestElem + lstrlenW(wszSource) + 1);
|
||
|
*((LPWSTR)szDestElem)++ = L'\0';
|
||
|
dwReturnLength = (DWORD)((LPWSTR)szDestElem - (LPWSTR)mszDest);
|
||
|
// return len is in wide char
|
||
|
|
||
|
Bailout:
|
||
|
|
||
|
return dwReturnLength;
|
||
|
}
|
||
|
|
||
|
DWORD __stdcall
|
||
|
PdhpSQLAddStringToMultiSz (
|
||
|
IN LPVOID mszDest,
|
||
|
IN LPWSTR wszSource
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Appends wszSource to mszDest (source & dest assumed to be both
|
||
|
UNICODE)
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OUT LPVOID mszDest Multi-SZ list to get new string
|
||
|
IN LPSTR szSource string to add
|
||
|
|
||
|
ReturnValue:
|
||
|
|
||
|
The new length of the destination string including both
|
||
|
trailing NULL characters
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LPVOID szDestElem;
|
||
|
DWORD dwReturnLength;
|
||
|
|
||
|
// check arguments
|
||
|
|
||
|
if ((mszDest == NULL) || (wszSource == NULL)) return 0; // invalid buffers
|
||
|
if (*wszSource == '\0') return 0; // no source string to add
|
||
|
|
||
|
|
||
|
// go to end of dest string
|
||
|
//
|
||
|
for (szDestElem = mszDest;(*(LPWSTR)szDestElem != 0); )
|
||
|
{
|
||
|
// goto the next item
|
||
|
szDestElem = (LPVOID)((LPWSTR)szDestElem +
|
||
|
(lstrlenW((LPCWSTR)szDestElem)+1));
|
||
|
}
|
||
|
|
||
|
// if here (at end of multi sz), then add string
|
||
|
// szDestElem is at end of list
|
||
|
|
||
|
lstrcpyW ((LPWSTR)szDestElem, wszSource);
|
||
|
szDestElem = (LPVOID)((LPWSTR)szDestElem + lstrlenW(wszSource) + 1);
|
||
|
*((LPWSTR)szDestElem)++ = L'\0';
|
||
|
dwReturnLength = (DWORD)((LPWSTR)szDestElem - (LPWSTR)mszDest);
|
||
|
// return len is in wide char
|
||
|
|
||
|
return dwReturnLength;
|
||
|
}
|
||
|
|
||
|
PPDH_SQL_BULK_COPY
|
||
|
PdhiBindBulkCopyStructure(
|
||
|
IN PPDHI_LOG pLog
|
||
|
)
|
||
|
{
|
||
|
PDH_STATUS Status = ERROR_SUCCESS;
|
||
|
PPDH_SQL_BULK_COPY pBulk = (PPDH_SQL_BULK_COPY) pLog->lpMappedFileBase;
|
||
|
RETCODE rc;
|
||
|
|
||
|
if (pBulk != NULL) return pBulk;
|
||
|
|
||
|
pBulk = G_ALLOC(sizeof(PDH_SQL_BULK_COPY));
|
||
|
if (pBulk != NULL) {
|
||
|
pLog->lpMappedFileBase = pBulk;
|
||
|
pBulk->dbGuid = pLog->guidSQL;
|
||
|
pBulk->dwRecordCount = 0;
|
||
|
|
||
|
rc = bcp_initW(pLog->hdbcSQL, L"CounterData", NULL, NULL, DB_IN);
|
||
|
if (rc == FAIL) {
|
||
|
Status = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = bcp_bind(pLog->hdbcSQL,
|
||
|
(LPCBYTE) & (pBulk->dbGuid),
|
||
|
0,
|
||
|
sizeof(GUID),
|
||
|
NULL,
|
||
|
0,
|
||
|
SQLUNIQUEID,
|
||
|
1);
|
||
|
if (rc == FAIL) {
|
||
|
Status = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = bcp_bind(pLog->hdbcSQL,
|
||
|
(LPCBYTE) & (pBulk->dbCounterId),
|
||
|
0,
|
||
|
sizeof(INT),
|
||
|
NULL,
|
||
|
0,
|
||
|
SQLINT4,
|
||
|
2);
|
||
|
if (rc == FAIL) {
|
||
|
Status = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = bcp_bind(pLog->hdbcSQL,
|
||
|
(LPCBYTE) & (pBulk->dbRecordIndex),
|
||
|
0,
|
||
|
sizeof(INT),
|
||
|
NULL,
|
||
|
0,
|
||
|
SQLINT4,
|
||
|
3);
|
||
|
if (rc == FAIL) {
|
||
|
Status = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = bcp_bind(pLog->hdbcSQL,
|
||
|
(LPCBYTE) (pBulk->dbDateTime),
|
||
|
0,
|
||
|
24,
|
||
|
NULL,
|
||
|
0,
|
||
|
SQLCHARACTER,
|
||
|
4);
|
||
|
if (rc == FAIL) {
|
||
|
Status = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = bcp_bind(pLog->hdbcSQL,
|
||
|
(LPCBYTE) & (pBulk->dbCounterValue),
|
||
|
0,
|
||
|
sizeof(double),
|
||
|
NULL,
|
||
|
0,
|
||
|
SQLFLT8,
|
||
|
5);
|
||
|
if (rc == FAIL) {
|
||
|
Status = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = bcp_bind(pLog->hdbcSQL,
|
||
|
(LPCBYTE) & (pBulk->dbFirstValueA),
|
||
|
0,
|
||
|
sizeof(INT),
|
||
|
NULL,
|
||
|
0,
|
||
|
SQLINT4,
|
||
|
6);
|
||
|
if (rc == FAIL) {
|
||
|
Status = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = bcp_bind(pLog->hdbcSQL,
|
||
|
(LPCBYTE) & (pBulk->dbFirstValueB),
|
||
|
0,
|
||
|
sizeof(INT),
|
||
|
NULL,
|
||
|
0,
|
||
|
SQLINT4,
|
||
|
7);
|
||
|
if (rc == FAIL) {
|
||
|
Status = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = bcp_bind(pLog->hdbcSQL,
|
||
|
(LPCBYTE) & (pBulk->dbSecondValueA),
|
||
|
0,
|
||
|
sizeof(INT),
|
||
|
NULL,
|
||
|
0,
|
||
|
SQLINT4,
|
||
|
8);
|
||
|
if (rc == FAIL) {
|
||
|
Status = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = bcp_bind(pLog->hdbcSQL,
|
||
|
(LPCBYTE) & (pBulk->dbSecondValueB),
|
||
|
0,
|
||
|
sizeof(INT),
|
||
|
NULL,
|
||
|
0,
|
||
|
SQLINT4,
|
||
|
9);
|
||
|
if (rc == FAIL) {
|
||
|
Status = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = bcp_bind(pLog->hdbcSQL,
|
||
|
(LPCBYTE) & (pBulk->dbMultiCount),
|
||
|
0,
|
||
|
sizeof(INT),
|
||
|
NULL,
|
||
|
0,
|
||
|
SQLINT4,
|
||
|
10);
|
||
|
if (rc == FAIL) {
|
||
|
Status = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
Status = PDH_MEMORY_ALLOCATION_FAILURE;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
if (Status != ERROR_SUCCESS) {
|
||
|
if (pBulk != NULL) G_FREE(pBulk);
|
||
|
pBulk = pLog->lpMappedFileBase = NULL;
|
||
|
Status = ReportSQLError(pLog, SQL_ERROR, NULL, Status);
|
||
|
SetLastError(Status);
|
||
|
}
|
||
|
return pBulk;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiSqlUpdateCounterDetails(
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN BOOL bBeforeSendRow,
|
||
|
IN PPDHI_LOG_MACHINE pMachine,
|
||
|
IN PPDHI_LOG_OBJECT pObject,
|
||
|
IN PPDHI_LOG_COUNTER pCounter,
|
||
|
IN LONGLONG TimeBase,
|
||
|
IN LPWSTR szMachine,
|
||
|
IN LPWSTR szObject,
|
||
|
IN LPWSTR szCounter,
|
||
|
IN DWORD dwCounterType,
|
||
|
IN DWORD dwDefaultScale,
|
||
|
IN LPWSTR szInstance,
|
||
|
IN DWORD dwInstance,
|
||
|
IN LPWSTR szParent,
|
||
|
IN DWORD dwParent
|
||
|
)
|
||
|
{
|
||
|
PDH_STATUS Status = ERROR_SUCCESS;
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
DWORD dwCounterId;
|
||
|
SQLLEN dwCounterIdLen;
|
||
|
SQLLEN dwRowCount;
|
||
|
|
||
|
PPDH_SQL_BULK_COPY pBulk = (PPDH_SQL_BULK_COPY) pLog->lpMappedFileBase;
|
||
|
|
||
|
if (! bBeforeSendRow) {
|
||
|
if (pBulk != NULL && pBulk->dwRecordCount > 0) {
|
||
|
DBINT rcBCP = bcp_batch(pLog->hdbcSQL);
|
||
|
if (rcBCP < 0) {
|
||
|
DebugPrint((1,"bcp_batch(%05d,0x%08X,%d,%d)\n",
|
||
|
__LINE__, pLog->hdbcSQL, rcBCP, pBulk->dwRecordCount));
|
||
|
ReportSQLError(pLog, SQL_ERROR, NULL, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
}
|
||
|
pBulk->dwRecordCount = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// need to cover the following cases where 0 = NULL, 1 = present,
|
||
|
// can't have an Instance Index without an Instance Name
|
||
|
//
|
||
|
// Instance Name
|
||
|
// Instance Index
|
||
|
// Parent Name
|
||
|
// Parent Object ID
|
||
|
// 0000
|
||
|
// 1000 pos 4 & 5 are countertype,defscale
|
||
|
// 0010
|
||
|
// 0001
|
||
|
// 1100
|
||
|
// 1010
|
||
|
// 1001
|
||
|
// 0011
|
||
|
// 1110
|
||
|
// 1101
|
||
|
// 1011
|
||
|
// 1111
|
||
|
//
|
||
|
if ( (szInstance == NULL || szInstance[0] == L'\0')
|
||
|
&& dwInstance == 0
|
||
|
&& (szParent == NULL || szParent[0] == L'\0')
|
||
|
&& dwParent == 0) {
|
||
|
swprintf(szSQLStmt, // 0000
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d, NULL,NULL,NULL,NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
}
|
||
|
else if ( (szInstance != NULL && szInstance[0] != '\0')
|
||
|
&& dwInstance == 0
|
||
|
&& (szParent == NULL || szParent[0] == '\0')
|
||
|
&& dwParent == 0) {
|
||
|
swprintf(szSQLStmt, // 1000
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d, '%ws',NULL,NULL,NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
|
||
|
szInstance, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
|
||
|
}
|
||
|
else if ( (szInstance == NULL || szInstance[0] == '\0')
|
||
|
&& dwInstance == 0
|
||
|
&& (szParent != NULL && szParent[0] != '\0')
|
||
|
&& dwParent == 0) {
|
||
|
swprintf(szSQLStmt, // 0010
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d, NULL,NULL,'%ws',NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
|
||
|
szParent, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
}
|
||
|
else if ( (szInstance == NULL || szInstance[0] == '\0')
|
||
|
&& dwInstance == 0
|
||
|
&& (szParent == NULL || szParent[0] == '\0')
|
||
|
&& dwParent != 0) {
|
||
|
swprintf(szSQLStmt, // 0001
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d, NULL,NULL,NULL,%d,%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
|
||
|
dwParent, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
}
|
||
|
else if ( (szInstance != NULL && szInstance[0] != '\0')
|
||
|
&& dwInstance != 0
|
||
|
&& (szParent == NULL || szParent[0] == '\0')
|
||
|
&& dwParent == 0) {
|
||
|
swprintf(szSQLStmt, // 1100
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d, '%ws',%d,NULL,NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
|
||
|
szInstance, dwInstance, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
}
|
||
|
else if ( (szInstance != NULL && szInstance[0] != '\0')
|
||
|
&& dwInstance == 0
|
||
|
&& (szParent != NULL && szParent[0] != '\0')
|
||
|
&& dwParent == 0) {
|
||
|
swprintf(szSQLStmt, // 1010
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d, '%ws',NULL,'%ws',NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
|
||
|
szInstance, szParent, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
}
|
||
|
else if ( (szInstance != NULL && szInstance[0] != '\0')
|
||
|
&& dwInstance == 0
|
||
|
&& (szParent == NULL || szParent[0] == '\0')
|
||
|
&& dwParent != 0) {
|
||
|
swprintf(szSQLStmt, // 1001
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d, '%ws',NULL,NULL,%d,%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
|
||
|
szInstance, dwParent, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
}
|
||
|
else if ( (szInstance == NULL || szInstance[0] == '\0')
|
||
|
&& dwInstance == 0
|
||
|
&& (szParent != NULL && szParent[0] != '\0')
|
||
|
&& dwParent != 0) {
|
||
|
swprintf(szSQLStmt, // 0011
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d, NULL,NULL,'%ws',%d,%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
|
||
|
szParent, dwParent, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
}
|
||
|
else if ( (szInstance != NULL && szInstance[0] != '\0')
|
||
|
&& dwInstance != 0
|
||
|
&& (szParent != NULL && szParent[0] != '\0')
|
||
|
&& dwParent == 0) {
|
||
|
swprintf(szSQLStmt, // 1110
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d, '%ws',%d,'%ws',NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
|
||
|
szInstance, dwInstance, szParent, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
}
|
||
|
else if ( (szInstance != NULL && szInstance[0] != '\0')
|
||
|
&& dwInstance != 0
|
||
|
&& (szParent == NULL || szParent[0] == '\0')
|
||
|
&& dwParent != 0) {
|
||
|
swprintf(szSQLStmt, //1101
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d, '%ws',%d,NULL,%d,%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
|
||
|
szInstance, dwInstance, dwParent, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
}
|
||
|
else if ( (szInstance != NULL && szInstance[0] != '\0')
|
||
|
&& dwInstance == 0
|
||
|
&& (szParent != NULL && szParent[0] != '\0')
|
||
|
&& dwParent != 0) {
|
||
|
swprintf(szSQLStmt, // 1011
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d, '%ws',NULL,'%ws',%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
|
||
|
szInstance, szParent, dwParent, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
}
|
||
|
else if ( (szInstance != NULL && szInstance[0] != '\0')
|
||
|
&& dwInstance != 0
|
||
|
&& (szParent != NULL && szParent[0] != '\0')
|
||
|
&& dwParent != 0) {
|
||
|
swprintf(szSQLStmt, // 1111
|
||
|
L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws', %d, %d,'%ws',%d,'%ws',%d,%d) Select @@Identity commit transaction AddCounterDetails",
|
||
|
szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
|
||
|
szInstance, dwInstance, szParent, dwParent, LODWORD(TimeBase), HIDWORD(TimeBase));
|
||
|
}
|
||
|
else {
|
||
|
Status = PDH_INVALID_ARGUMENT;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLRowCount(hstmt, & dwRowCount);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ROWCOUNT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLMoreResults(hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_MORE_RESULTS_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_SLONG, & dwCounterId, 0, & dwCounterIdLen);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLFetch(hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
if (SQL_NO_DATA == rc) {
|
||
|
Status = PDH_NO_DATA;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
if (pCounter != NULL) {
|
||
|
pCounter->dwCounterID = dwCounterId;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
PPDHI_LOG_COUNTER
|
||
|
PdhiSqlFindCounter(
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN PPDHI_LOG_MACHINE * MachineTable,
|
||
|
IN LPWSTR szMachine,
|
||
|
IN LPWSTR szObject,
|
||
|
IN LPWSTR szCounter,
|
||
|
IN DWORD dwCounterType,
|
||
|
IN DWORD dwDefaultScale,
|
||
|
IN LPWSTR szInstance,
|
||
|
IN DWORD dwInstance,
|
||
|
IN LPWSTR szParent,
|
||
|
IN DWORD dwParent,
|
||
|
IN LONGLONG TimeBase,
|
||
|
IN BOOL bBeforeSendRow,
|
||
|
IN BOOL bInsert
|
||
|
)
|
||
|
{
|
||
|
PPDHI_LOG_MACHINE pMachine = NULL;
|
||
|
PPDHI_LOG_OBJECT pObject = NULL;
|
||
|
PPDHI_LOG_COUNTER pCounter = NULL;
|
||
|
PPDHI_LOG_COUNTER pNode = NULL;
|
||
|
PPDHI_LOG_COUNTER * pStack[MAX_BTREE_DEPTH];
|
||
|
PPDHI_LOG_COUNTER * pLink;
|
||
|
int dwStack = 0;
|
||
|
PPDHI_LOG_COUNTER pParent;
|
||
|
PPDHI_LOG_COUNTER pSibling;
|
||
|
PPDHI_LOG_COUNTER pChild;
|
||
|
int iCompare;
|
||
|
BOOL bUpdateCounterDetail = FALSE;
|
||
|
|
||
|
pMachine = PdhiFindLogMachine(MachineTable, szMachine, bInsert);
|
||
|
if (pMachine == NULL) goto Cleanup;
|
||
|
|
||
|
pObject = PdhiFindLogObject(pMachine, & (pMachine->ObjTable), szObject, bInsert);
|
||
|
if (pObject == NULL) goto Cleanup;
|
||
|
|
||
|
pStack[dwStack ++] = & (pObject->CtrTable);
|
||
|
pCounter = pObject->CtrTable;
|
||
|
while (pCounter != NULL) {
|
||
|
iCompare = PdhiCompareLogCounterInstance(pCounter,
|
||
|
szCounter, szInstance, dwInstance, szParent);
|
||
|
if (iCompare == 0) {
|
||
|
if (dwCounterType < pCounter->dwCounterType) {
|
||
|
iCompare = -1;
|
||
|
}
|
||
|
else if (dwCounterType > pCounter->dwCounterType) {
|
||
|
iCompare = 1;
|
||
|
}
|
||
|
else {
|
||
|
iCompare = 0;
|
||
|
}
|
||
|
}
|
||
|
if (iCompare < 0) {
|
||
|
pStack[dwStack ++] = & (pCounter->left);
|
||
|
pCounter = pCounter->left;
|
||
|
}
|
||
|
else if (iCompare > 0) {
|
||
|
pStack[dwStack ++] = & (pCounter->right);
|
||
|
pCounter = pCounter->right;
|
||
|
}
|
||
|
else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pCounter == NULL) {
|
||
|
pCounter = G_ALLOC(sizeof(PDHI_LOG_COUNTER) + sizeof(WCHAR) * (3 * (PDH_SQL_STRING_SIZE + 1)));
|
||
|
if (pCounter == NULL) goto Cleanup;
|
||
|
|
||
|
pCounter->bIsRed = TRUE;
|
||
|
pCounter->left = NULL;
|
||
|
pCounter->right = NULL;
|
||
|
pCounter->dwCounterType = dwCounterType;
|
||
|
pCounter->dwDefaultScale = dwDefaultScale;
|
||
|
pCounter->dwInstance = dwInstance;
|
||
|
pCounter->dwParent = dwParent;
|
||
|
pCounter->TimeStamp = 0;
|
||
|
pCounter->TimeBase = TimeBase;
|
||
|
|
||
|
pCounter->szCounter = (LPWSTR)
|
||
|
(((PCHAR) pCounter) + sizeof(PDHI_LOG_COUNTER));
|
||
|
lstrcpynW(pCounter->szCounter, szCounter, PDH_SQL_STRING_SIZE);
|
||
|
if (szInstance == NULL || szInstance[0] == L'\0') {
|
||
|
pCounter->szInstance = NULL;
|
||
|
}
|
||
|
else {
|
||
|
pCounter->szInstance = (LPWSTR) (((PCHAR) pCounter)
|
||
|
+ sizeof(PDHI_LOG_COUNTER)
|
||
|
+ sizeof(WCHAR) * (PDH_SQL_STRING_SIZE + 1));
|
||
|
lstrcpynW(pCounter->szInstance, szInstance, PDH_SQL_STRING_SIZE);
|
||
|
}
|
||
|
|
||
|
if (szParent == NULL || szParent[0] == L'\0') {
|
||
|
pCounter->szParent = NULL;
|
||
|
}
|
||
|
else {
|
||
|
pCounter->szParent = (LPWSTR) (((PCHAR) pCounter)
|
||
|
+ sizeof(PDHI_LOG_COUNTER)
|
||
|
+ 2 * sizeof(WCHAR) * (PDH_SQL_STRING_SIZE + 1));
|
||
|
lstrcpynW(pCounter->szParent, szParent, PDH_SQL_STRING_SIZE);
|
||
|
}
|
||
|
|
||
|
if (bInsert) {
|
||
|
bUpdateCounterDetail = TRUE;
|
||
|
}
|
||
|
|
||
|
pLink = pStack[-- dwStack];
|
||
|
* pLink = pCounter;
|
||
|
|
||
|
pChild = NULL;
|
||
|
pNode = pCounter;
|
||
|
while (dwStack > 0) {
|
||
|
pLink = pStack[-- dwStack];
|
||
|
pParent = * pLink;
|
||
|
if (! pParent->bIsRed) {
|
||
|
pSibling = (pParent->left == pNode)
|
||
|
? pParent->right : pParent->left;
|
||
|
if (pSibling && pSibling->bIsRed) {
|
||
|
pNode->bIsRed = FALSE;
|
||
|
pSibling->bIsRed = FALSE;
|
||
|
pParent->bIsRed = TRUE;
|
||
|
}
|
||
|
else {
|
||
|
if (pChild && pChild->bIsRed) {
|
||
|
if (pChild == pNode->left) {
|
||
|
if (pNode == pParent->left) {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->left = pNode->right;
|
||
|
pNode->right = pParent;
|
||
|
pNode->bIsRed = FALSE;
|
||
|
* pLink = pNode;
|
||
|
}
|
||
|
else {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->right = pChild->left;
|
||
|
pChild->left = pParent;
|
||
|
pNode->left = pChild->right;
|
||
|
pChild->right = pNode;
|
||
|
pChild->bIsRed = FALSE;
|
||
|
* pLink = pChild;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (pNode == pParent->right) {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->right = pNode->left;
|
||
|
pNode->left = pParent;
|
||
|
pNode->bIsRed = FALSE;
|
||
|
* pLink = pNode;
|
||
|
}
|
||
|
else {
|
||
|
pParent->bIsRed = TRUE;
|
||
|
pParent->left = pChild->right;
|
||
|
pChild->right = pParent;
|
||
|
pNode->right = pChild->left;
|
||
|
pChild->left = pNode;
|
||
|
pChild->bIsRed = FALSE;
|
||
|
* pLink = pChild;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
pChild = pNode;
|
||
|
pNode = pParent;
|
||
|
}
|
||
|
|
||
|
pObject->CtrTable->bIsRed = FALSE;
|
||
|
}
|
||
|
|
||
|
if (bUpdateCounterDetail && pCounter) {
|
||
|
PdhiSqlUpdateCounterDetails(pLog,
|
||
|
bBeforeSendRow,
|
||
|
pMachine,
|
||
|
pObject,
|
||
|
pCounter,
|
||
|
pCounter->TimeBase,
|
||
|
pMachine->szMachine,
|
||
|
pObject->szObject,
|
||
|
pCounter->szCounter,
|
||
|
dwCounterType,
|
||
|
dwDefaultScale,
|
||
|
pCounter->szInstance,
|
||
|
dwInstance,
|
||
|
pCounter->szParent,
|
||
|
dwParent);
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
return pCounter;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiSqlBuildCounterObjectNode(
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN LPWSTR szMachine,
|
||
|
IN LPWSTR szObject
|
||
|
)
|
||
|
{
|
||
|
PDH_STATUS Status = ERROR_SUCCESS;
|
||
|
RETCODE rc = SQL_SUCCESS;
|
||
|
HSTMT hstmt = NULL;
|
||
|
DWORD CounterID = 0;
|
||
|
SQLLEN dwCounterID = 0;
|
||
|
WCHAR CounterName[PDH_SQL_STRING_SIZE];
|
||
|
SQLLEN dwCounterName = 0;
|
||
|
DWORD CounterType = 0;
|
||
|
SQLLEN dwCounterType = 0;
|
||
|
DWORD DefaultScale = 0;
|
||
|
SQLLEN dwDefaultScale = 0;
|
||
|
WCHAR InstanceName[PDH_SQL_STRING_SIZE];
|
||
|
SQLLEN dwInstanceName = 0;
|
||
|
DWORD InstanceIndex = 0;
|
||
|
SQLLEN dwInstanceIndex = 0;
|
||
|
WCHAR ParentName[PDH_SQL_STRING_SIZE];
|
||
|
SQLLEN dwParentName = 0;
|
||
|
DWORD ParentObjectID = 0;
|
||
|
SQLLEN dwParentObjectID = 0;
|
||
|
LARGE_INTEGER lTimeBase;
|
||
|
SQLLEN dwTimeBaseA = 0;
|
||
|
SQLLEN dwTimeBaseB = 0;
|
||
|
WCHAR SQLStmt[SQLSTMTSIZE];
|
||
|
BOOL bFind = FALSE;
|
||
|
PPDHI_LOG_OBJECT pObject = NULL;
|
||
|
PPDHI_LOG_MACHINE pMachine;
|
||
|
PPDHI_LOG_COUNTER pCounter;
|
||
|
|
||
|
for (pMachine = ((PPDHI_LOG_MACHINE) (pLog->pPerfmonInfo));
|
||
|
pMachine != NULL && lstrcmpiW(pMachine->szMachine, szMachine) != 0;
|
||
|
pMachine = pMachine->next);
|
||
|
if (pMachine != NULL) {
|
||
|
pObject = pMachine->ObjTable;
|
||
|
while (pObject != NULL) {
|
||
|
int iCompare = lstrcmpiW(szObject, pObject->szObject);
|
||
|
if (iCompare < 0) pObject = pObject->left;
|
||
|
else if (iCompare > 0) pObject = pObject->right;
|
||
|
else break;
|
||
|
}
|
||
|
}
|
||
|
if (pObject != NULL) goto Cleanup;
|
||
|
|
||
|
swprintf(SQLStmt,
|
||
|
L"select CounterID, CounterName, CounterType, DefaultScale, InstanceName, InstanceIndex, ParentName, ParentObjectID, TimeBaseA, TimeBaseB from CounterDetails where MachineName = '%ws' and ObjectName = '%ws'",
|
||
|
szMachine, szObject);
|
||
|
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_LONG, & CounterID, 0, & dwCounterID);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 2, SQL_C_WCHAR, CounterName, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwCounterName);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 3, SQL_C_LONG, & CounterType, 0, & dwCounterType);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 4, SQL_C_LONG, & DefaultScale, 0, & dwDefaultScale);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 5, SQL_C_WCHAR, InstanceName, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwInstanceName);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 6, SQL_C_LONG, & InstanceIndex, 0, & dwInstanceIndex);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 7, SQL_C_WCHAR, ParentName, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwParentName);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 8, SQL_C_LONG, & ParentObjectID, 0, & dwParentObjectID);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 9, SQL_C_LONG, & lTimeBase.LowPart, 0, & dwTimeBaseA);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 10, SQL_C_LONG, & lTimeBase.HighPart, 0, & dwTimeBaseB);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLExecDirectW(hstmt, SQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
ZeroMemory(CounterName, sizeof(CounterName));
|
||
|
ZeroMemory(InstanceName, sizeof(InstanceName));
|
||
|
ZeroMemory(ParentName, sizeof(ParentName));
|
||
|
CounterType = DefaultScale = InstanceIndex = ParentObjectID = 0;
|
||
|
rc = SQLFetch(hstmt);
|
||
|
while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
|
||
|
pCounter = PdhiSqlFindCounter(
|
||
|
pLog,
|
||
|
(PPDHI_LOG_MACHINE *) (& (pLog->pPerfmonInfo)),
|
||
|
szMachine,
|
||
|
szObject,
|
||
|
CounterName,
|
||
|
CounterType,
|
||
|
DefaultScale,
|
||
|
InstanceName,
|
||
|
InstanceIndex,
|
||
|
ParentName,
|
||
|
ParentObjectID,
|
||
|
0,
|
||
|
TRUE,
|
||
|
FALSE);
|
||
|
if (pCounter != NULL) {
|
||
|
pCounter->dwCounterID = CounterID;
|
||
|
if (dwTimeBaseA != SQL_NULL_DATA && dwTimeBaseB != SQL_NULL_DATA) {
|
||
|
pCounter->TimeBase = lTimeBase.QuadPart;
|
||
|
}
|
||
|
else {
|
||
|
pCounter->TimeBase = 0;
|
||
|
pCounter->dwCounterType = PERF_DOUBLE_RAW;
|
||
|
}
|
||
|
}
|
||
|
ZeroMemory(CounterName, sizeof(CounterName));
|
||
|
ZeroMemory(InstanceName, sizeof(InstanceName));
|
||
|
ZeroMemory(ParentName, sizeof(ParentName));
|
||
|
CounterType = DefaultScale = InstanceIndex = ParentObjectID = 0;
|
||
|
rc = SQLFetch(hstmt);
|
||
|
}
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
|
||
|
Cleanup:
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiSqlGetCounterArray(
|
||
|
IN PPDHI_COUNTER pCounter,
|
||
|
IN LPDWORD lpdwBufferSize,
|
||
|
IN LPDWORD lpdwItemCount,
|
||
|
IN LPVOID ItemBuffer
|
||
|
)
|
||
|
{
|
||
|
PDH_STATUS Status = ERROR_SUCCESS;
|
||
|
PDH_STATUS PdhFnStatus = ERROR_SUCCESS;
|
||
|
DWORD dwRequiredSize = 0;
|
||
|
PPDHI_RAW_COUNTER_ITEM pThisItem = NULL;
|
||
|
PPDHI_RAW_COUNTER_ITEM pLastItem = NULL;
|
||
|
LPWSTR szThisItem = NULL;
|
||
|
LPWSTR szLastItem = NULL;
|
||
|
PPDH_RAW_COUNTER pThisRawCounter = NULL;
|
||
|
PPDH_RAW_COUNTER pLastRawCounter = NULL;
|
||
|
PPDH_FMT_COUNTERVALUE_ITEM_W pThisFmtItem = NULL;
|
||
|
DWORD dwThisItemIndex;
|
||
|
LPWSTR wszNextString;
|
||
|
DWORD dwRetItemCount = 0;
|
||
|
|
||
|
LIST_ENTRY InstList;
|
||
|
PPDHI_INSTANCE pInstance;
|
||
|
WCHAR szPound[16];
|
||
|
|
||
|
InitializeListHead(& InstList);
|
||
|
Status = WAIT_FOR_AND_LOCK_MUTEX(pCounter->pOwner->hMutex);
|
||
|
if (Status != ERROR_SUCCESS) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
if(pCounter->pThisRawItemList == NULL) {
|
||
|
Status = PDH_CSTATUS_ITEM_NOT_VALIDATED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwRetItemCount = pCounter->pThisRawItemList->dwItemCount;
|
||
|
dwThisItemIndex = 0;
|
||
|
|
||
|
if (ItemBuffer != NULL) {
|
||
|
pThisRawCounter = (PPDH_RAW_COUNTER) ItemBuffer;
|
||
|
}
|
||
|
else {
|
||
|
pThisRawCounter = NULL;
|
||
|
}
|
||
|
assert(((DWORD) pThisRawCounter & 0x00000007) == 0);
|
||
|
|
||
|
dwRequiredSize = (DWORD) (dwRetItemCount * sizeof(PDH_RAW_COUNTER));
|
||
|
if ((ItemBuffer != NULL) && (dwRequiredSize <= * lpdwBufferSize)) {
|
||
|
pThisFmtItem = (PPDH_FMT_COUNTERVALUE_ITEM_W)
|
||
|
(((LPBYTE) ItemBuffer) + dwRequiredSize);
|
||
|
}
|
||
|
else {
|
||
|
pThisFmtItem = NULL;
|
||
|
}
|
||
|
assert(((DWORD) pThisFmtItem & 0x00000007) == 0);
|
||
|
|
||
|
dwRequiredSize +=
|
||
|
(DWORD) (dwRetItemCount * sizeof(PDH_FMT_COUNTERVALUE_ITEM_W));
|
||
|
if ((ItemBuffer != NULL) && (dwRequiredSize <= * lpdwBufferSize)) {
|
||
|
wszNextString = (LPWSTR) (((LPBYTE) ItemBuffer) + dwRequiredSize);
|
||
|
}
|
||
|
else {
|
||
|
wszNextString = NULL;
|
||
|
}
|
||
|
assert(((DWORD) wszNextString & 0x00000007) == 0);
|
||
|
|
||
|
for (pThisItem = & (pCounter->pThisRawItemList->pItemArray[0]);
|
||
|
dwThisItemIndex < dwRetItemCount;
|
||
|
dwThisItemIndex ++, pThisItem ++, pLastItem ++) {
|
||
|
szThisItem = (LPWSTR) ( ((LPBYTE) pCounter->pThisRawItemList)
|
||
|
+ pThisItem->szName);
|
||
|
pInstance = NULL;
|
||
|
Status = PdhiFindInstance(& InstList, szThisItem, TRUE, & pInstance);
|
||
|
if ( Status == ERROR_SUCCESS && pInstance != NULL
|
||
|
&& pInstance->dwCount > 1) {
|
||
|
ZeroMemory(szPound, 16 * sizeof(WCHAR));
|
||
|
_itow(pInstance->dwCount - 1, szPound, 10);
|
||
|
dwRequiredSize += (lstrlenW(szThisItem) + lstrlenW(szPound) + 2)
|
||
|
* sizeof(WCHAR);
|
||
|
}
|
||
|
else {
|
||
|
dwRequiredSize += (lstrlenW(szThisItem) + 1) * sizeof(WCHAR);
|
||
|
}
|
||
|
if ((dwRequiredSize <= * lpdwBufferSize) && (wszNextString != NULL)) {
|
||
|
DWORD dwNextString;
|
||
|
|
||
|
pThisFmtItem->szName = wszNextString;
|
||
|
lstrcpyW(wszNextString, szThisItem);
|
||
|
if (pInstance != NULL) {
|
||
|
if (pInstance->dwCount > 1) {
|
||
|
lstrcatW(wszNextString, cszPoundSign);
|
||
|
lstrcatW(wszNextString, szPound);
|
||
|
}
|
||
|
}
|
||
|
dwNextString = lstrlenW(wszNextString);
|
||
|
wszNextString += (dwNextString + 1);
|
||
|
Status = ERROR_SUCCESS;
|
||
|
}
|
||
|
else {
|
||
|
Status = PDH_MORE_DATA;
|
||
|
}
|
||
|
|
||
|
if (Status == ERROR_SUCCESS) {
|
||
|
if (pCounter->pThisRawItemList != NULL) {
|
||
|
pThisRawCounter->CStatus = pCounter->pThisRawItemList->CStatus;
|
||
|
pThisRawCounter->TimeStamp = pCounter->pThisRawItemList->TimeStamp;
|
||
|
pThisRawCounter->FirstValue = pThisItem->FirstValue;
|
||
|
pThisRawCounter->SecondValue = pThisItem->SecondValue;
|
||
|
pThisRawCounter->MultiCount = pThisItem->MultiCount;
|
||
|
}
|
||
|
else {
|
||
|
ZeroMemory(pThisRawCounter, sizeof(PDH_RAW_COUNTER));
|
||
|
}
|
||
|
|
||
|
pLastRawCounter = NULL;
|
||
|
if (pCounter->pLastRawItemList != NULL) {
|
||
|
PPDH_FMT_COUNTERVALUE_ITEM_W pFmtValue;
|
||
|
DWORD dwLastItem = pCounter->LastValue.MultiCount;
|
||
|
DWORD i;
|
||
|
|
||
|
pFmtValue = (PPDH_FMT_COUNTERVALUE_ITEM_W)
|
||
|
( ((LPBYTE) pCounter->pLastObject)
|
||
|
+ sizeof(PDH_RAW_COUNTER) * dwLastItem);
|
||
|
|
||
|
for (i = 0; i < dwLastItem; i ++) {
|
||
|
if (lstrcmpiW(pThisFmtItem->szName,
|
||
|
pFmtValue->szName) == 0) {
|
||
|
pLastRawCounter = (PPDH_RAW_COUNTER)
|
||
|
( ((LPBYTE) pCounter->pLastObject)
|
||
|
+ sizeof(PDH_RAW_COUNTER) * i);
|
||
|
break;
|
||
|
}
|
||
|
else {
|
||
|
pFmtValue = (PPDH_FMT_COUNTERVALUE_ITEM_W)
|
||
|
( ((LPBYTE) pFmtValue)
|
||
|
+ sizeof(PDH_FMT_COUNTERVALUE_ITEM_W));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PdhFnStatus = PdhiComputeFormattedValue(
|
||
|
pCounter->CalcFunc,
|
||
|
pCounter->plCounterInfo.dwCounterType,
|
||
|
pCounter->lScale,
|
||
|
PDH_FMT_DOUBLE | PDH_FMT_NOCAP100,
|
||
|
pThisRawCounter,
|
||
|
pLastRawCounter,
|
||
|
& pCounter->TimeBase,
|
||
|
0L,
|
||
|
& pThisFmtItem->FmtValue);
|
||
|
if (PdhFnStatus != ERROR_SUCCESS) {
|
||
|
//Status = PdhFnStatus;
|
||
|
pThisFmtItem->FmtValue.CStatus = PDH_CSTATUS_INVALID_DATA;
|
||
|
pThisFmtItem->FmtValue.doubleValue = 0;
|
||
|
}
|
||
|
|
||
|
pThisRawCounter = (PPDH_RAW_COUNTER)
|
||
|
(((LPBYTE) pThisRawCounter) + sizeof(PDH_RAW_COUNTER));
|
||
|
pThisFmtItem = (PPDH_FMT_COUNTERVALUE_ITEM_W)
|
||
|
(((LPBYTE) pThisFmtItem) + sizeof(PDH_FMT_COUNTERVALUE_ITEM_W));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dwRetItemCount = dwThisItemIndex;
|
||
|
|
||
|
Cleanup:
|
||
|
RELEASE_MUTEX(pCounter->pOwner->hMutex);
|
||
|
if (! IsListEmpty(& InstList)) {
|
||
|
PLIST_ENTRY pHead = & InstList;
|
||
|
PLIST_ENTRY pNext = pHead->Flink;
|
||
|
while (pNext != pHead) {
|
||
|
pInstance = CONTAINING_RECORD(pNext, PDHI_INSTANCE, Entry);
|
||
|
pNext = pNext->Flink;
|
||
|
RemoveEntryList(& pInstance->Entry);
|
||
|
G_FREE(pInstance);
|
||
|
}
|
||
|
}
|
||
|
if (Status == ERROR_SUCCESS || Status == PDH_MORE_DATA) {
|
||
|
* lpdwBufferSize = dwRequiredSize;
|
||
|
* lpdwItemCount = dwRetItemCount;
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
RETCODE
|
||
|
PdhiCheckSQLExist(IN HSTMT hstmt, IN RETCODE rcIn)
|
||
|
{
|
||
|
SQLCHAR szSQLStat[6];
|
||
|
SQLCHAR szMessage[1024];
|
||
|
RETCODE rc = rcIn;
|
||
|
SQLSMALLINT iMessage = 1024;
|
||
|
SQLSMALLINT iSize = 0;
|
||
|
SQLINTEGER iNativeError = 0;
|
||
|
|
||
|
ZeroMemory(szSQLStat, 6 * sizeof(SQLCHAR));
|
||
|
ZeroMemory(szMessage, 1024 * sizeof(SQLCHAR));
|
||
|
rc = SQLGetDiagRec(SQL_HANDLE_STMT,
|
||
|
hstmt,
|
||
|
1,
|
||
|
szSQLStat,
|
||
|
& iNativeError,
|
||
|
szMessage,
|
||
|
iMessage,
|
||
|
& iSize);
|
||
|
DebugPrint((4,"SQLGetDiagRec(0x%08X,%d,%s,%d,\"%s\")\n",
|
||
|
hstmt, rcIn, szSQLStat, rc, szMessage));
|
||
|
if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
|
||
|
if ( lstrcmpi(szSQLStat, "42S01") == 0
|
||
|
|| lstrcmpi(szSQLStat, "S0001") == 0
|
||
|
|| lstrcmpi(szSQLStat, "42S02") == 0
|
||
|
|| lstrcmpi(szSQLStat, "S0002") == 0
|
||
|
|| lstrcmpi(szSQLStat, "42S11") == 0
|
||
|
|| lstrcmpi(szSQLStat, "S0011") == 0
|
||
|
|| lstrcmpi(szSQLStat, "42S12") == 0
|
||
|
|| lstrcmpi(szSQLStat, "S0012") == 0) {
|
||
|
rc = SQL_SUCCESS;
|
||
|
}
|
||
|
else {
|
||
|
rc = rcIn;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
rc = rcIn;
|
||
|
}
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiSQLUpdateCounterDetailTimeBase(
|
||
|
PPDHI_LOG pLog,
|
||
|
DWORD dwCounterId,
|
||
|
LONGLONG lTimeBase,
|
||
|
BOOL bBeforeSendRow
|
||
|
)
|
||
|
{
|
||
|
PDH_STATUS Status = ERROR_SUCCESS;
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
|
||
|
if (! bBeforeSendRow) {
|
||
|
PPDH_SQL_BULK_COPY pBulk = (PPDH_SQL_BULK_COPY) pLog->lpMappedFileBase;
|
||
|
|
||
|
if (pBulk != NULL && pBulk->dwRecordCount > 0) {
|
||
|
DBINT rcBCP = bcp_batch(pLog->hdbcSQL);
|
||
|
if (rcBCP < 0) {
|
||
|
ReportSQLError(pLog, SQL_ERROR, NULL, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
}
|
||
|
pBulk->dwRecordCount = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
wsprintfW(szSQLStmt, L"UPDATE CounterDetails SET TimeBaseA = %d, TimeBaseB = %d WHERE CounterID = %d",
|
||
|
LODWORD(lTimeBase), HIDWORD(lTimeBase), dwCounterId);
|
||
|
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
}
|
||
|
else {
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
}
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiSQLExtendCounterDetail(
|
||
|
PPDHI_LOG pLog
|
||
|
)
|
||
|
{
|
||
|
PDH_STATUS Status = ERROR_SUCCESS;
|
||
|
BOOL bExtend = FALSE;
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
DWORD dwTimeBaseA;
|
||
|
SQLLEN lenTimeBaseA;
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
|
||
|
wsprintfW(szSQLStmt, L"SELECT TimeBaseA FROM CounterDetails");
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
}
|
||
|
else {
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_LONG, & dwTimeBaseA, 0, & lenTimeBaseA);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
}
|
||
|
else {
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
long iError;
|
||
|
short cbErrMsg = SQLSTMTSIZE;
|
||
|
WCHAR szErrMsg[SQLSTMTSIZE];
|
||
|
|
||
|
SQLErrorW(pLog->henvSQL, pLog->hdbcSQL, hstmt, NULL, & iError, szErrMsg, SQLSTMTSIZE, & cbErrMsg);
|
||
|
if (iError == 0x00CF) { // 207, Invalid Column Name.
|
||
|
bExtend = TRUE;
|
||
|
}
|
||
|
else {
|
||
|
ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
}
|
||
|
|
||
|
if (bExtend) {
|
||
|
wsprintfW(szSQLStmt, L"ALTER TABLE CounterDetails ADD TimeBaseA int NULL");
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
}
|
||
|
else {
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
}
|
||
|
|
||
|
if (Status == ERROR_SUCCESS) {
|
||
|
wsprintfW(szSQLStmt, L"ALTER TABLE CounterDetails ADD TimeBaseB int NULL");
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
}
|
||
|
else {
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhpCreateSQLTables (
|
||
|
IN PPDHI_LOG pLog)
|
||
|
{
|
||
|
// INTERNAL FUNCTION to
|
||
|
//Create the correct perfmon tables in the database
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
PDH_STATUS pdhCreateStatus = ERROR_SUCCESS;
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
BOOL bExistData = FALSE;
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
|
||
|
|
||
|
// difficult to cleanup old tables, also dangerous so we won't...
|
||
|
// PdhiOpenOutputSQLLog calls this routine to ensure the tables are here without checking
|
||
|
// create the CounterDetails Table
|
||
|
|
||
|
swprintf(szSQLStmt,L"CREATE TABLE CounterDetails(\
|
||
|
CounterID int IDENTITY PRIMARY KEY,\
|
||
|
MachineName varchar(%d) NOT NULL,\
|
||
|
ObjectName varchar(%d) NOT NULL,\
|
||
|
CounterName varchar(%d) NOT NULL,\
|
||
|
CounterType int NOT NULL,\
|
||
|
DefaultScale int NOT NULL,\
|
||
|
InstanceName varchar(%d),\
|
||
|
InstanceIndex int,\
|
||
|
ParentName varchar(%d),\
|
||
|
ParentObjectID int,\
|
||
|
TimeBaseA int,\
|
||
|
TimeBaseB int\
|
||
|
)", PDH_SQL_STRING_SIZE, PDH_SQL_STRING_SIZE, PDH_SQL_STRING_SIZE, PDH_SQL_STRING_SIZE, PDH_SQL_STRING_SIZE);
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// execute the create statement
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
rc = PdhiCheckSQLExist(hstmt, rc);
|
||
|
if (!(SQLSUCCEEDED(rc))) {
|
||
|
// don't report the error, as this could be called from
|
||
|
// opening a database that already exists...
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
else {
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
if ((pdhStatus = PdhiSQLExtendCounterDetail(pLog)) != ERROR_SUCCESS) goto Cleanup;
|
||
|
|
||
|
swprintf(szSQLStmt, L"ALTER TABLE CounterDetails ALTER COLUMN MachineName varchar(%d) NOT NULL",
|
||
|
PDH_SQL_STRING_SIZE);
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
swprintf(szSQLStmt, L"ALTER TABLE CounterDetails ALTER COLUMN ObjectName varchar(%d) NOT NULL",
|
||
|
PDH_SQL_STRING_SIZE);
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
swprintf(szSQLStmt, L"ALTER TABLE CounterDetails ALTER COLUMN CounterName varchar(%d) NOT NULL",
|
||
|
PDH_SQL_STRING_SIZE);
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
swprintf(szSQLStmt, L"ALTER TABLE CounterDetails ALTER COLUMN InstanceName varchar(%d)",
|
||
|
PDH_SQL_STRING_SIZE);
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
swprintf(szSQLStmt, L"ALTER TABLE CounterDetails ALTER COLUMN ParentName varchar(%d)",
|
||
|
PDH_SQL_STRING_SIZE);
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
// Create the CounterData table
|
||
|
swprintf(szSQLStmt,L"CREATE TABLE CounterData(\
|
||
|
GUID uniqueidentifier NOT NULL,\
|
||
|
CounterID int NOT NULL,\
|
||
|
RecordIndex int NOT NULL,\
|
||
|
CounterDateTime char(24) NOT NULL,\
|
||
|
CounterValue float NOT NULL,\
|
||
|
FirstValueA int,\
|
||
|
FirstValueB int,\
|
||
|
SecondValueA int,\
|
||
|
SecondValueB int,\
|
||
|
MultiCount int,\
|
||
|
)");
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// execute the create statement
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
rc = PdhiCheckSQLExist(hstmt, rc);
|
||
|
if (!(SQLSUCCEEDED(rc))) {
|
||
|
// don't report the error, as this could be called from
|
||
|
// opening a database that already exists...
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
else {
|
||
|
bExistData = TRUE;
|
||
|
}
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
if (! bExistData) {
|
||
|
// add the primary keys
|
||
|
swprintf(szSQLStmt,L"ALTER TABLE CounterData ADD PRIMARY KEY (GUID,counterID,RecordIndex)");
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// execute the create statement
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
rc = PdhiCheckSQLExist(hstmt, rc);
|
||
|
if (!(SQLSUCCEEDED(rc))) {
|
||
|
// don't report the error, as this could be called from
|
||
|
// opening a database that already exists...
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
// create the DisplayToID table
|
||
|
swprintf(szSQLStmt,L"CREATE TABLE DisplayToID(\
|
||
|
GUID uniqueidentifier NOT NULL PRIMARY KEY,\
|
||
|
RunID int,\
|
||
|
DisplayString varchar(%d) NOT NULL UNIQUE,\
|
||
|
LogStartTime char(24),\
|
||
|
LogStopTime char(24),\
|
||
|
NumberOfRecords int,\
|
||
|
MinutesToUTC int,\
|
||
|
TimeZoneName char(32)\
|
||
|
)", PDH_SQL_STRING_SIZE);
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// execute the create statement
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
rc = PdhiCheckSQLExist(hstmt, rc);
|
||
|
if (!(SQLSUCCEEDED(rc))) {
|
||
|
// don't report the error, as this could be called from
|
||
|
// opening a database that already exists...
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
}
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// execute the create statement
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
rc = PdhiCheckSQLExist(hstmt, rc);
|
||
|
if (!(SQLSUCCEEDED(rc))) {
|
||
|
// don't report the error, as this could be called from
|
||
|
// opening a database that already exists...
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if any failures to create a table, return that
|
||
|
if (ERROR_SUCCESS == pdhStatus) pdhStatus = pdhCreateStatus;
|
||
|
|
||
|
Cleanup:
|
||
|
if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiGetSQLLogCounterInfo (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN PPDHI_COUNTER pCounter
|
||
|
)
|
||
|
// Figures out if a particular counter is in the log...
|
||
|
// this must be fetched from SQL with a select since
|
||
|
// there is no header record, this will be a complex select
|
||
|
// Use the function PdhpGetSQLLogHeader - which will
|
||
|
// do this, and save the results for subsequent calls.
|
||
|
// store away in the pCounter structure the actual SQL index
|
||
|
// based on how this is used, I think the counterID can be resused.
|
||
|
// however, probably safer to assign one sequentially
|
||
|
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
PPDHI_SQL_LOG_INFO pLogInfo;
|
||
|
PPDHI_LOG_COUNTER pLogCounter = NULL;
|
||
|
DWORD dwCtrIndex = 0;
|
||
|
BOOL bNoMachine = FALSE;
|
||
|
LPWSTR szMachine;
|
||
|
|
||
|
pdhStatus = PdhpGetSQLLogHeader(pLog);
|
||
|
if (pdhStatus != ERROR_SUCCESS) goto Cleanup;
|
||
|
|
||
|
pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
|
||
|
if (pLogInfo == NULL) {
|
||
|
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
if (pCounter->pCounterPath->szMachineName == NULL) {
|
||
|
bNoMachine = TRUE;
|
||
|
szMachine = szStaticLocalMachineName;
|
||
|
}
|
||
|
else if (lstrcmpiW(pCounter->pCounterPath->szMachineName, L"\\\\.") == 0) {
|
||
|
bNoMachine = TRUE;
|
||
|
szMachine = szStaticLocalMachineName;
|
||
|
}
|
||
|
else {
|
||
|
szMachine = pCounter->pCounterPath->szMachineName;
|
||
|
}
|
||
|
|
||
|
pLogCounter = PdhiFindLogCounter(pLog,
|
||
|
& pLogInfo->MachineList,
|
||
|
szMachine,
|
||
|
pCounter->pCounterPath->szObjectName,
|
||
|
pCounter->pCounterPath->szCounterName,
|
||
|
0,
|
||
|
0,
|
||
|
pCounter->pCounterPath->szInstanceName,
|
||
|
pCounter->pCounterPath->dwIndex,
|
||
|
pCounter->pCounterPath->szParentName,
|
||
|
0,
|
||
|
& dwCtrIndex,
|
||
|
FALSE);
|
||
|
if (pLogCounter != NULL) {
|
||
|
if (bNoMachine) {
|
||
|
pCounter->pCounterPath->szMachineName = NULL;
|
||
|
}
|
||
|
pCounter->TimeBase = pLogCounter->TimeBase;
|
||
|
pCounter->plCounterInfo.dwObjectId = 0;
|
||
|
pCounter->plCounterInfo.lInstanceId = pLogCounter->dwInstance;
|
||
|
pCounter->plCounterInfo.szInstanceName = pLogCounter->szInstance;
|
||
|
pCounter->plCounterInfo.dwParentObjectId = pLogCounter->dwParent;
|
||
|
pCounter->plCounterInfo.szParentInstanceName = pLogCounter->szParent;
|
||
|
pCounter->plCounterInfo.dwCounterId = pLogCounter->dwCounterID;
|
||
|
pCounter->plCounterInfo.dwCounterType = pLogCounter->dwCounterType;
|
||
|
pCounter->plCounterInfo.lDefaultScale = pLogCounter->dwDefaultScale;
|
||
|
pCounter->plCounterInfo.dwCounterSize = (pLogCounter->dwCounterType & PERF_SIZE_LARGE)
|
||
|
? sizeof(LONGLONG) : sizeof(DWORD);
|
||
|
pCounter->plCounterInfo.dwSQLCounterId = dwCtrIndex;
|
||
|
pdhStatus = ERROR_SUCCESS;
|
||
|
}
|
||
|
else {
|
||
|
pdhStatus = PDH_CSTATUS_NO_COUNTER;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiOpenSQLLog (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN BOOL bOpenInput
|
||
|
)
|
||
|
{
|
||
|
// string to compare with file name to see if SQL
|
||
|
WCHAR szSQLType[] = L"SQL:";
|
||
|
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
RETCODE rc;
|
||
|
|
||
|
pLog->henvSQL = NULL ;
|
||
|
pLog->hdbcSQL = NULL ;
|
||
|
|
||
|
// format is SQL:DSNNAME!COMMENT
|
||
|
// parse out the DSN name and 'dataset' (comment) name from the LogFileName
|
||
|
// pLog->szDSN - pointer to Data Source Name within LogFileName
|
||
|
// (separators replaced with 0's)
|
||
|
// pLog->szCommentSQL - pointer to the Comment string that defines the
|
||
|
// name of the data set within the SQL database
|
||
|
|
||
|
pLog->szDSN = pLog->szLogFileName
|
||
|
+ (sizeof(szSQLType) / sizeof(WCHAR)) - 1;
|
||
|
|
||
|
pLog->szCommentSQL = wcschr((const wchar_t *) pLog->szDSN, '!');
|
||
|
if (NULL == pLog->szCommentSQL) {
|
||
|
return PDH_INVALID_DATASOURCE;
|
||
|
}
|
||
|
pLog->szCommentSQL[0] = 0; // null terminate the DSN name
|
||
|
pLog->szCommentSQL ++; // increment past to the Comment string
|
||
|
|
||
|
if (0 == lstrlenW(pLog->szCommentSQL)) {
|
||
|
return PDH_INVALID_DATASOURCE;
|
||
|
}
|
||
|
|
||
|
// initialize the rest of the SQL fields
|
||
|
pLog->dwNextRecordIdToWrite = 1; // start with record 1
|
||
|
pLog->dwRecord1Size = 0;
|
||
|
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
// obtain the ODBC environment and connection
|
||
|
//
|
||
|
|
||
|
rc = SQLAllocEnv(&pLog->henvSQL);
|
||
|
if (! SQLSUCCEEDED(rc)) goto Cleanup;
|
||
|
|
||
|
rc = SQLAllocConnect(pLog->henvSQL, &pLog->hdbcSQL);
|
||
|
if (! SQLSUCCEEDED(rc)) goto Cleanup;
|
||
|
|
||
|
rc = SQLSetConnectAttr(pLog->hdbcSQL,
|
||
|
SQL_COPT_SS_BCP,
|
||
|
(SQLPOINTER) SQL_BCP_ON,
|
||
|
SQL_IS_INTEGER);
|
||
|
if (! SQLSUCCEEDED(rc)) goto Cleanup;
|
||
|
|
||
|
rc = SQLConnectW(pLog->hdbcSQL,
|
||
|
(SQLWCHAR *) pLog->szDSN,
|
||
|
SQL_NTS,
|
||
|
NULL,
|
||
|
SQL_NULL_DATA,
|
||
|
NULL,
|
||
|
SQL_NULL_DATA);
|
||
|
|
||
|
Cleanup:
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,NULL,PDH_SQL_ALLOCCON_FAILED);
|
||
|
if (pLog->hdbcSQL) SQLDisconnect(pLog->hdbcSQL);
|
||
|
if (pLog->hdbcSQL) SQLFreeHandle(SQL_HANDLE_DBC, pLog->hdbcSQL);
|
||
|
if (pLog->henvSQL) SQLFreeHandle(SQL_HANDLE_ENV, pLog->henvSQL);
|
||
|
pLog->henvSQL = NULL;
|
||
|
pLog->hdbcSQL = NULL;
|
||
|
}
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiOpenInputSQLLog (
|
||
|
IN PPDHI_LOG pLog
|
||
|
)
|
||
|
// open SQL database for input - or anything that isn't actually creating a new space
|
||
|
// database MUST exist
|
||
|
{
|
||
|
PDH_STATUS pdhStatus;
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
LONG lMinutesToUTC = 0;
|
||
|
WCHAR szTimeZoneName[32];
|
||
|
SQLLEN dwTimeZoneLen;
|
||
|
|
||
|
pdhStatus = PdhiOpenSQLLog(pLog, TRUE);
|
||
|
if (SUCCEEDED (pdhStatus))
|
||
|
{
|
||
|
if ((pdhStatus = PdhiSQLExtendCounterDetail(pLog)) != ERROR_SUCCESS) goto Cleanup;
|
||
|
|
||
|
// Check that the database exists
|
||
|
// Select the guid & runid from DisplayToId table
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"select GUID, RunID, NumberOfRecords, MinutesToUTC, TimeZoneName from DisplayToID where DisplayString = '%ws'",
|
||
|
pLog->szCommentSQL);
|
||
|
|
||
|
// bind the columns
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_GUID, &pLog->guidSQL, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 2, SQL_C_LONG, &pLog->iRunidSQL, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 3, SQL_C_LONG, &pLog->dwNextRecordIdToWrite, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 4, SQL_C_LONG, &lMinutesToUTC, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 5, SQL_C_WCHAR, szTimeZoneName, sizeof(szTimeZoneName), &dwTimeZoneLen);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLFetch(hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_FETCH_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pLog->dwNextRecordIdToWrite ++; // increment number of current records to get next recordid to write
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiOpenOutputSQLLog (
|
||
|
IN PPDHI_LOG pLog
|
||
|
)
|
||
|
// open SQL database for output
|
||
|
// May have to create DB
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = PdhiOpenSQLLog(pLog, FALSE);
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
SQLLEN dwGuid = 0;
|
||
|
SQLLEN dwRunIdSQL = 0;
|
||
|
SQLLEN dwNextRecord = 0;
|
||
|
|
||
|
if (SUCCEEDED(pdhStatus)) {
|
||
|
// see if we need to create the database
|
||
|
// creating the tables is harmless, it won't drop
|
||
|
// them if they already exist, but ignore any errors
|
||
|
|
||
|
pdhStatus = PdhpCreateSQLTables(pLog);
|
||
|
|
||
|
// See if logset already exists. If it does, treat it as an
|
||
|
// logset append case.
|
||
|
//
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = PDH_SQL_ALLOC_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"select GUID, RunID, NumberOfRecords from DisplayToID where DisplayString = '%ws'",
|
||
|
pLog->szCommentSQL);
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_GUID,
|
||
|
& pLog->guidSQL, 0, & dwGuid);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = PDH_SQL_BIND_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 2, SQL_C_LONG,
|
||
|
& pLog->iRunidSQL, 0, & dwRunIdSQL);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = PDH_SQL_BIND_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 3, SQL_C_LONG,
|
||
|
& pLog->dwNextRecordIdToWrite, 0, & dwNextRecord);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = PDH_SQL_BIND_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLFetch(hstmt);
|
||
|
if ((! SQLSUCCEEDED(rc)) || (rc == SQL_NO_DATA)) {
|
||
|
pdhStatus = PDH_SQL_FETCH_FAILED;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pLog->dwNextRecordIdToWrite ++;
|
||
|
pLog->dwRecord1Size = 1;
|
||
|
|
||
|
Cleanup:
|
||
|
if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
|
||
|
if (pdhStatus != ERROR_SUCCESS) {
|
||
|
// initialize the GUID
|
||
|
HRESULT hr = CoCreateGuid(& pLog->guidSQL);
|
||
|
pLog->dwNextRecordIdToWrite = 1;
|
||
|
pLog->iRunidSQL = 0;
|
||
|
pdhStatus = ERROR_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(pdhStatus)) {
|
||
|
PPDH_SQL_BULK_COPY pBulk = PdhiBindBulkCopyStructure(pLog);
|
||
|
if (pBulk == NULL) {
|
||
|
pdhStatus = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
ReportSQLError (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
RETCODE rc,
|
||
|
HSTMT hstmt,
|
||
|
DWORD dwEventNumber)
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = dwEventNumber;
|
||
|
}
|
||
|
|
||
|
if (FAILED(pdhStatus))
|
||
|
{
|
||
|
// for now this will be reported only whe specifically enabled
|
||
|
short cbErrMsgSize = 512;
|
||
|
WCHAR szError[512];
|
||
|
LPWSTR lpszStrings[1];
|
||
|
DWORD dwData[1];
|
||
|
long iError;
|
||
|
lpszStrings[0] = szError;
|
||
|
SQLErrorW( pLog->henvSQL, pLog->hdbcSQL, hstmt, NULL, &iError, szError, 512, &cbErrMsgSize );
|
||
|
dwData[0] = iError;
|
||
|
if (pdhStatus == PDH_SQL_EXEC_DIRECT_FAILED && iError == 1105) {
|
||
|
pdhStatus = ERROR_DISK_FULL;
|
||
|
}
|
||
|
ReportEventW (hEventLog,
|
||
|
EVENTLOG_ERROR_TYPE, // error type
|
||
|
0, // category (not used)
|
||
|
(DWORD)dwEventNumber, // event,
|
||
|
NULL, // SID (not used),
|
||
|
1, // number of strings
|
||
|
1, // sizeof raw data
|
||
|
(LPCWSTR *)lpszStrings, // message text array
|
||
|
(LPVOID) & dwData[0]); // raw data
|
||
|
}
|
||
|
|
||
|
return pdhStatus ;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiCloseSQLLog (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN DWORD dwFlags
|
||
|
)
|
||
|
// close the SQL database
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
SQLLEN dwDateTimeLen;
|
||
|
WCHAR szDateTime[40];
|
||
|
OBJECT_NAME_STRUCT * pObjList;
|
||
|
OBJECT_ITEM_STRUCT * pObjItemList;
|
||
|
OBJECT_NAME_STRUCT * pNextObj;
|
||
|
OBJECT_ITEM_STRUCT * pNextObjItem;
|
||
|
DBINT rcBCP;
|
||
|
DWORD dwReturn;
|
||
|
WCHAR * pTimeZone;
|
||
|
TIME_ZONE_INFORMATION TimeZone;
|
||
|
LONG lMinutesToUTC = 0;
|
||
|
|
||
|
UNREFERENCED_PARAMETER (dwFlags);
|
||
|
|
||
|
if ((pLog->dwLogFormat & PDH_LOG_ACCESS_MASK) == PDH_LOG_WRITE_ACCESS)
|
||
|
{
|
||
|
// need to save the last datetime in the DisplayToID as well as the number of records written
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// first have to read the date time from the last record
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"select CounterDateTime from CounterData where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x' and RecordIndex = %d",
|
||
|
pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
|
||
|
pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
|
||
|
pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
|
||
|
pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7], (pLog->dwNextRecordIdToWrite - 1));
|
||
|
|
||
|
// bind the column
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_WCHAR, szDateTime, sizeof(szDateTime), &dwDateTimeLen);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLFetch(hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_FETCH_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// close the hstmt since we're done, and don't want more rows
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
if (SQL_NO_DATA != rc) // if there is no data, we didn't write any rows
|
||
|
{
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// szDateTime should have the correct date & time in it from above.
|
||
|
// get MinutesToUTC
|
||
|
//
|
||
|
dwReturn = GetTimeZoneInformation(&TimeZone);
|
||
|
|
||
|
if (dwReturn != TIME_ZONE_ID_INVALID)
|
||
|
{
|
||
|
if (dwReturn == TIME_ZONE_ID_DAYLIGHT)
|
||
|
{
|
||
|
pTimeZone = TimeZone.DaylightName;
|
||
|
lMinutesToUTC = TimeZone.Bias + TimeZone.DaylightBias;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pTimeZone = TimeZone.StandardName;
|
||
|
lMinutesToUTC = TimeZone.Bias + TimeZone.StandardBias;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"update DisplayToID set LogStopTime = '%ws', NumberOfRecords = %d, MinutesToUTC = %d, TimeZoneName = '%ws' where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x'",
|
||
|
szDateTime, (pLog->dwNextRecordIdToWrite - 1),
|
||
|
lMinutesToUTC,pTimeZone,
|
||
|
pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
|
||
|
pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
|
||
|
pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
|
||
|
pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
|
||
|
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
rcBCP = bcp_done(pLog->hdbcSQL);
|
||
|
if (pLog->lpMappedFileBase != NULL) {
|
||
|
G_FREE(pLog->lpMappedFileBase);
|
||
|
pLog->lpMappedFileBase = NULL;
|
||
|
}
|
||
|
|
||
|
if (pLog->pPerfmonInfo != NULL) {
|
||
|
PdhiFreeLogMachineTable(
|
||
|
(PPDHI_LOG_MACHINE *) (& (pLog->pPerfmonInfo)));
|
||
|
pLog->pPerfmonInfo = NULL;
|
||
|
}
|
||
|
pLog->dwRecord1Size = 0;
|
||
|
}// end of extra processing when closing a sql dataset open for writing
|
||
|
|
||
|
else if (pLog->pPerfmonInfo != NULL) {
|
||
|
PPDHI_SQL_LOG_INFO pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
|
||
|
|
||
|
PdhiFreeLogMachineTable((PPDHI_LOG_MACHINE *) (& pLogInfo->MachineList));
|
||
|
//PdhiFreeSqlCounterDataNode(pLogInfo->LogData, 0);
|
||
|
G_FREE(pLog->pPerfmonInfo);
|
||
|
pLog->pPerfmonInfo = NULL;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
// clean up the headers for the enumerations of counters
|
||
|
if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
if (pLog->hdbcSQL) {
|
||
|
SQLDisconnect(pLog->hdbcSQL);
|
||
|
SQLFreeHandle(SQL_HANDLE_DBC, pLog->hdbcSQL);
|
||
|
}
|
||
|
if (pLog->henvSQL) SQLFreeHandle(SQL_HANDLE_ENV, pLog->henvSQL);
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhpWriteSQLCounters(
|
||
|
IN PPDHI_LOG pLog
|
||
|
)
|
||
|
// write the CounterTable entries that are new.
|
||
|
// An entry might already exist for a counter from a previous run
|
||
|
// so the first step is to read a counter (server+object+instance name)
|
||
|
// and see if it exists - if so - just record the counterid in the
|
||
|
// PDHI_LOG structure under pLog->pQuery->pCounterListHead in the
|
||
|
// PDHI_COUNTER. If the counter doesn't exist - create it in SQL and
|
||
|
// record the counterid in the PDHI_LOG structure under
|
||
|
// pLog->pQuery->pCounterListHead in the PDHI_COUNTER.
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
PPDHI_COUNTER pCtrEntry;
|
||
|
|
||
|
if(NULL == pLog->pQuery) return ERROR_SUCCESS; // no counters to process
|
||
|
|
||
|
pCtrEntry = pLog->pQuery->pCounterListHead;
|
||
|
|
||
|
if (NULL != pCtrEntry)
|
||
|
do {
|
||
|
PPDHI_LOG_COUNTER pSqlCounter = NULL;
|
||
|
pdhStatus = PdhiSqlBuildCounterObjectNode(
|
||
|
pLog,
|
||
|
pCtrEntry->pCounterPath->szMachineName,
|
||
|
pCtrEntry->pCounterPath->szObjectName);
|
||
|
if (pdhStatus != ERROR_SUCCESS) return pdhStatus;
|
||
|
|
||
|
if ((pCtrEntry->dwFlags & PDHIC_MULTI_INSTANCE) == 0) {
|
||
|
pSqlCounter = PdhiSqlFindCounter(
|
||
|
pLog,
|
||
|
(PPDHI_LOG_MACHINE *) (& (pLog->pPerfmonInfo)),
|
||
|
pCtrEntry->pCounterPath->szMachineName,
|
||
|
pCtrEntry->pCounterPath->szObjectName,
|
||
|
pCtrEntry->pCounterPath->szCounterName,
|
||
|
pCtrEntry->plCounterInfo.dwCounterType,
|
||
|
pCtrEntry->plCounterInfo.lDefaultScale,
|
||
|
pCtrEntry->pCounterPath->szInstanceName,
|
||
|
pCtrEntry->pCounterPath->dwIndex,
|
||
|
pCtrEntry->pCounterPath->szParentName,
|
||
|
pCtrEntry->plCounterInfo.dwParentObjectId,
|
||
|
pCtrEntry->TimeBase,
|
||
|
TRUE,
|
||
|
TRUE);
|
||
|
if (pSqlCounter != NULL) {
|
||
|
pCtrEntry->pBTreeNode = (LPVOID) pSqlCounter;
|
||
|
pCtrEntry->plCounterInfo.dwSQLCounterId = pSqlCounter->dwCounterID;
|
||
|
if (pSqlCounter->dwCounterType == PERF_DOUBLE_RAW) {
|
||
|
pSqlCounter->dwCounterType = pCtrEntry->plCounterInfo.dwCounterType;
|
||
|
pSqlCounter->TimeBase = pCtrEntry->TimeBase;
|
||
|
pdhStatus = PdhiSQLUpdateCounterDetailTimeBase(pLog,
|
||
|
pCtrEntry->plCounterInfo.dwSQLCounterId,
|
||
|
pCtrEntry->TimeBase,
|
||
|
TRUE);
|
||
|
if (pdhStatus != ERROR_SUCCESS) {
|
||
|
pSqlCounter->dwCounterType = PERF_DOUBLE_RAW;
|
||
|
pSqlCounter->TimeBase = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pCtrEntry = pCtrEntry->next.flink;
|
||
|
} while (pCtrEntry != pLog->pQuery->pCounterListHead); // loop thru pCtrEntry's
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiWriteSQLLogHeader (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN LPCWSTR szUserCaption
|
||
|
)
|
||
|
// there is no 'header record' in the SQL database,
|
||
|
// but we need to write the CounterTable entries that are new.
|
||
|
// use PdhpWriteSQLCounters to do that
|
||
|
// then write the DisplayToID record to identify this logset
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
|
||
|
DBG_UNREFERENCED_PARAMETER (szUserCaption);
|
||
|
|
||
|
pdhStatus = PdhpWriteSQLCounters(pLog);
|
||
|
|
||
|
if (pLog->dwRecord1Size == 0) {
|
||
|
// we also need to write the DisplayToID record at this point
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"insert into DisplayToID values ('%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x',%d,'%ws',0,0,0,0,'')",
|
||
|
pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
|
||
|
pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
|
||
|
pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
|
||
|
pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7],
|
||
|
pLog->iRunidSQL,
|
||
|
pLog->szCommentSQL);
|
||
|
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiWriteOneSQLRecord(
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN PPDHI_COUNTER pCounter,
|
||
|
IN DWORD dwCounterID,
|
||
|
IN PPDH_RAW_COUNTER pThisValue,
|
||
|
IN PPDH_FMT_COUNTERVALUE pFmtValue,
|
||
|
IN SYSTEMTIME * stTimeStamp,
|
||
|
IN LPWSTR szDateTime
|
||
|
)
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
RETCODE rc;
|
||
|
SYSTEMTIME st;
|
||
|
PDH_FMT_COUNTERVALUE pdhValue;
|
||
|
PPDH_SQL_BULK_COPY pBulk = PdhiBindBulkCopyStructure(pLog);
|
||
|
|
||
|
if ( pThisValue->CStatus != ERROR_SUCCESS
|
||
|
|| ( pThisValue->TimeStamp.dwLowDateTime == 0
|
||
|
&& pThisValue->TimeStamp.dwHighDateTime == 0)) {
|
||
|
SystemTimeToFileTime(stTimeStamp, & pThisValue->TimeStamp);
|
||
|
}
|
||
|
PdhpConvertFileTimeToSQLString(& (pThisValue->TimeStamp),
|
||
|
szDateTime);
|
||
|
FileTimeToSystemTime(& (pThisValue->TimeStamp), & st);
|
||
|
|
||
|
if (pBulk == NULL) {
|
||
|
pdhStatus = GetLastError();
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pBulk->dbCounterId = dwCounterID;
|
||
|
pBulk->dbRecordIndex = pLog->dwNextRecordIdToWrite;
|
||
|
pBulk->dbFirstValueA = LODWORD(pThisValue->FirstValue);
|
||
|
pBulk->dbFirstValueB = HIDWORD(pThisValue->FirstValue);
|
||
|
pBulk->dbSecondValueA = LODWORD(pThisValue->SecondValue);
|
||
|
pBulk->dbSecondValueB = HIDWORD(pThisValue->SecondValue);
|
||
|
pBulk->dbMultiCount = (pCounter->plCounterInfo.dwCounterType == PERF_DOUBLE_RAW)
|
||
|
? MULTI_COUNT_DOUBLE_RAW : pThisValue->MultiCount;
|
||
|
|
||
|
sprintf(pBulk->dbDateTime,
|
||
|
"%04d-%02d-%02d %02d:%02d:%02d.%03d",
|
||
|
st.wYear, st.wMonth, st.wDay,
|
||
|
st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
|
||
|
|
||
|
pBulk->dbCounterValue = pFmtValue->doubleValue;
|
||
|
rc = bcp_sendrow(pLog->hdbcSQL);
|
||
|
if (rc == FAIL) {
|
||
|
DebugPrint((1,"bcp_sendrow(\"%ws\",%d,%d,\"%s\")(%d,%d)\n",
|
||
|
pCounter->szFullName,
|
||
|
pBulk->dbCounterId,
|
||
|
pBulk->dbRecordIndex,
|
||
|
pBulk->dbDateTime,
|
||
|
rc,
|
||
|
pBulk->dwRecordCount));
|
||
|
pdhStatus = PDH_SQL_EXEC_DIRECT_FAILED;
|
||
|
}
|
||
|
else {
|
||
|
pBulk->dwRecordCount ++;
|
||
|
if (pBulk->dwRecordCount == PDH_SQL_BULK_COPY_REC) {
|
||
|
DBINT rcBCP = bcp_batch(pLog->hdbcSQL);
|
||
|
if (rcBCP < 0) {
|
||
|
DebugPrint((1,"bcp_batch(%05d,0x%08X,%d,%d)\n",
|
||
|
__LINE__, pLog->hdbcSQL, rcBCP, pBulk->dwRecordCount));
|
||
|
pdhStatus = ReportSQLError(
|
||
|
pLog, SQL_ERROR, NULL, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
}
|
||
|
pBulk->dwRecordCount = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiWriteSQLLogRecord (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN SYSTEMTIME *stTimeStamp,
|
||
|
IN LPCWSTR szUserString
|
||
|
)
|
||
|
// write multiple CounterData rows - one for each counter. use the
|
||
|
// SQLCounterID from PDHI_COUNTER, pLog->pQuery->pCounterListHead to
|
||
|
// get the counterid for this entry.
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
PPDHI_COUNTER pThisCounter;
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
WCHAR szDateTime[30];
|
||
|
DWORD dwReturn;
|
||
|
DWORD dwCounterID;
|
||
|
WCHAR * pTimeZone;
|
||
|
TIME_ZONE_INFORMATION TimeZone;
|
||
|
LONG lMinutesToUTC = 0;
|
||
|
DBINT rcBCP;
|
||
|
PPDH_SQL_BULK_COPY pBulk;
|
||
|
PDH_FMT_COUNTERVALUE PdhValue;
|
||
|
PPDHI_LOG_COUNTER pSqlCounter;
|
||
|
ULONGLONG ThisTimeStamp;
|
||
|
|
||
|
UNREFERENCED_PARAMETER (stTimeStamp);
|
||
|
DBG_UNREFERENCED_PARAMETER (szUserString);
|
||
|
|
||
|
// see if we've written to many records already
|
||
|
if (0 < pLog->llMaxSize) // ok we have a limit
|
||
|
if (pLog->llMaxSize < pLog->dwNextRecordIdToWrite) return PDH_LOG_FILE_TOO_SMALL;
|
||
|
|
||
|
// check each counter in the list of counters for this query and
|
||
|
// write them to the file
|
||
|
|
||
|
pThisCounter = pLog->pQuery ? pLog->pQuery->pCounterListHead : NULL;
|
||
|
|
||
|
if (pThisCounter != NULL) {
|
||
|
// lock the query while we read the data so the values
|
||
|
// written to the log will all be from the same sample
|
||
|
WAIT_FOR_AND_LOCK_MUTEX(pThisCounter->pOwner->hMutex);
|
||
|
do {
|
||
|
if ((pThisCounter->dwFlags & PDHIC_MULTI_INSTANCE) != 0) {
|
||
|
DWORD dwSize;
|
||
|
DWORD dwItem;
|
||
|
|
||
|
if ( pThisCounter->pLastObject != NULL
|
||
|
&& pThisCounter->pLastObject != pThisCounter->pThisObject) {
|
||
|
G_FREE(pThisCounter->pLastObject);
|
||
|
}
|
||
|
pThisCounter->pLastObject = pThisCounter->pThisObject;
|
||
|
pThisCounter->LastValue.MultiCount =
|
||
|
pThisCounter->ThisValue.MultiCount;
|
||
|
|
||
|
pThisCounter->pThisObject = NULL;
|
||
|
pThisCounter->ThisValue.MultiCount = 0;
|
||
|
dwSize = 0;
|
||
|
pdhStatus = PDH_MORE_DATA;
|
||
|
|
||
|
while (pdhStatus == PDH_MORE_DATA) {
|
||
|
pdhStatus = PdhiSqlGetCounterArray(pThisCounter,
|
||
|
& dwSize, & dwItem,
|
||
|
(LPVOID) pThisCounter->pThisObject);
|
||
|
if (pdhStatus == PDH_MORE_DATA) {
|
||
|
LPVOID pTemp = pThisCounter->pThisObject;
|
||
|
|
||
|
if (pTemp != NULL) {
|
||
|
pThisCounter->pThisObject = G_REALLOC(pTemp, dwSize);
|
||
|
if (pThisCounter->pThisObject == NULL) {
|
||
|
G_FREE(pTemp);
|
||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
pThisCounter->pThisObject = G_ALLOC(dwSize);
|
||
|
if (pThisCounter->pThisObject == NULL) {
|
||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (pdhStatus == ERROR_SUCCESS) {
|
||
|
PPDH_RAW_COUNTER pRawValue;
|
||
|
PPDH_FMT_COUNTERVALUE_ITEM_W pFmtValue;
|
||
|
DWORD dwInstanceName;
|
||
|
DWORD dwParentName;
|
||
|
DWORD dwInstanceIndex;
|
||
|
WCHAR szInstanceName[PDH_SQL_STRING_SIZE];
|
||
|
WCHAR szParentName[PDH_SQL_STRING_SIZE];
|
||
|
|
||
|
pThisCounter->ThisValue.MultiCount = dwItem;
|
||
|
pRawValue = (PPDH_RAW_COUNTER) (pThisCounter->pThisObject);
|
||
|
pFmtValue = (PPDH_FMT_COUNTERVALUE_ITEM_W)
|
||
|
( ((LPBYTE) pThisCounter->pThisObject)
|
||
|
+ sizeof(PDH_RAW_COUNTER) * dwItem);
|
||
|
for (dwSize = 0; dwSize < dwItem; dwSize ++) {
|
||
|
dwInstanceName = PDH_SQL_STRING_SIZE;
|
||
|
dwParentName = PDH_SQL_STRING_SIZE;
|
||
|
dwInstanceIndex = 0;
|
||
|
ZeroMemory(szInstanceName, sizeof(szInstanceName));
|
||
|
ZeroMemory(szParentName, sizeof(szParentName));
|
||
|
PdhParseInstanceNameW(pFmtValue->szName,
|
||
|
szInstanceName,
|
||
|
& dwInstanceName,
|
||
|
szParentName,
|
||
|
& dwParentName,
|
||
|
& dwInstanceIndex);
|
||
|
pSqlCounter = PdhiSqlFindCounter(
|
||
|
pLog,
|
||
|
(PPDHI_LOG_MACHINE *) (& (pLog->pPerfmonInfo)),
|
||
|
pThisCounter->pCounterPath->szMachineName,
|
||
|
pThisCounter->pCounterPath->szObjectName,
|
||
|
pThisCounter->pCounterPath->szCounterName,
|
||
|
pThisCounter->plCounterInfo.dwCounterType,
|
||
|
pThisCounter->plCounterInfo.lDefaultScale,
|
||
|
szInstanceName,
|
||
|
dwInstanceIndex,
|
||
|
szParentName,
|
||
|
pThisCounter->plCounterInfo.dwParentObjectId,
|
||
|
pThisCounter->TimeBase,
|
||
|
FALSE,
|
||
|
TRUE);
|
||
|
ThisTimeStamp = MAKELONGLONG(
|
||
|
pRawValue->TimeStamp.dwLowDateTime,
|
||
|
pRawValue->TimeStamp.dwHighDateTime);
|
||
|
if (pSqlCounter != NULL) {
|
||
|
if (pSqlCounter->dwCounterType == PERF_DOUBLE_RAW) {
|
||
|
pSqlCounter->dwCounterType = pThisCounter->plCounterInfo.dwCounterType;
|
||
|
pSqlCounter->TimeBase = pThisCounter->TimeBase;
|
||
|
pdhStatus = PdhiSQLUpdateCounterDetailTimeBase(pLog,
|
||
|
pSqlCounter->dwCounterID,
|
||
|
pThisCounter->TimeBase,
|
||
|
FALSE);
|
||
|
if (pdhStatus != ERROR_SUCCESS) {
|
||
|
pSqlCounter->dwCounterType = PERF_DOUBLE_RAW;
|
||
|
pSqlCounter->TimeBase = 0;
|
||
|
}
|
||
|
}
|
||
|
if (pSqlCounter->TimeStamp < ThisTimeStamp) {
|
||
|
dwCounterID = pSqlCounter->dwCounterID;
|
||
|
pSqlCounter->TimeStamp = ThisTimeStamp;
|
||
|
if (dwCounterID == 0) {
|
||
|
DebugPrint((1,"bcp_sendrow-1(\"%ws\",\"%ws\",%d,\"%ws\")\n",
|
||
|
pThisCounter->pCounterPath->szCounterName,
|
||
|
szInstanceName,
|
||
|
dwInstanceIndex,
|
||
|
szParentName));
|
||
|
}
|
||
|
pdhStatus = PdhiWriteOneSQLRecord(
|
||
|
pLog,
|
||
|
pThisCounter,
|
||
|
dwCounterID,
|
||
|
pRawValue,
|
||
|
& (pFmtValue->FmtValue),
|
||
|
stTimeStamp,
|
||
|
szDateTime);
|
||
|
}
|
||
|
}
|
||
|
pRawValue = (PPDH_RAW_COUNTER)
|
||
|
( ((LPBYTE) pRawValue)
|
||
|
+ sizeof(PDH_RAW_COUNTER));
|
||
|
pFmtValue = (PPDH_FMT_COUNTERVALUE_ITEM_W)
|
||
|
( ((LPBYTE) pFmtValue)
|
||
|
+ sizeof(PDH_FMT_COUNTERVALUE_ITEM_W));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
pSqlCounter = (PPDHI_LOG_COUNTER) pThisCounter->pBTreeNode;
|
||
|
ThisTimeStamp = MAKELONGLONG(
|
||
|
pThisCounter->ThisValue.TimeStamp.dwLowDateTime,
|
||
|
pThisCounter->ThisValue.TimeStamp.dwHighDateTime);
|
||
|
if (pSqlCounter != NULL) {
|
||
|
if (pSqlCounter->TimeStamp < ThisTimeStamp) {
|
||
|
dwCounterID = pThisCounter->plCounterInfo.dwSQLCounterId;
|
||
|
pSqlCounter->TimeStamp = ThisTimeStamp;
|
||
|
pdhStatus = PdhiComputeFormattedValue(
|
||
|
pThisCounter->CalcFunc,
|
||
|
pThisCounter->plCounterInfo.dwCounterType,
|
||
|
pThisCounter->lScale,
|
||
|
PDH_FMT_DOUBLE | PDH_FMT_NOCAP100,
|
||
|
& (pThisCounter->ThisValue),
|
||
|
& (pThisCounter->LastValue),
|
||
|
& (pThisCounter->TimeBase),
|
||
|
0L,
|
||
|
& PdhValue);
|
||
|
if ( (pdhStatus != ERROR_SUCCESS)
|
||
|
|| ( (PdhValue.CStatus != PDH_CSTATUS_VALID_DATA)
|
||
|
&& (PdhValue.CStatus != PDH_CSTATUS_NEW_DATA))) {
|
||
|
PdhValue.doubleValue = 0.0;
|
||
|
}
|
||
|
if (dwCounterID == 0) {
|
||
|
DebugPrint((1,"bcp_sendrow-2(\"%ws\",\"%ws\",%d,\"%ws\")\n",
|
||
|
pThisCounter->pCounterPath->szCounterName,
|
||
|
pThisCounter->pCounterPath->szInstanceName,
|
||
|
pThisCounter->pCounterPath->dwIndex,
|
||
|
pThisCounter->pCounterPath->szParentName));
|
||
|
}
|
||
|
pdhStatus = PdhiWriteOneSQLRecord(
|
||
|
pLog,
|
||
|
pThisCounter,
|
||
|
dwCounterID,
|
||
|
& (pThisCounter->ThisValue),
|
||
|
& PdhValue,
|
||
|
stTimeStamp,
|
||
|
szDateTime);
|
||
|
}
|
||
|
#if DBG
|
||
|
else {
|
||
|
DebugPrint((1,"DuplicateCounter-2(\"%ws\",%d,%I64d)\n",
|
||
|
pThisCounter->szFullName,
|
||
|
pThisCounter->plCounterInfo.dwSQLCounterId,
|
||
|
ThisTimeStamp));
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
#if DBG
|
||
|
else {
|
||
|
DebugPrint((1,"NullCounter-2(\"%ws\",%I64d)\n",
|
||
|
pThisCounter->szFullName,
|
||
|
ThisTimeStamp));
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
pThisCounter = pThisCounter->next.flink; // go to next in list
|
||
|
} while (pThisCounter != pLog->pQuery->pCounterListHead);
|
||
|
// free (i.e. unlock) the query
|
||
|
|
||
|
rcBCP = bcp_batch(pLog->hdbcSQL);
|
||
|
if (rcBCP < 0) {
|
||
|
pBulk = (PPDH_SQL_BULK_COPY) pLog->lpMappedFileBase;
|
||
|
if (pBulk != NULL) {
|
||
|
DebugPrint((1,"bcp_batch(%05d,0x%08X,%d,0x%08X,%d)\n",
|
||
|
__LINE__, pLog->hdbcSQL, rcBCP,
|
||
|
pBulk, pBulk->dwRecordCount));
|
||
|
pBulk->dwRecordCount = 0;
|
||
|
}
|
||
|
return ReportSQLError(pLog, SQL_ERROR, NULL, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
}
|
||
|
|
||
|
RELEASE_MUTEX(pThisCounter->pOwner->hMutex);
|
||
|
pLog->dwNextRecordIdToWrite++;
|
||
|
}
|
||
|
|
||
|
// if this is the first record then save the start time in DisplayToID
|
||
|
// we also need to write the DisplayToID record at this point (we just incremented
|
||
|
// so check for 2)
|
||
|
|
||
|
if (2 == pLog->dwNextRecordIdToWrite)
|
||
|
{
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
}
|
||
|
else {
|
||
|
// szDateTime should have the correct date & time in it from above.
|
||
|
// get MinutesToUTC
|
||
|
//
|
||
|
dwReturn = GetTimeZoneInformation(&TimeZone);
|
||
|
|
||
|
if (dwReturn != TIME_ZONE_ID_INVALID)
|
||
|
{
|
||
|
if (dwReturn == TIME_ZONE_ID_DAYLIGHT)
|
||
|
{
|
||
|
pTimeZone = TimeZone.DaylightName;
|
||
|
lMinutesToUTC = TimeZone.Bias + TimeZone.DaylightBias;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pTimeZone = TimeZone.StandardName;
|
||
|
lMinutesToUTC = TimeZone.Bias + TimeZone.StandardBias;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"update DisplayToID set LogStartTime = '%ws', MinutesToUTC = %d, TimeZoneName = '%ws' where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x'",
|
||
|
szDateTime, lMinutesToUTC,pTimeZone,
|
||
|
pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
|
||
|
pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
|
||
|
pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
|
||
|
pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
|
||
|
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
}
|
||
|
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pdhStatus == ERROR_SUCCESS)
|
||
|
{
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
}
|
||
|
else {
|
||
|
swprintf(szSQLStmt,
|
||
|
L"update DisplayToID set LogStopTime = '%ws', NumberOfRecords = %d where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x'",
|
||
|
szDateTime,
|
||
|
(pLog->dwNextRecordIdToWrite - 1),
|
||
|
pLog->guidSQL.Data1,
|
||
|
pLog->guidSQL.Data2,
|
||
|
pLog->guidSQL.Data3,
|
||
|
pLog->guidSQL.Data4[0],
|
||
|
pLog->guidSQL.Data4[1],
|
||
|
pLog->guidSQL.Data4[2],
|
||
|
pLog->guidSQL.Data4[3],
|
||
|
pLog->guidSQL.Data4[4],
|
||
|
pLog->guidSQL.Data4[5],
|
||
|
pLog->guidSQL.Data4[6],
|
||
|
pLog->guidSQL.Data4[7]);
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
}
|
||
|
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiEnumMachinesFromSQLLog (
|
||
|
PPDHI_LOG pLog,
|
||
|
LPVOID pBuffer,
|
||
|
LPDWORD lpdwBufferSize,
|
||
|
BOOL bUnicodeDest
|
||
|
)
|
||
|
// Use the results of the function PdhpGetSQLLogHeader to build the list
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
DWORD dwBufferUsed = 0;
|
||
|
DWORD dwNewBuffer = 0;
|
||
|
DWORD dwItemCount = 0;
|
||
|
LPVOID LocalBuffer = NULL;
|
||
|
LPVOID TempBuffer = NULL;
|
||
|
DWORD LocalBufferSize = 0;
|
||
|
PPDHI_LOG_MACHINE pMachine;
|
||
|
PPDHI_SQL_LOG_INFO pLogInfo = NULL;
|
||
|
|
||
|
pdhStatus = PdhpGetSQLLogHeader(pLog);
|
||
|
if (pdhStatus == ERROR_SUCCESS) {
|
||
|
pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
|
||
|
if (pLogInfo == NULL) {
|
||
|
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
|
||
|
}
|
||
|
}
|
||
|
if (pdhStatus != ERROR_SUCCESS) goto Cleanup;
|
||
|
|
||
|
LocalBufferSize = MEDIUM_BUFFER_SIZE;
|
||
|
LocalBuffer = G_ALLOC(LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
||
|
if (LocalBuffer == NULL) {
|
||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwItemCount = 0;
|
||
|
dwBufferUsed = 0;
|
||
|
dwItemCount = 0;
|
||
|
for (pMachine = pLogInfo->MachineList; pMachine != NULL; pMachine = pMachine->next) {
|
||
|
if (pMachine->szMachine != NULL) {
|
||
|
dwNewBuffer = (lstrlenW(pMachine->szMachine) + 1);
|
||
|
while (LocalBufferSize < (dwBufferUsed + dwNewBuffer)) {
|
||
|
TempBuffer = LocalBuffer;
|
||
|
LocalBufferSize += MEDIUM_BUFFER_SIZE;
|
||
|
LocalBuffer = G_REALLOC(TempBuffer, LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
||
|
if (LocalBuffer == NULL) {
|
||
|
if (TempBuffer != NULL) G_FREE(TempBuffer);
|
||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
}
|
||
|
dwNewBuffer = AddUniqueWideStringToMultiSz((LPVOID) LocalBuffer, pMachine->szMachine, bUnicodeDest);
|
||
|
}
|
||
|
else {
|
||
|
dwNewBuffer = 0;
|
||
|
}
|
||
|
if (dwNewBuffer > 0) {
|
||
|
dwBufferUsed = dwNewBuffer;
|
||
|
dwItemCount ++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pdhStatus == ERROR_SUCCESS) {
|
||
|
if (dwItemCount > 0) {
|
||
|
dwBufferUsed ++;
|
||
|
}
|
||
|
if (pBuffer && (dwBufferUsed <= * lpdwBufferSize)) {
|
||
|
RtlCopyMemory(pBuffer, LocalBuffer, dwBufferUsed * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
||
|
}
|
||
|
else {
|
||
|
if (pBuffer != NULL) {
|
||
|
RtlCopyMemory(pBuffer, LocalBuffer, (* lpdwBufferSize) * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
||
|
}
|
||
|
pdhStatus = PDH_MORE_DATA;
|
||
|
}
|
||
|
* lpdwBufferSize = dwBufferUsed;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
if (LocalBuffer != NULL) G_FREE(LocalBuffer);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiEnumObjectsFromSQLLog (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN LPCWSTR szMachineName,
|
||
|
IN LPVOID pBuffer,
|
||
|
IN LPDWORD lpdwBufferSize,
|
||
|
IN DWORD dwDetailLevel,
|
||
|
IN BOOL bUnicodeDest
|
||
|
)
|
||
|
// Use the results of the function PdhpGetSQLLogHeader to build the lists
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
DWORD dwBufferUsed = 0;
|
||
|
DWORD dwNewBuffer = 0;
|
||
|
DWORD dwItemCount = 0;
|
||
|
LPVOID LocalBuffer = NULL;
|
||
|
LPVOID TempBuffer = NULL;
|
||
|
DWORD LocalBufferSize = 0;
|
||
|
PPDHI_LOG_MACHINE pMachine = NULL;
|
||
|
PPDHI_LOG_OBJECT pObject = NULL;
|
||
|
LPWSTR szLocMachine = (LPWSTR) szMachineName;
|
||
|
PPDHI_SQL_LOG_INFO pLogInfo = NULL;
|
||
|
|
||
|
UNREFERENCED_PARAMETER(dwDetailLevel);
|
||
|
pdhStatus = PdhpGetSQLLogHeader(pLog);
|
||
|
if (pdhStatus == ERROR_SUCCESS) {
|
||
|
pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
|
||
|
if (pLogInfo == NULL) {
|
||
|
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
|
||
|
}
|
||
|
}
|
||
|
if (pdhStatus != ERROR_SUCCESS) goto Cleanup;
|
||
|
|
||
|
LocalBufferSize = MEDIUM_BUFFER_SIZE;
|
||
|
LocalBuffer = G_ALLOC(LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
||
|
if (LocalBuffer == NULL) {
|
||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
if (szLocMachine == NULL) szLocMachine = (LPWSTR) szStaticLocalMachineName;
|
||
|
|
||
|
dwBufferUsed = 0;
|
||
|
dwNewBuffer = 0;
|
||
|
dwItemCount = 0;
|
||
|
|
||
|
for (pMachine = pLogInfo->MachineList; pMachine != NULL; pMachine = pMachine->next) {
|
||
|
if (lstrcmpiW(pMachine->szMachine, szLocMachine) == 0) break;
|
||
|
}
|
||
|
|
||
|
if (pMachine != NULL) {
|
||
|
for (pObject = pMachine->ObjList; pObject != NULL; pObject = pObject->next) {
|
||
|
if (pObject->szObject != NULL) {
|
||
|
dwNewBuffer = (lstrlenW(pObject->szObject) + 1);
|
||
|
while (LocalBufferSize < (dwBufferUsed + dwNewBuffer)) {
|
||
|
LocalBufferSize += MEDIUM_BUFFER_SIZE;
|
||
|
TempBuffer = LocalBuffer;
|
||
|
LocalBuffer = G_REALLOC(TempBuffer,
|
||
|
LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
||
|
if (LocalBuffer == NULL) {
|
||
|
if (TempBuffer != NULL) G_FREE(TempBuffer);
|
||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
}
|
||
|
dwNewBuffer = AddUniqueWideStringToMultiSz((LPVOID) LocalBuffer, pObject->szObject, bUnicodeDest);
|
||
|
}
|
||
|
else {
|
||
|
dwNewBuffer = 0;
|
||
|
}
|
||
|
if (dwNewBuffer > 0) {
|
||
|
dwBufferUsed = dwNewBuffer;
|
||
|
dwItemCount ++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
pdhStatus = PDH_CSTATUS_NO_MACHINE;
|
||
|
}
|
||
|
|
||
|
if (pdhStatus == ERROR_SUCCESS) {
|
||
|
if (dwItemCount > 0) {
|
||
|
dwBufferUsed ++;
|
||
|
}
|
||
|
if (dwBufferUsed > 0) {
|
||
|
if (pBuffer && (dwBufferUsed <= * lpdwBufferSize)) {
|
||
|
RtlCopyMemory(pBuffer, LocalBuffer, dwBufferUsed * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
||
|
}
|
||
|
else {
|
||
|
if (pBuffer) RtlCopyMemory(pBuffer,
|
||
|
LocalBuffer,
|
||
|
(* lpdwBufferSize) * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
||
|
pdhStatus = PDH_MORE_DATA;
|
||
|
}
|
||
|
}
|
||
|
* lpdwBufferSize = dwBufferUsed;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
G_FREE(LocalBuffer);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiEnumObjectItemsFromSQLLog (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN LPCWSTR szMachineName,
|
||
|
IN LPCWSTR szObjectName,
|
||
|
IN PDHI_COUNTER_TABLE CounterTable,
|
||
|
IN DWORD dwDetailLevel,
|
||
|
IN DWORD dwFlags
|
||
|
)
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
PPDHI_SQL_LOG_INFO pLogInfo = NULL;
|
||
|
DWORD dwItemCount = 0;
|
||
|
LPWSTR szFullInstance = NULL;
|
||
|
DWORD dwFullInstance = SMALL_BUFFER_SIZE;
|
||
|
LPWSTR szLocMachine = (LPWSTR) szMachineName;
|
||
|
PPDHI_INSTANCE pInstance;
|
||
|
PPDHI_INST_LIST pInstList;
|
||
|
PPDHI_LOG_MACHINE pMachine = NULL;
|
||
|
PPDHI_LOG_OBJECT pObject = NULL;
|
||
|
PPDHI_LOG_COUNTER pCounter = NULL;
|
||
|
|
||
|
UNREFERENCED_PARAMETER(dwDetailLevel);
|
||
|
UNREFERENCED_PARAMETER(dwFlags);
|
||
|
|
||
|
pdhStatus = PdhpGetSQLLogHeader(pLog);
|
||
|
if (pdhStatus == ERROR_SUCCESS) {
|
||
|
pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
|
||
|
if (pLogInfo == NULL) {
|
||
|
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
|
||
|
}
|
||
|
}
|
||
|
if (pdhStatus != ERROR_SUCCESS) goto Cleanup;
|
||
|
|
||
|
if (szLocMachine == NULL) szLocMachine = (LPWSTR) szStaticLocalMachineName;
|
||
|
|
||
|
for (pMachine = pLogInfo->MachineList; pMachine != NULL; pMachine = pMachine->next) {
|
||
|
if (lstrcmpiW(pMachine->szMachine, szLocMachine) == 0) break;
|
||
|
}
|
||
|
|
||
|
if (pMachine != NULL) {
|
||
|
pObject = PdhiFindLogObject(pMachine, & (pMachine->ObjTable), (LPWSTR) szObjectName, FALSE);
|
||
|
}
|
||
|
else {
|
||
|
pdhStatus = PDH_CSTATUS_NO_MACHINE;
|
||
|
pObject = NULL;
|
||
|
}
|
||
|
|
||
|
if (pObject != NULL) {
|
||
|
WCHAR szIndexNumber[20];
|
||
|
|
||
|
szFullInstance = G_ALLOC(dwFullInstance * sizeof(WCHAR));
|
||
|
if (szFullInstance == NULL) {
|
||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
for (pCounter = pObject->CtrList; pCounter != NULL; pCounter = pCounter->next) {
|
||
|
pdhStatus = PdhiFindCounterInstList(CounterTable, pCounter->szCounter, & pInstList);
|
||
|
if (pdhStatus != ERROR_SUCCESS) continue;
|
||
|
|
||
|
if (pCounter->szInstance != NULL && pCounter->szInstance[0] != L'\0') {
|
||
|
if (pCounter->szParent != NULL && pCounter->szParent[0] != L'\0') {
|
||
|
swprintf(szFullInstance, L"%ws%ws%ws", pCounter->szParent, L"/", pCounter->szInstance);
|
||
|
}
|
||
|
else {
|
||
|
lstrcpynW(szFullInstance, pCounter->szInstance, dwFullInstance);
|
||
|
}
|
||
|
if (pCounter->dwInstance > 0) {
|
||
|
ZeroMemory(szIndexNumber, 20 * sizeof(WCHAR));
|
||
|
_ultow(pCounter->dwInstance, szIndexNumber, 10);
|
||
|
lstrcatW(szFullInstance, L"#");
|
||
|
lstrcatW(szFullInstance, szIndexNumber);
|
||
|
}
|
||
|
pdhStatus = PdhiFindInstance(& pInstList->InstList, szFullInstance, TRUE, & pInstance);
|
||
|
}
|
||
|
|
||
|
if (pdhStatus == ERROR_SUCCESS) {
|
||
|
dwItemCount ++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (pdhStatus == ERROR_SUCCESS) {
|
||
|
pdhStatus = PDH_CSTATUS_NO_OBJECT;
|
||
|
}
|
||
|
if (dwItemCount > 0) {
|
||
|
// then the routine was successful. Errors that occurred
|
||
|
// while scanning will be ignored as long as at least
|
||
|
// one entry was successfully read
|
||
|
|
||
|
pdhStatus = ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
G_FREE(szFullInstance);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiGetMatchingSQLLogRecord (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN LONGLONG *pStartTime,
|
||
|
IN LPDWORD pdwIndex
|
||
|
)
|
||
|
// find the counter detail rows with the correct start time & GUID,
|
||
|
// and return the record index
|
||
|
// and build the result
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
DWORD dwCounterId;
|
||
|
DWORD dwRecordIndex;
|
||
|
WCHAR szCounterDateTime[TIME_FIELD_BUFF_SIZE];
|
||
|
LONGLONG locStartTime = (* pStartTime) - 10;
|
||
|
LARGE_INTEGER i64FirstValue, i64SecondValue;
|
||
|
DWORD dwMultiCount;
|
||
|
WCHAR szStartDate[30];
|
||
|
|
||
|
PdhpConvertFileTimeToSQLString((LPFILETIME) (& locStartTime), szStartDate);
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"select CounterID, RecordIndex, CounterDateTime, FirstValueA, FirstValueB, SecondValueA, SecondValueB, MultiCount from CounterData where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x' and CounterDateTime >= '%ws'",
|
||
|
pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
|
||
|
pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
|
||
|
pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
|
||
|
pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7], szStartDate);
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// bind the columns
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_LONG, &dwCounterId, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 2, SQL_C_LONG, &dwRecordIndex, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 3, SQL_C_WCHAR, szCounterDateTime, sizeof(szCounterDateTime), NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 4, SQL_C_LONG, &i64FirstValue.LowPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 5, SQL_C_LONG, &i64FirstValue.HighPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 6, SQL_C_LONG, &i64SecondValue.LowPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 7, SQL_C_LONG, &i64SecondValue.HighPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 8, SQL_C_LONG, &dwMultiCount, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// execute the select statement
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
|
||
|
rc = SQLFetch(hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_FETCH_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
if (SQL_NO_DATA == rc)
|
||
|
{
|
||
|
pdhStatus = PDH_NO_DATA;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pLog->dwLastRecordRead = dwRecordIndex;
|
||
|
*pdwIndex = dwRecordIndex;
|
||
|
|
||
|
Cleanup:
|
||
|
if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiGetCounterValueFromSQLLog (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN DWORD dwIndex,
|
||
|
IN PPDHI_COUNTER pCounter,
|
||
|
IN PPDH_RAW_COUNTER pValue
|
||
|
)
|
||
|
// looks like this read one counter from the record line
|
||
|
// SQL can do this with a select
|
||
|
// It turns out the caller of this routine is looping thru
|
||
|
// pLog->pQuery->pCounterListHead and getting the pPath from PDHI_COUNTER
|
||
|
// then use the dwIndex as a recordid to get the pPath structure, so we can use the
|
||
|
// SQLCounterID from pPath directly and then use the dwIndex as a recordid.
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
DWORD dwMultiCount;
|
||
|
WCHAR szCounterDateTime[TIME_FIELD_BUFF_SIZE];
|
||
|
FILETIME ftCounterDateTime;
|
||
|
LARGE_INTEGER i64FirstValue, i64SecondValue;
|
||
|
DOUBLE dCounterValue;
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"select FirstValueA, FirstValueB, SecondValueA, SecondValueB, MultiCount, CounterDateTime, CounterValue from CounterData where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x' and CounterID = %d and RecordIndex = %d",
|
||
|
pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
|
||
|
pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
|
||
|
pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
|
||
|
pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7], pCounter->plCounterInfo.dwSQLCounterId,dwIndex);
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// bind the columns
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_LONG, &i64FirstValue.LowPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 2, SQL_C_LONG, &i64FirstValue.HighPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 3, SQL_C_LONG, &i64SecondValue.LowPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 4, SQL_C_LONG, &i64SecondValue.HighPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 5, SQL_C_LONG, &dwMultiCount, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 6, SQL_C_WCHAR, szCounterDateTime, sizeof(szCounterDateTime), NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 7, SQL_C_DOUBLE, &dCounterValue, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// execute the select statement
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLFetch(hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_FETCH_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
if (SQL_NO_DATA == rc)
|
||
|
{
|
||
|
pdhStatus = PDH_NO_MORE_DATA;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// build a raw counter on pValue
|
||
|
pValue->CStatus = PDH_CSTATUS_VALID_DATA;
|
||
|
PdhpConvertSQLStringToFileTime(szCounterDateTime,&ftCounterDateTime);
|
||
|
pValue->TimeStamp = ftCounterDateTime;
|
||
|
|
||
|
if (dwMultiCount == MULTI_COUNT_DOUBLE_RAW) {
|
||
|
pCounter->plCounterInfo.dwCounterType = PERF_DOUBLE_RAW;
|
||
|
pValue->FirstValue = i64FirstValue.QuadPart;
|
||
|
pValue->MultiCount = 1;
|
||
|
pValue->SecondValue = i64SecondValue.QuadPart;
|
||
|
}
|
||
|
else if (pCounter->plCounterInfo.dwCounterType == PERF_DOUBLE_RAW) {
|
||
|
(double) pValue->FirstValue = dCounterValue;
|
||
|
pValue->SecondValue = 0;
|
||
|
pValue->MultiCount = 1;
|
||
|
}
|
||
|
else {
|
||
|
pValue->FirstValue = i64FirstValue.QuadPart;
|
||
|
pValue->MultiCount = dwMultiCount;
|
||
|
pValue->SecondValue = i64SecondValue.QuadPart;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiGetTimeRangeFromSQLLog (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN LPDWORD pdwNumEntries,
|
||
|
IN PPDH_TIME_INFO pInfo,
|
||
|
IN LPDWORD pdwBufferSize
|
||
|
)
|
||
|
// The function PdhpGetSQLLogHeader or another routine that does
|
||
|
// something similar and saves the time range - which will
|
||
|
// do this, and save the results for subsequent calls - also
|
||
|
// gets the time range for a particular GUID. SQL will never
|
||
|
// have multiple's per DB as it assigns a new GUID for each run.
|
||
|
|
||
|
/*++
|
||
|
the first entry in the buffer returned is the total time range covered
|
||
|
in the file, if there are multiple time blocks in the log file, then
|
||
|
subsequent entries will identify each segment in the file.
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
LONGLONG llStartTime = MAX_TIME_VALUE;
|
||
|
LONGLONG llEndTime = MIN_TIME_VALUE;
|
||
|
SQLLEN dwStartTimeStat;
|
||
|
SQLLEN dwEndTimeStat;
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
WCHAR szStartTime[TIME_FIELD_BUFF_SIZE];
|
||
|
WCHAR szEndTime[TIME_FIELD_BUFF_SIZE];
|
||
|
DWORD dwNumberOfRecords;
|
||
|
SQLLEN dwNumRecStat;
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"select LogStartTime, LogStopTime, NumberOfRecords from DisplayToID where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x'",
|
||
|
pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
|
||
|
pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
|
||
|
pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
|
||
|
pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// bind the date columns column
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_WCHAR, szStartTime, sizeof(szStartTime), &dwStartTimeStat);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 2, SQL_C_WCHAR, szEndTime, sizeof(szEndTime), &dwEndTimeStat);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 3, SQL_C_LONG, &dwNumberOfRecords, 0, &dwNumRecStat);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// execute the select statement
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
rc = SQLFetch(hstmt);
|
||
|
if (SQL_NO_DATA == rc)
|
||
|
{
|
||
|
pdhStatus = PDH_NO_DATA;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// if anything is missing - could try and re-create from existing log file
|
||
|
if ((SQL_NULL_DATA == dwStartTimeStat) ||
|
||
|
(SQL_NULL_DATA == dwEndTimeStat) ||
|
||
|
(SQL_NULL_DATA == dwNumRecStat))
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_DATA;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// convert the dates
|
||
|
PdhpConvertSQLStringToFileTime (szStartTime,(LPFILETIME)&llStartTime);
|
||
|
PdhpConvertSQLStringToFileTime (szEndTime,(LPFILETIME)&llEndTime);
|
||
|
|
||
|
// we have the info so update the args.
|
||
|
if (*pdwBufferSize >= sizeof(PDH_TIME_INFO))
|
||
|
{
|
||
|
*(LONGLONG *)(&pInfo->StartTime) = llStartTime;
|
||
|
*(LONGLONG *)(&pInfo->EndTime) = llEndTime;
|
||
|
pInfo->SampleCount = dwNumberOfRecords;
|
||
|
*pdwBufferSize = sizeof(PDH_TIME_INFO);
|
||
|
*pdwNumEntries = 1;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiReadRawSQLLogRecord (
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN FILETIME *ftRecord,
|
||
|
IN PPDH_RAW_LOG_RECORD pBuffer,
|
||
|
IN LPDWORD pdwBufferLength
|
||
|
)
|
||
|
// requirement to connect counter/instance names makes this difficult - not needed anyway
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER (pLog);
|
||
|
UNREFERENCED_PARAMETER (ftRecord);
|
||
|
UNREFERENCED_PARAMETER (pBuffer);
|
||
|
UNREFERENCED_PARAMETER (pdwBufferLength);
|
||
|
|
||
|
return PDH_NOT_IMPLEMENTED;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhpGetSQLLogHeader(
|
||
|
PPDHI_LOG pLog
|
||
|
)
|
||
|
{
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
PPDHI_SQL_LOG_INFO pLogInfo;
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
LPWSTR szSQLStmt = NULL;
|
||
|
LPWSTR szMachineNamel = NULL;
|
||
|
LPWSTR szObjectNamel = NULL;
|
||
|
LPWSTR szCounterNamel = NULL;
|
||
|
LPWSTR szInstanceNamel = NULL;
|
||
|
LPWSTR szParentNamel = NULL;
|
||
|
DWORD dwInstanceIndexl;
|
||
|
DWORD dwParentObjIdl;
|
||
|
DWORD dwSQLCounterIdl;
|
||
|
DWORD dwCounterTypel;
|
||
|
LARGE_INTEGER lTimeBase;
|
||
|
LONG lDefaultScalel;
|
||
|
SQLLEN dwMachineNameLen;
|
||
|
SQLLEN dwObjectNameLen;
|
||
|
SQLLEN dwCounterNameLen;
|
||
|
SQLLEN dwInstanceNameLen;
|
||
|
SQLLEN dwParentNameLen;
|
||
|
SQLLEN dwInstanceIndexStat;
|
||
|
SQLLEN dwParentObjIdStat;
|
||
|
SQLLEN dwTimeBaseA;
|
||
|
SQLLEN dwTimeBaseB;
|
||
|
SQLLEN dwSQLCounterId;
|
||
|
|
||
|
if (pLog->pPerfmonInfo != NULL) return ERROR_SUCCESS;
|
||
|
|
||
|
pLogInfo = (PPDHI_SQL_LOG_INFO) G_ALLOC(sizeof(PDHI_SQL_LOG_INFO));
|
||
|
szSQLStmt = (LPWSTR) G_ALLOC((SQLSTMTSIZE + 5 * PDH_SQL_STRING_SIZE) * sizeof(WCHAR));
|
||
|
if (pLogInfo == NULL || szSQLStmt == NULL) {
|
||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pLog->pPerfmonInfo = pLogInfo;
|
||
|
szMachineNamel = szSQLStmt + SQLSTMTSIZE;
|
||
|
szObjectNamel = szMachineNamel + PDH_SQL_STRING_SIZE;
|
||
|
szCounterNamel = szObjectNamel + PDH_SQL_STRING_SIZE;
|
||
|
szInstanceNamel = szCounterNamel + PDH_SQL_STRING_SIZE;
|
||
|
szParentNamel = szInstanceNamel + PDH_SQL_STRING_SIZE;
|
||
|
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
swprintf(szSQLStmt,
|
||
|
L"select distinct MachineName, ObjectName, CounterName, CounterType, DefaultScale, InstanceName, InstanceIndex, ParentName, ParentObjectID, CounterID, TimeBaseA, TimeBaseB from CounterDetails where CounterID in (select distinct CounterID from CounterData where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x') Order by MachineName, ObjectName, CounterName, InstanceName, InstanceIndex ",
|
||
|
pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
|
||
|
pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
|
||
|
pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
|
||
|
pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
|
||
|
|
||
|
// note SQL returns the size in bytes without the terminating character
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_WCHAR, szMachineNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwMachineNameLen);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 2, SQL_C_WCHAR, szObjectNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwObjectNameLen);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 3, SQL_C_WCHAR, szCounterNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwCounterNameLen);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 4, SQL_C_LONG, & dwCounterTypel, 0, NULL);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 5, SQL_C_LONG, & lDefaultScalel, 0, NULL);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
// check for SQL_NULL_DATA on the index's and on Instance Name & Parent Name
|
||
|
rc = SQLBindCol(hstmt, 6, SQL_C_WCHAR, szInstanceNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwInstanceNameLen);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 7, SQL_C_LONG, & dwInstanceIndexl, 0, & dwInstanceIndexStat);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 8, SQL_C_WCHAR, szParentNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwParentNameLen);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 9, SQL_C_LONG, & dwParentObjIdl, 0, & dwParentObjIdStat);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 10, SQL_C_LONG, & dwSQLCounterIdl, 0, & dwSQLCounterId);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 11, SQL_C_LONG, & lTimeBase.LowPart, 0, & dwTimeBaseA);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 12, SQL_C_LONG, & lTimeBase.HighPart, 0, & dwTimeBaseB);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// execute the sql command
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
rc = SQLFetch(hstmt);
|
||
|
while (rc != SQL_NO_DATA) {
|
||
|
PPDHI_LOG_COUNTER pCounter;
|
||
|
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
|
||
|
break;
|
||
|
}
|
||
|
else {
|
||
|
LPWSTR szInstance = (dwInstanceNameLen != SQL_NULL_DATA) ? (szInstanceNamel) : (NULL);
|
||
|
LPWSTR szParent = (dwParentNameLen != SQL_NULL_DATA) ? (szParentNamel) : (NULL);
|
||
|
|
||
|
if (dwInstanceIndexStat == SQL_NULL_DATA) dwInstanceIndexl = 0;
|
||
|
if (dwParentObjIdStat == SQL_NULL_DATA) dwParentObjIdl = 0;
|
||
|
|
||
|
pCounter = PdhiFindLogCounter(pLog,
|
||
|
& pLogInfo->MachineList,
|
||
|
szMachineNamel,
|
||
|
szObjectNamel,
|
||
|
szCounterNamel,
|
||
|
dwCounterTypel,
|
||
|
lDefaultScalel,
|
||
|
szInstance,
|
||
|
dwInstanceIndexl,
|
||
|
szParent,
|
||
|
dwParentObjIdl,
|
||
|
& dwSQLCounterIdl,
|
||
|
TRUE);
|
||
|
if (pCounter == NULL) {
|
||
|
pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_CSTATUS_NO_COUNTER);
|
||
|
break;
|
||
|
}
|
||
|
if (dwTimeBaseA != SQL_NULL_DATA && dwTimeBaseB != SQL_NULL_DATA) {
|
||
|
pCounter->TimeBase = lTimeBase.QuadPart;
|
||
|
}
|
||
|
else {
|
||
|
pCounter->dwCounterType = PERF_DOUBLE_RAW;
|
||
|
pCounter->TimeBase = 0;
|
||
|
pCounter->dwDefaultScale = 0;
|
||
|
}
|
||
|
}
|
||
|
rc = SQLFetch(hstmt);
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
G_FREE(szSQLStmt);
|
||
|
if (pdhStatus != ERROR_SUCCESS) {
|
||
|
G_FREE(pLogInfo);
|
||
|
pLog->pPerfmonInfo = NULL;
|
||
|
}
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiVerifySQLDB (
|
||
|
LPCWSTR szDataSource)
|
||
|
{
|
||
|
// INTERNAL FUNCTION to
|
||
|
// Check that a DSN points to a database that contains the correct Perfmon tables.
|
||
|
// select from the tables and check for an error
|
||
|
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
PDHI_LOG Log; // a fake log structure - just to make opens work ok
|
||
|
|
||
|
WCHAR szMachineNamel[PDH_SQL_STRING_SIZE+1];
|
||
|
WCHAR szObjectNamel[PDH_SQL_STRING_SIZE+1];
|
||
|
WCHAR szCounterNamel[PDH_SQL_STRING_SIZE+1];
|
||
|
WCHAR szInstanceNamel[PDH_SQL_STRING_SIZE+1];
|
||
|
WCHAR szParentNamel[PDH_SQL_STRING_SIZE+1];
|
||
|
|
||
|
SQLLEN dwMachineNameLen;
|
||
|
SQLLEN dwObjectNameLen;
|
||
|
SQLLEN dwCounterNameLen;
|
||
|
SQLLEN dwInstanceNameLen;
|
||
|
SQLLEN dwParentNameLen;
|
||
|
|
||
|
DWORD dwInstanceIndexl;
|
||
|
DWORD dwParentObjIdl;
|
||
|
SQLLEN dwInstanceIndexStat;
|
||
|
SQLLEN dwParentObjIdStat;
|
||
|
|
||
|
DWORD dwSQLCounterIdl;
|
||
|
DWORD dwCounterTypel;
|
||
|
LONG lDefaultScalel;
|
||
|
LONG lMinutesToUTC = 0;
|
||
|
WCHAR szTimeZoneName[32];
|
||
|
SQLLEN dwTimeZoneLen;
|
||
|
|
||
|
|
||
|
DWORD dwNumOfRecs;
|
||
|
double dblCounterValuel;
|
||
|
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
DWORD dwMultiCount;
|
||
|
WCHAR szCounterDateTime[TIME_FIELD_BUFF_SIZE];
|
||
|
|
||
|
LARGE_INTEGER i64FirstValue, i64SecondValue;
|
||
|
|
||
|
ZeroMemory((void *)(&Log), sizeof(PDHI_LOG));
|
||
|
|
||
|
// open the database
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
// obtain the ODBC environment and connection
|
||
|
//
|
||
|
|
||
|
rc = SQLAllocEnv(&Log.henvSQL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_ALLOC_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLAllocConnect(Log.henvSQL, &Log.hdbcSQL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_ALLOCCON_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLSetConnectAttr(Log.hdbcSQL,
|
||
|
SQL_COPT_SS_BCP,
|
||
|
(SQLPOINTER) SQL_BCP_ON,
|
||
|
SQL_IS_INTEGER);
|
||
|
if (! SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_ALLOCCON_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLConnectW(Log.hdbcSQL,
|
||
|
(SQLWCHAR*)szDataSource, SQL_NTS,
|
||
|
NULL, SQL_NULL_DATA, // Use password & user name from DSN
|
||
|
NULL, SQL_NULL_DATA);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_CONNECT_FAILED);
|
||
|
pdhStatus = PDH_INVALID_DATASOURCE;
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
// do a select on the CounterDetails Table
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"select MachineName, ObjectName, CounterName, CounterType, DefaultScale, InstanceName, InstanceIndex, ParentName, ParentObjectID, CounterID from CounterDetails");
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(Log.hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
// note SQL returns the size in bytes without the terminating character
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_WCHAR, szMachineNamel, sizeof(szMachineNamel), &dwMachineNameLen);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 2, SQL_C_WCHAR, szObjectNamel, sizeof(szObjectNamel), &dwObjectNameLen);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 3, SQL_C_WCHAR, szCounterNamel, sizeof(szCounterNamel), &dwCounterNameLen);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 4, SQL_C_LONG, &dwCounterTypel, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 5, SQL_C_LONG, &lDefaultScalel, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 6, SQL_C_WCHAR, szInstanceNamel, sizeof(szInstanceNamel), &dwInstanceNameLen);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 7, SQL_C_LONG, &dwInstanceIndexl, 0, &dwInstanceIndexStat);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 8, SQL_C_WCHAR, szParentNamel, sizeof(szParentNamel), &dwParentNameLen);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 9, SQL_C_LONG, &dwParentObjIdl, 0, &dwParentObjIdStat);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 10, SQL_C_LONG, &dwSQLCounterIdl, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
// execute the sql command
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_SQLDB;
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
// do a select on the DisplayToID Table
|
||
|
|
||
|
swprintf(szSQLStmt,L"select GUID, RunID, DisplayString, LogStartTime, LogStopTime, NumberOfRecords, MinutesToUTC, TimeZoneName from DisplayToID");
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(Log.hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
// bind the column names - reuse local strings as needed
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_GUID, &Log.guidSQL, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 2, SQL_C_LONG, &Log.iRunidSQL, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
// DislayString
|
||
|
rc = SQLBindCol(hstmt, 3, SQL_C_WCHAR, szMachineNamel, sizeof(szMachineNamel), &dwMachineNameLen);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
//LogStartTime
|
||
|
rc = SQLBindCol(hstmt, 4, SQL_C_WCHAR, szObjectNamel, sizeof(szObjectNamel), &dwObjectNameLen);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
//LogStopTime
|
||
|
rc = SQLBindCol(hstmt, 5, SQL_C_WCHAR, szCounterNamel, sizeof(szCounterNamel), &dwCounterNameLen);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 6, SQL_C_LONG, &dwNumOfRecs, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 7, SQL_C_LONG, &lMinutesToUTC, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 8, SQL_C_WCHAR, szTimeZoneName, sizeof(szTimeZoneName), &dwTimeZoneLen);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// execute the sql command
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_SQLDB;
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
hstmt = NULL;
|
||
|
|
||
|
// do a select on the CounterData Table
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"select GUID, CounterID, RecordIndex, CounterDateTime, CounterValue, FirstValueA, FirstValueB, SecondValueA, SecondValueB, MultiCount from CounterData");
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(Log.hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
// bind the columns
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_GUID, &Log.guidSQL, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
rc = SQLBindCol(hstmt, 2, SQL_C_LONG, &dwSQLCounterIdl, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
// record index
|
||
|
rc = SQLBindCol(hstmt, 3, SQL_C_LONG, &dwNumOfRecs, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 4, SQL_C_WCHAR, szCounterDateTime, sizeof(szCounterDateTime), NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 5, SQL_C_DOUBLE, &dblCounterValuel, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 6, SQL_C_LONG, &i64FirstValue.LowPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 7, SQL_C_LONG, &i64FirstValue.HighPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 8, SQL_C_LONG, &i64SecondValue.LowPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 9, SQL_C_LONG, &i64SecondValue.HighPart, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLBindCol(hstmt, 10, SQL_C_LONG, &dwMultiCount, 0, NULL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// execute the select statement
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = E_FAIL; // PDH_INVALID_SQLDB
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
// close the database
|
||
|
|
||
|
CleanupExit: // verify db
|
||
|
if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
if (Log.hdbcSQL) {
|
||
|
SQLDisconnect(Log.hdbcSQL);
|
||
|
SQLFreeHandle(SQL_HANDLE_DBC, Log.hdbcSQL);
|
||
|
}
|
||
|
if (Log.henvSQL) SQLFreeHandle(SQL_HANDLE_ENV, Log.henvSQL);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhVerifySQLDBA (
|
||
|
LPCSTR szDataSource)
|
||
|
{
|
||
|
//Check that a DSN points to a database that contains the correct Perfmon tables.
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
WCHAR wszDataSource[PDH_SQL_STRING_SIZE+1];
|
||
|
DWORD dwLength;
|
||
|
|
||
|
// check args
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
|
||
|
if (szDataSource != NULL)
|
||
|
{
|
||
|
WCHAR TestChar;
|
||
|
// test for read access to the name
|
||
|
TestChar = *szDataSource;
|
||
|
if (TestChar == 0)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
}
|
||
|
else pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
|
||
|
if (ERROR_SUCCESS == pdhStatus)
|
||
|
{
|
||
|
dwLength = lstrlenA(szDataSource);
|
||
|
RtlZeroMemory(wszDataSource, sizeof(wszDataSource));
|
||
|
MultiByteToWideChar(_getmbcp(),
|
||
|
0,
|
||
|
szDataSource,
|
||
|
dwLength,
|
||
|
(LPWSTR) wszDataSource,
|
||
|
PDH_SQL_STRING_SIZE);
|
||
|
pdhStatus = PdhiVerifySQLDB(wszDataSource);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhVerifySQLDBW (
|
||
|
LPCWSTR szDataSource)
|
||
|
{
|
||
|
//Check that a DSN points to a database that contains the correct Perfmon tables.
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
|
||
|
if (szDataSource != NULL)
|
||
|
{
|
||
|
WCHAR TestChar;
|
||
|
// test for read access to the name
|
||
|
TestChar = *szDataSource;
|
||
|
if (TestChar == 0)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
}
|
||
|
else pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
|
||
|
if (ERROR_SUCCESS == pdhStatus)
|
||
|
{
|
||
|
pdhStatus = PdhiVerifySQLDB (szDataSource);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiCreateSQLTables (
|
||
|
LPCWSTR szDataSource)
|
||
|
{
|
||
|
// INTERNAL FUNCTION to
|
||
|
//Create the correct perfmon tables in the database pointed to by a DSN.
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
RETCODE rc;
|
||
|
PDHI_LOG Log; // a fake log structure - just to make opens work ok
|
||
|
|
||
|
ZeroMemory((void *)(&Log), sizeof(PDHI_LOG));
|
||
|
|
||
|
// open the database
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
// obtain the ODBC environment and connection
|
||
|
//
|
||
|
|
||
|
rc = SQLAllocEnv(&Log.henvSQL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_ALLOC_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLAllocConnect(Log.henvSQL, &Log.hdbcSQL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_ALLOCCON_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLSetConnectAttr(Log.hdbcSQL,
|
||
|
SQL_COPT_SS_BCP,
|
||
|
(SQLPOINTER) SQL_BCP_ON,
|
||
|
SQL_IS_INTEGER);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_ALLOCCON_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLConnectW(Log.hdbcSQL,
|
||
|
(SQLWCHAR*)szDataSource, SQL_NTS,
|
||
|
NULL, SQL_NULL_DATA, // Use password & user name from DSN
|
||
|
NULL, SQL_NULL_DATA);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_CONNECT_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
// actually create the tables
|
||
|
pdhStatus = PdhpCreateSQLTables(&Log);
|
||
|
|
||
|
CleanupExit:
|
||
|
if (Log.hdbcSQL) SQLDisconnect(Log.hdbcSQL);
|
||
|
if (Log.hdbcSQL) SQLFreeHandle(SQL_HANDLE_DBC, Log.hdbcSQL);
|
||
|
if (Log.henvSQL) SQLFreeHandle(SQL_HANDLE_ENV, Log.henvSQL);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhCreateSQLTablesA (
|
||
|
LPCSTR szDataSource)
|
||
|
{
|
||
|
//Create the correct perfmon tables in the database pointed to by a DSN.
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
|
||
|
WCHAR wszDataSource[PDH_SQL_STRING_SIZE+1];
|
||
|
DWORD dwLength;
|
||
|
|
||
|
// check args
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
|
||
|
if (szDataSource != NULL)
|
||
|
{
|
||
|
WCHAR TestChar;
|
||
|
// test for read access to the name
|
||
|
TestChar = *szDataSource;
|
||
|
if (TestChar == 0)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
}
|
||
|
else pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
|
||
|
if (ERROR_SUCCESS == pdhStatus)
|
||
|
{
|
||
|
dwLength = lstrlenA(szDataSource);
|
||
|
ZeroMemory(wszDataSource, sizeof(wszDataSource));
|
||
|
MultiByteToWideChar(_getmbcp(),
|
||
|
0,
|
||
|
szDataSource,
|
||
|
dwLength,
|
||
|
(LPWSTR) wszDataSource,
|
||
|
PDH_SQL_STRING_SIZE);
|
||
|
pdhStatus = PdhiCreateSQLTables (wszDataSource);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhCreateSQLTablesW (
|
||
|
LPCWSTR szDataSource)
|
||
|
{
|
||
|
//Create the correct perfmon tables in the database pointed to by a DSN.
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
|
||
|
if (szDataSource != NULL)
|
||
|
{
|
||
|
WCHAR TestChar;
|
||
|
// test for read access to the name
|
||
|
TestChar = *szDataSource;
|
||
|
if (TestChar == 0)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
}
|
||
|
else pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
|
||
|
if (ERROR_SUCCESS == pdhStatus)
|
||
|
{
|
||
|
pdhStatus = PdhiCreateSQLTables (szDataSource);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiEnumLogSetNames (
|
||
|
LPCWSTR szDataSource,
|
||
|
LPVOID mszDataSetNameList,
|
||
|
LPDWORD pcchBufferLength,
|
||
|
BOOL bUnicodeDest)
|
||
|
{
|
||
|
//Return the list of Log set names in the database pointed to by the DSN.
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
PDH_STATUS pdhBuffStatus = ERROR_SUCCESS;
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
PDHI_LOG Log; // a fake log structure - just to make opens work ok
|
||
|
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
WCHAR szDisplayStringl[PDH_SQL_STRING_SIZE+1];
|
||
|
|
||
|
SQLLEN dwDisplayStringLen;
|
||
|
DWORD dwNewBuffer;
|
||
|
DWORD dwListUsed;
|
||
|
DWORD dwAdditionalSpace;
|
||
|
|
||
|
ZeroMemory((void *)(&Log), sizeof(PDHI_LOG));
|
||
|
|
||
|
// open the database
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
// obtain the ODBC environment and connection
|
||
|
//
|
||
|
|
||
|
rc = SQLAllocEnv(&Log.henvSQL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_ALLOC_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
|
||
|
rc = SQLAllocConnect(Log.henvSQL, &Log.hdbcSQL);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_ALLOCCON_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLSetConnectAttr(Log.hdbcSQL,
|
||
|
SQL_COPT_SS_BCP,
|
||
|
(SQLPOINTER) SQL_BCP_ON,
|
||
|
SQL_IS_INTEGER);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_ALLOCCON_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
rc = SQLConnectW(Log.hdbcSQL,
|
||
|
(SQLWCHAR*)szDataSource, SQL_NTS,
|
||
|
NULL, SQL_NULL_DATA, // Use password & user name from DSN
|
||
|
NULL, SQL_NULL_DATA);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,NULL,PDH_SQL_CONNECT_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
// do a select
|
||
|
// loop around in a fetch and
|
||
|
// build the list of names
|
||
|
|
||
|
swprintf(szSQLStmt,L"select DisplayString from DisplayToID");
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(Log.hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
// bind the machine name column
|
||
|
rc = SQLBindCol(hstmt, 1, SQL_C_WCHAR, szDisplayStringl, sizeof(szDisplayStringl), &dwDisplayStringLen);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_BIND_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
// execute the select statement
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
dwListUsed=1 *(bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)); // include the null terminator to start;
|
||
|
dwAdditionalSpace = 0; // used to accumulate additional memory size req. when buffer overflows
|
||
|
|
||
|
// loop around the result set using fetch
|
||
|
while ( (rc = SQLFetch(hstmt)) != SQL_NO_DATA)
|
||
|
{
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_FETCH_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
// Append the DisplayName to the returned list
|
||
|
dwNewBuffer = (lstrlenW (szDisplayStringl) + 1) *
|
||
|
(bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR));
|
||
|
|
||
|
if (0 == *pcchBufferLength)
|
||
|
{
|
||
|
// SQL won't let non unique LogSet names into the database
|
||
|
// so we don't really have to worry about duplicates
|
||
|
dwListUsed += dwNewBuffer;
|
||
|
}
|
||
|
else
|
||
|
{// we actually think we have an extra terminator - so for an exact fit test against one extra in the output buffer
|
||
|
if ((dwListUsed + dwNewBuffer) > *pcchBufferLength * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)))
|
||
|
{
|
||
|
pdhBuffStatus = PDH_MORE_DATA;
|
||
|
dwAdditionalSpace += dwNewBuffer;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// add the display name
|
||
|
dwNewBuffer = PdhpAddUniqueUnicodeStringToMultiSz(
|
||
|
(LPVOID)mszDataSetNameList,
|
||
|
(LPWSTR)szDisplayStringl,
|
||
|
bUnicodeDest);
|
||
|
|
||
|
if (dwNewBuffer != 0) // if it got added returned new length in TCHAR
|
||
|
{
|
||
|
dwListUsed = dwNewBuffer * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // end of while fetch
|
||
|
|
||
|
if (!SQLSUCCEEDED(rc))
|
||
|
{
|
||
|
pdhStatus = ReportSQLError(&Log,rc,hstmt,PDH_SQL_FETCH_FAILED);
|
||
|
goto CleanupExit;
|
||
|
}
|
||
|
|
||
|
if (0 == *pcchBufferLength)
|
||
|
{
|
||
|
pdhBuffStatus = PDH_MORE_DATA;
|
||
|
*pcchBufferLength = (dwListUsed / (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
||
|
}
|
||
|
else if (pdhBuffStatus == PDH_MORE_DATA)
|
||
|
{
|
||
|
*pcchBufferLength = ((dwListUsed + dwAdditionalSpace) / (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pcchBufferLength = (dwListUsed / (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
||
|
}
|
||
|
pdhStatus = pdhBuffStatus;
|
||
|
|
||
|
// close the database
|
||
|
|
||
|
CleanupExit:
|
||
|
if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
if (Log.hdbcSQL) {
|
||
|
SQLDisconnect(Log.hdbcSQL);
|
||
|
SQLFreeHandle(SQL_HANDLE_DBC, Log.hdbcSQL);
|
||
|
}
|
||
|
if (Log.henvSQL) SQLFreeHandle(SQL_HANDLE_ENV, Log.henvSQL);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhEnumLogSetNamesA (
|
||
|
LPCSTR szDataSource,
|
||
|
LPSTR mszDataSetNameList,
|
||
|
LPDWORD pcchBufferLength)
|
||
|
{
|
||
|
//Return the list of Log set names in the database pointed to by the DSN.
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
DWORD dwBufferSize;
|
||
|
|
||
|
WCHAR wszDataSource[PDH_SQL_STRING_SIZE+1];
|
||
|
DWORD dwLength;
|
||
|
|
||
|
// check args
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
|
||
|
if (szDataSource != NULL)
|
||
|
{
|
||
|
WCHAR TestChar;
|
||
|
// test for read access to the name
|
||
|
TestChar = *szDataSource;
|
||
|
if (TestChar == 0)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
}
|
||
|
else pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
|
||
|
if (mszDataSetNameList != NULL)
|
||
|
{
|
||
|
// test for write access to the name
|
||
|
*mszDataSetNameList = 0;
|
||
|
}
|
||
|
|
||
|
if (pdhStatus == ERROR_SUCCESS && mszDataSetNameList != NULL)
|
||
|
{
|
||
|
if (*pcchBufferLength >= sizeof(DWORD))
|
||
|
{
|
||
|
// test writing to the buffers to make sure they are valid
|
||
|
CLEAR_FIRST_FOUR_BYTES (mszDataSetNameList);
|
||
|
mszDataSetNameList[*pcchBufferLength -1] = 0;
|
||
|
}
|
||
|
else if (*pcchBufferLength >= sizeof(WCHAR))
|
||
|
{
|
||
|
// then just try the first byte
|
||
|
*mszDataSetNameList = 0;
|
||
|
}
|
||
|
else if (*pcchBufferLength != 0)
|
||
|
{
|
||
|
// it's smaller than a character so return if not 0
|
||
|
pdhStatus = PDH_MORE_DATA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pdhStatus == ERROR_SUCCESS)
|
||
|
{
|
||
|
dwBufferSize = *pcchBufferLength;
|
||
|
*pcchBufferLength = 0;
|
||
|
*pcchBufferLength = dwBufferSize;
|
||
|
}
|
||
|
|
||
|
if (ERROR_SUCCESS == pdhStatus)
|
||
|
{
|
||
|
dwLength = lstrlenA(szDataSource);
|
||
|
ZeroMemory(wszDataSource, sizeof(wszDataSource));
|
||
|
MultiByteToWideChar(_getmbcp(),
|
||
|
0,
|
||
|
szDataSource,
|
||
|
dwLength,
|
||
|
(LPWSTR) wszDataSource,
|
||
|
PDH_SQL_STRING_SIZE);
|
||
|
pdhStatus = PdhiEnumLogSetNames (wszDataSource,
|
||
|
mszDataSetNameList,
|
||
|
pcchBufferLength,
|
||
|
FALSE);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhEnumLogSetNamesW (
|
||
|
LPCWSTR szDataSource,
|
||
|
LPWSTR mszDataSetNameList,
|
||
|
LPDWORD pcchBufferLength)
|
||
|
{
|
||
|
//Return the list of Log set names in the database pointed to by the DSN.
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
DWORD dwBufferSize;
|
||
|
|
||
|
// check args
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
|
||
|
if (szDataSource != NULL)
|
||
|
{
|
||
|
WCHAR TestChar;
|
||
|
// test for read access to the name
|
||
|
TestChar = *szDataSource;
|
||
|
if (TestChar == 0)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
}
|
||
|
else pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
|
||
|
if (mszDataSetNameList != NULL)
|
||
|
{
|
||
|
// test for write access to the name
|
||
|
*mszDataSetNameList = 0;
|
||
|
}
|
||
|
|
||
|
if (pdhStatus == ERROR_SUCCESS && mszDataSetNameList != NULL)
|
||
|
{
|
||
|
if (*pcchBufferLength >= sizeof(DWORD))
|
||
|
{
|
||
|
// test writing to the buffers to make sure they are valid
|
||
|
CLEAR_FIRST_FOUR_BYTES (mszDataSetNameList);
|
||
|
mszDataSetNameList[*pcchBufferLength -1] = 0;
|
||
|
}
|
||
|
else if (*pcchBufferLength >= sizeof(WCHAR))
|
||
|
{
|
||
|
// then just try the first byte
|
||
|
*mszDataSetNameList = 0;
|
||
|
}
|
||
|
else if (*pcchBufferLength != 0)
|
||
|
{
|
||
|
// it's smaller than a character so return if not 0
|
||
|
pdhStatus = PDH_MORE_DATA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pdhStatus == ERROR_SUCCESS)
|
||
|
{
|
||
|
dwBufferSize = *pcchBufferLength;
|
||
|
*pcchBufferLength = 0;
|
||
|
*pcchBufferLength = dwBufferSize;
|
||
|
}
|
||
|
|
||
|
if (ERROR_SUCCESS == pdhStatus)
|
||
|
{
|
||
|
|
||
|
pdhStatus = PdhiEnumLogSetNames (szDataSource,
|
||
|
mszDataSetNameList,
|
||
|
pcchBufferLength,
|
||
|
TRUE);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhGetLogSetGUID (
|
||
|
HLOG hLog,
|
||
|
GUID *pGuid,
|
||
|
int *pRunId)
|
||
|
{
|
||
|
//Retrieve the GUID for an open Log Set
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
|
||
|
PPDHI_LOG pLog;
|
||
|
|
||
|
if (IsValidLogHandle (hLog)) {
|
||
|
pLog = (PPDHI_LOG)hLog;
|
||
|
WAIT_FOR_AND_LOCK_MUTEX (pLog->hLogMutex);
|
||
|
// make sure it's still valid as it could have
|
||
|
// been deleted while we were waiting
|
||
|
|
||
|
if (IsValidLogHandle (hLog))
|
||
|
{
|
||
|
pLog = (PPDHI_LOG)hLog;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
// test the parameters before continuing
|
||
|
if ((pGuid == NULL) && (pRunId == NULL))
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (pGuid != NULL)
|
||
|
{
|
||
|
// if not NULL, it must be valid
|
||
|
*pGuid = pLog->guidSQL;
|
||
|
}
|
||
|
if (pRunId != NULL)
|
||
|
{
|
||
|
// if not NULL, it must be valid
|
||
|
*pRunId = pLog->iRunidSQL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
// something failed so give up here
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_HANDLE;
|
||
|
}
|
||
|
|
||
|
RELEASE_MUTEX (pLog->hLogMutex);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_HANDLE;
|
||
|
}
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiSetLogSetRunID (
|
||
|
PPDHI_LOG pLog,
|
||
|
int RunId)
|
||
|
{
|
||
|
//Set the RunID for an open Log Set
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
|
||
|
HSTMT hstmt = NULL;
|
||
|
RETCODE rc;
|
||
|
|
||
|
WCHAR szSQLStmt[SQLSTMTSIZE];
|
||
|
|
||
|
pLog->iRunidSQL = RunId;
|
||
|
|
||
|
// allocate an hstmt
|
||
|
rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
swprintf(szSQLStmt,
|
||
|
L"update DisplayToID set RunID = %d where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x'",
|
||
|
RunId,
|
||
|
pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
|
||
|
pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
|
||
|
pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
|
||
|
pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
|
||
|
|
||
|
rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
|
||
|
if (!SQLSUCCEEDED(rc)) {
|
||
|
pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_EXEC_DIRECT_FAILED);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhSetLogSetRunID (
|
||
|
HLOG hLog,
|
||
|
int RunId)
|
||
|
{
|
||
|
//Set the RunID for an open Log Set
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
|
||
|
PPDHI_LOG pLog;
|
||
|
|
||
|
if (IsValidLogHandle (hLog))
|
||
|
{
|
||
|
pLog = (PPDHI_LOG)hLog;
|
||
|
WAIT_FOR_AND_LOCK_MUTEX (pLog->hLogMutex);
|
||
|
// make sure it's still valid as it could have
|
||
|
// been deleted while we were waiting
|
||
|
|
||
|
if (IsValidLogHandle (hLog))
|
||
|
{
|
||
|
pLog = (PPDHI_LOG)hLog;
|
||
|
|
||
|
pdhStatus = PdhiSetLogSetRunID (pLog, RunId);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_HANDLE;
|
||
|
}
|
||
|
|
||
|
RELEASE_MUTEX (pLog->hLogMutex);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pdhStatus = PDH_INVALID_HANDLE;
|
||
|
}
|
||
|
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|
||
|
PDH_FUNCTION
|
||
|
PdhiListHeaderFromSQLLog(
|
||
|
IN PPDHI_LOG pLog,
|
||
|
IN LPVOID pBufferArg,
|
||
|
IN LPDWORD pcchBufferSize,
|
||
|
IN BOOL bUnicode
|
||
|
)
|
||
|
{
|
||
|
PPDHI_SQL_LOG_INFO pLogInfo;
|
||
|
PPDHI_LOG_MACHINE pMachine;
|
||
|
PPDHI_LOG_OBJECT pObject;
|
||
|
PPDHI_LOG_COUNTER pCounter;
|
||
|
PDH_COUNTER_PATH_ELEMENTS_W pdhPathElem;
|
||
|
WCHAR szPathString[SMALL_BUFFER_SIZE];
|
||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
||
|
DWORD dwNewBuffer = 0;
|
||
|
DWORD dwBufferUsed = 0;
|
||
|
DWORD nItemCount = 0;
|
||
|
|
||
|
if (pcchBufferSize == NULL) {
|
||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
pdhStatus = PdhpGetSQLLogHeader(pLog);
|
||
|
if (pdhStatus != ERROR_SUCCESS) goto Cleanup;
|
||
|
|
||
|
pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
|
||
|
if (pLogInfo == NULL) {
|
||
|
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
for (pMachine = pLogInfo->MachineList; pMachine != NULL; pMachine = pMachine->next) {
|
||
|
for (pObject = pMachine->ObjList; pObject != NULL; pObject = pObject->next) {
|
||
|
for (pCounter = pObject->CtrList; pCounter != NULL; pCounter = pCounter->next) {
|
||
|
ZeroMemory(szPathString, SMALL_BUFFER_SIZE * sizeof(WCHAR));
|
||
|
dwNewBuffer = SMALL_BUFFER_SIZE;
|
||
|
ZeroMemory(& pdhPathElem, sizeof(PDH_COUNTER_PATH_ELEMENTS_W));
|
||
|
pdhPathElem.szMachineName = pMachine->szMachine;
|
||
|
pdhPathElem.szObjectName = pObject->szObject;
|
||
|
pdhPathElem.szCounterName = pCounter->szCounter;
|
||
|
pdhPathElem.szInstanceName = pCounter->szInstance;
|
||
|
pdhPathElem.szParentInstance = pCounter->szParent;
|
||
|
pdhPathElem.dwInstanceIndex = (pCounter->dwInstance != 0)
|
||
|
? (pCounter->dwInstance) : (PERF_NO_UNIQUE_ID);
|
||
|
pdhStatus = PdhMakeCounterPathW(& pdhPathElem, szPathString, & dwNewBuffer, 0);
|
||
|
if (pdhStatus != ERROR_SUCCESS || dwNewBuffer == 0) continue;
|
||
|
|
||
|
if ((dwBufferUsed + dwNewBuffer) < * pcchBufferSize) {
|
||
|
if (pBufferArg != NULL) {
|
||
|
dwNewBuffer = AddUniqueWideStringToMultiSz((LPVOID) pBufferArg, szPathString, bUnicode);
|
||
|
}
|
||
|
else {
|
||
|
dwNewBuffer += dwBufferUsed;
|
||
|
pdhStatus = PDH_MORE_DATA;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
dwNewBuffer += dwBufferUsed;
|
||
|
pdhStatus = PDH_MORE_DATA;
|
||
|
}
|
||
|
if (dwNewBuffer > 0) dwBufferUsed = dwNewBuffer;
|
||
|
nItemCount ++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (nItemCount > 0 && pdhStatus != PDH_INSUFFICIENT_BUFFER && pdhStatus != PDH_MORE_DATA) {
|
||
|
pdhStatus = ERROR_SUCCESS;
|
||
|
}
|
||
|
if (pBufferArg == NULL) {
|
||
|
dwBufferUsed ++;
|
||
|
}
|
||
|
|
||
|
* pcchBufferSize = dwBufferUsed;
|
||
|
|
||
|
Cleanup:
|
||
|
return pdhStatus;
|
||
|
}
|
||
|
|