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.
668 lines
18 KiB
668 lines
18 KiB
/*****************************************************************************\
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
\*****************************************************************************/
|
|
|
|
#include <assert.h>
|
|
#include <windows.h>
|
|
#include <string.h>
|
|
#include <tchar.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <pdh.h>
|
|
|
|
#include <pdhp.h>
|
|
#include <ntsecapi.h>
|
|
|
|
#include <shlwapi.h>
|
|
#include <shlwapip.h>
|
|
|
|
#include "plogman.h"
|
|
|
|
PDH_FUNCTION
|
|
PlaiReadRegistryPlaTime (
|
|
HKEY hKey,
|
|
LPCWSTR cwszValueName,
|
|
PPLA_TIME_INFO pstiData
|
|
)
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD dwType = 0;
|
|
DWORD dwBufferSize = 0;
|
|
PLA_TIME_INFO slqLocal;
|
|
|
|
memset (&slqLocal, 0, sizeof(PLA_TIME_INFO));
|
|
|
|
dwStatus = RegQueryValueExW (
|
|
hKey,
|
|
cwszValueName,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwBufferSize );
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
if ( (dwBufferSize == sizeof(PLA_TIME_INFO)) && ( REG_BINARY == dwType ) ) {
|
|
// then there's something to read
|
|
dwType = 0;
|
|
dwStatus = RegQueryValueExW (
|
|
hKey,
|
|
cwszValueName,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)&slqLocal,
|
|
&dwBufferSize);
|
|
} else {
|
|
// nothing to read
|
|
dwStatus = ERROR_NO_DATA;
|
|
}
|
|
}
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
*pstiData = slqLocal;
|
|
}
|
|
|
|
return PlaiErrorToPdhStatus( dwStatus );
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PlaiWriteRegistryPlaTime (
|
|
HKEY hKey,
|
|
LPCWSTR cwszValueName,
|
|
PPLA_TIME_INFO pstiData
|
|
)
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD dwValue = sizeof(PLA_TIME_INFO);
|
|
|
|
dwStatus = RegSetValueExW (
|
|
hKey,
|
|
cwszValueName,
|
|
0L,
|
|
REG_BINARY,
|
|
(CONST BYTE *)pstiData,
|
|
dwValue);
|
|
|
|
return PlaiErrorToPdhStatus( dwStatus );
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PlaiReadRegistryDwordValue (
|
|
HKEY hKey,
|
|
LPCWSTR cwszValueName,
|
|
LPDWORD pdwValue
|
|
)
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD dwValue = sizeof(DWORD);
|
|
DWORD dwType = 0;
|
|
DWORD dwBufferSize = 0;
|
|
|
|
dwStatus = RegQueryValueExW (
|
|
hKey,
|
|
cwszValueName,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwBufferSize );
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
if ( ( dwBufferSize == sizeof(DWORD) )
|
|
&& ( ( REG_DWORD == dwType ) || ( REG_BINARY == dwType ) ) ) {
|
|
// then there's something to read
|
|
dwType = 0;
|
|
dwStatus = RegQueryValueExW (
|
|
hKey,
|
|
cwszValueName,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)&dwValue,
|
|
&dwBufferSize);
|
|
} else {
|
|
// nothing to read
|
|
dwStatus = ERROR_NO_DATA;
|
|
}
|
|
} // else hr has error.
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
*pdwValue = dwValue;
|
|
}
|
|
|
|
return PlaiErrorToPdhStatus( dwStatus );
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PlaiWriteRegistryDwordValue (
|
|
HKEY hKey,
|
|
LPCWSTR cwszValueName,
|
|
LPDWORD pdwValue
|
|
)
|
|
{
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD dwValue = sizeof(DWORD);
|
|
|
|
dwStatus = RegSetValueExW (
|
|
hKey,
|
|
cwszValueName,
|
|
0L,
|
|
dwType,
|
|
(CONST BYTE *)pdwValue,
|
|
dwValue);
|
|
|
|
return PlaiErrorToPdhStatus( dwStatus );
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PlaiReadRegistryStringValue(
|
|
HKEY hKey,
|
|
LPCWSTR strKey,
|
|
DWORD dwFlags,
|
|
LPWSTR* pszBuffer,
|
|
DWORD* dwBufLen
|
|
)
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD dwDataType;
|
|
DWORD dwDataSize = 0;
|
|
LPWSTR pBuffer;
|
|
|
|
dwStatus = RegQueryValueExW(
|
|
hKey,
|
|
strKey,
|
|
NULL,
|
|
&dwDataType,
|
|
(LPBYTE)NULL,
|
|
(LPDWORD)&dwDataSize
|
|
);
|
|
|
|
if( (dwFlags & READ_REG_MUI) ){
|
|
if( dwDataSize < 1024 ){
|
|
dwDataSize = 1024;
|
|
}
|
|
dwStatus = ERROR_SUCCESS;
|
|
}
|
|
|
|
if( ERROR_SUCCESS == dwStatus ){
|
|
|
|
pBuffer = *pszBuffer;
|
|
|
|
if( pBuffer == NULL || dwDataSize > G_SIZE(pBuffer) ){
|
|
|
|
if( pBuffer != NULL ){
|
|
pBuffer = (LPWSTR)G_REALLOC( pBuffer, dwDataSize );
|
|
}else{
|
|
pBuffer = (LPWSTR)G_ALLOC( dwDataSize );
|
|
}
|
|
|
|
if( pBuffer ){
|
|
*pszBuffer = pBuffer;
|
|
}else{
|
|
G_FREE( (*pszBuffer) );
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if( dwFlags & READ_REG_MUI ){
|
|
|
|
const int cBuffer = 512;
|
|
WCHAR strKeyIndirect[cBuffer];
|
|
LPWSTR szIndirect = L" Indirect";
|
|
|
|
if( wcslen(strKey) + wcslen( szIndirect ) + sizeof(WCHAR ) > cBuffer ){
|
|
dwStatus = ERROR_INVALID_DATA;
|
|
}else{
|
|
StringCchPrintfW( strKeyIndirect, cBuffer, L"%s%s", strKey, szIndirect );
|
|
|
|
dwStatus = SHLoadRegUIStringW (
|
|
hKey,
|
|
strKeyIndirect,
|
|
*pszBuffer,
|
|
dwDataSize/sizeof(WCHAR)
|
|
);
|
|
|
|
if( ERROR_SUCCESS == dwStatus ){
|
|
*dwBufLen = (DWORD)((char*)&(*pszBuffer)[wcslen(*pszBuffer)]
|
|
- (char*)&(*pszBuffer)[0]);
|
|
*dwBufLen += sizeof(WCHAR);
|
|
}else{
|
|
*dwBufLen = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if( !(dwFlags & READ_REG_MUI) ||
|
|
((dwFlags & READ_REG_MUI) && ERROR_SUCCESS != dwStatus) ){
|
|
|
|
dwStatus = RegQueryValueExW(
|
|
hKey,
|
|
strKey,
|
|
NULL,
|
|
&dwDataType,
|
|
(LPBYTE)*pszBuffer,
|
|
(LPDWORD)&dwDataSize
|
|
);
|
|
|
|
if( dwStatus == ERROR_SUCCESS ){
|
|
*dwBufLen = dwDataSize;
|
|
}else{
|
|
*dwBufLen = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( ERROR_SUCCESS == dwStatus && !(dwFlags&READ_REG_BLOB) ){
|
|
(*pszBuffer)[(*dwBufLen/sizeof(WCHAR))-1] = L'\0';
|
|
}
|
|
|
|
return PlaiErrorToPdhStatus( dwStatus );
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PlaiWriteRegistryStringValue (
|
|
HKEY hKey,
|
|
LPCWSTR cwszValueName,
|
|
DWORD dwType,
|
|
LPCWSTR pszBuffer,
|
|
DWORD cbBufferLength
|
|
)
|
|
{
|
|
// writes the contents of pszBuffer to szValue under hKey
|
|
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
CONST BYTE *pLclBuffer;
|
|
|
|
if ( NULL == pszBuffer ) {
|
|
// substitute an empty string
|
|
pLclBuffer = (CONST BYTE *)L"\0";
|
|
cbBufferLength = sizeof(WCHAR);
|
|
} else {
|
|
// use args passed in
|
|
pLclBuffer = (CONST BYTE *)pszBuffer;
|
|
if( cbBufferLength == 0 ){
|
|
cbBufferLength = BYTE_SIZE( pszBuffer ) + (DWORD)sizeof(UNICODE_NULL);
|
|
}
|
|
}
|
|
|
|
dwStatus = RegSetValueExW (hKey,
|
|
cwszValueName,
|
|
0L,
|
|
dwType,
|
|
(CONST BYTE *)pLclBuffer,
|
|
cbBufferLength );
|
|
|
|
return PlaiErrorToPdhStatus( dwStatus );
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PlaiWriteRegistryLastModified( HKEY hkeyQuery )
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
|
|
PLA_TIME_INFO plqLastModified;
|
|
SYSTEMTIME stLocalTime;
|
|
FILETIME ftModified;
|
|
|
|
RegFlushKey( hkeyQuery );
|
|
|
|
dwStatus = RegQueryInfoKey (
|
|
hkeyQuery,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&ftModified );
|
|
|
|
if( ERROR_SUCCESS != dwStatus ) {
|
|
GetLocalTime (&stLocalTime);
|
|
SystemTimeToFileTime (&stLocalTime, &ftModified);
|
|
}
|
|
|
|
plqLastModified.wDataType = PLA_TT_DTYPE_DATETIME;
|
|
plqLastModified.wTimeType = PLA_TT_TTYPE_LAST_MODIFIED;
|
|
plqLastModified.dwAutoMode = PLA_AUTO_MODE_NONE;
|
|
plqLastModified.llDateTime = *(LONGLONG *)&ftModified;
|
|
|
|
if( ERROR_SUCCESS == dwStatus ){
|
|
return PlaiWriteRegistryPlaTime (
|
|
hkeyQuery,
|
|
L"Last Modified",
|
|
&plqLastModified
|
|
);
|
|
}
|
|
|
|
return PlaiErrorToPdhStatus( dwStatus );
|
|
}
|
|
|
|
DWORD
|
|
PlaiCreateQuery(
|
|
HKEY hkeyMachine,
|
|
HKEY& rhkeyLogQueries
|
|
)
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
HKEY hkeySysmonLog;
|
|
DWORD dwDisposition;
|
|
|
|
rhkeyLogQueries = NULL;
|
|
|
|
dwStatus = RegOpenKeyExW (
|
|
hkeyMachine,
|
|
L"System\\CurrentControlSet\\Services\\SysmonLog",
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hkeySysmonLog);
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
// Create registry subkey for Log Queries
|
|
dwStatus = RegCreateKeyExW (
|
|
hkeySysmonLog,
|
|
L"Log Queries",
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE,
|
|
NULL,
|
|
&rhkeyLogQueries,
|
|
&dwDisposition);
|
|
|
|
RegCloseKey( hkeySysmonLog );
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiPlaGetVersion(
|
|
LPCWSTR strComputer,
|
|
PPLA_VERSION pVersion )
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
HKEY hkeyMachine = HKEY_LOCAL_MACHINE;
|
|
HKEY hkeyQuery = NULL;
|
|
DWORD cbBufferSize = 0;
|
|
DWORD dwType;
|
|
WCHAR szRegValue[MAX_PATH];
|
|
PLA_VERSION version;
|
|
|
|
ZeroMemory( &version, sizeof(PLA_VERSION) );
|
|
|
|
if ( NULL != strComputer ) {
|
|
if ( wcslen( strComputer) ) {
|
|
|
|
dwStatus = RegConnectRegistryW (
|
|
strComputer,
|
|
HKEY_LOCAL_MACHINE,
|
|
&hkeyMachine
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
|
|
dwStatus = RegOpenKeyExW (
|
|
hkeyMachine,
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion",
|
|
0,
|
|
KEY_READ,
|
|
&hkeyQuery
|
|
);
|
|
|
|
if( ERROR_SUCCESS == dwStatus ){
|
|
dwStatus = RegQueryValueExW (
|
|
hkeyQuery,
|
|
L"CurrentVersion",
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&cbBufferSize
|
|
);
|
|
|
|
if( ERROR_SUCCESS == dwStatus ) {
|
|
if( (MAX_PATH*sizeof(WCHAR) > cbBufferSize ) &&
|
|
(sizeof(WCHAR) < cbBufferSize) &&
|
|
(REG_SZ == dwType ) )
|
|
{
|
|
ZeroMemory ( szRegValue, MAX_PATH );
|
|
|
|
dwStatus = RegQueryValueExW (
|
|
hkeyQuery,
|
|
L"CurrentVersion",
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)szRegValue,
|
|
&cbBufferSize
|
|
);
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
version.dwMajorVersion = _wtol ( szRegValue );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( ERROR_SUCCESS == dwStatus ){
|
|
dwStatus = RegQueryValueExW (
|
|
hkeyQuery,
|
|
L"CurrentBuildNumber",
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&cbBufferSize
|
|
);
|
|
|
|
if( ERROR_SUCCESS == dwStatus ) {
|
|
if( (MAX_PATH*sizeof(WCHAR) > cbBufferSize ) &&
|
|
(sizeof(WCHAR) < cbBufferSize) &&
|
|
(REG_SZ == dwType ) )
|
|
{
|
|
ZeroMemory ( szRegValue, MAX_PATH );
|
|
|
|
dwStatus = RegQueryValueExW (
|
|
hkeyQuery,
|
|
L"CurrentBuildNumber",
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)szRegValue,
|
|
&cbBufferSize
|
|
);
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
version.dwBuild = _wtol ( szRegValue );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
memcpy( pVersion, &version, sizeof(PLA_VERSION) );
|
|
|
|
if ( NULL != hkeyMachine && HKEY_LOCAL_MACHINE != hkeyMachine ) {
|
|
RegCloseKey ( hkeyMachine );
|
|
}
|
|
|
|
if( NULL != hkeyQuery ){
|
|
RegCloseKey( hkeyQuery );
|
|
}
|
|
|
|
return PlaiErrorToPdhStatus( dwStatus );
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PlaiConnectToRegistry(
|
|
LPCWSTR strComputer,
|
|
HKEY& rhkeyLogQueries,
|
|
BOOL bQueries,
|
|
BOOL bWrite )
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
HKEY hkeyMachine = HKEY_LOCAL_MACHINE;
|
|
|
|
if ( NULL != strComputer ) {
|
|
if( wcslen( strComputer ) ){
|
|
dwStatus = RegConnectRegistryW (
|
|
strComputer,
|
|
HKEY_LOCAL_MACHINE,
|
|
&hkeyMachine );
|
|
}
|
|
}
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
if( bQueries ){
|
|
if ( bWrite ) {
|
|
dwStatus = RegOpenKeyExW (
|
|
hkeyMachine,
|
|
L"System\\CurrentControlSet\\Services\\SysmonLog\\Log Queries",
|
|
0,
|
|
KEY_READ|KEY_WRITE,
|
|
&rhkeyLogQueries );
|
|
}else{
|
|
dwStatus = RegOpenKeyExW (
|
|
hkeyMachine,
|
|
L"System\\CurrentControlSet\\Services\\SysmonLog\\Log Queries",
|
|
0,
|
|
KEY_READ,
|
|
&rhkeyLogQueries );
|
|
}
|
|
}else{
|
|
dwStatus = RegOpenKeyExW (
|
|
hkeyMachine,
|
|
L"System\\CurrentControlSet\\Services\\SysmonLog",
|
|
0,
|
|
KEY_READ,
|
|
&rhkeyLogQueries );
|
|
}
|
|
|
|
if ( ERROR_SUCCESS != dwStatus ) {
|
|
dwStatus = PlaiCreateQuery( hkeyMachine, rhkeyLogQueries );
|
|
}
|
|
}
|
|
|
|
if ( NULL != hkeyMachine && HKEY_LOCAL_MACHINE != hkeyMachine ) {
|
|
RegCloseKey ( hkeyMachine );
|
|
}
|
|
|
|
return PlaiErrorToPdhStatus( dwStatus );
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PlaiConnectAndLockQuery (
|
|
LPCWSTR strComputer,
|
|
LPCWSTR strQuery,
|
|
HKEY& rhkeyQuery,
|
|
BOOL bWrite )
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
|
HKEY hkeyQuery = NULL;
|
|
HKEY hkeyLogQueries = NULL;
|
|
|
|
rhkeyQuery = NULL;
|
|
dwStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhPlaMutex);
|
|
|
|
if( ERROR_SUCCESS == dwStatus || WAIT_ABANDONED == dwStatus ){
|
|
|
|
pdhStatus = PlaiConnectToRegistry (
|
|
strComputer,
|
|
hkeyLogQueries,
|
|
TRUE,
|
|
bWrite
|
|
);
|
|
|
|
if( ERROR_SUCCESS == pdhStatus ){
|
|
DWORD nCollections = 0;
|
|
DWORD nMaxSubKeyLength = 0;
|
|
|
|
dwStatus = RegQueryInfoKey(
|
|
hkeyLogQueries,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&nCollections,
|
|
&nMaxSubKeyLength,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if( ERROR_SUCCESS == dwStatus ){
|
|
|
|
LPWSTR strCollection;
|
|
LPWSTR strQueryName = NULL;
|
|
DWORD dwQueryName = 0;
|
|
|
|
DWORD dwSize = (sizeof(WCHAR)*(nMaxSubKeyLength+1));
|
|
|
|
strCollection = (LPWSTR)G_ALLOC( dwSize );
|
|
|
|
if( strCollection ){
|
|
|
|
dwStatus = ERROR_FILE_NOT_FOUND;
|
|
|
|
for( ULONG i = 0; i<nCollections; i++ ){
|
|
dwStatus = RegEnumKey( hkeyLogQueries, i, strCollection, dwSize );
|
|
if( ERROR_SUCCESS == dwStatus ) {
|
|
|
|
dwStatus = RegOpenKeyExW (
|
|
hkeyLogQueries,
|
|
strCollection,
|
|
0,
|
|
bWrite ? KEY_READ | KEY_WRITE : KEY_READ,
|
|
&hkeyQuery
|
|
);
|
|
|
|
if( ERROR_SUCCESS == dwStatus ){
|
|
if( !_wcsicmp( strCollection, strQuery ) ){
|
|
break;
|
|
}
|
|
|
|
PlaiReadRegistryStringValue( hkeyQuery, szCollection, READ_REG_MUI, &strQueryName, &dwQueryName );
|
|
|
|
if( strQueryName != NULL && !_wcsicmp( strQueryName, strQuery ) ){
|
|
break;
|
|
}
|
|
dwStatus = ERROR_FILE_NOT_FOUND;
|
|
if ( NULL != hkeyQuery ) {
|
|
RegCloseKey ( hkeyQuery );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
G_FREE( strQueryName );
|
|
G_FREE( strCollection );
|
|
|
|
}else{
|
|
dwStatus = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( NULL != hkeyLogQueries ){
|
|
RegCloseKey ( hkeyLogQueries );
|
|
}
|
|
|
|
if( ERROR_SUCCESS != dwStatus || ERROR_SUCCESS != pdhStatus){
|
|
RELEASE_MUTEX( hPdhPlaMutex );
|
|
}else{
|
|
rhkeyQuery = hkeyQuery;
|
|
}
|
|
}
|
|
|
|
if( ERROR_SUCCESS != pdhStatus ){
|
|
return pdhStatus;
|
|
}else{
|
|
return PlaiErrorToPdhStatus( dwStatus );
|
|
}
|
|
}
|