mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1181 lines
41 KiB
1181 lines
41 KiB
/*++
|
|
|
|
Copyright (C) 1995-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
log_ctrl.c
|
|
|
|
Abstract:
|
|
|
|
Log file control interface helper functions
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <pdh.h>
|
|
#include "pdhidef.h"
|
|
#include "pdhmsg.h"
|
|
#include "strings.h"
|
|
|
|
#define PDH_LOGSVC_CTRL_FNMASK ((DWORD)(PDH_LOGSVC_CTRL_ADD \
|
|
| PDH_LOGSVC_CTRL_REMOVE \
|
|
| PDH_LOGSVC_CTRL_INFO \
|
|
))
|
|
|
|
|
|
//
|
|
// Internal Logging utility functions
|
|
//
|
|
LONG
|
|
GetCurrentServiceState (
|
|
SC_HANDLE hService,
|
|
BOOL * bStopped,
|
|
BOOL * bPaused)
|
|
{
|
|
SERVICE_STATUS ssData;
|
|
LONG lStatus = ERROR_SUCCESS;
|
|
|
|
BOOL bServiceStopped = FALSE;
|
|
BOOL bServicePaused = FALSE;
|
|
|
|
if (ControlService (
|
|
hService, SERVICE_CONTROL_INTERROGATE,
|
|
&ssData)) {
|
|
switch (ssData.dwCurrentState) {
|
|
|
|
case SERVICE_STOPPED:
|
|
bServiceStopped = TRUE;
|
|
bServicePaused = FALSE;
|
|
break;
|
|
|
|
case SERVICE_START_PENDING:
|
|
bServiceStopped = TRUE;
|
|
bServicePaused = FALSE;
|
|
break;
|
|
|
|
case SERVICE_STOP_PENDING:
|
|
bServiceStopped = FALSE;
|
|
bServicePaused = FALSE;
|
|
break;
|
|
|
|
case SERVICE_RUNNING:
|
|
bServiceStopped = FALSE;
|
|
bServicePaused = FALSE;
|
|
break;
|
|
|
|
case SERVICE_CONTINUE_PENDING:
|
|
bServiceStopped = FALSE;
|
|
bServicePaused = FALSE;
|
|
break;
|
|
|
|
case SERVICE_PAUSE_PENDING:
|
|
bServiceStopped = FALSE;
|
|
bServicePaused = FALSE;
|
|
break;
|
|
|
|
case SERVICE_PAUSED:
|
|
bServiceStopped = FALSE;
|
|
bServicePaused = TRUE;
|
|
break;
|
|
|
|
default:
|
|
;// no op
|
|
}
|
|
} else {
|
|
bServiceStopped = TRUE;
|
|
bServicePaused = TRUE;
|
|
}
|
|
|
|
*bStopped = bServiceStopped;
|
|
*bPaused = bServicePaused;
|
|
|
|
return lStatus;
|
|
}
|
|
|
|
STATIC_PDH_FUNCTION
|
|
PdhiSetLogQueryState (
|
|
IN LPCWSTR szMachineName,
|
|
IN LPCWSTR szQueryName,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
DBG_UNREFERENCED_PARAMETER(szMachineName);
|
|
DBG_UNREFERENCED_PARAMETER(szQueryName);
|
|
DBG_UNREFERENCED_PARAMETER(dwFlags);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
STATIC_PDH_FUNCTION
|
|
PdhiGetLogQueryState (
|
|
IN SC_HANDLE hService,
|
|
IN LPCWSTR szMachineName,
|
|
IN LPCWSTR szQueryName,
|
|
IN LPDWORD pdwFlags
|
|
)
|
|
{
|
|
BOOL bStopped, bPaused;
|
|
DWORD dwStatus;
|
|
|
|
UNREFERENCED_PARAMETER(szMachineName);
|
|
UNREFERENCED_PARAMETER(szQueryName);
|
|
|
|
// first get service status
|
|
GetCurrentServiceState (hService, &bStopped, &bPaused);
|
|
|
|
if (bStopped) {
|
|
dwStatus = PDH_LOGSVC_STATUS_STOPPED;
|
|
} else if (bPaused) {
|
|
dwStatus = PDH_LOGSVC_STATUS_PAUSED;
|
|
} else {
|
|
dwStatus = PDH_LOGSVC_STATUS_RUNNING;
|
|
}
|
|
|
|
if (dwStatus == PDH_LOGSVC_STATUS_RUNNING) {
|
|
// get status of specific query
|
|
// connect to machine, if necssary
|
|
// open registry key of log service
|
|
// read value of query status
|
|
// adjust status, if necessary
|
|
}
|
|
|
|
// return status of query
|
|
*pdwFlags = dwStatus;
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
STATIC_PDH_FUNCTION
|
|
PdhiLogServiceAddCommandT (
|
|
IN LPCWSTR szMachineName,
|
|
IN LPCWSTR szQueryName,
|
|
IN DWORD dwFlags,
|
|
IN LPVOID pInfoBuffer,
|
|
IN LPDWORD pdwBufferSize,
|
|
IN BOOL bWideChar
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(szMachineName);
|
|
UNREFERENCED_PARAMETER(szQueryName);
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
UNREFERENCED_PARAMETER(pInfoBuffer);
|
|
UNREFERENCED_PARAMETER(pdwBufferSize);
|
|
UNREFERENCED_PARAMETER(bWideChar);
|
|
|
|
return PDH_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
STATIC_PDH_FUNCTION
|
|
PdhiLogServiceRemoveCommandT (
|
|
IN LPCWSTR szMachineName,
|
|
IN LPCWSTR szQueryName,
|
|
IN DWORD dwFlags,
|
|
IN LPVOID pInfoBuffer,
|
|
IN LPDWORD pdwBufferSize,
|
|
IN BOOL bWideChar
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(szMachineName);
|
|
UNREFERENCED_PARAMETER(szQueryName);
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
UNREFERENCED_PARAMETER(pInfoBuffer);
|
|
UNREFERENCED_PARAMETER(pdwBufferSize);
|
|
UNREFERENCED_PARAMETER(bWideChar);
|
|
|
|
return PDH_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
STATIC_PDH_FUNCTION
|
|
PdhiLogServiceInfoCommandT (
|
|
IN LPCWSTR szMachineName,
|
|
IN LPCWSTR szQueryName,
|
|
IN DWORD dwFlags,
|
|
IN LPVOID pInfoBuffer,
|
|
IN LPDWORD pdwBufferSize,
|
|
IN BOOL bWideChar
|
|
)
|
|
{
|
|
|
|
LONG lStatus = ERROR_SUCCESS;
|
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
|
|
|
DWORD dwRegValType;
|
|
DWORD dwRegValue;
|
|
DWORD dwRegValueSize;
|
|
|
|
WCHAR szTempFilePath[MAX_PATH];
|
|
WCHAR szRegString[MAX_PATH];
|
|
WCHAR szDriveName[MAX_PATH];
|
|
|
|
HKEY hKeyMachine = NULL;
|
|
HKEY hKeyLogSettings = NULL;
|
|
HKEY hKeyLogQuery = NULL;
|
|
|
|
CHAR *pNextChar = NULL;
|
|
WCHAR *pNextWideChar = NULL;
|
|
|
|
DWORD dwCharSize;
|
|
|
|
DWORD dwSize;
|
|
DWORD dwRequiredSize = sizeof(PDH_LOG_SERVICE_QUERY_INFO_W);
|
|
DWORD dwRemainingSize = 0;
|
|
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
|
|
dwCharSize = bWideChar ? sizeof(WCHAR) : sizeof(CHAR);
|
|
|
|
setlocale( LC_ALL, "" ); // to make wcstombs work predictably
|
|
|
|
if (*pdwBufferSize < sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
// then then this is either too small or a size request in either
|
|
// case we won't copy any data and only estimate the size required
|
|
dwRemainingSize = 0;
|
|
} else {
|
|
dwRemainingSize = *pdwBufferSize - sizeof(PDH_LOG_SERVICE_QUERY_INFO_W);
|
|
}
|
|
|
|
// get root key to registry
|
|
if (szMachineName != NULL) {
|
|
lStatus = RegConnectRegistryW (
|
|
(LPWSTR)szMachineName,
|
|
HKEY_LOCAL_MACHINE,
|
|
&hKeyMachine);
|
|
if (lStatus != ERROR_SUCCESS) {
|
|
pdhStatus = PDH_CANNOT_CONNECT_MACHINE;
|
|
}
|
|
} else {
|
|
// use predefined key handle
|
|
hKeyMachine = HKEY_LOCAL_MACHINE;
|
|
lStatus = ERROR_SUCCESS;
|
|
}
|
|
|
|
if (pInfoBuffer == NULL) {
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
lStatus = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (lStatus == ERROR_SUCCESS) {
|
|
// open registry key to service
|
|
lStatus = RegOpenKeyExW (
|
|
hKeyMachine,
|
|
cszLogQueries,
|
|
0,
|
|
KEY_READ,
|
|
&hKeyLogSettings);
|
|
if (lStatus != ERROR_SUCCESS) {
|
|
pdhStatus = PDH_LOGSVC_NOT_OPENED;
|
|
}
|
|
}
|
|
|
|
if (lStatus == ERROR_SUCCESS) {
|
|
// open registry to specified log query
|
|
lStatus = RegOpenKeyExW (
|
|
hKeyLogSettings,
|
|
(szQueryName != NULL ? szQueryName : cszDefault),
|
|
0,
|
|
KEY_READ,
|
|
&hKeyLogQuery);
|
|
|
|
if (lStatus != ERROR_SUCCESS) {
|
|
pdhStatus = PDH_LOGSVC_QUERY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
// continue
|
|
|
|
if (lStatus == ERROR_SUCCESS) {
|
|
|
|
// initialize string pointers
|
|
if (bWideChar && (pInfoBuffer != NULL)) {
|
|
pNextWideChar = (WCHAR *)(&((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)[1]);
|
|
} else {
|
|
pNextChar = (CHAR *)(&((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)[1]);
|
|
}
|
|
|
|
// read log file format
|
|
dwRegValType = 0;
|
|
dwRegValue = 0;
|
|
dwRegValueSize = sizeof(DWORD);
|
|
lStatus = RegQueryValueExW (
|
|
hKeyLogQuery,
|
|
cszLogFileType,
|
|
NULL,
|
|
&dwRegValType,
|
|
(LPBYTE)&dwRegValue,
|
|
&dwRegValueSize);
|
|
if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
// this data goes into the fixed portion of the structure
|
|
if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_DWORD)) {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->dwFileType = dwRegValue;
|
|
} else {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->dwFileType = PDH_LOG_TYPE_UNDEFINED;
|
|
}
|
|
}
|
|
|
|
//read sample interval
|
|
dwRegValType = 0;
|
|
dwRegValue = 0;
|
|
dwRegValueSize = sizeof(DWORD);
|
|
lStatus = RegQueryValueExW (
|
|
hKeyLogQuery,
|
|
cszAutoNameInterval,
|
|
NULL,
|
|
&dwRegValType,
|
|
(LPBYTE)&dwRegValue,
|
|
&dwRegValueSize);
|
|
|
|
if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
// this data goes into the fixed portion of the structure
|
|
if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_DWORD)) {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameInterval = dwRegValue;
|
|
} else {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameInterval = 0;
|
|
dwRegValue = 0;
|
|
}
|
|
}
|
|
|
|
if (dwRegValue == 0) {
|
|
// initialize the rest of the manual name field(s)
|
|
dwRegValType = 0;
|
|
dwRegValueSize = MAX_PATH * sizeof(WCHAR);
|
|
memset (szRegString, 0, dwRegValueSize);
|
|
lStatus = RegQueryValueExW (
|
|
hKeyLogQuery,
|
|
cszLogFileName,
|
|
NULL,
|
|
&dwRegValType,
|
|
(LPBYTE)&szRegString[0],
|
|
&dwRegValueSize);
|
|
|
|
if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_SZ)) {
|
|
dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
|
|
if (dwRequiredSize <= *pdwBufferSize) {
|
|
if (bWideChar) {
|
|
// copy widestrings
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = pNextWideChar;
|
|
lstrcpyW (pNextWideChar, szRegString);
|
|
pNextWideChar += dwRegValueSize / sizeof (WCHAR);
|
|
} else {
|
|
// convert to ansi char
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->szBaseFileName = pNextChar;
|
|
wcstombs (pNextChar, szRegString, (dwRegValueSize /sizeof(WCHAR)));
|
|
pNextChar += dwRegValueSize / sizeof (WCHAR);
|
|
}
|
|
dwRemainingSize -= dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
|
|
} else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
// no room for this string, but keep the required
|
|
// total;
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = NULL;
|
|
} else {
|
|
// it's an empty buffer
|
|
}
|
|
} else {
|
|
if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = NULL;
|
|
}
|
|
}
|
|
|
|
// if the filename doesn't specify a directory, then use the
|
|
lstrcpyW (szTempFilePath, szRegString);
|
|
|
|
_wsplitpath ((LPCWSTR)szTempFilePath, szDriveName, szRegString,
|
|
NULL, NULL);
|
|
if ((lstrlenW(szDriveName) == 0) && (lstrlenW(szRegString) == 0)) {
|
|
// default log file directory
|
|
dwRegValType = 0;
|
|
dwRegValueSize = MAX_PATH * sizeof(WCHAR);
|
|
memset (szRegString, 0, dwRegValueSize);
|
|
lStatus = RegQueryValueExW (
|
|
hKeyLogQuery,
|
|
cszLogDefaultDir,
|
|
NULL,
|
|
&dwRegValType,
|
|
(LPBYTE)&szRegString[0],
|
|
&dwRegValueSize);
|
|
|
|
} else {
|
|
// the file parsing function leaves the trailing backslash
|
|
// so remove it before concatenating it.
|
|
dwSize = lstrlenW(szRegString);
|
|
if (dwSize > 0) {
|
|
if (szRegString[dwSize-1] == L'\\') {
|
|
szRegString[dwSize-1] = 0;
|
|
}
|
|
lStatus = ERROR_SUCCESS;
|
|
dwRegValType = REG_SZ;
|
|
dwRegValueSize = dwSize;
|
|
} else {
|
|
lStatus = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_SZ)) {
|
|
dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
|
|
if (dwRequiredSize <= *pdwBufferSize) {
|
|
if (bWideChar) {
|
|
// copy widestrings
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = pNextWideChar;
|
|
lstrcpyW (pNextWideChar, szRegString);
|
|
pNextWideChar += dwRegValueSize / sizeof (WCHAR);
|
|
} else {
|
|
// convert to ansi char
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->szDefaultDir = pNextChar;
|
|
wcstombs (pNextChar, szRegString, (dwRegValueSize /sizeof(WCHAR)));
|
|
pNextChar += dwRegValueSize / sizeof (WCHAR);
|
|
}
|
|
dwRemainingSize -= dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
|
|
} else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
// no room for this string, but keep the required
|
|
// total;
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = NULL;
|
|
} else {
|
|
// no buffer for this
|
|
}
|
|
} else {
|
|
if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
// get values for controls
|
|
dwRegValType = 0;
|
|
dwRegValueSize = MAX_PATH * sizeof(WCHAR);
|
|
memset (szRegString, 0, dwRegValueSize);
|
|
lStatus = RegQueryValueExW (
|
|
hKeyLogQuery,
|
|
cszLogDefaultDir,
|
|
NULL,
|
|
&dwRegValType,
|
|
(LPBYTE)&szRegString[0],
|
|
&dwRegValueSize);
|
|
|
|
if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_SZ)) {
|
|
dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
|
|
if (dwRequiredSize <= *pdwBufferSize) {
|
|
if (bWideChar) {
|
|
// copy widestrings
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = pNextWideChar;
|
|
lstrcpyW (pNextWideChar, szRegString);
|
|
pNextWideChar += dwRegValueSize / sizeof (WCHAR);
|
|
} else {
|
|
// convert to ansi char
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->szDefaultDir = pNextChar;
|
|
wcstombs (pNextChar, szRegString, (dwRegValueSize/sizeof(WCHAR)));
|
|
pNextChar += dwRegValueSize / sizeof (WCHAR);
|
|
}
|
|
dwRemainingSize -= dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
|
|
} else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
// no room for this string, but keep the required
|
|
// total;
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = NULL;
|
|
} else {
|
|
// no room for anything
|
|
}
|
|
} else {
|
|
if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = NULL;
|
|
}
|
|
}
|
|
|
|
// base filename
|
|
dwRegValType = 0;
|
|
dwRegValueSize = MAX_PATH * sizeof(WCHAR);
|
|
memset (szRegString, 0, dwRegValueSize);
|
|
lStatus = RegQueryValueExW (
|
|
hKeyLogQuery,
|
|
cszBaseFileName,
|
|
NULL,
|
|
&dwRegValType,
|
|
(LPBYTE)&szRegString[0],
|
|
&dwRegValueSize);
|
|
|
|
|
|
if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_SZ)) {
|
|
dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
|
|
if (dwRequiredSize <= *pdwBufferSize) {
|
|
if (bWideChar) {
|
|
// copy widestrings
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = pNextWideChar;
|
|
lstrcpyW (pNextWideChar, szRegString);
|
|
pNextWideChar += dwRegValueSize / sizeof (WCHAR);
|
|
} else {
|
|
// convert to ansi char
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->szBaseFileName = pNextChar;
|
|
wcstombs (pNextChar, szRegString, (dwRegValueSize/sizeof(WCHAR)));
|
|
pNextChar += dwRegValueSize / sizeof (WCHAR);
|
|
}
|
|
dwRemainingSize -= dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
|
|
} else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
// no room for this string, but keep the required
|
|
// total;
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = NULL;
|
|
} else {
|
|
// no buffer
|
|
}
|
|
} else {
|
|
if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = NULL;
|
|
}
|
|
}
|
|
|
|
// get auto name format
|
|
dwRegValType = 0;
|
|
dwRegValue = 0;
|
|
dwRegValueSize = sizeof(DWORD);
|
|
lStatus = RegQueryValueExW (
|
|
hKeyLogQuery,
|
|
cszLogFileAutoFormat,
|
|
NULL,
|
|
&dwRegValType,
|
|
(LPBYTE)&dwRegValue,
|
|
&dwRegValueSize);
|
|
|
|
if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_DWORD)) {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameFormat = dwRegValue;
|
|
} else {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameFormat = PDH_LOGSVC_NAME_UNDEFINED;
|
|
}
|
|
}
|
|
|
|
dwRegValType = 0;
|
|
dwRegValue = 0;
|
|
dwRegValueSize = sizeof(DWORD);
|
|
lStatus = RegQueryValueExW (
|
|
hKeyLogQuery,
|
|
cszAutoRenameUnits,
|
|
NULL,
|
|
&dwRegValType,
|
|
(LPBYTE)&dwRegValue,
|
|
&dwRegValueSize);
|
|
|
|
if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_DWORD)) {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameUnits = dwRegValue;
|
|
} else {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameUnits = PDH_LOGSVC_RENAME_UNDEFINED;
|
|
}
|
|
}
|
|
|
|
dwRegValType = 0;
|
|
dwRegValueSize = MAX_PATH * sizeof(WCHAR);
|
|
memset (szRegString, 0, dwRegValueSize);
|
|
lStatus = RegQueryValueExW (
|
|
hKeyLogQuery,
|
|
cszCommandFile,
|
|
NULL,
|
|
&dwRegValType,
|
|
(LPBYTE)&szRegString[0],
|
|
&dwRegValueSize);
|
|
|
|
if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_SZ)) {
|
|
dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
|
|
if (dwRequiredSize <= *pdwBufferSize) {
|
|
if (bWideChar) {
|
|
// copy widestrings
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCommandFilename = pNextWideChar;
|
|
lstrcpyW (pNextWideChar, szRegString);
|
|
pNextWideChar += dwRegValueSize / sizeof (WCHAR);
|
|
} else {
|
|
// convert to ansi char
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->PdlCommandFilename = pNextChar;
|
|
wcstombs (pNextChar, szRegString, (dwRegValueSize/sizeof(WCHAR)));
|
|
pNextChar += dwRegValueSize / sizeof (WCHAR);
|
|
}
|
|
dwRemainingSize -= dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
|
|
} else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
// no room for this string, but keep the required
|
|
// total;
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCommandFilename = NULL;
|
|
} else {
|
|
// no buffer
|
|
}
|
|
} else {
|
|
if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCommandFilename = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// get counter string!
|
|
|
|
// find out buffer size required
|
|
dwRegValType = 0;
|
|
dwRegValue = 0;
|
|
dwRegValueSize = 0;
|
|
lStatus = RegQueryValueExW (
|
|
hKeyLogQuery,
|
|
cszCounterList,
|
|
NULL,
|
|
&dwRegValType,
|
|
NULL,
|
|
&dwRegValueSize);
|
|
|
|
if (dwRegValueSize > 0) {
|
|
// there's room in the caller's buffer so go ahead and
|
|
// fill it
|
|
dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
|
|
if (dwRequiredSize <= *pdwBufferSize) {
|
|
|
|
dwRegValueSize = dwRemainingSize;
|
|
dwRegValType = 0;
|
|
dwRegValue = 0;
|
|
if (bWideChar) {
|
|
lStatus = RegQueryValueExW (
|
|
hKeyLogQuery,
|
|
cszCounterList,
|
|
NULL,
|
|
&dwRegValType,
|
|
(LPBYTE)pNextWideChar,
|
|
&dwRegValueSize);
|
|
|
|
if (lStatus == ERROR_SUCCESS) {
|
|
// assign pointer to buffer
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCounterList = pNextWideChar;
|
|
pNextWideChar += dwRegValueSize / sizeof (WCHAR);
|
|
dwRemainingSize -= dwRegValueSize;
|
|
} else {
|
|
// assign null pointer
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCounterList = NULL;
|
|
}
|
|
} else {
|
|
lStatus = RegQueryValueExA (
|
|
hKeyLogQuery,
|
|
caszCounterList,
|
|
NULL,
|
|
&dwRegValType,
|
|
(LPBYTE)pNextChar,
|
|
&dwRegValueSize);
|
|
|
|
if (lStatus == ERROR_SUCCESS) {
|
|
// assign pointer to buffer
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->PdlCounterList = pNextChar;
|
|
pNextChar += dwRegValueSize;
|
|
dwRemainingSize -= dwRegValueSize;
|
|
} else {
|
|
// assign null pointer
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->PdlCounterList = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
// no room so don't copy anything
|
|
}
|
|
} else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
// no counters defined so return NULL
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCounterList = NULL;
|
|
} else {
|
|
// no buffer
|
|
}
|
|
} //end if registry opened ok
|
|
|
|
// close open registry keys
|
|
|
|
if (hKeyMachine != NULL) RegCloseKey (hKeyMachine);
|
|
if (hKeyLogSettings != NULL) RegCloseKey (hKeyLogSettings);
|
|
if (hKeyLogQuery != NULL) RegCloseKey (hKeyLogQuery);
|
|
|
|
// test to see if the buffer estimate and pointer location line up
|
|
// assuming it was big enough in the first place
|
|
assert ((dwRequiredSize <= *pdwBufferSize) ?
|
|
((pNextChar != NULL) ? (dwRequiredSize == ((DWORD)pNextChar - (DWORD)pInfoBuffer)) :
|
|
(dwRequiredSize == ((DWORD)pNextWideChar - (DWORD)pInfoBuffer))) : TRUE);
|
|
|
|
if (lStatus == ERROR_SUCCESS) {
|
|
if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
|
|
// if there's enough buffer to write this...
|
|
if (*pdwBufferSize >= dwRequiredSize) {
|
|
// and there was enough for the requested data
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->dwSize = dwRequiredSize;
|
|
} else {
|
|
// return the amount used
|
|
((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->dwSize = *pdwBufferSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
// save required size
|
|
*pdwBufferSize = dwRequiredSize;
|
|
|
|
return pdhStatus;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhLogServiceCommandA (
|
|
IN LPCSTR szMachineName,
|
|
IN LPCSTR szQueryName,
|
|
IN DWORD dwFlags,
|
|
IN LPDWORD pdwStatus
|
|
)
|
|
{
|
|
LPWSTR wszQueryName = NULL;
|
|
LPWSTR wszMachineName = NULL;
|
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
|
|
|
// test access to query name
|
|
|
|
if (szQueryName != NULL) {
|
|
DWORD dwNameLength = 0;
|
|
try {
|
|
CHAR cTest;
|
|
|
|
cTest = szQueryName[0];
|
|
dwNameLength = lstrlenA (szQueryName);
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
// unable to access name argument
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
// allocate wide name buffer
|
|
wszQueryName = G_ALLOC ((dwNameLength + 1) * sizeof (WCHAR));
|
|
if (wszQueryName != NULL) {
|
|
mbstowcs (wszQueryName, szQueryName, dwNameLength);
|
|
} else {
|
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
} else {
|
|
// make a null arg for the function
|
|
wszQueryName = NULL;
|
|
}
|
|
|
|
if ((szMachineName != NULL) && (pdhStatus == ERROR_SUCCESS)) {
|
|
DWORD dwNameLength = 0;
|
|
try {
|
|
CHAR cTest;
|
|
|
|
cTest = szMachineName[0];
|
|
dwNameLength = lstrlenA (szMachineName);
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
// unable to access name argument
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
// allocate wide name buffer
|
|
wszMachineName = G_ALLOC ((dwNameLength + 1) * sizeof (WCHAR));
|
|
if (wszMachineName != NULL) {
|
|
mbstowcs (wszMachineName, szMachineName, dwNameLength);
|
|
} else {
|
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
} else {
|
|
// make a null arg for the function
|
|
wszMachineName = NULL;
|
|
}
|
|
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
// call wide string version
|
|
pdhStatus = PdhLogServiceCommandW (
|
|
wszMachineName,
|
|
wszQueryName,
|
|
dwFlags,
|
|
pdwStatus);
|
|
}
|
|
|
|
if (wszQueryName != NULL) G_FREE (wszQueryName);
|
|
if (wszMachineName != NULL) G_FREE (wszMachineName);
|
|
|
|
return pdhStatus;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhLogServiceCommandW (
|
|
IN LPCWSTR szMachineName,
|
|
IN LPCWSTR szQueryName,
|
|
IN DWORD dwFlags,
|
|
IN LPDWORD pdwStatus
|
|
)
|
|
{
|
|
SC_HANDLE hSC = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
SERVICE_STATUS ssData;
|
|
DWORD dwTimeout;
|
|
DWORD dwStatus;
|
|
BOOL bStopped = FALSE;
|
|
BOOL bPaused = FALSE;
|
|
LONG lStatus = ERROR_SUCCESS;
|
|
BOOL bWait;
|
|
LPWSTR szLocalQueryName = NULL;
|
|
|
|
// test arguments
|
|
try {
|
|
WCHAR wcTest;
|
|
DWORD dwTest;
|
|
|
|
if (szMachineName != NULL) {
|
|
wcTest = szMachineName[0];
|
|
} // null is valid for the local machine
|
|
|
|
if (szQueryName != NULL) {
|
|
wcTest = szQueryName[0];
|
|
} // null is a valid query name.
|
|
|
|
if (pdwStatus != NULL) {
|
|
dwTest = *pdwStatus;
|
|
*pdwStatus = 0;
|
|
*pdwStatus = dwTest;
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
lStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
|
|
if (lStatus == ERROR_SUCCESS) {
|
|
if ((dwFlags & PDH_LOGSVC_TRACE_LOG) == PDH_LOGSVC_TRACE_LOG) {
|
|
lStatus = PDH_NOT_IMPLEMENTED;
|
|
} else {
|
|
// this must be a perf log command
|
|
// open SC database
|
|
hSC = OpenSCManagerW (szMachineName, NULL, SC_MANAGER_ALL_ACCESS);
|
|
|
|
if (hSC == NULL) {
|
|
// open service
|
|
hService = OpenServiceW (hSC, cszPerfDataLog,
|
|
SERVICE_START | SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL);
|
|
} // else hService will still be NULL so get the last error below
|
|
|
|
if (hService != NULL) {
|
|
// determine wait flag value
|
|
bWait = (dwFlags & PDH_LOGSVC_NO_WAIT) ? FALSE : TRUE;
|
|
|
|
if (szQueryName == NULL) {
|
|
if ((dwFlags & PDH_LOGSVC_ALL_QUERIES) == PDH_LOGSVC_ALL_QUERIES) {
|
|
// start / stop the service and all log queries
|
|
if ((dwFlags & PDH_LOGSVC_CMD_START) == PDH_LOGSVC_CMD_START) {
|
|
// start the service and start all logs set to run
|
|
StartService (hService, 0, NULL);
|
|
if ( bWait ) {
|
|
// wait for the service to start before returning
|
|
dwTimeout = 20;
|
|
while (dwTimeout) {
|
|
GetCurrentServiceState (hService, &bStopped, &bPaused);
|
|
if (bStopped) {
|
|
Sleep(500);
|
|
} else {
|
|
break;
|
|
}
|
|
--dwTimeout;
|
|
}
|
|
if (bStopped) {
|
|
dwStatus = PDH_LOGSVC_STATUS_STOPPED;
|
|
} else if (bPaused) {
|
|
dwStatus = PDH_LOGSVC_STATUS_PAUSED;
|
|
} else {
|
|
dwStatus = PDH_LOGSVC_STATUS_RUNNING;
|
|
}
|
|
} else {
|
|
dwStatus = PDH_LOGSVC_STATUS_PENDING;
|
|
}
|
|
|
|
} else if ((dwFlags & PDH_LOGSVC_CMD_STOP) == PDH_LOGSVC_CMD_STOP) {
|
|
ControlService (hService, SERVICE_CONTROL_STOP, &ssData);
|
|
if ( bWait ) {
|
|
// wait for the service to stop before returning
|
|
dwTimeout = 20;
|
|
while (dwTimeout) {
|
|
GetCurrentServiceState (hService, &bStopped, &bPaused);
|
|
if (!bStopped) {
|
|
Sleep(500);
|
|
} else {
|
|
break;
|
|
}
|
|
--dwTimeout;
|
|
}
|
|
if (bStopped) {
|
|
dwStatus = PDH_LOGSVC_STATUS_STOPPED;
|
|
} else if (bPaused) {
|
|
dwStatus = PDH_LOGSVC_STATUS_PAUSED;
|
|
} else {
|
|
dwStatus = PDH_LOGSVC_STATUS_RUNNING;
|
|
}
|
|
}
|
|
} else {
|
|
// unknown operation
|
|
lStatus = PDH_UNKNOWN_LOGSVC_COMMAND;
|
|
}
|
|
} else {
|
|
// this is just a generic log command.
|
|
szLocalQueryName = (LPWSTR)cszDefault;
|
|
}
|
|
}
|
|
|
|
if (szLocalQueryName != NULL) {
|
|
// then this command is for a named service
|
|
lStatus = PdhiSetLogQueryState (
|
|
szMachineName,
|
|
szLocalQueryName,
|
|
(dwFlags & (PDH_LOGSVC_CMD_START | PDH_LOGSVC_CMD_STOP)));
|
|
if (lStatus == ERROR_SUCCESS) {
|
|
// service entry was updated to desired status
|
|
|
|
if (!ControlService (hService,
|
|
SERVICE_CONTROL_PARAMCHANGE, &ssData)) {
|
|
lStatus = GetLastError ();
|
|
}
|
|
lStatus = PdhiGetLogQueryState (
|
|
hService, szMachineName,
|
|
szLocalQueryName, &dwStatus);
|
|
}
|
|
}
|
|
|
|
|
|
CloseServiceHandle (hService);
|
|
} else {
|
|
lStatus = GetLastError();
|
|
assert (lStatus != 0);
|
|
}
|
|
// close handles
|
|
if (hSC != NULL) CloseServiceHandle (hSC);
|
|
}
|
|
}
|
|
|
|
return lStatus;
|
|
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhLogServiceControlA (
|
|
IN LPCSTR szMachineName,
|
|
IN LPCSTR szQueryName,
|
|
IN DWORD dwFlags,
|
|
IN PPDH_LOG_SERVICE_QUERY_INFO_A pInfoBuffer,
|
|
IN LPDWORD pdwBufferSize
|
|
)
|
|
{
|
|
LPWSTR wszQueryName = NULL;
|
|
LPWSTR wszMachineName = NULL;
|
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
|
DWORD dwCmdFn;
|
|
|
|
// test access to query name
|
|
|
|
if (szQueryName != NULL) {
|
|
DWORD dwNameLength = 0;
|
|
try {
|
|
CHAR cTest;
|
|
|
|
cTest = szQueryName[0];
|
|
dwNameLength = lstrlenA (szQueryName);
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
// unable to access name argument
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
// allocate wide name buffer
|
|
wszQueryName = G_ALLOC ((dwNameLength + 1) * sizeof (WCHAR));
|
|
if (wszQueryName != NULL) {
|
|
mbstowcs (wszQueryName, szQueryName, dwNameLength);
|
|
} else {
|
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
} else {
|
|
// make a null arg for the function
|
|
wszQueryName = NULL;
|
|
}
|
|
|
|
if ((szMachineName != NULL) && (pdhStatus == ERROR_SUCCESS)) {
|
|
DWORD dwNameLength = 0;
|
|
try {
|
|
CHAR cTest;
|
|
|
|
cTest = szMachineName[0];
|
|
dwNameLength = lstrlenA (szMachineName);
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
// unable to access name argument
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
// allocate wide name buffer
|
|
wszMachineName = G_ALLOC ((dwNameLength + 1) * sizeof (WCHAR));
|
|
if (wszMachineName != NULL) {
|
|
mbstowcs (wszMachineName, szMachineName, dwNameLength);
|
|
} else {
|
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
} else {
|
|
// make a null arg for the function
|
|
wszMachineName = NULL;
|
|
}
|
|
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
try {
|
|
DWORD dwTest;
|
|
|
|
if (pdwBufferSize != NULL) {
|
|
dwTest = *pdwBufferSize;
|
|
*pdwBufferSize = 0;
|
|
*pdwBufferSize = dwTest;
|
|
} else {
|
|
// null is NOT valid
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
}
|
|
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
// dispatch to "action" function based on command code
|
|
dwCmdFn = dwFlags & PDH_LOGSVC_CTRL_FNMASK;
|
|
switch (dwCmdFn) {
|
|
case PDH_LOGSVC_CTRL_ADD:
|
|
// call universal string version
|
|
pdhStatus = PdhiLogServiceAddCommandT (
|
|
wszMachineName,
|
|
wszQueryName,
|
|
dwFlags,
|
|
(LPVOID)pInfoBuffer,
|
|
pdwBufferSize,
|
|
FALSE);
|
|
break;
|
|
|
|
case PDH_LOGSVC_CTRL_REMOVE:
|
|
// call universal string version
|
|
pdhStatus = PdhiLogServiceRemoveCommandT (
|
|
wszMachineName,
|
|
wszQueryName,
|
|
dwFlags,
|
|
(LPVOID)pInfoBuffer,
|
|
pdwBufferSize,
|
|
FALSE);
|
|
break;
|
|
|
|
case PDH_LOGSVC_CTRL_INFO:
|
|
// call universal string version
|
|
pdhStatus = PdhiLogServiceInfoCommandT (
|
|
wszMachineName,
|
|
wszQueryName,
|
|
dwFlags,
|
|
(LPVOID)pInfoBuffer,
|
|
pdwBufferSize,
|
|
FALSE);
|
|
break;
|
|
|
|
default:
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if (wszQueryName != NULL) G_FREE (wszQueryName);
|
|
if (wszMachineName != NULL) G_FREE (wszMachineName);
|
|
|
|
return pdhStatus;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhLogServiceControlW (
|
|
IN LPCWSTR szMachineName,
|
|
IN LPCWSTR szQueryName,
|
|
IN DWORD dwFlags,
|
|
IN PPDH_LOG_SERVICE_QUERY_INFO_W pInfoBuffer,
|
|
IN LPDWORD pdwBufferSize
|
|
)
|
|
{
|
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
|
DWORD dwCmdFn;
|
|
|
|
// test access to query name
|
|
|
|
if (szQueryName != NULL) {
|
|
WCHAR cTest;
|
|
try {
|
|
cTest = szQueryName[0];
|
|
if (cTest == 0) {
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
// unable to access name argument
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
} else {
|
|
// NULL is OK
|
|
}
|
|
|
|
// test access to machine name
|
|
|
|
if ((szMachineName != NULL) && (pdhStatus == ERROR_SUCCESS)) {
|
|
WCHAR cTest;
|
|
try {
|
|
cTest = szMachineName[0];
|
|
if (cTest == 0) {
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
// unable to access name argument
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
} else {
|
|
// NULL is OK
|
|
}
|
|
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
try {
|
|
DWORD dwTest;
|
|
|
|
if (pdwBufferSize != NULL) {
|
|
dwTest = *pdwBufferSize;
|
|
*pdwBufferSize = 0;
|
|
*pdwBufferSize = dwTest;
|
|
} else {
|
|
// null is NOT valid
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
}
|
|
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
// dispatch to "action" function based on command code
|
|
dwCmdFn = dwFlags & PDH_LOGSVC_CTRL_FNMASK;
|
|
switch (dwCmdFn) {
|
|
case PDH_LOGSVC_CTRL_ADD:
|
|
// call universal string version
|
|
pdhStatus = PdhiLogServiceAddCommandT (
|
|
szMachineName,
|
|
szQueryName,
|
|
dwFlags,
|
|
(LPVOID)pInfoBuffer,
|
|
pdwBufferSize,
|
|
TRUE);
|
|
break;
|
|
|
|
case PDH_LOGSVC_CTRL_REMOVE:
|
|
// call universal string version
|
|
pdhStatus = PdhiLogServiceRemoveCommandT (
|
|
szMachineName,
|
|
szQueryName,
|
|
dwFlags,
|
|
(LPVOID)pInfoBuffer,
|
|
pdwBufferSize,
|
|
TRUE);
|
|
break;
|
|
|
|
case PDH_LOGSVC_CTRL_INFO:
|
|
// call universal string version
|
|
pdhStatus = PdhiLogServiceInfoCommandT (
|
|
szMachineName,
|
|
szQueryName,
|
|
dwFlags,
|
|
(LPVOID)pInfoBuffer,
|
|
pdwBufferSize,
|
|
TRUE);
|
|
break;
|
|
|
|
default:
|
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
return pdhStatus;
|
|
}
|