windows-nt/Source/XPSP1/NT/admin/pchealth/client/common/fhclicfg/fhclicfg.cpp

1763 lines
48 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/******************************************************************************
Copyright (c) 2000 Microsoft Corporation
Module Name:
fhclicfg.cpp
Abstract:
Client configuration class
Revision History:
created derekm 03/31/00
******************************************************************************/
#include "stdafx.h"
#include "pfrcfg.h"
// allow the configuration to be settable
#define ENABLE_SRV_CONFIG_SETTING 1
/////////////////////////////////////////////////////////////////////////////
// defaults
const EEnDis c_eedDefShowUI = eedEnabled;
const EEnDis c_eedDefReport = eedEnabled;
const EIncEx c_eieDefShutdown = eieExclude;
const EEnDis c_eedDefShowUISrv = eedDisabled;
const EEnDis c_eedDefReportSrv = eedDisabled;
const EIncEx c_eieDefShutdownSrv = eieInclude;
const EEnDis c_eedDefTextLog = eedDisabled;
const EIncEx c_eieDefApps = eieInclude;
const EIncEx c_eieDefKernel = eieInclude;
const EIncEx c_eieDefMSApps = eieInclude;
const EIncEx c_eieDefWinComp = eieInclude;
const BOOL c_fForceQueue = FALSE;
const BOOL c_fForceQueueSrv = TRUE;
const DWORD c_cDefHangPipes = c_cMinPipes;
const DWORD c_cDefFaultPipes = c_cMinPipes;
const DWORD c_cDefMaxUserQueue = 10;
#if defined(DEBUG) || defined(_DEBUG)
const DWORD c_dwDefInternal = 1;
#else
const DWORD c_dwDefInternal = 0;
#endif
const WCHAR c_wszDefSrvI[] = L"officewatson";
const WCHAR c_wszDefSrvE[] = L"watson.microsoft.com";
/////////////////////////////////////////////////////////////////////////////
// utility
// **************************************************************************
HRESULT AddToArray(SAppList &sal, SAppItem *psai)
{
USE_TRACING("AddToArray");
HRESULT hr = NOERROR;
DWORD i = sal.cSlotsUsed;
BOOL fUseFreedSlot = FALSE;
// first, skim thru the array & see if there are any empty slots
if (sal.cSlotsEmpty > 0 && sal.rgsai != NULL)
{
for (i = 0; i < sal.cSlotsUsed; i++)
{
if (sal.rgsai[i].wszApp == NULL)
{
sal.cSlotsEmpty--;
fUseFreedSlot = TRUE;
break;
}
}
}
// nope, see if we need to grow the array
if (sal.cSlotsUsed >= sal.cSlots && fUseFreedSlot == FALSE)
{
SAppItem *rgsai = NULL;
DWORD cSlots;
if (sal.cSlots == 0)
cSlots = 16;
else
cSlots = 2 * sal.cSlots;
rgsai = (SAppItem *)MyAlloc(cSlots * sizeof(SAppItem));
VALIDATEEXPR(hr, (rgsai == NULL), E_OUTOFMEMORY);
if (FAILED(hr))
goto done;
if (sal.rgsai != NULL)
{
CopyMemory(rgsai, sal.rgsai, sal.cSlots * sizeof(SAppItem));
MyFree(sal.rgsai);
}
sal.rgsai = rgsai;
sal.cSlots = cSlots;
}
// if we are appending, then gotta increase cSlotsUsed
if (sal.cSlotsUsed == i)
sal.cSlotsUsed++;
sal.rgsai[i].dwState = psai->dwState;
sal.rgsai[i].wszApp = psai->wszApp;
done:
return hr;
}
// **************************************************************************
BOOL ClearCPLDW(HKEY hkeyCPL)
{
DWORD dw;
WCHAR wch = L'\0';
BOOL fCleared = FALSE;
HKEY hkeyDW = NULL;
if (hkeyCPL == NULL)
return TRUE;
// first, try deleting the key. If that succeeded or it doesn't exist,
// then we're done.
dw = RegDeleteKeyW(hkeyCPL, c_wszRKDW);
if (dw == ERROR_SUCCESS || dw == ERROR_PATH_NOT_FOUND ||
dw == ERROR_FILE_NOT_FOUND)
{
fCleared = TRUE;
goto done;
}
// Otherwise, need to open the key
dw = RegOpenKeyExW(hkeyCPL, c_wszRKDW, 0, KEY_READ | KEY_WRITE, &hkeyDW);
if (dw != ERROR_SUCCESS)
goto done;
// try to delete the file path value from it.
dw = RegDeleteValueW(hkeyDW, c_wszRVDumpPath);
if (dw == ERROR_SUCCESS || dw == ERROR_PATH_NOT_FOUND ||
dw == ERROR_FILE_NOT_FOUND)
{
fCleared = TRUE;
goto done;
}
// ok, last try. Try to write an empty string to the value
dw = RegSetValueExW(hkeyDW, c_wszRVDumpPath, 0, REG_SZ, (LPBYTE)wch,
sizeof(wch));
if (dw == ERROR_SUCCESS)
{
fCleared = TRUE;
goto done;
}
done:
if (hkeyDW != NULL)
RegCloseKey(hkeyDW);
return fCleared;
}
/////////////////////////////////////////////////////////////////////////////
// CPFFaultClientCfg- init & term
// **************************************************************************
CPFFaultClientCfg::CPFFaultClientCfg()
{
OSVERSIONINFOEXW osvi;
INIT_TRACING
USE_TRACING("CPFFaultClientCfg::CPFFaultClientCfg");
InitializeCriticalSection(&m_cs);
ZeroMemory(m_wszDump, sizeof(m_wszDump));
ZeroMemory(m_wszSrv, sizeof(m_wszSrv));
ZeroMemory(m_rgLists, sizeof(m_rgLists));
ZeroMemory(&osvi, sizeof(osvi));
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionExW((OSVERSIONINFOW *)&osvi);
if (osvi.wProductType == VER_NT_SERVER)
{
m_eieShutdown = c_eieDefShutdownSrv;
m_fForceQueue = c_fForceQueueSrv;
m_fSrv = TRUE;
}
else
{
m_eieShutdown = c_eieDefShutdown;
m_fForceQueue = c_fForceQueue;
m_fSrv = FALSE;
}
m_eedUI = c_eedDefShowUI;
m_eedReport = c_eedDefReport;
m_eieApps = c_eieDefApps;
m_eedTextLog = c_eedDefTextLog;
m_eieMS = c_eieDefMSApps;
m_eieWin = c_eieDefWinComp;
m_eieKernel = c_eieDefKernel;
m_cFaultPipes = c_cDefFaultPipes;
m_cHangPipes = c_cDefHangPipes;
m_cMaxQueueItems = c_cDefMaxUserQueue;
m_dwStatus = 0;
m_dwDirty = 0;
m_pbWinApps = NULL;
m_fRead = FALSE;
m_fRO = FALSE;
}
// **************************************************************************
CPFFaultClientCfg::~CPFFaultClientCfg(void)
{
this->Clear();
DeleteCriticalSection(&m_cs);
}
// **************************************************************************
void CPFFaultClientCfg::Clear(void)
{
USE_TRACING("CPFFaultClientCfg::Clear");
DWORD i;
for(i = 0; i < epfltListCount; i++)
{
if (m_rgLists[i].hkey != NULL)
RegCloseKey(m_rgLists[i].hkey);
if (m_rgLists[i].rgsai != NULL)
{
DWORD iSlot;
for (iSlot = 0; iSlot < m_rgLists[i].cSlotsUsed; iSlot++)
{
if (m_rgLists[i].rgsai[iSlot].wszApp != NULL)
MyFree(m_rgLists[i].rgsai[iSlot].wszApp);
}
MyFree(m_rgLists[i].rgsai);
}
}
ZeroMemory(m_wszDump, sizeof(m_wszDump));
ZeroMemory(m_wszSrv, sizeof(m_wszSrv));
ZeroMemory(m_rgLists, sizeof(m_rgLists));
if (m_fSrv)
{
m_eieShutdown = c_eieDefShutdownSrv;
m_fForceQueue = c_fForceQueueSrv;
}
else
{
m_eieShutdown = c_eieDefShutdown;
m_fForceQueue = c_fForceQueue;
}
m_eedUI = c_eedDefShowUI;
m_eedReport = c_eedDefReport;
m_eieApps = c_eieDefApps;
m_eedTextLog = c_eedDefTextLog;
m_eieMS = c_eieDefMSApps;
m_eieWin = c_eieDefWinComp;
m_eieKernel = c_eieDefKernel;
m_cFaultPipes = c_cDefFaultPipes;
m_cHangPipes = c_cDefHangPipes;
m_cMaxQueueItems = c_cDefMaxUserQueue;
m_dwStatus = 0;
m_dwDirty = 0;
m_pbWinApps = NULL;
m_fRead = FALSE;
m_fRO = FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CPFFaultClientCfg- exposed
// **************************************************************************
HRESULT CPFFaultClientCfg::Read(EReadOptions ero)
{
USE_TRACING("CPFFaultClientCfg::Read");
CAutoUnlockCS aucs(&m_cs);
HRESULT hr = NOERROR;
WCHAR wch = L'\0', *wszDefSrv;
DWORD cb, dw, i, cKeys = 0, iReport = 0, iShowUI = 0;
DWORD dwOpt;
HKEY rghkeyCfg[2], hkeyCfgDW = NULL, hkeyCPL = NULL;
BOOL fHavePolicy = FALSE;
// this will automatically unlock when the fn exits
aucs.Lock();
dwOpt = (ero == eroCPRW) ? orkWantWrite : 0;
this->Clear();
rghkeyCfg[0] = NULL;
rghkeyCfg[1] = NULL;
// if we open read-only, then we will also try to read from the policy
// settings cuz they override the control panel settings. If the user
// wants write access, then we don't bother cuz we don't support writing
// to the policy keys via this object.
// We use the RegOpenKeyEx function directly here cuz I don't want to
// create the key if it doesn't exist (and that's what OpenRegKey will do)
if (ero == eroPolicyRO)
{
TESTERR(hr, RegOpenKeyExW(HKEY_LOCAL_MACHINE, c_wszRPCfgPolicy, 0,
KEY_READ | KEY_WOW64_64KEY, &rghkeyCfg[0]));
if (SUCCEEDED(hr))
{
cKeys = 1;
fHavePolicy = TRUE;
DBG_MSG("policy found");
}
}
// open the control panel reg key
TESTHR(hr, OpenRegKey(HKEY_LOCAL_MACHINE, c_wszRPCfg, 0,
&rghkeyCfg[cKeys]));
if (SUCCEEDED(hr))
{
// need to check if a filepath exists in the DW control panel key. If
// so, disable reporting & enable the UI (if reporting was enabled)
if (ClearCPLDW(rghkeyCfg[cKeys]) == FALSE)
m_dwStatus |= CPL_CORPPATH_SET;
hkeyCPL = rghkeyCfg[cKeys];
cKeys++;
}
// if we couldn't open either key successfully, then we don't need to do
// anything else. The call to 'this->Clear()' above has already set
// all the values to their defaults.
VALIDATEPARM(hr, (cKeys == 0));
if (FAILED(hr))
{
hr = NOERROR;
goto doneValidate;
}
// read in the report value
cb = sizeof(m_eedReport);
dw = c_eedDefReport;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVDoReport, NULL,
(PBYTE)&m_eedReport, &cb, (PBYTE)&dw, sizeof(dw),
&iReport));
if (FAILED(hr))
goto done;
// read in the ui value
cb = sizeof(m_eedUI);
dw = c_eedDefShowUI;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVShowUI, NULL,
(PBYTE)&m_eedUI, &cb, (PBYTE)&dw, sizeof(dw),
&iShowUI));
if (FAILED(hr))
goto done;
// set the policy info (note that the policy key is always set into
// slot 0 of the array)
if (fHavePolicy)
{
if (iReport == 0)
m_dwStatus |= REPORT_POLICY;
if (iShowUI == 0)
m_dwStatus |= SHOWUI_POLICY;
ErrorTrace(0, " iReport = %d, iShowUI = %d", iReport, iShowUI);
// if we used the default value for reporting (we didn't find the
// 'report' value anywhere) then try to use the control panel settings
// for the rest of the stuff.
if (iReport == 2 && cKeys == 2)
iReport = 1;
// if THAT doesn't exist, just bail cuz all of the other values have
// already been set to their defaults
else if (iReport == 1 && cKeys == 1)
goto doneValidate;
// only use the key where we read the 'DoReport' value from. Don't care
// what the other key has to say...
if (iReport == 1)
{
HKEY hkeySwap = rghkeyCfg[0];
rghkeyCfg[0] = rghkeyCfg[1];
rghkeyCfg[1] = hkeySwap;
DBG_MSG("POLICY and CPL controls INVERTED!!!");
}
cKeys = 1;
}
// read in the inclusion list value
cb = sizeof(m_eieApps);
dw = c_eieDefApps;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVAllNone, NULL,
(PBYTE)&m_eieApps, &cb, (PBYTE)&dw, sizeof(dw)));
if (FAILED(hr))
goto done;
// read in the inc MS value
cb = sizeof(m_eieMS);
dw = c_eieDefMSApps;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVIncMS, NULL,
(PBYTE)&m_eieMS, &cb, (PBYTE)&dw, sizeof(dw)));
if (FAILED(hr))
goto done;
// read in the inc Windows components
cb = sizeof(m_eieWin);
dw = c_eieDefWinComp;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVIncWinComp, NULL,
(PBYTE)&m_eieWin, &cb, (PBYTE)&dw, sizeof(dw)));
if (FAILED(hr))
goto done;
// read in the text log value
cb = sizeof(m_eedTextLog);
dw = c_eedDefTextLog;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVDoTextLog, NULL,
(PBYTE)&m_eedTextLog, &cb, (PBYTE)&dw, sizeof(dw)));
if (FAILED(hr))
goto done;
// read in the include kernel faults value
cb = sizeof(m_eieKernel);
dw = c_eieDefKernel;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVIncKernel, NULL,
(PBYTE)&m_eieKernel, &cb, (PBYTE)&dw,
sizeof(dw)));
if (FAILED(hr))
goto done;
// read in the include shutdown errs value
cb = sizeof(m_eieShutdown);
dw = (m_fSrv) ? c_eieDefShutdownSrv : c_eieDefShutdown;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVIncShutdown, NULL,
(PBYTE)&m_eieShutdown, &cb, (PBYTE)&dw,
sizeof(dw)));
if (FAILED(hr))
goto done;
// read in the # of fault pipes value
cb = sizeof(m_cFaultPipes);
dw = c_cDefFaultPipes;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVNumFaultPipe, NULL,
(PBYTE)&m_cFaultPipes, &cb, (PBYTE)&dw,
sizeof(dw)));
if (FAILED(hr))
goto done;
// read in the # of hang pipes value
cb = sizeof(m_cHangPipes);
dw = c_cDefHangPipes;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVNumHangPipe, NULL,
(PBYTE)&m_cHangPipes, &cb, (PBYTE)&dw,
sizeof(dw)));
if (FAILED(hr))
goto done;
// read in the max queue size value
cb = sizeof(m_cMaxQueueItems);
dw = c_cDefMaxUserQueue;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVMaxQueueSize, NULL,
(PBYTE)&m_cMaxQueueItems, &cb, (PBYTE)&dw,
sizeof(dw)));
if (FAILED(hr))
goto done;
// read in the force queue mode value
cb = sizeof(m_fForceQueue);
dw = (m_fSrv) ? c_fForceQueueSrv : c_fForceQueue;
TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVForceQueue, NULL,
(PBYTE)&m_fForceQueue, &cb, (PBYTE)&dw,
sizeof(dw)));
if (FAILED(hr))
goto done;
m_dwUseInternal=0;
wcscpy(m_wszSrv, c_wszDefSrvE);
// the dump path is stored in the DW reg key, so we need to try to
// open it up. However, we only need this value if we're going
// to go into headless mode
if (m_eedReport == eedEnabled && m_eedUI == eedDisabled)
{
// if the cpl corp path is set, we can't let DW do any reporting...
if ((m_dwStatus & REPORT_POLICY) == 0 &&
(m_dwStatus & CPL_CORPPATH_SET) != 0 &&
m_eedReport == eedEnabled)
m_eedReport = eedDisabled;
if (m_eedReport == eedEnabled)
{
TESTERR(hr, RegOpenKeyExW(rghkeyCfg[0], c_wszRKDW, 0, KEY_READ,
&hkeyCfgDW));
if (SUCCEEDED(hr))
{
// read in the dump path value
cb = sizeof(m_wszDump);
TESTHR(hr, ReadRegEntry(&hkeyCfgDW, 1, c_wszRVDumpPath, NULL,
(PBYTE)m_wszDump, &cb, (PBYTE)&wch,
sizeof(wch)));
if (FAILED(hr))
goto done;
}
}
}
// it's ok if these fail. The code below will correctly deal with the
// situation...
TESTHR(hr, OpenRegKey(rghkeyCfg[0], c_wszRKExList, dwOpt,
&m_rgLists[epfltExclude].hkey));
if (FAILED(hr))
m_rgLists[epfltExclude].hkey = NULL;
TESTHR(hr, OpenRegKey(rghkeyCfg[0], c_wszRKIncList, dwOpt,
&m_rgLists[epfltInclude].hkey));
if (FAILED(hr))
m_rgLists[epfltInclude].hkey = NULL;
hr = NOERROR;
doneValidate:
// validate the data we've read and reset the values to defaults if they
// are outside of the allowable range of values
if (m_eedUI != eedEnabled && m_eedUI != eedDisabled &&
m_eedUI != eedEnabledNoCheck)
m_eedUI = c_eedDefShowUI;
if (m_eedReport != eedEnabled && m_eedReport != eedDisabled)
m_eedReport = c_eedDefReport;
if (m_eedTextLog != eedEnabled && m_eedTextLog != eedDisabled)
m_eedTextLog = c_eedDefTextLog;
if (m_eieApps != eieIncDisabled && m_eieApps != eieExDisabled &&
m_eieApps != eieInclude && m_eieApps != eieExclude)
m_eieApps = c_eieDefApps;
if (m_eieMS != eieInclude && m_eieMS != eieExclude)
m_eieMS = c_eieDefMSApps;
if (m_eieKernel != eieInclude && m_eieKernel != eieExclude)
m_eieKernel = c_eieDefKernel;
if (m_eieShutdown != eieInclude && m_eieShutdown != eieExclude)
m_eieShutdown = (m_fSrv) ? c_eieDefShutdownSrv : c_eieDefShutdown;
if (m_eieWin != eieInclude && m_eieWin != eieExclude)
m_eieWin = c_eieDefWinComp;
if (m_dwUseInternal != 1 && m_dwUseInternal != 0)
m_dwUseInternal = c_dwDefInternal;
if (m_cFaultPipes < c_cMinPipes)
m_cFaultPipes = c_cMinPipes;
else if (m_cFaultPipes > c_cMaxPipes)
m_cFaultPipes = c_cMaxPipes;
if (m_cHangPipes == c_cMinPipes)
m_cHangPipes = c_cMinPipes;
else if (m_cHangPipes > c_cMaxPipes)
m_cHangPipes = c_cMaxPipes;
if (m_cMaxQueueItems > c_cMaxQueue)
m_cMaxQueueItems = c_cMaxQueue;
if (m_fForceQueue != c_fForceQueue && m_fForceQueue != c_fForceQueueSrv)
m_fForceQueue = (m_fSrv) ? c_fForceQueueSrv : c_fForceQueue;
m_fRead = TRUE;
m_fRO = (ero != eroCPRW);
aucs.Unlock();
done:
if (rghkeyCfg[0] != NULL)
RegCloseKey(rghkeyCfg[0]);
if (rghkeyCfg[1] != NULL)
RegCloseKey(rghkeyCfg[1]);
if (hkeyCfgDW != NULL)
RegCloseKey(hkeyCfgDW);
if (FAILED(hr))
this->Clear();
return hr;
}
#ifndef PFCLICFG_LITE
// **************************************************************************
BOOL CPFFaultClientCfg::HasWriteAccess(void)
{
USE_TRACING("CPFFaultClientCfg::HasWriteAccess");
HRESULT hr = NOERROR;
DWORD dwOpt = orkWantWrite;
HKEY hkeyMain = NULL, hkey = NULL;
// attempt to open all the keys we use for the control panal to see if we
// have write access to them. We only do this for the control panal cuz
// this class does not support writing out policy values, just reading
// them...
TESTHR(hr, OpenRegKey(HKEY_LOCAL_MACHINE, c_wszRPCfg, dwOpt, &hkeyMain));
if (FAILED(hr))
goto done;
RegCloseKey(hkey);
hkey = NULL;
TESTHR(hr, OpenRegKey(hkeyMain, c_wszRKExList, dwOpt, &hkey));
if (FAILED(hr))
goto done;
RegCloseKey(hkey);
hkey = NULL;
TESTHR(hr, OpenRegKey(hkeyMain, c_wszRKIncList, dwOpt, &hkey));
if (FAILED(hr))
goto done;
done:
if (hkeyMain != NULL)
RegCloseKey(hkeyMain);
if (hkey != NULL)
RegCloseKey(hkey);
return (SUCCEEDED(hr));
}
// **************************************************************************
HRESULT CPFFaultClientCfg::Write(void)
{
USE_TRACING("CPFFaultClientCfg::Write");
CAutoUnlockCS aucs(&m_cs);
HRESULT hr = NOERROR;
DWORD dwOpt = orkWantWrite;
HKEY hkeyCfg = NULL;
// this will automatically unlock when the fn exits
aucs.Lock();
if (m_fRO)
{
hr = E_ACCESSDENIED;
goto done;
}
TESTHR(hr, OpenRegKey(HKEY_LOCAL_MACHINE, c_wszRPCfg, dwOpt, &hkeyCfg));
if (FAILED(hr))
goto done;
// inclusion / exclusion list value
if ((m_dwDirty & FHCC_ALLNONE) != 0)
{
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVAllNone, 0, REG_DWORD,
(PBYTE)&m_eieApps, sizeof(m_eieApps)));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_ALLNONE;
}
// ms apps in except list value
if ((m_dwDirty & FHCC_INCMS) != 0)
{
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVIncMS, 0, REG_DWORD,
(PBYTE)&m_eieMS, sizeof(m_eieMS)));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_INCMS;
}
// ms apps in except list value
if ((m_dwDirty & FHCC_WINCOMP) != 0)
{
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVIncWinComp, 0, REG_DWORD,
(PBYTE)&m_eieWin, sizeof(m_eieWin)));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_WINCOMP;
}
// show UI value
if ((m_dwDirty & FHCC_SHOWUI) != 0)
{
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVShowUI, 0, REG_DWORD,
(PBYTE)&m_eedUI, sizeof(m_eedUI)));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_SHOWUI;
}
// do reporting value
if ((m_dwDirty & FHCC_DOREPORT) != 0)
{
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVDoReport, 0, REG_DWORD,
(PBYTE)&m_eedReport, sizeof(m_eedReport)));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_DOREPORT;
}
// include kernel faults value
if ((m_dwDirty & FHCC_R0INCLUDE) != 0)
{
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVIncKernel, 0, REG_DWORD,
(PBYTE)&m_eieKernel, sizeof(m_eieKernel)));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_R0INCLUDE;
}
// include shutdown value
if ((m_dwDirty & FHCC_INCSHUTDOWN) != 0)
{
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVIncShutdown, 0, REG_DWORD,
(PBYTE)&m_eieShutdown,
sizeof(m_eieShutdown)));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_INCSHUTDOWN;
}
// # fault pipes value
if ((m_dwDirty & FHCC_NUMFAULTPIPE) != 0)
{
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVNumFaultPipe, 0, REG_DWORD,
(PBYTE)&m_cFaultPipes,
sizeof(m_cFaultPipes)));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_NUMFAULTPIPE;
}
// # hang pipes value
if ((m_dwDirty & FHCC_NUMHANGPIPE) != 0)
{
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVNumHangPipe, 0, REG_DWORD,
(PBYTE)&m_cHangPipes,
sizeof(m_cHangPipes)));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_NUMHANGPIPE;
}
// max user fault queue size value
if ((m_dwDirty & FHCC_QUEUESIZE) != 0)
{
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVMaxQueueSize, 0, REG_DWORD,
(PBYTE)&m_cMaxQueueItems,
sizeof(m_cMaxQueueItems)));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_QUEUESIZE;
}
// default Server value
if ((m_dwDirty & FHCC_DEFSRV) != 0)
{
DWORD cb;
cb = wcslen(m_wszSrv) * sizeof(WCHAR);
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVDefSrv, 0, REG_DWORD,
(PBYTE)m_wszSrv, cb));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_DEFSRV;
}
// dump path value
if ((m_dwDirty & FHCC_DUMPPATH) != 0)
{
DWORD cb;
cb = wcslen(m_wszDump) * sizeof(WCHAR);
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVDumpPath, 0, REG_DWORD,
(PBYTE)m_wszDump, cb));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_DUMPPATH;
}
// force queue mode value
if ((m_dwDirty & FHCC_FORCEQUEUE) != 0)
{
TESTERR(hr, RegSetValueExW(hkeyCfg, c_wszRVForceQueue, 0, REG_DWORD,
(PBYTE)&m_fForceQueue,
sizeof(m_fForceQueue)));
if (FAILED(hr))
goto done;
m_dwDirty &= ~FHCC_FORCEQUEUE;
}
aucs.Unlock();
done:
if (hkeyCfg != NULL)
RegCloseKey(hkeyCfg);
return hr;
}
#endif // PFCLICFG_LITE
// **************************************************************************
BOOL CPFFaultClientCfg::ShouldCollect(LPWSTR wszAppPath, BOOL *pfIsMSApp)
{
USE_TRACING("CPFFaultClientCfg::ShouldCollect");
CAutoUnlockCS aucs(&m_cs);
HRESULT hr = NOERROR;
WCHAR *pwszApp, wszName[MAX_PATH], wszAppPathLocal[MAX_PATH];
DWORD i, cb, dwChecked, dw, dwMS, dwType;
BOOL fCollect = FALSE;
if (wszAppPath == NULL)
{
GetModuleFileNameW(NULL, wszAppPathLocal, sizeofSTRW(wszAppPathLocal));
wszAppPath = wszAppPathLocal;
}
if (pfIsMSApp != NULL)
*pfIsMSApp = FALSE;
aucs.Lock();
if (m_fRead == FALSE)
{
TESTHR(hr, this->Read());
if (FAILED(hr))
goto done;
}
// if we have reporting turned off or the 'programs' checkbox has been cleared
// in the control panel, then we are definitely not reporting
if (m_eedReport == eedDisabled || m_eieApps == eieExDisabled ||
m_eieApps == eieIncDisabled)
{
fCollect = FALSE;
goto done;
}
// get a pointer to the app name
for (pwszApp = wszAppPath + wcslen(wszAppPath);
*pwszApp != L'\\' && pwszApp != wszAppPath;
pwszApp--);
if (*pwszApp == L'\\')
pwszApp++;
// are we collecting everything by default?
if (m_eieApps == eieInclude)
fCollect = TRUE;
if (fCollect == FALSE || pfIsMSApp != NULL)
{
// nope, check if it's another Microsoft app...
dwMS = IsMicrosoftApp(wszAppPath, NULL, 0);
if (dwMS != 0 && pfIsMSApp != NULL)
*pfIsMSApp = TRUE;
// is it a windows component?
if (m_eieWin == eieInclude && (dwMS & APP_WINCOMP) != 0)
fCollect = TRUE;
// is it a MS app?
if (m_eieMS == eieInclude && (dwMS & APP_MSAPP) != 0)
fCollect = TRUE;
}
// see if it's on the inclusion list (only need to do this if we aren't
// already collecting).
// Note that if the value is not a DWORD key or we get back an error
// saying that we don't have enuf space to hold the data, we just assume
// that it should be included.
if (fCollect == FALSE && m_rgLists[epfltInclude].hkey != NULL)
{
cb = sizeof(dwChecked);
dwType = REG_DWORD;
dw = RegQueryValueExW(m_rgLists[epfltInclude].hkey, pwszApp, NULL,
&dwType, (PBYTE)&dwChecked, &cb);
if ((dw == ERROR_SUCCESS &&
(dwChecked == 1 || dwType != REG_DWORD)) ||
dw == ERROR_MORE_DATA)
fCollect = TRUE;
}
// see if it's on the exclusion list (only need to do this if we are going
// to collect something)
// Note that if the value is not a DWORD key or we get back an error
// saying that we don't have enuf space to hold the data, we just assume
// that it should be excluded.
if (fCollect && m_rgLists[epfltExclude].hkey != NULL)
{
cb = sizeof(dwChecked);
dwType = REG_DWORD;
dw = RegQueryValueExW(m_rgLists[epfltExclude].hkey, pwszApp, NULL,
&dwType, (PBYTE)&dwChecked, &cb);
if ((dw == ERROR_SUCCESS &&
(dwChecked == 1 || dwType != REG_DWORD)) ||
dw == ERROR_MORE_DATA)
fCollect = FALSE;
}
done:
return fCollect;
}
/////////////////////////////////////////////////////////////////////////////
// CPFFaultClientCfg- get properties
// **************************************************************************
static inline LPCWSTR get_string(LPWSTR wszOut, LPWSTR wszSrc, int cchOut)
{
LPCWSTR wszRet;
SetLastError(0);
if (wszOut == NULL)
{
wszRet = wszSrc;
}
else
{
wszRet = wszOut;
if (cchOut < lstrlenW(wszSrc))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return NULL;
}
lstrcpyW(wszOut, wszSrc);
}
return wszRet;
}
// **************************************************************************
LPCWSTR CPFFaultClientCfg::get_DumpPath(LPWSTR wsz, int cch)
{
USE_TRACING("CPFFaultClientCfg::get_DumpPath");
CAutoUnlockCS aucs(&m_cs);
aucs.Lock();
return get_string(wsz, m_wszDump, cch);
}
// **************************************************************************
LPCWSTR CPFFaultClientCfg::get_DefaultServer(LPWSTR wsz, int cch)
{
USE_TRACING("CPFFaultClientCfg::get_DefaultServer");
CAutoUnlockCS aucs(&m_cs);
aucs.Lock();
return get_string(wsz, m_wszSrv, cch);
}
#ifndef PFCLICFG_LITE
/////////////////////////////////////////////////////////////////////////////
// CPFFaultClientCfg- set properties
// **************************************************************************
BOOL CPFFaultClientCfg::set_DumpPath(LPCWSTR wsz)
{
USE_TRACING("CPFFaultClientCfg::set_DumpPath");
CAutoUnlockCS aucs(&m_cs);
if (wsz == NULL ||
(wcslen(wsz) + 1) > sizeofSTRW(m_wszDump))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
wcscpy(m_wszDump, wsz);
m_dwDirty |= FHCC_DUMPPATH;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_DefaultServer(LPCWSTR wsz)
{
USE_TRACING("CPFFaultClientCfg::set_DefaultServer");
CAutoUnlockCS aucs(&m_cs);
if (wsz == NULL ||
(wcslen(wsz) + 1) > sizeofSTRW(m_wszSrv))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
wcscpy(m_wszSrv, wsz);
m_dwDirty |= FHCC_DEFSRV;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_ShowUI(EEnDis eed)
{
USE_TRACING("CPFFaultClientCfg::set_ShowUI");
CAutoUnlockCS aucs(&m_cs);
if (eed & ~1 && (DWORD)eed != 3)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
m_eedUI = eed;
m_dwDirty |= FHCC_SHOWUI;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_DoReport(EEnDis eed)
{
USE_TRACING("CPFFaultClientCfg::set_DoReport");
CAutoUnlockCS aucs(&m_cs);
if (eed & ~1)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
m_eedReport = eed;
m_dwDirty |= FHCC_DOREPORT;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_AllOrNone(EIncEx eie)
{
USE_TRACING("CPFFaultClientCfg::set_AllOrNone");
CAutoUnlockCS aucs(&m_cs);
if (eie & ~3)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
m_eieApps = eie;
m_dwDirty |= FHCC_ALLNONE;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_IncMSApps(EIncEx eie)
{
USE_TRACING("CPFFaultClientCfg::set_IncMSApps");
CAutoUnlockCS aucs(&m_cs);
if (eie & ~1)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
m_eieMS = eie;
m_dwDirty |= FHCC_INCMS;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_IncWinComp(EIncEx eie)
{
USE_TRACING("CPFFaultClientCfg::set_IncWinComp");
CAutoUnlockCS aucs(&m_cs);
if (eie & ~1)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
m_eieWin = eie;
m_dwDirty |= FHCC_WINCOMP;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_IncKernel(EIncEx eie)
{
USE_TRACING("CPFFaultClientCfg::set_IncKernel");
CAutoUnlockCS aucs(&m_cs);
if (eie & ~1)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
m_eieKernel = eie;
m_dwDirty |= FHCC_R0INCLUDE;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_IncShutdown(EIncEx eie)
{
USE_TRACING("CPFFaultClientCfg::set_IncShutdown");
CAutoUnlockCS aucs(&m_cs);
if (eie & ~1)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
m_eieShutdown = eie;
m_dwDirty |= FHCC_INCSHUTDOWN;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_ForceQueueMode(BOOL fForceQueueMode)
{
USE_TRACING("CPFFaultClientCfg::set_IncKernel");
CAutoUnlockCS aucs(&m_cs);
if (fForceQueueMode & ~1)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
m_fForceQueue = fForceQueueMode;
m_dwDirty |= FHCC_FORCEQUEUE;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_NumFaultPipes(DWORD cPipes)
{
USE_TRACING("CPFFaultClientCfg::set_NumFaultPipes");
CAutoUnlockCS aucs(&m_cs);
if (cPipes == 0 || cPipes > 8)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
m_cFaultPipes = cPipes;
m_dwDirty |= FHCC_NUMFAULTPIPE;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_NumHangPipes(DWORD cPipes)
{
USE_TRACING("CPFFaultClientCfg::set_NumHangPipes");
CAutoUnlockCS aucs(&m_cs);
if (cPipes == 0 || cPipes > 8)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
m_cHangPipes = cPipes;
m_dwDirty |= FHCC_NUMHANGPIPE;
return TRUE;
}
// **************************************************************************
BOOL CPFFaultClientCfg::set_MaxUserQueueSize(DWORD cItems)
{
USE_TRACING("CPFFaultClientCfg::set_MaxUserQueueSize");
CAutoUnlockCS aucs(&m_cs);
if (cItems == 0 || cItems > 256)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
aucs.Lock();
m_cMaxQueueItems = cItems;
m_dwDirty |= FHCC_QUEUESIZE;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// App lists
// **************************************************************************
HRESULT CPFFaultClientCfg::InitList(EPFListType epflt)
{
USE_TRACING("CPFFaultClientCfg::get_IncListCount");
CAutoUnlockCS aucs(&m_cs);
HRESULT hr = NOERROR;
DWORD cItems = 0;
VALIDATEPARM(hr, (epflt >= epfltListCount));
if (FAILED(hr))
goto done;
aucs.Lock();
if (m_fRead == FALSE)
{
hr = E_FAIL;
goto done;;
}
// if we've already initialized, then just clear the list out & return
if ((m_rgLists[epflt].dwState & epfaaInitialized) != 0)
{
this->ClearChanges(epflt);
m_rgLists[epflt].dwState &= ~epfaaInitialized;
}
if (m_rgLists[epflt].hkey != NULL)
{
TESTERR(hr, RegQueryInfoKeyW(m_rgLists[epflt].hkey, NULL, NULL, NULL,
NULL, NULL, NULL,
&m_rgLists[epflt].cItemsInReg,
&m_rgLists[epflt].cchMaxVal, NULL, NULL,
NULL));
if (FAILED(hr))
goto done;
}
else
{
m_rgLists[epflt].cItemsInReg = 0;
m_rgLists[epflt].cchMaxVal = 0;
}
m_rgLists[epflt].dwState |= epfaaInitialized;
done:
return hr;
}
// **************************************************************************
HRESULT CPFFaultClientCfg::get_ListRegInfo(EPFListType epflt, DWORD *pcbMaxName,
DWORD *pcApps)
{
USE_TRACING("CPFFaultClientCfg::get_ListRegInfo");
CAutoUnlockCS aucs(&m_cs);
HRESULT hr = NOERROR;
VALIDATEPARM(hr, (pcbMaxName == NULL || pcApps == NULL ||
epflt >= epfltListCount));
if (FAILED(hr))
goto done;
aucs.Lock();
*pcbMaxName = 0;
*pcApps = 0;
if (m_fRead == FALSE || (m_rgLists[epflt].dwState & epfaaInitialized) == 0)
{
hr = E_FAIL;
goto done;
}
*pcbMaxName = m_rgLists[epflt].cchMaxVal;
*pcApps = m_rgLists[epflt].cItemsInReg;
done:
return hr;
}
// **************************************************************************
HRESULT CPFFaultClientCfg::get_ListRegApp(EPFListType epflt, DWORD iApp,
LPWSTR wszApp, DWORD cchApp,
DWORD *pdwChecked)
{
USE_TRACING("CPFFaultClientCfg::get_ListApp");
CAutoUnlockCS aucs(&m_cs);
HRESULT hr = NOERROR;
WCHAR wsz[MAX_PATH];
DWORD cchName, cbData, dw, dwType = 0;
VALIDATEPARM(hr, (wszApp == NULL || pdwChecked == NULL ||
epflt >= epfltListCount));
if (FAILED(hr))
goto done;
*wszApp = L'\0';
*pdwChecked = 0;
aucs.Lock();
if (m_fRead == FALSE || (m_rgLists[epflt].dwState & epfaaInitialized) == 0)
{
hr = E_FAIL;
goto done;
}
cchName = cchApp;
cbData = sizeof(DWORD);
dw = RegEnumValueW(m_rgLists[epflt].hkey, iApp, wszApp, &cchName, NULL,
&dwType, (LPBYTE)pdwChecked, &cbData);
if (dw != ERROR_SUCCESS && dw != ERROR_NO_MORE_ITEMS)
{
if (dw == ERROR_MORE_DATA)
{
dw = RegEnumValueW(m_rgLists[epflt].hkey, iApp, wszApp, &cchName,
NULL, NULL, NULL, NULL);
*pdwChecked = 1;
}
TESTERR(hr, dw);
goto done;
}
if (dwType != REG_DWORD || (*pdwChecked != 1 && *pdwChecked != 0))
*pdwChecked = 1;
if (dw == ERROR_NO_MORE_ITEMS)
{
hr = S_FALSE;
goto done;
}
done:
return hr;
}
// **************************************************************************
HRESULT CPFFaultClientCfg::add_ListApp(EPFListType epflt, LPCWSTR wszApp)
{
USE_TRACING("CPFFaultClientCfg::add_ListApp");
CAutoUnlockCS aucs(&m_cs);
SAppItem sai;
HRESULT hr = NOERROR;
LPWSTR wszExe = NULL;
DWORD dw = 0, i;
VALIDATEPARM(hr, (wszApp == NULL || epflt >= epfltListCount));
if (FAILED(hr))
goto done;
aucs.Lock();
if (m_fRO == TRUE)
{
hr = E_ACCESSDENIED;
goto done;
}
if (m_fRead == FALSE || (m_rgLists[epflt].dwState & epfaaInitialized) == 0)
{
hr = E_FAIL;
goto done;
}
// first, check if it's already on the mod list
for (i = 0; i < m_rgLists[epflt].cSlotsUsed; i++)
{
if (m_rgLists[epflt].rgsai[i].wszApp != NULL &&
_wcsicmp(m_rgLists[epflt].rgsai[i].wszApp, wszApp) == 0)
{
SETADD(m_rgLists[epflt].rgsai[i].dwState);
SETCHECK(m_rgLists[epflt].rgsai[i].dwState);
goto done;
}
}
// add it to the list then...
wszExe = (LPWSTR)MyAlloc((wcslen(wszApp) + 1) * sizeof(WCHAR));
VALIDATEEXPR(hr, (wszExe == NULL), E_OUTOFMEMORY);
if (FAILED(hr))
goto done;
wcscpy(wszExe, wszApp);
sai.wszApp = wszExe;
SETADD(sai.dwState);
SETCHECK(sai.dwState);
TESTHR(hr, AddToArray(m_rgLists[epflt], &sai));
if (FAILED(hr))
goto done;
wszExe = NULL;
done:
if (wszExe != NULL)
MyFree(wszExe);
return hr;
}
// **************************************************************************
HRESULT CPFFaultClientCfg::del_ListApp(EPFListType epflt, LPWSTR wszApp)
{
USE_TRACING("CPFFaultClientCfg::del_ListApp");
CAutoUnlockCS aucs(&m_cs);
SAppItem sai;
HRESULT hr = NOERROR;
LPWSTR wszExe = NULL;
DWORD i;
VALIDATEPARM(hr, (wszApp == NULL || epflt >= epfltListCount));
if (FAILED(hr))
goto done;
aucs.Lock();
if (m_fRO == TRUE)
{
hr = E_ACCESSDENIED;
goto done;
}
// first, check if it's already on the mod list for add
for (i = 0; i < m_rgLists[epflt].cSlotsUsed; i++)
{
if (m_rgLists[epflt].rgsai[i].wszApp != NULL &&
_wcsicmp(m_rgLists[epflt].rgsai[i].wszApp, wszApp) == 0)
{
if (m_rgLists[epflt].rgsai[i].dwState & epfaaAdd)
{
// just set the wszApp field to NULL. we'll reuse it
// on the next add to the array (if any)
MyFree(m_rgLists[epflt].rgsai[i].wszApp);
m_rgLists[epflt].rgsai[i].wszApp = NULL;
m_rgLists[epflt].rgsai[i].dwState = 0;
m_rgLists[epflt].cSlotsEmpty++;
}
else
{
SETDEL(m_rgLists[epflt].rgsai[i].dwState);
}
goto done;
}
}
// add it to the list then...
wszExe = (LPWSTR)MyAlloc((wcslen(wszApp) + 1) * sizeof(WCHAR));
VALIDATEEXPR(hr, (wszExe == NULL), E_OUTOFMEMORY);
if (FAILED(hr))
goto done;
wcscpy(wszExe, wszApp);
sai.wszApp = wszExe;
SETDEL(sai.dwState);
TESTHR(hr, AddToArray(m_rgLists[epflt], &sai));
if (FAILED(hr))
goto done;
wszExe = NULL;
done:
if (wszExe != NULL)
MyFree(wszExe);
return hr;
}
// **************************************************************************
HRESULT CPFFaultClientCfg::mod_ListApp(EPFListType epflt, LPWSTR wszApp,
DWORD dwChecked)
{
USE_TRACING("CPFFaultClientCfg::del_ListApp");
CAutoUnlockCS aucs(&m_cs);
SAppItem sai;
HRESULT hr = NOERROR;
LPWSTR wszExe = NULL;
DWORD i;
VALIDATEPARM(hr, (wszApp == NULL || epflt >= epfltListCount));
if (FAILED(hr))
goto done;
aucs.Lock();
if (m_fRO == TRUE)
{
hr = E_ACCESSDENIED;
goto done;
}
// first, check if it's already on the mod list
for (i = 0; i < m_rgLists[epflt].cSlotsUsed; i++)
{
if (m_rgLists[epflt].rgsai[i].wszApp != NULL &&
_wcsicmp(m_rgLists[epflt].rgsai[i].wszApp, wszApp) == 0)
{
if (dwChecked == 0)
{
REMCHECK(m_rgLists[epflt].rgsai[i].dwState);
}
else
{
SETCHECK(m_rgLists[epflt].rgsai[i].dwState);
}
goto done;
}
}
// add it to the list then...
wszExe = (LPWSTR)MyAlloc((wcslen(wszApp) + 1) * sizeof(WCHAR));
VALIDATEEXPR(hr, (wszExe == NULL), E_OUTOFMEMORY);
if (FAILED(hr))
goto done;
wcscpy(wszExe, wszApp);
sai.wszApp = wszExe;
sai.dwState = ((dwChecked == 0) ? epfaaRemCheck : epfaaSetCheck);
TESTHR(hr, AddToArray(m_rgLists[epflt], &sai));
if (FAILED(hr))
goto done;
wszExe = NULL;
done:
if (wszExe != NULL)
MyFree(wszExe);
return hr;
}
// **************************************************************************
HRESULT CPFFaultClientCfg::ClearChanges(EPFListType epflt)
{
USE_TRACING("CPFFaultClientCfg::ClearChanges");
CAutoUnlockCS aucs(&m_cs);
HRESULT hr = NOERROR;
DWORD i;
VALIDATEPARM(hr, (epflt >= epfltListCount));
if (FAILED(hr))
goto done;
aucs.Lock();
if (m_fRead == FALSE || (m_rgLists[epflt].dwState & epfaaInitialized) == 0)
{
hr = E_FAIL;
goto done;
}
if (m_rgLists[epflt].rgsai == NULL)
goto done;
for(i = 0; i < m_rgLists[epflt].cSlotsUsed; i++)
{
m_rgLists[epflt].rgsai[i].dwState = 0;
if (m_rgLists[epflt].rgsai[i].wszApp != NULL)
{
MyFree(m_rgLists[epflt].rgsai[i].wszApp);
m_rgLists[epflt].rgsai[i].wszApp = NULL;
}
}
m_rgLists[epflt].cSlotsUsed = 0;
done:
return hr;
}
// **************************************************************************
HRESULT CPFFaultClientCfg::CommitChanges(EPFListType epflt)
{
USE_TRACING("CPFFaultClientCfg::CommitChanges");
CAutoUnlockCS aucs(&m_cs);
HRESULT hr = NOERROR;
DWORD i, dw;
VALIDATEPARM(hr, (epflt >= epfltListCount));
if (FAILED(hr))
goto done;
aucs.Lock();
if (m_fRO == TRUE)
{
hr = E_ACCESSDENIED;
goto done;
}
if (m_fRead == FALSE || (m_rgLists[epflt].dwState & epfaaInitialized) == 0)
{
hr = E_FAIL;
goto done;
}
if (m_rgLists[epflt].hkey == NULL)
{
hr = E_ACCESSDENIED;
goto done;
}
if (m_rgLists[epflt].rgsai == NULL)
goto done;
// don't need to compress the array. Since we always append & never
// delete out of the array until a commit, once I hit an 'Add', anything
// after that in the array MUST also be an 'Add'.
for (i = 0; i < m_rgLists[epflt].cSlotsUsed; i++)
{
if (m_rgLists[epflt].rgsai[i].wszApp == NULL)
{
m_rgLists[epflt].rgsai[i].dwState = 0;
continue;
}
if ((m_rgLists[epflt].rgsai[i].dwState & epfaaDelete) != 0)
{
dw = RegDeleteValueW(m_rgLists[epflt].hkey,
m_rgLists[epflt].rgsai[i].wszApp);
if (dw != ERROR_SUCCESS && dw != ERROR_FILE_NOT_FOUND)
{
TESTERR(hr, dw);
goto done;
}
}
else
{
DWORD dwChecked;
dwChecked = (ISCHECKED(m_rgLists[epflt].rgsai[i].dwState)) ? 1 : 0;
TESTERR(hr, RegSetValueExW(m_rgLists[epflt].hkey,
m_rgLists[epflt].rgsai[i].wszApp, 0,
REG_DWORD, (LPBYTE)&dwChecked,
sizeof(DWORD)));
if (FAILED(hr))
goto done;
}
MyFree(m_rgLists[epflt].rgsai[i].wszApp);
m_rgLists[epflt].rgsai[i].wszApp = NULL;
m_rgLists[epflt].rgsai[i].dwState = 0;
}
m_rgLists[epflt].cSlotsUsed = 0;
done:
return hr;
}
// **************************************************************************
BOOL CPFFaultClientCfg::IsOnList(EPFListType epflt, LPCWSTR wszApp)
{
USE_TRACING("CPFFaultClientCfg::IsOnList");
SAppList *psap;
HRESULT hr = NOERROR;
DWORD i;
HKEY hkey = NULL;
VALIDATEPARM(hr, (epflt >= epfltListCount || wszApp == NULL));
if (FAILED(hr))
goto done;
if ((m_rgLists[epflt].dwState & epfaaInitialized) == 0)
{
hr = E_FAIL;
goto done;
}
// first, check the mod list. This is because if we check the registry
// first, we miss the case where the user just deleted it and it's
// therefore sitting in the mod list
hr = S_FALSE;
for (i = 0; i < m_rgLists[epflt].cSlotsUsed; i++)
{
if (m_rgLists[epflt].rgsai[i].wszApp != NULL &&
_wcsicmp(m_rgLists[epflt].rgsai[i].wszApp, wszApp) == 0)
{
if ((m_rgLists[epflt].rgsai[i].dwState & epfaaDelete) == 0)
hr = NOERROR;
goto done;
}
}
// next, check the registry.
TESTERR(hr, RegQueryValueExW(m_rgLists[epflt].hkey, wszApp, NULL, NULL,
NULL, NULL));
if (SUCCEEDED(hr))
goto done;
done:
return (hr == NOERROR);
}
#endif PFCLICFG_LITE