/****************************************************************************** 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" #include // allow the configuration to be settable #define ENABLE_SRV_CONFIG_SETTING 1 ///////////////////////////////////////////////////////////////////////////// // tracing #ifdef THIS_FILE #undef THIS_FILE #endif static char __szTraceSourceFile[] = __FILE__; #define THIS_FILE __szTraceSourceFile ///////////////////////////////////////////////////////////////////////////// // 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; ErrorTrace(0, "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; ErrorTrace(0, "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; #ifndef NOTRACE // in for debug builds... // this would remove our "security risk" registry entries... // read in whether to use the internal server or not cb = sizeof(m_dwUseInternal); dw = c_dwDefInternal; TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVInternalSrv, NULL, (PBYTE)&m_dwUseInternal, &cb, (PBYTE)&dw, sizeof(dw))); if (FAILED(hr)) goto done; // get the default server wszDefSrv = (WCHAR *)((m_dwUseInternal == 1) ? c_wszDefSrvI : c_wszDefSrvE); if (m_dwUseInternal == 1 && m_fSrv) { cb = sizeof(m_wszSrv); dw = (wcslen(wszDefSrv) + 1) * sizeof(WCHAR); TESTHR(hr, ReadRegEntry(rghkeyCfg, cKeys, c_wszRVDefSrv, NULL, (PBYTE)m_wszSrv, &cb, (PBYTE)wszDefSrv, dw)); if (FAILED(hr)) goto done; } else { StringCbCopyW(m_wszSrv, sizeof(m_wszSrv), wszDefSrv); } #endif // force to normal behavior. (old code is commented out above) m_dwUseInternal = 0; StringCbCopyW(m_wszSrv, sizeof(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 <= 0) 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] = {0}; DWORD i, cb, dwChecked, dw, dwMS, dwType; BOOL fCollect = FALSE; if (wszAppPath == NULL) { if (GetModuleFileNameW(NULL, wszAppPathLocal, sizeofSTRW(wszAppPathLocal)-1) == 0) { goto done; } wszAppPathLocal[sizeofSTRW(wszAppPathLocal)-1]=0; 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; } StringCchCopyW(wszOut, cchOut, 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(); StringCbCopyW(m_wszDump, sizeof(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(); StringCbCopyW(m_wszSrv, sizeof(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 > c_cMaxQueue) { 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, cb; 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(cb = ((wcslen(wszApp) + 1) * sizeof(WCHAR))); VALIDATEEXPR(hr, (wszExe == NULL), E_OUTOFMEMORY); if (FAILED(hr)) goto done; StringCbCopyW(wszExe, cb, 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, cb; 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(cb = ((wcslen(wszApp) + 1) * sizeof(WCHAR))); VALIDATEEXPR(hr, (wszExe == NULL), E_OUTOFMEMORY); if (FAILED(hr)) goto done; StringCbCopyW(wszExe, cb, 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, cb; 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(cb = ((wcslen(wszApp) + 1) * sizeof(WCHAR))); VALIDATEEXPR(hr, (wszExe == NULL), E_OUTOFMEMORY); if (FAILED(hr)) goto done; StringCbCopyW(wszExe, cb, 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