windows-nt/Source/XPSP1/NT/sdktools/pdh/pdhlog/log_ctrl.c

1182 lines
41 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}