Leaked source code of windows server 2003
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.
 
 
 
 
 
 

16224 lines
504 KiB

#include "gptext.h"
#include <initguid.h>
#include "Policy.h"
#include "smartptr.h"
#include "wbemtime.h"
#include <strsafe.h>
#define RSOP_HELP_FILE TEXT("gpedit.hlp")
//
// ADM directory name
//
const TCHAR g_szADM[] = TEXT("Adm");
const TCHAR g_szNull[] = TEXT("");
const TCHAR g_szStrings[] = TEXT("strings");
const TCHAR szIFDEF[] = TEXT("#ifdef");
const TCHAR szIF[] = TEXT("#if");
const TCHAR szENDIF[] = TEXT("#endif");
const TCHAR szIFNDEF[] = TEXT("#ifndef");
const TCHAR szELSE[] = TEXT("#else");
const TCHAR szVERSION[] = TEXT("version");
const TCHAR szLT[] = TEXT("<");
const TCHAR szLTE[] = TEXT("<=");
const TCHAR szGT[] = TEXT(">");
const TCHAR szGTE[] = TEXT(">=");
const TCHAR szEQ[] = TEXT("==");
const TCHAR szNE[] = TEXT("!=");
const TCHAR szLISTBOX[] = TEXT("LISTBOX");
const TCHAR szEDIT[] = TEXT("EDIT");
const TCHAR szBUTTON[] = TEXT("BUTTON");
const TCHAR szSTATIC[] = TEXT("STATIC");
const TCHAR szCLASS[] = TEXT("CLASS");
const TCHAR szCATEGORY[] = TEXT("CATEGORY");
const TCHAR szPOLICY[] = TEXT("POLICY");
const TCHAR szUSER[] = TEXT("USER");
const TCHAR szMACHINE[] = TEXT("MACHINE");
const TCHAR szCHECKBOX[] = TEXT("CHECKBOX");
const TCHAR szTEXT[] = TEXT("TEXT");
const TCHAR szEDITTEXT[] = TEXT("EDITTEXT");
const TCHAR szNUMERIC[] = TEXT("NUMERIC");
const TCHAR szCOMBOBOX[] = TEXT("COMBOBOX");
const TCHAR szDROPDOWNLIST[] = TEXT("DROPDOWNLIST");
const TCHAR szUPDOWN[] = UPDOWN_CLASS;
const TCHAR szKEYNAME[] = TEXT("KEYNAME");
const TCHAR szVALUENAME[] = TEXT("VALUENAME");
const TCHAR szNAME[] = TEXT("NAME");
const TCHAR szEND[] = TEXT("END");
const TCHAR szPART[] = TEXT("PART");
const TCHAR szSUGGESTIONS[] = TEXT("SUGGESTIONS");
const TCHAR szDEFCHECKED[] = TEXT("DEFCHECKED");
const TCHAR szDEFAULT[] = TEXT("DEFAULT");
const TCHAR szMAXLENGTH[] = TEXT("MAXLEN");
const TCHAR szMIN[] = TEXT("MIN");
const TCHAR szMAX[] = TEXT("MAX");
const TCHAR szSPIN[] = TEXT("SPIN");
const TCHAR szREQUIRED[] = TEXT("REQUIRED");
const TCHAR szOEMCONVERT[] = TEXT("OEMCONVERT");
const TCHAR szTXTCONVERT[] = TEXT("TXTCONVERT");
const TCHAR szEXPANDABLETEXT[] = TEXT("EXPANDABLETEXT");
const TCHAR szVALUEON[] = TEXT("VALUEON");
const TCHAR szVALUEOFF[] = TEXT("VALUEOFF");
const TCHAR szVALUE[] = TEXT("VALUE");
const TCHAR szACTIONLIST[] = TEXT("ACTIONLIST");
const TCHAR szACTIONLISTON[] = TEXT("ACTIONLISTON");
const TCHAR szACTIONLISTOFF[] = TEXT("ACTIONLISTOFF");
const TCHAR szDELETE[] = TEXT("DELETE");
const TCHAR szITEMLIST[] = TEXT("ITEMLIST");
const TCHAR szSOFT[] = TEXT("SOFT");
const TCHAR szVALUEPREFIX[] = TEXT("VALUEPREFIX");
const TCHAR szADDITIVE[] = TEXT("ADDITIVE");
const TCHAR szEXPLICITVALUE[] = TEXT("EXPLICITVALUE");
const TCHAR szNOSORT[] = TEXT("NOSORT");
const TCHAR szHELP[] = TEXT("EXPLAIN");
const TCHAR szCLIENTEXT[] = TEXT("CLIENTEXT");
const TCHAR szSUPPORTED[] = TEXT("SUPPORTED");
const TCHAR szStringsSect[] = TEXT("[strings]");
const TCHAR szStrings[] = TEXT("strings");
const TCHAR szDELETEPREFIX[] = TEXT("**del.");
const TCHAR szSOFTPREFIX[] = TEXT("**soft.");
const TCHAR szDELVALS[] = TEXT("**delvals.");
const TCHAR szNOVALUE[] = TEXT(" ");
const TCHAR szUserPrefKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy Editor");
const TCHAR szPoliciesKey[] = TEXT("Software\\Policies\\Microsoft\\Windows\\Group Policy Editor");
const TCHAR szDefaultTemplates[] = TEXT("DefaultTemplates");
const TCHAR szAdditionalTemplates[] = TEXT("AdditionalTemplates");
// list of legal keyword entries in "CATEGORY" section
KEYWORDINFO pCategoryEntryCmpList[] = { {szKEYNAME,KYWD_ID_KEYNAME},
{szCATEGORY,KYWD_ID_CATEGORY},{szPOLICY,KYWD_ID_POLICY},
{szEND,KYWD_ID_END},{szHELP,KYWD_ID_HELP}, {NULL,0} };
KEYWORDINFO pCategoryTypeCmpList[] = { {szCATEGORY,KYWD_ID_CATEGORY},
{NULL,0} };
// list of legal keyword entries in "POLICY" section
KEYWORDINFO pPolicyEntryCmpList[] = { {szKEYNAME,KYWD_ID_KEYNAME},
{szVALUENAME,KYWD_ID_VALUENAME}, {szPART,KYWD_ID_PART},
{szVALUEON,KYWD_ID_VALUEON},{szVALUEOFF,KYWD_ID_VALUEOFF},
{szACTIONLISTON,KYWD_ID_ACTIONLISTON},{szACTIONLISTOFF,KYWD_ID_ACTIONLISTOFF},
{szEND,KYWD_ID_END},{szHELP,KYWD_ID_HELP}, {szCLIENTEXT,KYWD_ID_CLIENTEXT},
{szSUPPORTED,KYWD_ID_SUPPORTED}, {NULL, 0} };
KEYWORDINFO pPolicyTypeCmpList[] = { {szPOLICY,KYWD_ID_POLICY}, {NULL,0} };
// list of legal keyword entries in "PART" section
KEYWORDINFO pSettingsEntryCmpList[] = { {szCHECKBOX,KYWD_ID_CHECKBOX},
{szTEXT,KYWD_ID_TEXT},{szEDITTEXT,KYWD_ID_EDITTEXT},
{szNUMERIC,KYWD_ID_NUMERIC},{szCOMBOBOX,KYWD_ID_COMBOBOX},
{szDROPDOWNLIST,KYWD_ID_DROPDOWNLIST},{szLISTBOX,KYWD_ID_LISTBOX},
{szEND,KYWD_ID_END}, {szCLIENTEXT,KYWD_ID_CLIENTEXT}, {NULL,0}};
KEYWORDINFO pSettingsTypeCmpList[] = {{szPART,KYWD_ID_PART},{NULL,0}};
KEYWORDINFO pCheckboxCmpList[] = {
{szKEYNAME,KYWD_ID_KEYNAME},{szVALUENAME,KYWD_ID_VALUENAME},
{szVALUEON,KYWD_ID_VALUEON},{szVALUEOFF,KYWD_ID_VALUEOFF},
{szACTIONLISTON,KYWD_ID_ACTIONLISTON},{szACTIONLISTOFF,KYWD_ID_ACTIONLISTOFF},
{szDEFCHECKED, KYWD_ID_DEFCHECKED}, {szCLIENTEXT,KYWD_ID_CLIENTEXT},
{szEND,KYWD_ID_END},{NULL,0} };
KEYWORDINFO pTextCmpList[] = {{szEND,KYWD_ID_END},{NULL,0}};
KEYWORDINFO pEditTextCmpList[] = {
{szKEYNAME,KYWD_ID_KEYNAME},{szVALUENAME,KYWD_ID_VALUENAME},
{szDEFAULT,KYWD_ID_EDITTEXT_DEFAULT},
{szREQUIRED,KYWD_ID_REQUIRED},{szMAXLENGTH,KYWD_ID_MAXLENGTH},
{szOEMCONVERT,KYWD_ID_OEMCONVERT},{szSOFT,KYWD_ID_SOFT},
{szEND,KYWD_ID_END},{szEXPANDABLETEXT,KYWD_ID_EXPANDABLETEXT},
{szCLIENTEXT,KYWD_ID_CLIENTEXT}, {NULL,0} };
KEYWORDINFO pComboboxCmpList[] = {
{szKEYNAME,KYWD_ID_KEYNAME},{szVALUENAME,KYWD_ID_VALUENAME},
{szDEFAULT,KYWD_ID_COMBOBOX_DEFAULT},{szSUGGESTIONS,KYWD_ID_SUGGESTIONS},
{szREQUIRED,KYWD_ID_REQUIRED},{szMAXLENGTH,KYWD_ID_MAXLENGTH},
{szOEMCONVERT,KYWD_ID_OEMCONVERT},{szSOFT,KYWD_ID_SOFT},
{szEND,KYWD_ID_END},{szNOSORT, KYWD_ID_NOSORT},
{szEXPANDABLETEXT,KYWD_ID_EXPANDABLETEXT},{szCLIENTEXT,KYWD_ID_CLIENTEXT}, {NULL,0} };
KEYWORDINFO pNumericCmpList[] = {
{szKEYNAME,KYWD_ID_KEYNAME},{szVALUENAME,KYWD_ID_VALUENAME},
{szMIN, KYWD_ID_MIN},{szMAX,KYWD_ID_MAX},{szSPIN,KYWD_ID_SPIN},
{szDEFAULT,KYWD_ID_NUMERIC_DEFAULT},{szREQUIRED,KYWD_ID_REQUIRED},
{szTXTCONVERT,KYWD_ID_TXTCONVERT},{szSOFT,KYWD_ID_SOFT},
{szEND,KYWD_ID_END}, {szCLIENTEXT,KYWD_ID_CLIENTEXT}, {NULL,0} };
KEYWORDINFO pDropdownlistCmpList[] = {
{szKEYNAME,KYWD_ID_KEYNAME},{szVALUENAME,KYWD_ID_VALUENAME},
{szREQUIRED,KYWD_ID_REQUIRED},{szITEMLIST,KYWD_ID_ITEMLIST},
{szEND,KYWD_ID_END},{szNOSORT, KYWD_ID_NOSORT},{szCLIENTEXT,KYWD_ID_CLIENTEXT}, {NULL,0}};
KEYWORDINFO pListboxCmpList[] = {
{szKEYNAME,KYWD_ID_KEYNAME},{szVALUEPREFIX,KYWD_ID_VALUEPREFIX},
{szADDITIVE,KYWD_ID_ADDITIVE},{szNOSORT, KYWD_ID_NOSORT},
{szEXPLICITVALUE,KYWD_ID_EXPLICITVALUE},{szEXPANDABLETEXT,KYWD_ID_EXPANDABLETEXT},
{szEND,KYWD_ID_END},{szCLIENTEXT,KYWD_ID_CLIENTEXT}, {NULL,0} };
KEYWORDINFO pClassCmpList[] = { {szCLASS, KYWD_ID_CLASS},
{szCATEGORY,KYWD_ID_CATEGORY}, {szStringsSect,KYWD_ID_STRINGSSECT},
{NULL,0} };
KEYWORDINFO pClassTypeCmpList[] = { {szUSER, KYWD_ID_USER},
{szMACHINE,KYWD_ID_MACHINE}, {NULL,0} };
KEYWORDINFO pVersionCmpList[] = { {szVERSION, KYWD_ID_VERSION}, {NULL,0}};
KEYWORDINFO pOperatorCmpList[] = { {szGT, KYWD_ID_GT}, {szGTE,KYWD_ID_GTE},
{szLT, KYWD_ID_LT}, {szLTE,KYWD_ID_LTE}, {szEQ,KYWD_ID_EQ},
{szNE, KYWD_ID_NE}, {NULL,0}};
//
// Help ID's
//
DWORD aADMHelpIds[] = {
// Templates dialog
IDC_TEMPLATELIST, (IDH_HELPFIRST + 0),
IDC_ADDTEMPLATES, (IDH_HELPFIRST + 1),
IDC_REMOVETEMPLATES, (IDH_HELPFIRST + 2),
0, 0
};
DWORD aPolicyHelpIds[] = {
// ADM Policy UI page
IDC_NOCONFIG, (IDH_HELPFIRST + 11),
IDC_ENABLED, (IDH_HELPFIRST + 12),
IDC_DISABLED, (IDH_HELPFIRST + 13),
IDC_POLICY_PREVIOUS, (IDH_HELPFIRST + 14),
IDC_POLICY_NEXT, (IDH_HELPFIRST + 15),
0, 0
};
DWORD aExplainHelpIds[] = {
// Explain page
IDC_POLICY_PREVIOUS, (IDH_HELPFIRST + 14),
IDC_POLICY_NEXT, (IDH_HELPFIRST + 15),
0, 0
};
DWORD aPrecedenceHelpIds[] = {
// Precedence page
IDC_POLICY_PRECEDENCE, (IDH_HELPFIRST + 16),
IDC_POLICY_PREVIOUS, (IDH_HELPFIRST + 14),
IDC_POLICY_NEXT, (IDH_HELPFIRST + 15),
0, 0
};
DWORD aFilteringHelpIds[] = {
// Filtering options
IDC_STATIC, (DWORD) (-1), // disabled help
IDC_FILTERING_ICON, (DWORD) (-1), // disabled help
IDC_SUPPORTEDONTITLE, (DWORD) (-1), // disabled help
IDC_SUPPORTEDOPTION, (IDH_HELPFIRST + 20),
IDC_FILTERLIST, (IDH_HELPFIRST + 21),
IDC_SELECTALL, (IDH_HELPFIRST + 22),
IDC_DESELECTALL, (IDH_HELPFIRST + 23),
IDC_SHOWCONFIG, (IDH_HELPFIRST + 24),
IDC_SHOWPOLICIES, (IDH_HELPFIRST + 25),
0, 0
};
#define ADM_USELOCAL_KEY TEXT("Software\\Policies\\Microsoft\\Windows\\Group Policy")
#define GPE_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy Editor")
#define GPE_POLICIES_KEY TEXT("Software\\Policies\\Microsoft\\Windows\\Group Policy Editor")
#define ADM_USELOCAL_VALUE TEXT("OnlyUseLocalAdminFiles")
#define POLICYONLY_VALUE TEXT("ShowPoliciesOnly")
#define DISABLE_AUTOUPDATE_VALUE TEXT("DisableAutoADMUpdate")
#define SOFTWARE_POLICIES TEXT("Software\\Policies")
#define WINDOWS_POLICIES TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies")
typedef struct _GPOERRORINFO
{
DWORD dwError;
LPTSTR lpMsg;
LPTSTR lpDetails;
} GPOERRORINFO, *LPGPOERRORINFO;
//
// Help ids
//
DWORD aErrorHelpIds[] =
{
0, 0
};
LPHASHTABLE CreateHashTable (void);
VOID FreeHashTable (LPHASHTABLE lpTable);
ULONG CalculateHashInfo(LPTSTR lpName, DWORD dwChars, DWORD *pdwHashValue);
BOOL AddHashEntry (LPHASHTABLE lpTable, LPTSTR lpName, DWORD dwChars);
LPTSTR FindHashEntry (LPHASHTABLE lpTable, LPTSTR lpName, DWORD dwChars);
#if DBG
VOID DumpHashTableDetails (LPHASHTABLE lpTable);
#endif
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicyComponentData object implementation //
// //
///////////////////////////////////////////////////////////////////////////////
CPolicyComponentData::CPolicyComponentData(BOOL bUser, BOOL bRSOP)
{
TCHAR szEvent[200];
HRESULT hr = S_OK;
m_cRef = 1;
InterlockedIncrement(&g_cRefThisDll);
m_hwndFrame = NULL;
m_pScope = NULL;
m_pConsole = NULL;
m_hRoot = NULL;
m_hSWPolicies = NULL;
m_pGPTInformation = NULL;
m_pRSOPInformation = NULL;
m_pRSOPRegistryData = NULL;
m_pszNamespace = NULL;
m_bUserScope = bUser;
m_bRSOP = bRSOP;
m_pMachineCategoryList = NULL;
m_nMachineDataItems = 0;
m_pUserCategoryList = NULL;
m_nUserDataItems = 0;
m_pSupportedStrings = 0;
m_iSWPoliciesLen = lstrlen(SOFTWARE_POLICIES);
m_iWinPoliciesLen = lstrlen(WINDOWS_POLICIES);
m_bUseSupportedOnFilter = FALSE;
m_pDefaultHashTable = NULL;
m_pLanguageHashTable = NULL;
m_pLocaleHashTable = NULL;
if (bRSOP)
{
m_bShowConfigPoliciesOnly = TRUE;
}
else
{
m_bShowConfigPoliciesOnly = FALSE;
}
m_pSnapin = NULL;
m_hTemplateThread = NULL;
hr = StringCchPrintf (szEvent, ARRAYSIZE(szEvent), TEXT("gptext: ADM files ready event, %d:%d"), bUser, GetTickCount());
ASSERT(SUCCEEDED(hr));
m_ADMEvent = CreateEvent (NULL, TRUE, FALSE, szEvent);
if (!m_ADMEvent)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::CPolicyComponentData: Failed to create ADM event with %d."),
GetLastError()));
}
LoadString (g_hInstance, IDS_POLICY_NAME, m_szRootName, ROOT_NAME_SIZE);
m_pExtraSettingsRoot = NULL;
m_bExtraSettingsInitialized = FALSE;
}
CPolicyComponentData::~CPolicyComponentData()
{
//
// Wait for the Template thread to finish before continuing.
//
if (m_hTemplateThread)
WaitForSingleObject(m_hTemplateThread, INFINITE);
FreeTemplates ();
if (m_pExtraSettingsRoot)
{
FreeTable ((TABLEENTRY *)m_pExtraSettingsRoot);
}
if (m_pScope)
{
m_pScope->Release();
}
if (m_pConsole)
{
m_pConsole->Release();
}
if (m_pGPTInformation)
{
m_pGPTInformation->Release();
}
if (m_pRSOPInformation)
{
m_pRSOPInformation->Release();
}
if (m_pRSOPRegistryData)
{
FreeRSOPRegistryData();
}
if (m_pszNamespace)
{
LocalFree (m_pszNamespace);
}
CloseHandle (m_ADMEvent);
if (m_hTemplateThread)
CloseHandle (m_hTemplateThread);
m_hTemplateThread = NULL;
InterlockedDecrement(&g_cRefThisDll);
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicyComponentData object implementation (IUnknown) //
// //
///////////////////////////////////////////////////////////////////////////////
HRESULT CPolicyComponentData::QueryInterface (REFIID riid, void **ppv)
{
if (IsEqualIID(riid, IID_IComponentData) || IsEqualIID(riid, IID_IUnknown))
{
*ppv = (LPCOMPONENT)this;
m_cRef++;
return S_OK;
}
else if (IsEqualIID(riid, IID_IExtendContextMenu))
{
*ppv = (LPEXTENDCONTEXTMENU)this;
m_cRef++;
return S_OK;
}
else if (IsEqualIID(riid, IID_IPersistStreamInit))
{
*ppv = (LPPERSISTSTREAMINIT)this;
m_cRef++;
return S_OK;
}
else if (IsEqualIID(riid, IID_ISnapinHelp))
{
*ppv = (LPSNAPINHELP)this;
m_cRef++;
return S_OK;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
}
ULONG CPolicyComponentData::AddRef (void)
{
return ++m_cRef;
}
ULONG CPolicyComponentData::Release (void)
{
if (--m_cRef == 0) {
delete this;
return 0;
}
return m_cRef;
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicyComponentData object implementation (IComponentData) //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPolicyComponentData::Initialize(LPUNKNOWN pUnknown)
{
HRESULT hr;
HBITMAP bmp16x16;
LPIMAGELIST lpScopeImage;
//
// QI for IConsoleNameSpace
//
hr = pUnknown->QueryInterface(IID_IConsoleNameSpace2, (LPVOID *)&m_pScope);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::Initialize: Failed to QI for IConsoleNameSpace.")));
return hr;
}
//
// QI for IConsole
//
hr = pUnknown->QueryInterface(IID_IConsole, (LPVOID *)&m_pConsole);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::Initialize: Failed to QI for IConsole.")));
m_pScope->Release();
m_pScope = NULL;
return hr;
}
m_pConsole->GetMainWindow (&m_hwndFrame);
//
// Query for the scope imagelist interface
//
hr = m_pConsole->QueryScopeImageList(&lpScopeImage);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::Initialize: Failed to QI for scope imagelist.")));
m_pScope->Release();
m_pScope = NULL;
m_pConsole->Release();
m_pConsole=NULL;
return hr;
}
// Load the bitmaps from the dll
bmp16x16=LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_16x16));
// Set the images
lpScopeImage->ImageListSetStrip(reinterpret_cast<LONG_PTR *>(bmp16x16),
reinterpret_cast<LONG_PTR *>(bmp16x16),
0, RGB(255, 0, 255));
lpScopeImage->Release();
//
// Create the root of the Extra Settings node if appropriate
//
if (m_bRSOP)
{
DWORD dwBufSize;
REGITEM *pTmp;
TCHAR szBuffer[100];
m_pExtraSettingsRoot = (REGITEM *) GlobalAlloc(GPTR, sizeof(REGITEM));
if (!m_pExtraSettingsRoot)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::Initialize: GlobalAlloc failed with %d"), GetLastError()));
return HRESULT_FROM_WIN32(GetLastError());
}
m_pExtraSettingsRoot->dwSize = sizeof(REGITEM);
m_pExtraSettingsRoot->dwType = (ETYPE_ROOT | ETYPE_REGITEM);
LoadString (g_hInstance, IDS_EXTRAREGSETTINGS, szBuffer, ARRAYSIZE(szBuffer));
pTmp = (REGITEM *) AddDataToEntry((TABLEENTRY *)m_pExtraSettingsRoot,
(BYTE *)szBuffer,(lstrlen(szBuffer)+1) * sizeof(TCHAR),&(m_pExtraSettingsRoot->uOffsetName),
&dwBufSize);
if (!pTmp)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::Initialize: AddDataToEntry failed.")));
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
m_pExtraSettingsRoot = pTmp;
}
return S_OK;
}
STDMETHODIMP CPolicyComponentData::Destroy(VOID)
{
return S_OK;
}
STDMETHODIMP CPolicyComponentData::CreateComponent(LPCOMPONENT *ppComponent)
{
HRESULT hr;
CPolicySnapIn *pSnapIn;
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::CreateComponent: Entering.")));
//
// Initialize
//
*ppComponent = NULL;
//
// Create the snapin view
//
pSnapIn = new CPolicySnapIn(this);
if (!pSnapIn)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::CreateComponent: Failed to create CPolicySnapIn.")));
return E_OUTOFMEMORY;
}
//
// QI for IComponent
//
hr = pSnapIn->QueryInterface(IID_IComponent, (LPVOID *)ppComponent);
pSnapIn->Release(); // release QI
m_pSnapin = pSnapIn;
return hr;
}
STDMETHODIMP CPolicyComponentData::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
LPDATAOBJECT* ppDataObject)
{
HRESULT hr = E_NOINTERFACE;
CPolicyDataObject *pDataObject;
LPPOLICYDATAOBJECT pPolicyDataObject;
//
// Create a new DataObject
//
pDataObject = new CPolicyDataObject(this); // ref == 1
if (!pDataObject)
return E_OUTOFMEMORY;
//
// QI for the private GPTDataObject interface so we can set the cookie
// and type information.
//
hr = pDataObject->QueryInterface(IID_IPolicyDataObject, (LPVOID *)&pPolicyDataObject);
if (FAILED(hr))
{
pDataObject->Release();
return (hr);
}
pPolicyDataObject->SetType(type);
pPolicyDataObject->SetCookie(cookie);
pPolicyDataObject->Release();
//
// QI for a normal IDataObject to return.
//
hr = pDataObject->QueryInterface(IID_IDataObject, (LPVOID *)ppDataObject);
pDataObject->Release(); // release initial ref
return hr;
}
STDMETHODIMP CPolicyComponentData::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
{
HRESULT hr = S_OK;
switch(event)
{
case MMCN_REMOVE_CHILDREN:
if ( ((HSCOPEITEM)arg != NULL) && m_bRSOP && (m_pRSOPInformation != NULL) )
{
if ( (m_hRoot == NULL) || ((HSCOPEITEM)arg == m_hRoot) )
{
FreeRSOPRegistryData();
m_hRoot = NULL;
m_hSWPolicies = NULL;
m_pRSOPInformation->Release();
m_pRSOPInformation = NULL;
}
}
break;
case MMCN_EXPAND:
if (arg == TRUE)
if (m_bRSOP)
{
if ( m_pRSOPInformation == NULL )
{
lpDataObject->QueryInterface(IID_IRSOPInformation, (LPVOID *)&m_pRSOPInformation);
if (m_pRSOPInformation)
{
m_pszNamespace = (LPOLESTR) LocalAlloc (LPTR, 350 * sizeof(TCHAR));
if (m_pszNamespace)
{
if (m_pRSOPInformation->GetNamespace((m_bUserScope ? GPO_SECTION_USER : GPO_SECTION_MACHINE),
m_pszNamespace, 350) == S_OK)
{
InitializeRSOPRegistryData();
// Check if there are any entries
if ( m_pRSOPRegistryData == NULL )
{
LocalFree( m_pszNamespace );
m_pszNamespace = NULL;
m_pRSOPInformation->Release();
m_pRSOPInformation = NULL;
}
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::Notify: Failed to query for namespace")));
LocalFree (m_pszNamespace);
m_pszNamespace = NULL;
}
}
}
}
if (m_pszNamespace && m_pRSOPRegistryData)
{
hr = EnumerateScopePane(lpDataObject, (HSCOPEITEM)param);
}
}
else
{
if (!m_pGPTInformation)
{
lpDataObject->QueryInterface(IID_IGPEInformation, (LPVOID *)&m_pGPTInformation);
}
if (m_pGPTInformation)
{
hr = EnumerateScopePane(lpDataObject, (HSCOPEITEM)param);
}
}
break;
default:
break;
}
return hr;
}
STDMETHODIMP CPolicyComponentData::GetDisplayInfo(LPSCOPEDATAITEM pItem)
{
TABLEENTRY * pTableEntry;
if (pItem == NULL)
return E_POINTER;
if (pItem->lParam == 0)
{
pItem->displayname = m_szRootName;
}
else
{
pTableEntry = (TABLEENTRY *)(pItem->lParam);
pItem->displayname = GETNAMEPTR(pTableEntry);
}
return S_OK;
}
STDMETHODIMP CPolicyComponentData::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
{
HRESULT hr = S_FALSE;
LPPOLICYDATAOBJECT pPolicyDataObjectA, pPolicyDataObjectB;
MMC_COOKIE cookie1, cookie2;
if (lpDataObjectA == NULL || lpDataObjectB == NULL)
return E_POINTER;
//
// QI for the private GPTDataObject interface
//
if (FAILED(lpDataObjectA->QueryInterface(IID_IPolicyDataObject,
(LPVOID *)&pPolicyDataObjectA)))
{
return S_FALSE;
}
if (FAILED(lpDataObjectB->QueryInterface(IID_IPolicyDataObject,
(LPVOID *)&pPolicyDataObjectB)))
{
pPolicyDataObjectA->Release();
return S_FALSE;
}
pPolicyDataObjectA->GetCookie(&cookie1);
pPolicyDataObjectB->GetCookie(&cookie2);
if (cookie1 == cookie2)
{
hr = S_OK;
}
pPolicyDataObjectA->Release();
pPolicyDataObjectB->Release();
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicyComponentData object implementation (IExtendContextMenu) //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPolicyComponentData::AddMenuItems(LPDATAOBJECT piDataObject,
LPCONTEXTMENUCALLBACK pCallback,
LONG *pInsertionAllowed)
{
HRESULT hr = S_OK;
TCHAR szMenuItem[100];
TCHAR szDescription[250];
CONTEXTMENUITEM item;
LPPOLICYDATAOBJECT pPolicyDataObject;
MMC_COOKIE cookie = -1;
DATA_OBJECT_TYPES type = CCT_UNINITIALIZED;
if (!m_bRSOP)
{
if (SUCCEEDED(piDataObject->QueryInterface(IID_IPolicyDataObject,
(LPVOID *)&pPolicyDataObject)))
{
pPolicyDataObject->GetType(&type);
pPolicyDataObject->GetCookie(&cookie);
pPolicyDataObject->Release();
}
if ((type == CCT_SCOPE) && (cookie == 0))
{
LoadString (g_hInstance, IDS_TEMPLATES, szMenuItem, 100);
LoadString (g_hInstance, IDS_TEMPLATESDESC, szDescription, 250);
item.strName = szMenuItem;
item.strStatusBarText = szDescription;
item.lCommandID = IDM_TEMPLATES;
item.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP;
item.fFlags = 0;
item.fSpecialFlags = 0;
hr = pCallback->AddItem(&item);
if (FAILED(hr))
return (hr);
item.strName = szMenuItem;
item.strStatusBarText = szDescription;
item.lCommandID = IDM_TEMPLATES2;
item.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TASK;
item.fFlags = 0;
item.fSpecialFlags = 0;
hr = pCallback->AddItem(&item);
}
}
return (hr);
}
STDMETHODIMP CPolicyComponentData::Command(LONG lCommandID, LPDATAOBJECT piDataObject)
{
if ((lCommandID == IDM_TEMPLATES) || (lCommandID == IDM_TEMPLATES2))
{
m_bTemplatesColumn = 0;
if (DialogBoxParam (g_hInstance, MAKEINTRESOURCE(IDD_TEMPLATES),
m_hwndFrame, TemplatesDlgProc, (LPARAM) this))
{
//
// Refresh the adm namespace
//
PostMessage (HWND_BROADCAST, m_pSnapin->m_uiRefreshMsg, 0, (LPARAM) GetCurrentProcessId());
}
}
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicyComponentData object implementation (IPersistStreamInit) //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPolicyComponentData::GetClassID(CLSID *pClassID)
{
if (!pClassID)
{
return E_FAIL;
}
if (m_bUserScope)
*pClassID = CLSID_PolicySnapInUser;
else
*pClassID = CLSID_PolicySnapInMachine;
return S_OK;
}
STDMETHODIMP CPolicyComponentData::IsDirty(VOID)
{
return S_FALSE;
}
STDMETHODIMP CPolicyComponentData::Load(IStream *pStm)
{
return S_OK;
}
STDMETHODIMP CPolicyComponentData::Save(IStream *pStm, BOOL fClearDirty)
{
return S_OK;
}
STDMETHODIMP CPolicyComponentData::GetSizeMax(ULARGE_INTEGER *pcbSize)
{
DWORD dwSize = 0;
if (!pcbSize)
{
return E_FAIL;
}
ULISet32(*pcbSize, dwSize);
return S_OK;
}
STDMETHODIMP CPolicyComponentData::InitNew(void)
{
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicyComponentData object implementation (ISnapinHelp) //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPolicyComponentData::GetHelpTopic(LPOLESTR *lpCompiledHelpFile)
{
LPOLESTR lpHelpFile;
lpHelpFile = (LPOLESTR) CoTaskMemAlloc (MAX_PATH * sizeof(WCHAR));
if (!lpHelpFile)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::GetHelpTopic: Failed to allocate memory.")));
return E_OUTOFMEMORY;
}
ExpandEnvironmentStringsW (L"%SystemRoot%\\Help\\gptext.chm",
lpHelpFile, MAX_PATH);
*lpCompiledHelpFile = lpHelpFile;
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicyComponentData object implementation (Internal functions) //
// //
///////////////////////////////////////////////////////////////////////////////
HRESULT CPolicyComponentData::EnumerateScopePane (LPDATAOBJECT lpDataObject, HSCOPEITEM hParent)
{
SCOPEDATAITEM item;
HRESULT hr;
TABLEENTRY *pTemp = NULL;
DWORD dwResult;
CPolicySnapIn * pSnapin = NULL, *pSnapinTemp;
BOOL bRootItem = FALSE;
HANDLE hEvents[1];
if (!m_hRoot)
{
DWORD dwID;
m_hRoot = hParent;
m_hTemplateThread = CreateThread (NULL, 0,
(LPTHREAD_START_ROUTINE) LoadTemplatesThread,
(LPVOID) this, 0, &dwID);
if (m_hTemplateThread)
{
SetThreadPriority(m_hTemplateThread, THREAD_PRIORITY_LOWEST);
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::EnumerateScopePane: Failed to create adm thread with %d"),
GetLastError()));
LoadTemplates();
}
}
if (m_hRoot == hParent)
{
item.mask = SDI_STR | SDI_STATE | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM | SDI_CHILDREN;
item.displayname = MMC_CALLBACK;
item.nImage = 0;
item.nOpenImage = 1;
item.nState = 0;
item.cChildren = 1;
item.lParam = 0;
item.relativeID = hParent;
m_pScope->Expand(hParent);
if (SUCCEEDED(m_pScope->InsertItem (&item)))
{
m_hSWPolicies = item.ID;
}
return S_OK;
}
hEvents[0] = m_ADMEvent;
if (WaitForSingleObject (m_ADMEvent, 250) != WAIT_OBJECT_0)
{
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::EnumerateScopePane: Waiting for ADM event to be signaled.")));
for (;;) {
SetCursor (LoadCursor(NULL, IDC_WAIT));
dwResult = MsgWaitForMultipleObjects(1, hEvents, FALSE, INFINITE, QS_ALLINPUT);
if (dwResult == WAIT_OBJECT_0 ) {
break;
}
else if (dwResult == WAIT_OBJECT_0 + 1 ) {
MSG msg;
while ( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else {
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::EnumerateScopePane: MsgWaitForMultipleObjects returned %d ."), dwResult));
break;
}
}
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::EnumerateScopePane: ADM event has been signaled.")));
SetCursor (LoadCursor(NULL, IDC_ARROW));
}
item.mask = SDI_PARAM;
item.ID = hParent;
hr = m_pScope->GetItem (&item);
if (FAILED(hr))
return hr;
EnterCriticalSection (&g_ADMCritSec);
if (item.lParam)
{
pTemp = ((TABLEENTRY *)item.lParam)->pChild;
}
else
{
bRootItem = TRUE;
if (m_bUserScope)
{
if (m_pUserCategoryList)
{
pTemp = m_pUserCategoryList->pChild;
}
else
{
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::EnumerateScopePane: Empty user list.")));
}
}
else
{
if (m_pMachineCategoryList)
{
pTemp = m_pMachineCategoryList->pChild;
}
else
{
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::EnumerateScopePane: Empty machine list.")));
}
}
}
//
// If the user has set the focus on a adm node and then saves the console file,
// the IComponent won't be created yet. We need to create a temporary IComponent
// to parse the data and then release it.
//
if (m_pSnapin)
{
pSnapinTemp = m_pSnapin;
}
else
{
pSnapinTemp = pSnapin = new CPolicySnapIn(this);
}
while (pTemp)
{
if (pTemp->dwType == ETYPE_CATEGORY)
{
BOOL bAdd = TRUE;
if (m_bUseSupportedOnFilter)
{
bAdd = IsAnyPolicyAllowedPastFilter(pTemp);
}
if (bAdd && m_bShowConfigPoliciesOnly)
{
if (pSnapinTemp)
{
bAdd = pSnapinTemp->IsAnyPolicyEnabled(pTemp);
}
}
if (bAdd)
{
m_pScope->Expand(hParent);
item.mask = SDI_STR | SDI_STATE | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM | SDI_CHILDREN;
item.displayname = MMC_CALLBACK;
item.nImage = 0;
item.nOpenImage = 1;
item.nState = 0;
item.cChildren = (CheckForChildCategories(pTemp) ? 1 : 0);
item.lParam = (LPARAM) pTemp;
item.relativeID = hParent;
m_pScope->InsertItem (&item);
}
}
pTemp = pTemp->pNext;
}
//
// Add the Extra Registry Settings node if appropriate
//
if (bRootItem && m_pExtraSettingsRoot)
{
if (!m_bExtraSettingsInitialized)
{
InitializeExtraSettings();
m_bExtraSettingsInitialized = TRUE;
if (LOWORD(dwDebugLevel) == DL_VERBOSE)
{
DumpRSOPRegistryData();
}
}
if (m_pExtraSettingsRoot->pChild)
{
m_pScope->Expand(hParent);
item.mask = SDI_STR | SDI_STATE | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM | SDI_CHILDREN;
item.displayname = MMC_CALLBACK;
item.nImage = 0;
item.nOpenImage = 1;
item.nState = 0;
item.cChildren = 0;
item.lParam = (LPARAM) m_pExtraSettingsRoot;
item.relativeID = hParent;
m_pScope->InsertItem (&item);
}
}
if (pSnapin)
{
pSnapin->Release();
}
LeaveCriticalSection (&g_ADMCritSec);
return S_OK;
}
BOOL CPolicyComponentData::CheckForChildCategories (TABLEENTRY *pParent)
{
TABLEENTRY * pTemp;
if (pParent->pChild)
{
pTemp = pParent->pChild;
while (pTemp)
{
if (pTemp->dwType == ETYPE_CATEGORY)
{
return TRUE;
}
pTemp = pTemp->pNext;
}
}
return FALSE;
}
#if DBG
//
// These are a couple of debugging helper functions that will dump
// the adm namespace to the debugger. Call DumpCurrentTable() to
// get the full namespace.
//
VOID CPolicyComponentData::DumpEntry (TABLEENTRY * pEntry, UINT uIndent)
{
UINT i;
TCHAR szDebug[50];
if (!pEntry)
return;
if (pEntry == (TABLEENTRY*) ULongToPtr(0xfeeefeee))
{
OutputDebugString (TEXT("Invalid memory address found.\r\n"));
return;
}
while (pEntry)
{
if ((pEntry->dwType & ETYPE_CATEGORY) || (pEntry->dwType & ETYPE_POLICY))
{
for (i=0; i<uIndent; i++)
OutputDebugString(TEXT(" "));
OutputDebugString (GETNAMEPTR(pEntry));
if (pEntry->pNext && pEntry->pChild)
StringCchPrintf (szDebug, ARRAYSIZE(szDebug), TEXT(" (0x%x, 0x%x)"),pEntry->pNext, pEntry->pChild);
else if (!pEntry->pNext && pEntry->pChild)
StringCchPrintf (szDebug, ARRAYSIZE(szDebug), TEXT(" (NULL, 0x%x)"),pEntry->pChild);
else if (pEntry->pNext && !pEntry->pChild)
StringCchPrintf (szDebug, ARRAYSIZE(szDebug), TEXT(" (0x%x, NULL)"),pEntry->pNext);
OutputDebugString (szDebug);
OutputDebugString (TEXT("\r\n"));
}
if (pEntry->pChild)
DumpEntry(pEntry->pChild, (uIndent + 4));
pEntry = pEntry->pNext;
}
}
VOID CPolicyComponentData::DumpCurrentTable (void)
{
OutputDebugString (TEXT("\r\n"));
OutputDebugString (TEXT("\r\n"));
DumpEntry (m_pListCurrent, 4);
OutputDebugString (TEXT("\r\n"));
OutputDebugString (TEXT("\r\n"));
}
#endif
VOID CPolicyComponentData::FreeTemplates (void)
{
EnterCriticalSection (&g_ADMCritSec);
if (m_pMachineCategoryList)
{
FreeTable(m_pMachineCategoryList);
m_pMachineCategoryList = NULL;
m_nMachineDataItems = 0;
}
if (m_pUserCategoryList)
{
FreeTable(m_pUserCategoryList);
m_pUserCategoryList = NULL;
m_nUserDataItems = 0;
}
if (m_pSupportedStrings)
{
FreeSupportedData(m_pSupportedStrings);
m_pSupportedStrings = NULL;
}
LeaveCriticalSection (&g_ADMCritSec);
}
////////////////////////////////////////////////////////////////////////////
// //
// BOOL CPolicyComponentData::IsADMAutoUpdateDisabled() //
// //
// Purpose: Checks if autoupdate of ADM templates is disabled or not //
// //
// Returns: TRUE if autoupdate is disabled. //
// FALSE otherwise //
// //
////////////////////////////////////////////////////////////////////////////
BOOL CPolicyComponentData::IsADMAutoUpdateDisabled(void)
{
BOOL bDisableAutoUpdate = FALSE;
HKEY hKey;
DWORD dwSize;
DWORD dwType;
if (RegOpenKeyEx (HKEY_CURRENT_USER, GPE_KEY, 0,
KEY_READ, &hKey) == ERROR_SUCCESS)
{
dwSize = sizeof(bDisableAutoUpdate);
RegQueryValueEx (hKey, DISABLE_AUTOUPDATE_VALUE, NULL, &dwType,
(LPBYTE) &bDisableAutoUpdate, &dwSize);
RegCloseKey (hKey);
}
if (RegOpenKeyEx (HKEY_CURRENT_USER, GPE_POLICIES_KEY, 0,
KEY_READ, &hKey) == ERROR_SUCCESS)
{
dwSize = sizeof(bDisableAutoUpdate);
RegQueryValueEx (hKey, DISABLE_AUTOUPDATE_VALUE, NULL, &dwType,
(LPBYTE) &bDisableAutoUpdate, &dwSize);
RegCloseKey (hKey);
}
if (bDisableAutoUpdate)
{
DebugMsg((DM_VERBOSE, TEXT("IsADMAutoUpdateDisabled: Automatic update of ADM files is disabled.")));
return TRUE;
}
return FALSE;
}
DWORD CPolicyComponentData::LoadTemplatesThread (CPolicyComponentData * pCD)
{
HRESULT hr;
HINSTANCE hInstDLL;
hInstDLL = LoadLibrary (TEXT("gptext.dll"));
Sleep(0);
hr = pCD->LoadTemplates();
if (hInstDLL)
{
FreeLibraryAndExitThread (hInstDLL, (DWORD) hr);
}
return (DWORD)hr;
}
void CPolicyComponentData::AddTemplates(LPTSTR lpDest, LPCTSTR lpValueName, UINT idRes)
{
TCHAR szFiles[MAX_PATH];
TCHAR szSrc[MAX_PATH];
TCHAR szDest[MAX_PATH];
TCHAR szLogFile[MAX_PATH];
LPTSTR lpTemp, lpFileName, lpSrc, lpEnd;
HKEY hKey;
DWORD dwSize, dwType;
HRESULT hr = S_OK;
//
// Add the adm files. We get this list from 3 possible
// places. The resources, user preferences, policy.
//
hr = StringCchCopy (szDest, ARRAYSIZE(szDest), lpDest);
ASSERT(SUCCEEDED(hr));
lpEnd = CheckSlash (szDest);
hr = StringCchCopy (szLogFile, ARRAYSIZE(szLogFile), lpDest);
ASSERT(SUCCEEDED(hr));
hr = StringCchCat (szLogFile, ARRAYSIZE(szLogFile), TEXT("\\admfiles.ini"));
ASSERT(SUCCEEDED(hr));
ExpandEnvironmentStrings (TEXT("%SystemRoot%\\Inf"), szSrc, ARRAYSIZE(szSrc));
lpSrc = CheckSlash (szSrc);
ZeroMemory (szFiles, sizeof(szFiles));
LoadString (g_hInstance, idRes, szFiles,
ARRAYSIZE(szFiles));
if (RegOpenKeyEx (HKEY_CURRENT_USER, szUserPrefKey, 0,
KEY_READ, &hKey) == ERROR_SUCCESS)
{
dwSize = sizeof(szFiles);
RegQueryValueEx (hKey, lpValueName, NULL, &dwType,
(LPBYTE) szFiles, &dwSize);
RegCloseKey (hKey);
}
if (RegOpenKeyEx (HKEY_CURRENT_USER, szPoliciesKey, 0,
KEY_READ, &hKey) == ERROR_SUCCESS)
{
dwSize = sizeof(szFiles);
RegQueryValueEx (hKey, lpValueName, NULL, &dwType,
(LPBYTE) szFiles, &dwSize);
RegCloseKey (hKey);
}
//
// Parse off the filenames
//
lpTemp = lpFileName = szFiles;
while (*lpTemp)
{
while (*lpTemp && (*lpTemp != TEXT(';')))
lpTemp++;
if (*lpTemp == TEXT(';'))
{
*lpTemp = TEXT('\0');
lpTemp++;
}
while (*lpFileName == TEXT(' '))
lpFileName++;
hr = StringCchCopy (lpEnd, ARRAYSIZE(szDest) - (lpEnd - szDest), lpFileName);
ASSERT(SUCCEEDED(hr));
hr = StringCchCopy (lpSrc, ARRAYSIZE(szSrc) - (lpSrc - szSrc), lpFileName);
ASSERT(SUCCEEDED(hr));
//
// Check if this file is already in the admfile.ini log
// If so, skip it
//
if (!GetPrivateProfileInt (TEXT("FileList"), lpFileName, 0, szLogFile))
{
if (CopyFile (szSrc, szDest, FALSE))
{
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::AddTemplates: Successfully copied %s to %s."), szSrc, szDest));
WritePrivateProfileString (TEXT("FileList"), lpFileName, TEXT("1"), szLogFile);
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::AddTemplates: Failed to copy %s to %s with %d."), szSrc, szDest, GetLastError()));
}
}
lpFileName = lpTemp;
}
SetFileAttributes (szLogFile, FILE_ATTRIBUTE_HIDDEN);
}
void CPolicyComponentData::AddDefaultTemplates(LPTSTR lpDest)
{
AddTemplates (lpDest, szDefaultTemplates, IDS_DEFAULTTEMPLATES);
}
void CPolicyComponentData::AddNewADMsToExistingGPO (LPTSTR lpDest)
{
TCHAR szLogFile[MAX_PATH];
WIN32_FILE_ATTRIBUTE_DATA fad;
HRESULT hr = S_OK;
//
// This method will add any new adm files to a GPO.
//
// Note: the admfiles.ini file is new post-W2k, so we have to do a special
// case when upgrading a GPO created by w2k to create that file and add
// the default filenames
//
hr = StringCchCopy (szLogFile, ARRAYSIZE(szLogFile), lpDest);
ASSERT(SUCCEEDED(hr));
hr = StringCchCat (szLogFile, ARRAYSIZE(szLogFile), TEXT("\\admfiles.ini"));
ASSERT(SUCCEEDED(hr));
if (!GetFileAttributesEx (szLogFile, GetFileExInfoStandard, &fad))
{
WritePrivateProfileString (TEXT("FileList"), TEXT("system.adm"), TEXT("1"), szLogFile);
WritePrivateProfileString (TEXT("FileList"), TEXT("inetres.adm"), TEXT("1"), szLogFile);
WritePrivateProfileString (TEXT("FileList"), TEXT("conf.adm"), TEXT("1"), szLogFile);
}
AddTemplates (lpDest, szAdditionalTemplates, IDS_ADDITIONALTTEMPLATES);
}
HRESULT CPolicyComponentData::CreateAdmIniFile (WCHAR *szAdmDirPath)
{
WCHAR szIniFilePath[MAX_PATH];
WCHAR szFileList[MAX_PATH];
WCHAR *lpStart;
WCHAR *lpCharLoc;
HRESULT hr;
hr = StringCchCopy(szIniFilePath, ARRAYSIZE(szIniFilePath), szAdmDirPath);
if (FAILED(hr))
{
return hr;
}
if (lstrlen (szIniFilePath) < MAX_PATH - 1)
{
CheckSlash (szIniFilePath);
}
else
{
return STRSAFE_E_INSUFFICIENT_BUFFER;
}
hr = StringCchCat (szIniFilePath, ARRAYSIZE(szIniFilePath), L"admfiles.ini");
if (FAILED(hr))
{
return hr;
}
if (LoadString (g_hInstance, IDS_DEFAULTTEMPLATES, szFileList, ARRAYSIZE(szFileList)) == 0)
{
return HRESULT_FROM_WIN32(GetLastError());
}
lpStart = szFileList;
lpCharLoc = szFileList;
while (lpCharLoc)
{
lpCharLoc = wcschr (lpStart, L';');
if (lpCharLoc)
{
*lpCharLoc = L'\0';
}
if (!WritePrivateProfileString (L"FileList", lpStart, L"1", szIniFilePath))
{
return HRESULT_FROM_WIN32(GetLastError());
}
if (lpCharLoc)
{
lpStart = lpCharLoc + 1;
}
}
(void) SetFileAttributes (szIniFilePath, FILE_ATTRIBUTE_HIDDEN);
return S_OK;
}
void CPolicyComponentData::UpdateExistingTemplates(LPTSTR lpDest)
{
WIN32_FILE_ATTRIBUTE_DATA fadSrc, fadDest;
TCHAR szSrc[MAX_PATH];
TCHAR szDest[MAX_PATH];
LPTSTR lpSrc, lpEnd;
WIN32_FIND_DATA fd;
HANDLE hFindFile;
HRESULT hr = S_OK;
//
// Add any new adm files shipped with the OS
//
AddNewADMsToExistingGPO (lpDest);
//
// Build the path to the source directory
//
ExpandEnvironmentStrings (TEXT("%SystemRoot%\\Inf"), szSrc, ARRAYSIZE(szSrc));
lpSrc = CheckSlash (szSrc);
//
// Build the path to the destination directory
//
hr = StringCchCopy (szDest, ARRAYSIZE(szDest), lpDest);
ASSERT(SUCCEEDED(hr));
lpEnd = CheckSlash (szDest);
hr = StringCchCopy (lpEnd, ARRAYSIZE(szDest) - (lpEnd - szDest), TEXT("*.adm"));
ASSERT(SUCCEEDED(hr));
//
// Enumerate the files
//
hFindFile = FindFirstFile(szDest, &fd);
if (hFindFile != INVALID_HANDLE_VALUE)
{
do
{
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
hr = StringCchCopy (lpEnd, ARRAYSIZE(szDest) - (lpEnd - szDest), fd.cFileName);
ASSERT(SUCCEEDED(hr));
hr = StringCchCopy (lpSrc, ARRAYSIZE(szSrc) - (lpSrc - szSrc), fd.cFileName);
ASSERT(SUCCEEDED(hr));
//
// Get the file attributes of the source and destination
//
ZeroMemory (&fadSrc, sizeof(fadSrc));
ZeroMemory (&fadDest, sizeof(fadDest));
GetFileAttributesEx (szSrc, GetFileExInfoStandard, &fadSrc);
GetFileAttributesEx (szDest, GetFileExInfoStandard, &fadDest);
//
// If the source is a newer than the dest
// copy the .adm file
//
BOOL bUpdateNeeded;
bUpdateNeeded = FALSE;
//
// Check the time stamp to see if the
// source is newer than the destination -- if so, an update is needed
//
if (CompareFileTime(&fadSrc.ftLastWriteTime, &fadDest.ftLastWriteTime) == 1)
{
bUpdateNeeded = TRUE;
}
if ( bUpdateNeeded )
{
if (CopyFile (szSrc, szDest, FALSE))
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::UpdateExistingTemplates: Successfully copied %s to %s."), szSrc, szDest));
else
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::UpdateExistingTemplates: Failed to copy %s to %s with %d."), szSrc, szDest, GetLastError()));
}
}
} while (FindNextFile(hFindFile, &fd));
FindClose(hFindFile);
}
}
HRESULT CPolicyComponentData::LoadGPOTemplates (void)
{
LPTSTR lpEnd;
UINT iResult;
HKEY hAdmKey;
DWORD dwError;
DWORD dwRegVal = 0;
DWORD dwSize;
TCHAR szPath[MAX_PATH];
BOOL bADMAutoUpdateDisabled = FALSE;
BOOL bReadFromINF = FALSE;
HRESULT hr;
//
// Get the path to the GPO directory in sysvol
//
hr = m_pGPTInformation->GetFileSysPath(GPO_SECTION_ROOT, szPath, MAX_PATH);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadGPOTemplates: Failed to get gpt path.")));
return hr;
}
//
// Build the ADM path name
//
(void) CheckSlash (szPath);
hr = StringCchCat (szPath, ARRAYSIZE(szPath), g_szADM);
if (FAILED(hr))
{
return hr;
}
//
// Create ADM directory, if it doesn't exist
//
iResult = CreateNestedDirectory (szPath, NULL);
if (!iResult)
{
return E_FAIL;
}
//
// Check if adm use local adm policy is set
//
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADM_USELOCAL_KEY, 0, KEY_EXECUTE, &hAdmKey);
if ( ERROR_SUCCESS == dwError )
{
dwSize = sizeof(DWORD);
dwError = RegQueryValueEx(hAdmKey, ADM_USELOCAL_VALUE, NULL, NULL, (LPBYTE) &dwRegVal, &dwSize);
if ( ERROR_SUCCESS == dwError && 1 == dwRegVal)
{
bReadFromINF = TRUE;
}
RegCloseKey(hAdmKey);
}
if (!bReadFromINF)
{
//
// Check if the user wants their ADM files updated automatically
//
bADMAutoUpdateDisabled = IsADMAutoUpdateDisabled();
if (bADMAutoUpdateDisabled)
{
if (1 == iResult)
{
//
// Empty ADM directory is created. Read from INF
//
bReadFromINF = TRUE;
}
else
{
//
// Check if any files of type *.adm exists
// If not, read from INF directory
//
hr = IsFilePresent (szPath, L"*.adm");
if (SUCCEEDED(hr))
{
if (S_FALSE == hr)
{
bReadFromINF = TRUE;
}
}
else
{
return hr;
}
}
}
else
{
if (1 == iResult)
{
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::LoadGPOTemplates: adding default templates")));
AddDefaultTemplates(szPath);
}
else
{
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::LoadGPOTemplates: Updating templates")));
UpdateExistingTemplates(szPath);
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::LoadGPOTemplates: Finished updating templates")));
}
}
}
if (bReadFromINF)
{
//
// Create admfiles.ini file if Adm file is created
// This need not be done when update is done since
// AddDefaultTemplates function creates this file.
//
if (1 == iResult)
{
hr = CreateAdmIniFile (szPath);
if (FAILED(hr))
{
return hr;
}
}
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::LoadGPOTemplates: Reading from inf")));
iResult = ExpandEnvironmentStrings ( L"%SystemRoot%\\inf", szPath, MAX_PATH);
if (0 == iResult )
{
dwError = GetLastError();
return (HRESULT_FROM_WIN32(dwError));
}
}
//
// Enumerate the files
//
lpEnd = CheckSlash (szPath);
hr = StringCchCopy (lpEnd, ARRAYSIZE(szPath) - (lpEnd - szPath), TEXT("*.adm"));
if (FAILED(hr))
{
return hr;
}
HANDLE hFindFile;
WIN32_FIND_DATA fd;
hFindFile = FindFirstFile(szPath, &fd);
if (hFindFile != INVALID_HANDLE_VALUE)
{
do
{
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
hr = StringCchCopy (lpEnd, ARRAYSIZE(szPath) - (lpEnd - szPath), fd.cFileName);
if (FAILED(hr))
{
FindClose(hFindFile);
return hr;
}
ParseTemplate (szPath);
}
} while (FindNextFile(hFindFile, &fd));
FindClose(hFindFile);
}
return S_OK;
}
#define WINLOGON_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon")
#define SYSTEM_POLICIES_KEY TEXT("Software\\Policies\\Microsoft\\Windows\\System")
#define SLOW_LINK_TRANSFER_RATE 500 // Kbps
BOOL CPolicyComponentData::IsSlowLink (LPTSTR lpFileName)
{
LPTSTR lpComputerName = NULL, lpTemp;
LPSTR lpComputerNameA = NULL;
BOOL bResult = FALSE;
DWORD dwSize, dwResult, dwType;
struct hostent *hostp;
ULONG inaddr, ulSpeed, ulTransferRate;
LONG lResult;
HKEY hKey;
HRESULT hr = S_OK;
DWORD dwLen = 0;
//
// Get the slow timeout
//
ulTransferRate = SLOW_LINK_TRANSFER_RATE;
lResult = RegOpenKeyEx(HKEY_CURRENT_USER,
WINLOGON_KEY,
0,
KEY_READ,
&hKey);
if (lResult == ERROR_SUCCESS)
{
dwSize = sizeof(ulTransferRate);
RegQueryValueEx (hKey,
TEXT("GroupPolicyMinTransferRate"),
NULL,
&dwType,
(LPBYTE) &ulTransferRate,
&dwSize);
RegCloseKey (hKey);
}
lResult = RegOpenKeyEx(HKEY_CURRENT_USER,
SYSTEM_POLICIES_KEY,
0,
KEY_READ,
&hKey);
if (lResult == ERROR_SUCCESS)
{
dwSize = sizeof(ulTransferRate);
RegQueryValueEx (hKey,
TEXT("GroupPolicyMinTransferRate"),
NULL,
&dwType,
(LPBYTE) &ulTransferRate,
&dwSize);
RegCloseKey (hKey);
}
//
// If the transfer rate is 0, then always download adm files
//
if (!ulTransferRate)
{
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::IsSlowLink: Slow link transfer rate is 0. Always download adm files.")));
goto Exit;
}
//
// Copy the namespace to a buffer we can edit and drop the leading \\ if present
//
dwLen = lstrlen(lpFileName) + 1;
lpComputerName = (LPTSTR) LocalAlloc (LPTR, (dwLen) * sizeof(TCHAR));
if (!lpComputerName)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::IsSlowLink: Failed to allocate memory for computer name with %d"),
GetLastError()));
goto Exit;
}
if ((*lpFileName == TEXT('\\')) && (*(lpFileName+1) == TEXT('\\')))
{
hr = StringCchCopy (lpComputerName, dwLen, (lpFileName+2));
}
else
{
hr = StringCchCopy (lpComputerName, dwLen, lpFileName);
}
ASSERT(SUCCEEDED(hr));
//
// Find the slash between the computer name and the share name and replace it with null
//
lpTemp = lpComputerName;
while (*lpTemp && (*lpTemp != TEXT('\\')))
{
lpTemp++;
}
if (!(*lpTemp))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::IsSlowLink: Didn't find slash between computer name and share name in %s"),
lpComputerName));
goto Exit;
}
*lpTemp = TEXT('\0');
//
// Allocate a buffer for the ANSI name
//
// Note this buffer is allocated twice as large so handle DBCS characters
//
dwSize = (lstrlen(lpComputerName) + 1) * 2;
lpComputerNameA = (LPSTR) LocalAlloc (LPTR, dwSize);
if (!lpComputerNameA)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::IsSlowLink: Failed to allocate memory for ansi computer name with %d"),
GetLastError()));
goto Exit;
}
//
// Convert the computer name to ANSI
//
if (WideCharToMultiByte (CP_ACP, 0, lpComputerName, -1, lpComputerNameA, dwSize, NULL, NULL))
{
//
// Get the host information for the computer
//
hostp = gethostbyname(lpComputerNameA);
if (hostp)
{
//
// Get the ip address of the computer
//
inaddr = *(long *)hostp->h_addr;
//
// Get the transfer rate
//
dwResult = PingComputer (inaddr, &ulSpeed);
if (dwResult == ERROR_SUCCESS)
{
if (ulSpeed)
{
//
// If the delta time is greater that the timeout time, then this
// is a slow link.
//
if (ulSpeed < ulTransferRate)
{
bResult = TRUE;
}
}
}
else {
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::IsSlowLink: PingComputer failed with error %d. Treat it as slow link"), dwResult));
bResult = TRUE;
}
}
}
Exit:
if (lpComputerName)
{
LocalFree (lpComputerName);
}
if (lpComputerNameA)
{
LocalFree (lpComputerNameA);
}
return bResult;
}
HRESULT CPolicyComponentData::AddADMFile (LPTSTR lpFileName, LPTSTR lpFullFileName,
FILETIME *pFileTime, DWORD dwErr, LPRSOPADMFILE *lpHead)
{
LPRSOPADMFILE lpTemp;
HRESULT hr = S_OK;
//
// First, check if this file is already in the link list
//
lpTemp = *lpHead;
while (lpTemp)
{
if (!lstrcmpi(lpFileName, lpTemp->szFileName))
{
if (CompareFileTime(pFileTime, &lpTemp->FileTime) == 1)
{
hr = StringCchCopy (lpTemp->szFullFileName, ARRAYSIZE(lpTemp->szFullFileName), lpFullFileName);
if(FAILED(hr))
return hr;
lpTemp->FileTime.dwLowDateTime = pFileTime->dwLowDateTime;
lpTemp->FileTime.dwHighDateTime = pFileTime->dwHighDateTime;
}
return S_OK;
}
lpTemp = lpTemp->pNext;
}
//
// Add a new node
//
lpTemp = (LPRSOPADMFILE) LocalAlloc (LPTR, sizeof(RSOPADMFILE));
if (!lpTemp)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::AddADMFile: Failed to allocate memory for adm file node")));
return (HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY));
}
hr = StringCchCopy (lpTemp->szFileName, ARRAYSIZE(lpTemp->szFileName), lpFileName);
if (FAILED(hr))
{
LocalFree(lpTemp);
return hr;
}
hr = StringCchCopy (lpTemp->szFullFileName, ARRAYSIZE(lpTemp->szFullFileName), lpFullFileName);
if (FAILED(hr))
{
LocalFree(lpTemp);
return hr;
}
lpTemp->FileTime.dwLowDateTime = pFileTime->dwLowDateTime;
lpTemp->FileTime.dwHighDateTime = pFileTime->dwHighDateTime;
lpTemp->dwError = dwErr;
lpTemp->pNext = *lpHead;
*lpHead = lpTemp;
return S_OK;
}
///////////////////////////////////////////////////////////////////////////
// //
// HRESULT CPolicyComponentData::GetLocalADMFiles(LPRSOPADMFILE *lpHead) //
// //
// Purpose: Prepares a list of the *.adm filees present in %windir%\inf //
// directory //
// //
// Parameters: //
// lpHead [IN OUT] - Linked list containing list of file names //
// //
////////////////////////////////////////////////////////////////////////////
HRESULT CPolicyComponentData::GetLocalADMFiles(
LPRSOPADMFILE *lpHead)
{
WCHAR szPath[MAX_PATH];
WCHAR szFileName[MAX_PATH];
WCHAR szFullFileName[MAX_PATH];
WCHAR *pTemp;
HANDLE hFindFile;
HRESULT hr;
FILETIME FileTime;
WIN32_FIND_DATA fd;
ExpandEnvironmentStrings (L"%SystemRoot%\\Inf", szPath, ARRAYSIZE(szPath));
pTemp = CheckSlash (szPath);
hr = StringCchCopy (pTemp, ARRAYSIZE(szPath) - (pTemp - szPath), L"*.adm");
ASSERT(SUCCEEDED(hr));
FileTime.dwLowDateTime = 0;
FileTime.dwHighDateTime = 0;
//
// Enumerate the files
//
hFindFile = FindFirstFile(szPath, &fd);
if (hFindFile != INVALID_HANDLE_VALUE)
{
do
{
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
hr = StringCchCopy (szFileName, ARRAYSIZE(szFileName), fd.cFileName);
if (FAILED(hr))
{
FindClose(hFindFile);
return hr;
}
ExpandEnvironmentStrings (L"%SystemRoot%\\Inf\\", szFullFileName, ARRAYSIZE(szPath));
hr = StringCchCat (szFullFileName, ARRAYSIZE(szFileName), szFileName);
if (FAILED(hr))
{
FindClose(hFindFile);
return hr;
}
hr = AddADMFile (szFileName, szFullFileName, &FileTime, 0, lpHead);
if (FAILED(hr))
{
FindClose(hFindFile);
return hr;
}
}
} while (FindNextFile(hFindFile, &fd));
FindClose(hFindFile);
}
return S_OK;
}
HRESULT CPolicyComponentData::LoadRSOPTemplates (void)
{
BSTR pLanguage = NULL, pQuery = NULL;
BSTR pName = NULL, pLastWriteTime = NULL, pNamespace = NULL;
IEnumWbemClassObject * pEnum = NULL;
IWbemClassObject *pObjects[2];
HRESULT hr;
ULONG ulRet;
VARIANT varName, varLastWriteTime;
IWbemLocator *pIWbemLocator = NULL;
IWbemServices *pIWbemServices = NULL;
SYSTEMTIME SysTime;
FILETIME FileTime;
LPTSTR lpFileName;
LPRSOPADMFILE lpADMFiles = NULL, lpTemp, lpDelete, lpFailedAdmFiles = NULL;
DWORD dwFailedAdm = 0;
XBStr xbstrWbemTime;
DWORD dwError;
TCHAR szPath[MAX_PATH];
BOOL bSlowLink = FALSE;
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::LoadRSOPTemplates: Entering")));
CoInitialize(NULL);
//
// First get the local ADM files
// Any ADM Files found in the sysvol will be overwrite local ADM files
//
GetLocalADMFiles(&lpADMFiles);
//
// Allocate BSTRs for the query language and for the query itself
//
pLanguage = SysAllocString (TEXT("WQL"));
if (!pLanguage)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadRSOPTemplates: Failed to allocate memory for language")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
pQuery = SysAllocString (TEXT("SELECT name, lastWriteTime FROM RSOP_AdministrativeTemplateFile"));
if (!pQuery)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadRSOPTemplates: Failed to allocate memory for query")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
//
// Allocate BSTRs for the property names we want to retreive
//
pName = SysAllocString (TEXT("name"));
if (!pName)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadRSOPTemplates: Failed to allocate memory for name")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
pLastWriteTime = SysAllocString (TEXT("lastWriteTime"));
if (!pLastWriteTime)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadRSOPTemplates: Failed to allocate memory for last write time")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
//
// Create an instance of the WMI locator service
//
hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pIWbemLocator);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadRSOPTemplates: CoCreateInstance failed with 0x%x"), hr));
goto Exit;
}
//
// Allocate a BSTR for the namespace
//
pNamespace = SysAllocString (m_pszNamespace);
if (!pNamespace)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadRSOPTemplates: Failed to allocate memory for namespace")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
//
// Connect to the server
//
hr = pIWbemLocator->ConnectServer(pNamespace, NULL, NULL, 0L, 0L, NULL, NULL,
&pIWbemServices);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadRSOPTemplates: ConnectServer failed with 0x%x"), hr));
goto Exit;
}
// Set the proper security to encrypt the data
hr = CoSetProxyBlanket(pIWbemServices,
RPC_C_AUTHN_DEFAULT,
RPC_C_AUTHZ_DEFAULT,
COLE_DEFAULT_PRINCIPAL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
0);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadRSOPTemplates: CoSetProxyBlanket failed with 0x%x"), hr));
goto Exit;
}
//
// Execute the query
//
hr = pIWbemServices->ExecQuery (pLanguage, pQuery,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL, &pEnum);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadRSOPTemplates: Failed to query for %s with 0x%x"),
pQuery, hr));
goto Exit;
}
//
// Loop through the results
//
while (pEnum->Next(WBEM_INFINITE, 1, pObjects, &ulRet) == S_OK)
{
//
// Check for the "data not available case"
//
if (ulRet == 0)
{
hr = S_OK;
goto Exit;
}
//
// Get the name
//
hr = pObjects[0]->Get (pName, 0, &varName, NULL, NULL);
if (SUCCEEDED(hr))
{
//
// Get the last write time
//
hr = pObjects[0]->Get (pLastWriteTime, 0, &varLastWriteTime, NULL, NULL);
if (SUCCEEDED(hr))
{
xbstrWbemTime = varLastWriteTime.bstrVal;
hr = WbemTimeToSystemTime(xbstrWbemTime, SysTime);
if (SUCCEEDED(hr))
{
SystemTimeToFileTime (&SysTime, &FileTime);
lpFileName = varName.bstrVal + lstrlen(varName.bstrVal);
while ((lpFileName > varName.bstrVal) && (*lpFileName != TEXT('\\')))
lpFileName--;
if (*lpFileName == TEXT('\\'))
{
lpFileName++;
}
AddADMFile (lpFileName, varName.bstrVal, &FileTime, 0, &lpADMFiles);
}
VariantClear (&varLastWriteTime);
}
VariantClear (&varName);
}
pObjects[0]->Release();
}
//
// Parse the adm files
//
lpTemp = lpADMFiles;
while (lpTemp)
{
SetLastError(ERROR_SUCCESS);
if (!bSlowLink)
{
bSlowLink = IsSlowLink (lpTemp->szFullFileName);
}
if (bSlowLink || !ParseTemplate(lpTemp->szFullFileName))
{
//
// If the adm file failed to parse for any of the reasons listed
// below, switch over to using the local copy of the ADM file
//
dwError = GetLastError();
if (bSlowLink || ((dwError != ERROR_SUCCESS) &&
(dwError != ERROR_ALREADY_DISPLAYED)))
{
if (bSlowLink)
{
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::LoadRSOPTemplates: Using local copy of %s due to slow link detection."),
lpTemp->szFileName));
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadRSOPTemplates: Unable to parse template %s due to error %d. Switching to the local copy of %s."),
lpTemp->szFullFileName, dwError, lpTemp->szFileName));
AddADMFile (lpTemp->szFileName, lpTemp->szFullFileName, &(lpTemp->FileTime), dwError, &lpFailedAdmFiles);
dwFailedAdm++;
}
ExpandEnvironmentStrings (TEXT("%SystemRoot%\\inf\\"), szPath, MAX_PATH);
hr = StringCchCat (szPath, ARRAYSIZE(szPath), lpTemp->szFileName);
ASSERT(SUCCEEDED(hr));
ParseTemplate (szPath);
}
}
lpDelete = lpTemp;
lpTemp = lpTemp->pNext;
LocalFree (lpDelete);
}
hr = S_OK;
//
// Format a error msg for the failed adm files
// ignore any errors
//
if (dwFailedAdm) {
LPTSTR lpErr = NULL, lpEnd = NULL;
TCHAR szErrFormat[MAX_PATH];
TCHAR szError[MAX_PATH];
LoadString (g_hInstance, IDS_FAILED_RSOPFMT, szErrFormat, ARRAYSIZE(szErrFormat));
lpErr = (LPTSTR)LocalAlloc(LPTR, (600*dwFailedAdm)*sizeof(TCHAR));
if (!lpErr) {
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadRSOPTemplates: Couldn't allocate memory for the error buffer."), GetLastError()));
goto Exit;
}
lpTemp = lpFailedAdmFiles;
lpEnd = lpErr;
while (lpTemp) {
LoadMessage(lpTemp->dwError, szError, ARRAYSIZE(szError));
hr = StringCchPrintf(lpEnd, 600*dwFailedAdm - (lpEnd - lpErr), szErrFormat, lpTemp->szFileName, lpTemp->szFullFileName, szError);
ASSERT(SUCCEEDED(hr));
lpEnd += lstrlen(lpEnd);
lpDelete = lpTemp;
lpTemp = lpTemp->pNext;
LocalFree (lpDelete);
}
// we cannot pass in a owner window handle here, b'cos this
// is being done in a seperate thread and the main thread can be
// waiting for the templatethread event
ReportAdmError(NULL, 0, IDS_RSOP_ADMFAILED, lpErr);
lpFailedAdmFiles = NULL;
LocalFree(lpErr);
}
Exit:
if (pEnum)
{
pEnum->Release();
}
if (pIWbemLocator)
{
pIWbemLocator->Release();
}
if (pIWbemServices)
{
pIWbemServices->Release();
}
if (pLanguage)
{
SysFreeString (pLanguage);
}
if (pQuery)
{
SysFreeString (pQuery);
}
if (pName)
{
SysFreeString (pName);
}
if (pLastWriteTime)
{
SysFreeString (pLastWriteTime);
}
if (pNamespace)
{
SysFreeString (pNamespace);
}
lpTemp = lpFailedAdmFiles;
while (lpTemp) {
lpDelete = lpTemp;
lpTemp = lpTemp->pNext;
LocalFree (lpDelete);
}
lpFailedAdmFiles = NULL;
CoUninitialize();
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::LoadRSOPTemplates: Leaving")));
return hr;
}
HRESULT CPolicyComponentData::LoadTemplates (void)
{
HRESULT hr = E_FAIL;
if (m_bUserScope)
{
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::LoadTemplates: Entering for User")));
}
else
{
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::LoadTemplates: Entering for Machine")));
}
//
// Reset the ADM event
//
ResetEvent (m_ADMEvent);
//
// Free any old templates
//
FreeTemplates ();
EnterCriticalSection (&g_ADMCritSec);
//
// Prepare to load the templates
//
m_nUserDataItems = 0;
m_nMachineDataItems = 0;
m_pMachineCategoryList = (TABLEENTRY *) GlobalAlloc(GPTR,sizeof(TABLEENTRY));
if (!m_pMachineCategoryList)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadTemplates: Failed to alloc memory with %d"),
GetLastError()));
goto Exit;
}
m_pUserCategoryList = (TABLEENTRY *) GlobalAlloc(GPTR,sizeof(TABLEENTRY));
if (!m_pUserCategoryList)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::LoadTemplates: Failed to alloc memory with %d"),
GetLastError()));
GlobalFree (m_pMachineCategoryList);
goto Exit;
}
m_pMachineCategoryList->dwSize = m_pUserCategoryList->dwSize = sizeof(TABLEENTRY);
m_pMachineCategoryList->dwType = m_pUserCategoryList->dwType = ETYPE_ROOT;
//
// Load the appropriate template files
//
if (m_bRSOP)
{
hr = LoadRSOPTemplates();
}
else
{
hr = LoadGPOTemplates();
if (SUCCEEDED(hr))
{
TCHAR szUnknown[150];
LoadString (g_hInstance, IDS_NOSUPPORTINFO, szUnknown, ARRAYSIZE(szUnknown));
AddSupportedNode (&m_pSupportedStrings, szUnknown, TRUE);
if (m_bUserScope)
{
InitializeSupportInfo(m_pUserCategoryList, &m_pSupportedStrings);
}
else
{
InitializeSupportInfo(m_pMachineCategoryList, &m_pSupportedStrings);
}
}
}
Exit:
SetEvent (m_ADMEvent);
LeaveCriticalSection (&g_ADMCritSec);
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::LoadTemplates: Leaving")));
return hr;
}
BOOL CPolicyComponentData::ParseTemplate (LPTSTR lpFileName)
{
HANDLE hFile;
BOOL fMore;
UINT uRet;
LANGID langid;
TCHAR szLocalizedSection[20];
DWORD dwSize, dwRead;
LPVOID lpFile, lpTemp;
HRESULT hr = S_OK;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::ParseTemplate: Loading <%s>..."),
lpFileName));
//
// Set defaults
//
m_nFileLine = 1;
m_pListCurrent = m_pMachineCategoryList;
m_pnDataItemCount = &m_nMachineDataItems;
m_pszParseFileName = lpFileName;
//
// Read in the adm file
//
hFile = CreateFile (lpFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::ParseTemplate: Failed to load <%s> with %d"),
lpFileName, GetLastError()));
return FALSE;
}
dwSize = GetFileSize (hFile, NULL);
if (dwSize == 0xFFFFFFFF)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::ParseTemplates: Failed to get file size with %d."),
GetLastError()));
CloseHandle (hFile);
return FALSE;
}
if (!(lpFile = GlobalAlloc(GPTR, dwSize)))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::ParseTemplates: Failed to allocate memory for %d bytes with %d."),
dwSize, GetLastError()));
CloseHandle (hFile);
return FALSE;
}
if (!ReadFile (hFile, lpFile, dwSize, &dwRead, NULL))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::ParseTemplates: Failed to read file with %d."),
GetLastError()));
GlobalFree(lpFile);
CloseHandle (hFile);
return FALSE;
}
CloseHandle (hFile);
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::ParseTemplate: Finished reading file.")));
if (dwRead >= sizeof(WCHAR))
{
if (!IsTextUnicode(lpFile, dwRead, NULL))
{
if (!(lpTemp = GlobalAlloc(GPTR, dwSize * sizeof(WCHAR))))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::ParseTemplates: Failed to allocate memory for %d WCHARS with %d."),
dwSize, GetLastError()));
GlobalFree(lpFile);
return FALSE;
}
if ( !MultiByteToWideChar (CP_ACP, 0, (LPCSTR) lpFile, dwRead, (LPWSTR)lpTemp, dwRead) )
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::ParseTemplates: Failed to convert ANSI adm file to Unicode with %d."),
GetLastError()));
GlobalFree(lpTemp);
GlobalFree(lpFile);
return FALSE;
}
GlobalFree (lpFile);
lpFile = lpTemp;
dwRead *= sizeof(WCHAR);
}
}
m_pFilePtr = (LPWSTR)lpFile;
m_pFileEnd = (LPWSTR)((LPBYTE)lpFile + dwRead - 1);
//
// Read in the string sections
//
langid = GetUserDefaultLangID();
hr = StringCchPrintf (szLocalizedSection, ARRAYSIZE(szLocalizedSection), TEXT("[%04x]"), langid);
ASSERT(SUCCEEDED(hr));
m_pLocaleStrings = FindSection (szLocalizedSection);
if (m_pLocaleStrings)
{
m_pLocaleStrings += lstrlen(szLocalizedSection) + 2;
m_pLocaleStrings = CreateStringArray(m_pLocaleStrings);
m_pLocaleHashTable = CreateHashTable();
FillHashTable(m_pLocaleHashTable, m_pLocaleStrings);
}
hr = StringCchPrintf (szLocalizedSection, ARRAYSIZE(szLocalizedSection), TEXT("[%04x]"), PRIMARYLANGID(langid));
ASSERT(SUCCEEDED(hr));
m_pLanguageStrings = FindSection (szLocalizedSection);
if (m_pLanguageStrings)
{
m_pLanguageStrings += lstrlen(szLocalizedSection) + 2;
m_pLanguageStrings = CreateStringArray(m_pLanguageStrings);
m_pLanguageHashTable = CreateHashTable();
FillHashTable(m_pLanguageHashTable, m_pLanguageStrings);
}
m_pDefaultStrings = FindSection ((LPTSTR)szStringsSect);
if (m_pDefaultStrings)
{
LPTSTR lpEnd;
m_pDefaultStrings += lstrlen(szStringsSect) + 2;
lpEnd = m_pDefaultStrings;
m_pDefaultStrings = CreateStringArray(m_pDefaultStrings);
m_pDefaultHashTable = CreateHashTable();
FillHashTable(m_pDefaultHashTable, m_pDefaultStrings);
#if DBG
//DumpHashTableDetails (m_pDefaultHashTable);
#endif
//
// Now that all the string arrays are created, we can remove the strings
// from the end of the adm file so we don't have 2 copies of the strings
// in memory at the same time. Note, the [Strings] section has to come
// before the language or locale sections (because [strings] is a tag to the parser
// to stop parsing the adm language). So, we can safely chop off the file
// right after the [strings] tag.
//
GlobalReAlloc (m_pFilePtr, (lpEnd - m_pFilePtr + 1) * sizeof(WCHAR), 0);
m_pFileEnd = lpEnd;
}
//
// Parse the file
//
m_fInComment = FALSE;
do {
uRet=ParseClass(&fMore);
} while (fMore && uRet == ERROR_SUCCESS);
//
// Cleanup
//
GlobalFree(lpFile);
if (m_pLocaleStrings)
{
GlobalFree(m_pLocaleStrings);
}
if (m_pLanguageStrings)
{
GlobalFree(m_pLanguageStrings);
}
if (m_pDefaultStrings)
{
GlobalFree(m_pDefaultStrings);
}
if (m_pLocaleHashTable)
{
FreeHashTable (m_pLocaleHashTable);
m_pLocaleHashTable = NULL;
}
if (m_pLanguageHashTable)
{
FreeHashTable (m_pLanguageHashTable);
m_pLanguageHashTable = NULL;
}
if (m_pDefaultHashTable)
{
FreeHashTable (m_pDefaultHashTable);
m_pDefaultHashTable = NULL;
}
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::ParseTemplate: Finished.")));
return TRUE;
}
UINT CPolicyComponentData::ParseClass(BOOL *pfMore)
{
TCHAR szWordBuf[WORDBUFSIZE+1];
UINT uErr, nKeywordID, nClassID;
if (!GetNextWord(szWordBuf,ARRAYSIZE(szWordBuf),pfMore,&uErr))
return uErr;
if (!CompareKeyword(szWordBuf,pClassCmpList,&nKeywordID))
return ERROR_ALREADY_DISPLAYED;
switch (nKeywordID) {
case KYWD_ID_CATEGORY:
return ParseCategory(m_pListCurrent, FALSE,pfMore, NULL);
case KYWD_ID_CLASS:
if (!GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
pClassTypeCmpList,&nClassID,pfMore,&uErr))
return uErr;
switch (nClassID) {
case KYWD_ID_USER:
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::ParseClass: User section")));
m_pListCurrent = m_pUserCategoryList;
m_pnDataItemCount = &m_nUserDataItems;
m_bRetrieveString = (m_bUserScope ? TRUE : FALSE);
break;
case KYWD_ID_MACHINE:
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::ParseClass: Machine section")));
m_pListCurrent = m_pMachineCategoryList;
m_pnDataItemCount = &m_nMachineDataItems;
m_bRetrieveString = (m_bUserScope ? FALSE : TRUE);
break;
}
break;
// hack for localization: allow a "strings" section at the bottom, if we
// encounter that then we're thru with parsing
case KYWD_ID_STRINGSSECT:
*pfMore = FALSE; // that's all, folks
return ERROR_SUCCESS;
break;
}
return ERROR_SUCCESS;
}
TABLEENTRY * CPolicyComponentData::FindCategory(TABLEENTRY *pParent, LPTSTR lpName)
{
TABLEENTRY *pEntry = NULL, *pTemp;
if (m_bRetrieveString && pParent) {
pTemp = pParent->pChild;
while (pTemp) {
if (pTemp->dwType & ETYPE_CATEGORY) {
if (!lstrcmpi (lpName, GETNAMEPTR(pTemp))) {
pEntry = pTemp;
break;
}
}
pTemp = pTemp->pNext;
}
}
return pEntry;
}
/*******************************************************************
NAME: ParseEntry
SYNOPSIS: Main parsing "engine" for category, policy and part
parsing
NOTES: Allocates memory to build a temporary TABLEENTRY struct
describing the parsed information. Reads the beginning and end of a
section and loops through the words in each section, calling
a caller-defined ParseProc for each keyword to let the
caller handle appropriately. Passes the newly-constucted
TABLEENTRY to AddTableEntry to save it, and frees the temporary
memory.
This function is re-entrant.
The ENTRYDATA struct is declared on ParseEntry's stack
but used by the ParseProc to maintain state between
calls-- e.g., whether or not a key name has been found.
This can't be maintained as a static in the ParseProc because
the ParseProc may be reentered (for instance, if categories
have subcategories).
There are many possible error paths and there is some
memory dealloc that needs to be done in an error case. Rather
than do deallocs by hand on every error path or use a "goto
cleanup" (ick!), items to be freed are added to a "cleanup
list" and then CleanupAndReturn is called in an error condition,
which frees items on the list and returns a specified value.
ENTRY: ppes-- PARSEENTRYSTRUCT that specifes type of entry, the
parent table, a keyword list, a ParseProc callback
and other goodies
pfMore-- set to FALSE if at end of file
EXIT: ERROR_SUCCESS if successful, otherwise an error code
(can be ERROR_ALREADY_DISPLAYED)
********************************************************************/
UINT CPolicyComponentData::ParseEntry(PARSEENTRYSTRUCT *ppes,BOOL *pfMore,
LPTSTR pKeyName)
{
TCHAR szWordBuf[WORDBUFSIZE+1];
UINT uErr,nListIndex;
BOOL fFoundEnd = FALSE;
PARSEPROCSTRUCT pps;
ENTRYDATA EntryData;
DWORD dwBufSize = DEFAULT_TMP_BUF_SIZE;
TABLEENTRY *pTmp = NULL;
BOOL bNewEntry = TRUE;
memset(&pps,0,sizeof(pps));
memset(&EntryData,0,sizeof(EntryData));
pps.pdwBufSize = &dwBufSize;
pps.pData = &EntryData;
pps.pData->fParentHasKey = ppes->fParentHasKey;
pps.pEntryCmpList = ppes->pEntryCmpList;
// get the entry name
if (!GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),NULL,NULL,pfMore,&uErr)) {
return uErr;
}
if (ppes->dwEntryType & ETYPE_CATEGORY) {
pTmp = FindCategory (ppes->pParent, szWordBuf);
}
if (pTmp) {
bNewEntry = FALSE;
} else {
//
// Create a new table entry
//
if (!(pps.pTableEntry = (TABLEENTRY *) GlobalAlloc(GPTR,*pps.pdwBufSize)))
return ERROR_NOT_ENOUGH_MEMORY;
// initialize TABLEENTRY struct
pps.pTableEntry->dwSize = ppes->dwStructSize;
pps.pTableEntry->dwType = ppes->dwEntryType;
// store the entry name in pTableEntry
pTmp = (TABLEENTRY *) AddDataToEntry(pps.pTableEntry,
(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),&(pps.pTableEntry->uOffsetName),
pps.pdwBufSize);
if (!pTmp) {
GlobalFree ((HGLOBAL)pps.pTableEntry);
return ERROR_NOT_ENOUGH_MEMORY;
}
}
pps.pTableEntry = pTmp;
// loop through the body of the declaration
while (!fFoundEnd && GetNextSectionWord(szWordBuf,
ARRAYSIZE(szWordBuf),pps.pEntryCmpList,&nListIndex,pfMore,&uErr)) {
if ( (uErr = (*ppes->pParseProc) (this, nListIndex,&pps,pfMore,&fFoundEnd,pKeyName))
!= ERROR_SUCCESS) {
if (bNewEntry) {
GlobalFree ((HGLOBAL)pps.pTableEntry);
}
return (uErr);
}
if (!bNewEntry) {
if (pTmp != pps.pTableEntry) {
//
// We need to fix up the link list of pointers in case the tableentry
// has moved due to a realloc
//
if (pps.pTableEntry->pPrev) {
pps.pTableEntry->pPrev->pNext = pps.pTableEntry;
} else {
ppes->pParent->pChild = pps.pTableEntry;
}
if (pps.pTableEntry->pNext) {
pps.pTableEntry->pNext->pPrev = pps.pTableEntry;
}
pTmp = pps.pTableEntry;
}
}
}
if (uErr != ERROR_SUCCESS) {
if (bNewEntry) {
GlobalFree ((HGLOBAL)pps.pTableEntry);
}
return (uErr);
}
// Last word was "END"
// get the keyword that goes with "END" ("END CATGORY", "END POLICY", etc.)
if (!GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
ppes->pTypeCmpList,&nListIndex,pfMore,&uErr)) {
if (bNewEntry) {
GlobalFree ((HGLOBAL)pps.pTableEntry);
}
return (uErr);
}
// call the object's parse proc one last time to let it object if
// key name or something like that is missing
if ( (uErr = (*ppes->pParseProc) (this, KYWD_DONE,&pps,pfMore,&fFoundEnd,pKeyName))
!= ERROR_SUCCESS) {
if (bNewEntry) {
GlobalFree ((HGLOBAL)pps.pTableEntry);
}
return (uErr);
}
if (bNewEntry) {
// fix up linked list pointers. If parent has no children yet, make this
// 1st child; otherwise walk the list of children and insert this at the end
if (!ppes->pParent->pChild) {
ppes->pParent->pChild = pps.pTableEntry;
} else {
TABLEENTRY * pLastChild = ppes->pParent->pChild;
while (pLastChild->pNext) {
pLastChild = pLastChild->pNext;
}
pLastChild->pNext = pps.pTableEntry;
pps.pTableEntry->pPrev = pLastChild;
}
}
return ERROR_SUCCESS;
}
/*******************************************************************
NAME: ParseCategory
SYNOPSIS: Parses a category
NOTES: Sets up a PARSEENTRYSTRUCT and lets ParseEntry do the
work.
********************************************************************/
UINT CPolicyComponentData::ParseCategory(TABLEENTRY * pParent,
BOOL fParentHasKey,BOOL *pfMore,
LPTSTR pKeyName)
{
PARSEENTRYSTRUCT pes;
pes.pParent = pParent;
pes.dwEntryType = ETYPE_CATEGORY;
pes.pEntryCmpList = pCategoryEntryCmpList;
pes.pTypeCmpList = pCategoryTypeCmpList;
pes.pParseProc = CategoryParseProc;
pes.dwStructSize = sizeof(CATEGORY);
pes.fHasSubtable = TRUE;
pes.fParentHasKey = fParentHasKey;
return ParseEntry(&pes,pfMore,pKeyName);
}
/*******************************************************************
NAME: CategoryParseProc
SYNOPSIS: Keyword callback ParseProc for category parsing
ENTRY: nMsg-- index into pEntryCmpList array which specifies
keyword that was found.
ppps-- pointer to PARSEPROCSTRUCT that contains useful
data like a pointer to the TABLEENTRY being built
and a pointer to an ENTRYDATA struct to maintain
state between calls to the ParseProc
********************************************************************/
UINT CPolicyComponentData::CategoryParseProc(CPolicyComponentData * pCD,
UINT nMsg,PARSEPROCSTRUCT * ppps,
BOOL * pfMore,BOOL * pfFoundEnd,
LPTSTR pKeyName)
{
TCHAR szWordBuf[WORDBUFSIZE+1];
CATEGORY * pCategory = (CATEGORY *) ppps->pTableEntry;
TABLEENTRY * pOld = ppps->pTableEntry, *pTmp;
LPTSTR lpHelpBuf;
UINT uErr;
switch (nMsg) {
case KYWD_ID_KEYNAME:
// have we already found a key name?
if (ppps->pData->fHasKey) {
pCD->DisplayKeywordError(IDS_ParseErr_DUPLICATE_KEYNAME,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// get the key name
if (!pCD->GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
NULL,NULL,pfMore,&uErr))
return uErr;
// store the key name in pCategory
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pCategory,
(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),&(pCategory->uOffsetKeyName),
ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
ppps->pData->fHasKey = TRUE;
return ERROR_SUCCESS;
break;
case KYWD_ID_END:
*pfFoundEnd = TRUE;
return ERROR_SUCCESS;
break;
case KYWD_ID_POLICY:
case KYWD_ID_CATEGORY:
{
BOOL fHasKey = ppps->pData->fHasKey | ppps->pData->fParentHasKey;
if (nMsg == KYWD_ID_POLICY)
uErr=pCD->ParsePolicy((TABLEENTRY *) pCategory,fHasKey,pfMore,
(ppps->pData->fHasKey ? GETKEYNAMEPTR(pCategory) : pKeyName));
else
uErr=pCD->ParseCategory((TABLEENTRY *) pCategory,fHasKey,pfMore,
(ppps->pData->fHasKey ? GETKEYNAMEPTR(pCategory) : pKeyName));
}
return uErr;
break;
case KYWD_ID_HELP:
// have we already found a help string already?
if (pCategory->uOffsetHelp) {
pCD->DisplayKeywordError(IDS_ParseErr_DUPLICATE_HELP,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
lpHelpBuf = (LPTSTR) LocalAlloc (LPTR, HELPBUFSIZE * sizeof(TCHAR));
if (!lpHelpBuf) {
pCD->DisplayKeywordError(IDS_ErrOUTOFMEMORY,NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// get the help string
if (!pCD->GetNextSectionWord(lpHelpBuf,HELPBUFSIZE,
NULL,NULL,pfMore,&uErr)) {
LocalFree (lpHelpBuf);
return uErr;
}
// store the help string
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pCategory,
(BYTE *)lpHelpBuf,(lstrlen(lpHelpBuf)+1) * sizeof(TCHAR),&(pCategory->uOffsetHelp),
ppps->pdwBufSize);
LocalFree (lpHelpBuf);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
return ERROR_SUCCESS;
case KYWD_DONE:
if (!ppps->pData->fHasKey && pKeyName) {
// store the key name in pCategory
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pCategory,
(BYTE *)pKeyName,(lstrlen(pKeyName)+1) * sizeof(TCHAR),&(pCategory->uOffsetKeyName),
ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
ppps->pData->fHasKey = TRUE;
}
return ERROR_SUCCESS;
break;
default:
return ERROR_SUCCESS;
break;
}
}
/*******************************************************************
NAME: ParsePolicy
SYNOPSIS: Parses a policy
NOTES: Sets up a PARSEENTRYSTRUCT and lets ParseEntry do the
work.
********************************************************************/
UINT CPolicyComponentData::ParsePolicy(TABLEENTRY * pParent,
BOOL fParentHasKey,BOOL *pfMore,
LPTSTR pKeyName)
{
PARSEENTRYSTRUCT pes;
pes.pParent = pParent;
pes.dwEntryType = ETYPE_POLICY;
pes.pEntryCmpList = pPolicyEntryCmpList;
pes.pTypeCmpList = pPolicyTypeCmpList;
pes.pParseProc = PolicyParseProc;
pes.dwStructSize = sizeof(POLICY);
pes.fHasSubtable = TRUE;
pes.fParentHasKey = fParentHasKey;
return ParseEntry(&pes,pfMore, pKeyName);
}
/*******************************************************************
NAME: PolicyParseProc
SYNOPSIS: Keyword callback ParseProc for policy parsing
ENTRY: nMsg-- index into pEntryCmpList array which specifies
keyword that was found.
ppps-- pointer to PARSEPROCSTRUCT that contains useful
data like a pointer to the TABLEENTRY being built
and a pointer to an ENTRYDATA struct to maintain
state between calls to the ParseProc
********************************************************************/
UINT CPolicyComponentData::PolicyParseProc(CPolicyComponentData * pCD,
UINT nMsg,PARSEPROCSTRUCT * ppps,
BOOL * pfMore,BOOL * pfFoundEnd,LPTSTR pKeyName)
{
TCHAR szWordBuf[WORDBUFSIZE+1];
LPTSTR lpHelpBuf, lpKeyName;
POLICY * pPolicy = (POLICY *) ppps->pTableEntry;
TABLEENTRY * pOld = ppps->pTableEntry, *pTmp;
UINT uErr;
switch (nMsg) {
case KYWD_ID_KEYNAME:
// have we already found a key name?
if (ppps->pData->fHasKey) {
pCD->DisplayKeywordError(IDS_ParseErr_DUPLICATE_KEYNAME,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// get the key name
if (!pCD->GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
NULL,NULL,pfMore,&uErr))
return uErr;
// store the key name in pPolicy
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pPolicy,
(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1)*sizeof(TCHAR),&(pPolicy->uOffsetKeyName),ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
ppps->pData->fHasKey = TRUE;
return ERROR_SUCCESS;
case KYWD_ID_VALUENAME:
// have we already found a key name?
if (ppps->pData->fHasValue) {
pCD->DisplayKeywordError(IDS_ParseErr_DUPLICATE_VALUENAME,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// get the key name
if (!pCD->GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
NULL,NULL,pfMore,&uErr))
return uErr;
// store the key name in pSettings
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pPolicy,
(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),&(pPolicy->uOffsetValueName),
ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
ppps->pData->fHasValue = TRUE;
return ERROR_SUCCESS;
case KYWD_ID_HELP:
// have we already found a help string already?
if (pPolicy->uOffsetHelp) {
pCD->DisplayKeywordError(IDS_ParseErr_DUPLICATE_HELP,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
lpHelpBuf = (LPTSTR) LocalAlloc (LPTR, HELPBUFSIZE * sizeof(TCHAR));
if (!lpHelpBuf) {
pCD->DisplayKeywordError(IDS_ErrOUTOFMEMORY,NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// get the help string
if (!pCD->GetNextSectionWord(lpHelpBuf,HELPBUFSIZE,
NULL,NULL,pfMore,&uErr)) {
LocalFree (lpHelpBuf);
return uErr;
}
// store the help string
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pPolicy,
(BYTE *)lpHelpBuf,(lstrlen(lpHelpBuf)+1) * sizeof(TCHAR),&(pPolicy->uOffsetHelp),
ppps->pdwBufSize);
LocalFree (lpHelpBuf);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
return ERROR_SUCCESS;
case KYWD_ID_CLIENTEXT:
// have we already found a clientext string already?
if (pPolicy->uOffsetClientExt) {
pCD->DisplayKeywordError(IDS_ParseErr_DUPLICATE_CLIENTEXT,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// get the key name
if (!pCD->GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
NULL,NULL,pfMore,&uErr))
return uErr;
if (!ValidateGuid(szWordBuf))
{
pCD->DisplayKeywordError(IDS_ParseErr_INVALID_CLIENTEXT,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// store the clientext string in pSettings
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pPolicy,
(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),&(pPolicy->uOffsetClientExt),
ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
return ERROR_SUCCESS;
case KYWD_ID_SUPPORTED:
// have we already found a supported string already?
if (pPolicy->uOffsetSupported) {
pCD->DisplayKeywordError(IDS_ParseErr_DUPLICATE_SUPPORTED,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// get the supported platforms
if (!pCD->GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
NULL,NULL,pfMore,&uErr))
return uErr;
// store the supported string in pSettings
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pPolicy,
(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),&(pPolicy->uOffsetSupported),
ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
return ERROR_SUCCESS;
case KYWD_ID_END:
*pfFoundEnd = TRUE;
return ERROR_SUCCESS;
case KYWD_ID_PART:
{
BOOL fHasKey = ppps->pData->fHasKey | ppps->pData->fParentHasKey;
return pCD->ParseSettings((TABLEENTRY *) pPolicy,fHasKey,pfMore,
(ppps->pData->fHasKey ? GETKEYNAMEPTR(pPolicy) : pKeyName));
}
case KYWD_ID_VALUEON:
return pCD->ParseValue(ppps,&pPolicy->uOffsetValue_On,
&ppps->pTableEntry,pfMore);
case KYWD_ID_VALUEOFF:
return pCD->ParseValue(ppps,&pPolicy->uOffsetValue_Off,
&ppps->pTableEntry,pfMore);
case KYWD_ID_ACTIONLISTON:
return pCD->ParseActionList(ppps,&pPolicy->uOffsetActionList_On,
&ppps->pTableEntry,szACTIONLISTON,pfMore);
case KYWD_ID_ACTIONLISTOFF:
return pCD->ParseActionList(ppps,&pPolicy->uOffsetActionList_Off,
&ppps->pTableEntry,szACTIONLISTOFF,pfMore);
case KYWD_DONE:
if (!ppps->pData->fHasKey) {
if (!ppps->pData->fParentHasKey) {
pCD->DisplayKeywordError(IDS_ParseErr_NO_KEYNAME,NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// store the key name in pPolicy
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pPolicy,
(BYTE *)pKeyName,(lstrlen(pKeyName)+1)*sizeof(TCHAR),&(pPolicy->uOffsetKeyName),ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
pPolicy = (POLICY *) pTmp;
ppps->pData->fHasKey = TRUE;
}
if (!pPolicy->uOffsetValueName && !pPolicy->pChild)
{
if ((!pPolicy->uOffsetValue_On && pPolicy->uOffsetValue_Off) ||
(pPolicy->uOffsetValue_On && !pPolicy->uOffsetValue_Off))
{
pCD->DisplayKeywordError(IDS_ParseErr_MISSINGVALUEON_OR_OFF,NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
}
//
// Check if this is a real policy
//
lpKeyName = GETKEYNAMEPTR(ppps->pTableEntry);
if (!lpKeyName) {
return ERROR_INVALID_PARAMETER;
}
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpKeyName, pCD->m_iSWPoliciesLen,
SOFTWARE_POLICIES, pCD->m_iSWPoliciesLen) == CSTR_EQUAL)
{
((POLICY *) ppps->pTableEntry)->bTruePolicy = TRUE;
}
else if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpKeyName, pCD->m_iWinPoliciesLen,
WINDOWS_POLICIES, pCD->m_iWinPoliciesLen) == CSTR_EQUAL)
{
((POLICY *) ppps->pTableEntry)->bTruePolicy = TRUE;
}
( (POLICY *) ppps->pTableEntry)->uDataIndex = *pCD->m_pnDataItemCount;
(*pCD->m_pnDataItemCount) ++;
return ERROR_SUCCESS;
default:
break;
}
return ERROR_SUCCESS;
}
/*******************************************************************
NAME: ParseSettings
SYNOPSIS: Parses a policy setting
NOTES: Sets up a PARSEENTRYSTRUCT and lets ParseEntry do the
work.
********************************************************************/
UINT CPolicyComponentData::ParseSettings(TABLEENTRY * pParent,
BOOL fParentHasKey,BOOL *pfMore,
LPTSTR pKeyName)
{
PARSEENTRYSTRUCT pes;
pes.pParent = pParent;
pes.dwEntryType = ETYPE_SETTING;
pes.pEntryCmpList = pSettingsEntryCmpList;
pes.pTypeCmpList = pSettingsTypeCmpList;
pes.pParseProc = SettingsParseProc;
pes.dwStructSize = sizeof(SETTINGS);
pes.fHasSubtable = FALSE;
pes.fParentHasKey = fParentHasKey;
return ParseEntry(&pes,pfMore, pKeyName);
}
/*******************************************************************
NAME: SettingsParseProc
SYNOPSIS: Keyword callback ParseProc for policy settings parsing
ENTRY: nMsg-- index into pEntryCmpList array which specifies
keyword that was found.
ppps-- pointer to PARSEPROCSTRUCT that contains useful
data like a pointer to the TABLEENTRY being built
and a pointer to an ENTRYDATA struct to maintain
state between calls to the ParseProc
********************************************************************/
UINT CPolicyComponentData::SettingsParseProc(CPolicyComponentData *pCD,
UINT nMsg,PARSEPROCSTRUCT * ppps,
BOOL * pfMore,BOOL * pfFoundEnd,
LPTSTR pKeyName)
{
TCHAR szWordBuf[WORDBUFSIZE+1];
SETTINGS * pSettings = (SETTINGS *) ppps->pTableEntry;
BYTE * pObjectData = GETOBJECTDATAPTR(pSettings);
TABLEENTRY *pTmp;
UINT uErr;
switch (nMsg) {
case KYWD_ID_KEYNAME:
// have we already found a key name?
if (ppps->pData->fHasKey) {
pCD->DisplayKeywordError(IDS_ParseErr_DUPLICATE_KEYNAME,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// get the key name
if (!pCD->GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
NULL,NULL,pfMore,&uErr))
return uErr;
// store the key name in pSettings
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pSettings,
(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),&(pSettings->uOffsetKeyName),ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
ppps->pData->fHasKey = TRUE;
return ERROR_SUCCESS;
break;
case KYWD_ID_VALUENAME:
// have we already found a value name?
if (ppps->pData->fHasValue) {
pCD->DisplayKeywordError(IDS_ParseErr_DUPLICATE_VALUENAME,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// get the value name
if (!pCD->GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
NULL,NULL,pfMore,&uErr))
return uErr;
// store the value name in pSettings
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pSettings,
(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),&(pSettings->uOffsetValueName),
ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
ppps->pData->fHasValue = TRUE;
return ERROR_SUCCESS;
break;
case KYWD_ID_CLIENTEXT:
// have we already found a clientext string already?
if (pSettings->uOffsetClientExt) {
pCD->DisplayKeywordError(IDS_ParseErr_DUPLICATE_CLIENTEXT,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// get the clientext name
if (!pCD->GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
NULL,NULL,pfMore,&uErr))
return uErr;
if (!ValidateGuid(szWordBuf))
{
pCD->DisplayKeywordError(IDS_ParseErr_INVALID_CLIENTEXT,
NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// store the clientext string in pSettings
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pSettings,
(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),&(pSettings->uOffsetClientExt),
ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
return ERROR_SUCCESS;
case KYWD_ID_REQUIRED:
pSettings->dwFlags |= DF_REQUIRED;
return ERROR_SUCCESS;
break;
case KYWD_ID_EXPANDABLETEXT:
pSettings->dwFlags |= DF_EXPANDABLETEXT;
return ERROR_SUCCESS;
break;
case KYWD_ID_SUGGESTIONS:
return pCD->ParseSuggestions(ppps,&((POLICYCOMBOBOXINFO *)
(GETOBJECTDATAPTR(pSettings)))->uOffsetSuggestions,
&ppps->pTableEntry,pfMore);
case KYWD_ID_TXTCONVERT:
pSettings->dwFlags |= DF_TXTCONVERT;
return ERROR_SUCCESS;
break;
case KYWD_ID_END:
*pfFoundEnd = TRUE;
return ERROR_SUCCESS;
break;
case KYWD_ID_SOFT:
pSettings->dwFlags |= VF_SOFT;
return ERROR_SUCCESS;
break;
case KYWD_DONE:
if (!ppps->pData->fHasKey) {
if (!ppps->pData->fParentHasKey) {
pCD->DisplayKeywordError(IDS_ParseErr_NO_KEYNAME,NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
// store the key name in pSettings
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pSettings,
(BYTE *)pKeyName,(lstrlen(pKeyName)+1) * sizeof(TCHAR),&(pSettings->uOffsetKeyName),ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
ppps->pData->fHasKey = TRUE;
}
if (!ppps->pData->fHasValue) {
pCD->DisplayKeywordError(IDS_ParseErr_NO_VALUENAME,NULL,NULL);
return ERROR_ALREADY_DISPLAYED;
}
( (SETTINGS *) ppps->pTableEntry)->uDataIndex = *pCD->m_pnDataItemCount;
(*pCD->m_pnDataItemCount) ++;
return ERROR_SUCCESS;
break;
case KYWD_ID_CHECKBOX:
return (pCD->InitSettingsParse(ppps,ETYPE_SETTING | STYPE_CHECKBOX,
sizeof(CHECKBOXINFO),pCheckboxCmpList,&pSettings,&pObjectData));
break;
case KYWD_ID_TEXT:
ppps->pData->fHasValue = TRUE; // no key value for static text items
return (pCD->InitSettingsParse(ppps,ETYPE_SETTING | STYPE_TEXT,
0,pTextCmpList,&pSettings,&pObjectData));
break;
case KYWD_ID_EDITTEXT:
uErr=pCD->InitSettingsParse(ppps,ETYPE_SETTING | STYPE_EDITTEXT,
sizeof(EDITTEXTINFO),pEditTextCmpList,&pSettings,&pObjectData);
if (uErr != ERROR_SUCCESS) return uErr;
{
EDITTEXTINFO *pEditTextInfo = (EDITTEXTINFO *)
(GETOBJECTDATAPTR(((SETTINGS *) ppps->pTableEntry)));
if (!pEditTextInfo) {
return ERROR_INVALID_PARAMETER;
}
pEditTextInfo->nMaxLen = MAXSTRLEN-1;
}
break;
case KYWD_ID_COMBOBOX:
uErr=pCD->InitSettingsParse(ppps,ETYPE_SETTING | STYPE_COMBOBOX,
sizeof(POLICYCOMBOBOXINFO),pComboboxCmpList,&pSettings,&pObjectData);
if (uErr != ERROR_SUCCESS) return uErr;
{
EDITTEXTINFO *pEditTextInfo = (EDITTEXTINFO *)
(GETOBJECTDATAPTR(((SETTINGS *) ppps->pTableEntry)));
pEditTextInfo->nMaxLen = MAXSTRLEN-1;
}
break;
case KYWD_ID_NUMERIC:
uErr=pCD->InitSettingsParse(ppps,ETYPE_SETTING | STYPE_NUMERIC,
sizeof(NUMERICINFO),pNumericCmpList,&pSettings,&pObjectData);
if (uErr != ERROR_SUCCESS) return uErr;
if (!pObjectData) return ERROR_INVALID_PARAMETER;
( (NUMERICINFO *) pObjectData)->uDefValue = 1;
( (NUMERICINFO *) pObjectData)->uMinValue = 1;
( (NUMERICINFO *) pObjectData)->uMaxValue = 9999;
( (NUMERICINFO *) pObjectData)->uSpinIncrement = 1;
break;
case KYWD_ID_DROPDOWNLIST:
ppps->pEntryCmpList = pDropdownlistCmpList;
ppps->pTableEntry->dwType = ETYPE_SETTING | STYPE_DROPDOWNLIST;
return ERROR_SUCCESS;
break;
case KYWD_ID_LISTBOX:
uErr=pCD->InitSettingsParse(ppps,ETYPE_SETTING | STYPE_LISTBOX,
sizeof(LISTBOXINFO),pListboxCmpList,&pSettings,&pObjectData);
if (uErr != ERROR_SUCCESS) return uErr;
// listboxes have no single value name, set the value name to ""
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *) pSettings,
(BYTE *) g_szNull,(lstrlen(g_szNull)+1) * sizeof(TCHAR),&(pSettings->uOffsetValueName),
ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
ppps->pData->fHasValue = TRUE;
return ERROR_SUCCESS;
break;
case KYWD_ID_EDITTEXT_DEFAULT:
case KYWD_ID_COMBOBOX_DEFAULT:
// get the default text
if (!pCD->GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
NULL,NULL,pfMore,&uErr))
return uErr;
// store the default text in pTableEntry
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *)
pSettings,(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),
&((EDITTEXTINFO *) (GETOBJECTDATAPTR(pSettings)))->uOffsetDefText,
ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
((SETTINGS *) ppps->pTableEntry)->dwFlags |= DF_USEDEFAULT;
break;
case KYWD_ID_MAXLENGTH:
{
EDITTEXTINFO *pEditTextInfo = (EDITTEXTINFO *)
(GETOBJECTDATAPTR(pSettings));
if ((uErr=pCD->GetNextSectionNumericWord(
&pEditTextInfo->nMaxLen)) != ERROR_SUCCESS)
return uErr;
}
break;
case KYWD_ID_MAX:
if ((uErr=pCD->GetNextSectionNumericWord(
&((NUMERICINFO *)pObjectData)->uMaxValue)) != ERROR_SUCCESS)
return uErr;
break;
case KYWD_ID_MIN:
if ((uErr=pCD->GetNextSectionNumericWord(
&((NUMERICINFO *)pObjectData)->uMinValue)) != ERROR_SUCCESS)
return uErr;
break;
case KYWD_ID_SPIN:
if ((uErr=pCD->GetNextSectionNumericWord(
&((NUMERICINFO *)pObjectData)->uSpinIncrement)) != ERROR_SUCCESS)
return uErr;
break;
case KYWD_ID_NUMERIC_DEFAULT:
if ((uErr=pCD->GetNextSectionNumericWord(
&((NUMERICINFO *)pObjectData)->uDefValue)) != ERROR_SUCCESS)
return uErr;
pSettings->dwFlags |= (DF_DEFCHECKED | DF_USEDEFAULT);
break;
case KYWD_ID_DEFCHECKED:
pSettings->dwFlags |= (DF_DEFCHECKED | DF_USEDEFAULT);
break;
case KYWD_ID_VALUEON:
return pCD->ParseValue(ppps,&((CHECKBOXINFO *)
pObjectData)->uOffsetValue_On,
&ppps->pTableEntry,pfMore);
break;
case KYWD_ID_VALUEOFF:
return pCD->ParseValue(ppps,&((CHECKBOXINFO *)
pObjectData)->uOffsetValue_Off,
&ppps->pTableEntry,pfMore);
break;
case KYWD_ID_ACTIONLISTON:
return pCD->ParseActionList(ppps,&((CHECKBOXINFO *)
pObjectData)->uOffsetActionList_On,
&ppps->pTableEntry,szACTIONLISTON,pfMore);
break;
case KYWD_ID_ACTIONLISTOFF:
return pCD->ParseActionList(ppps,&((CHECKBOXINFO *)
pObjectData)->uOffsetActionList_Off,
&ppps->pTableEntry,szACTIONLISTOFF,pfMore);
break;
case KYWD_ID_ITEMLIST:
return pCD->ParseItemList(ppps,&pSettings->uOffsetObjectData,
pfMore);
break;
case KYWD_ID_VALUEPREFIX:
// get the string to be ised as prefix
if (!pCD->GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
NULL,NULL,pfMore,&uErr))
return uErr;
// store the string pTableEntry
pTmp = (TABLEENTRY *) pCD->AddDataToEntry((TABLEENTRY *)
pSettings,(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),
&((LISTBOXINFO *) (GETOBJECTDATAPTR(pSettings)))->uOffsetPrefix,
ppps->pdwBufSize);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
break;
case KYWD_ID_ADDITIVE:
pSettings->dwFlags |= DF_ADDITIVE;
return ERROR_SUCCESS;
break;
case KYWD_ID_EXPLICITVALUE:
pSettings->dwFlags |= DF_EXPLICITVALNAME;
return ERROR_SUCCESS;
break;
case KYWD_ID_NOSORT:
pSettings->dwFlags |= DF_NOSORT;
break;
}
return ERROR_SUCCESS;
}
UINT CPolicyComponentData::InitSettingsParse(PARSEPROCSTRUCT *ppps,DWORD dwType,DWORD dwSize,
KEYWORDINFO * pKeyList,SETTINGS ** ppSettings,BYTE **ppObjectData)
{
TABLEENTRY *pTmp;
if (dwSize) {
// increase the buffer to fit object-specific data if specified
pTmp = (TABLEENTRY *) AddDataToEntry(ppps->pTableEntry,
NULL,dwSize,&( ((SETTINGS * )ppps->pTableEntry)->uOffsetObjectData),
ppps->pdwBufSize);
if (!pTmp) return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
}
else ( (SETTINGS *) ppps->pTableEntry)->uOffsetObjectData= 0;
ppps->pEntryCmpList = pKeyList;
ppps->pTableEntry->dwType = dwType;
*ppSettings = (SETTINGS *) ppps->pTableEntry;
*ppObjectData = GETOBJECTDATAPTR((*ppSettings));
return ERROR_SUCCESS;
}
UINT CPolicyComponentData::ParseValue_W(PARSEPROCSTRUCT * ppps,TCHAR * pszWordBuf,
DWORD cbWordBuf,DWORD * pdwValue,DWORD * pdwFlags,BOOL * pfMore)
{
UINT uErr;
*pdwFlags = 0;
*pdwValue = 0;
// get the next word
if (!GetNextSectionWord(pszWordBuf,cbWordBuf,
NULL,NULL,pfMore,&uErr))
return uErr;
// if this keyword is "SOFT", set the soft flag and get the next word
if (!lstrcmpi(szSOFT,pszWordBuf)) {
*pdwFlags |= VF_SOFT;
if (!GetNextSectionWord(pszWordBuf,cbWordBuf,
NULL,NULL,pfMore,&uErr))
return uErr;
}
// this word is either the value to use, or the keyword "NUMERIC"
// followed by a numeric value to use
if (!lstrcmpi(szNUMERIC,pszWordBuf)) {
// get the next word
if (!GetNextSectionWord(pszWordBuf,cbWordBuf,
NULL,NULL,pfMore,&uErr))
return uErr;
if (!StringToNum(pszWordBuf,(UINT *)pdwValue)) {
DisplayKeywordError(IDS_ParseErr_NOT_NUMERIC,
pszWordBuf,NULL);
return ERROR_ALREADY_DISPLAYED;
}
*pdwFlags |= VF_ISNUMERIC;
} else {
// "DELETE" is a special word
if (!lstrcmpi(pszWordBuf,szDELETE))
*pdwFlags |= VF_DELETE;
}
return ERROR_SUCCESS;
}
UINT CPolicyComponentData::ParseValue(PARSEPROCSTRUCT * ppps,UINT * puOffsetData,
TABLEENTRY ** ppTableEntryNew,BOOL * pfMore)
{
TCHAR szWordBuf[WORDBUFSIZE+1];
STATEVALUE * pStateValue;
DWORD dwValue;
DWORD dwFlags = 0;
DWORD dwAlloc;
UINT uErr;
TABLEENTRY *pTmp;
HRESULT hr = S_OK;
// call worker function
uErr=ParseValue_W(ppps,szWordBuf,ARRAYSIZE(szWordBuf),&dwValue,
&dwFlags,pfMore);
if (uErr != ERROR_SUCCESS) return uErr;
dwAlloc = sizeof(STATEVALUE);
if (!dwFlags) dwAlloc += (lstrlen(szWordBuf) + 1) * sizeof(TCHAR);
// allocate temporary buffer to build STATEVALUE struct
pStateValue = (STATEVALUE *) GlobalAlloc(GPTR,dwAlloc);
if (!pStateValue)
return ERROR_NOT_ENOUGH_MEMORY;
pStateValue->dwFlags = dwFlags;
if (dwFlags & VF_ISNUMERIC)
pStateValue->dwValue = dwValue;
else if (!dwFlags) {
hr = StringCchCopy(pStateValue->szValue, lstrlen(szWordBuf) + 1, szWordBuf);
ASSERT(SUCCEEDED(hr));
}
pTmp=(TABLEENTRY *) AddDataToEntry(ppps->pTableEntry,
(BYTE *) pStateValue,dwAlloc,puOffsetData,NULL);
GlobalFree(pStateValue);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
*ppTableEntryNew = pTmp;
return FALSE;
}
#define DEF_SUGGESTBUF_SIZE 1024
#define SUGGESTBUF_INCREMENT 256
UINT CPolicyComponentData::ParseSuggestions(PARSEPROCSTRUCT * ppps,UINT * puOffsetData,
TABLEENTRY ** ppTableEntryNew,BOOL * pfMore)
{
TCHAR szWordBuf[WORDBUFSIZE+1];
TCHAR *pTmpBuf, *pTmp;
DWORD dwAlloc=DEF_SUGGESTBUF_SIZE * sizeof(TCHAR);
DWORD dwUsed = 0;
BOOL fContinue = TRUE;
UINT uErr;
TABLEENTRY *pTmpTblEntry;
HRESULT hr = S_OK;
KEYWORDINFO pSuggestionsTypeCmpList[] = { {szSUGGESTIONS,KYWD_ID_SUGGESTIONS},
{NULL,0} };
if (!(pTmpBuf = (TCHAR *) GlobalAlloc(GPTR,dwAlloc)))
return ERROR_NOT_ENOUGH_MEMORY;
// get the next word
while (fContinue && GetNextSectionWord(szWordBuf,
ARRAYSIZE(szWordBuf),NULL,NULL,pfMore,&uErr)) {
// if this word is "END", add the whole list to the setting object data
if (!lstrcmpi(szEND,szWordBuf)) {
// get the next word after "END, make sure it's "SUGGESTIONS"
if (!GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
pSuggestionsTypeCmpList,NULL,pfMore,&uErr)) {
GlobalFree(pTmpBuf);
return uErr;
}
// doubly-NULL terminate the list
*(pTmpBuf+dwUsed) = '\0';
dwUsed++;
pTmpTblEntry=(TABLEENTRY *)AddDataToEntry(ppps->pTableEntry,
(BYTE *)pTmpBuf,(dwUsed * sizeof(TCHAR)),puOffsetData,NULL);
if (!pTmpTblEntry) {
GlobalFree(pTmpBuf);
return ERROR_NOT_ENOUGH_MEMORY;
}
*ppTableEntryNew = pTmpTblEntry;
fContinue = FALSE;
} else {
// pack the word into the temporary buffer
UINT nLength = lstrlen(szWordBuf);
DWORD dwNeeded = (dwUsed + nLength + 2) * sizeof(TCHAR);
// resize buffer as necessary
if (dwNeeded > dwAlloc) {
while (dwAlloc < dwNeeded)
dwAlloc += SUGGESTBUF_INCREMENT;
if (!(pTmp = (TCHAR *) GlobalReAlloc(pTmpBuf,dwAlloc,
GMEM_MOVEABLE | GMEM_ZEROINIT)))
{
GlobalFree (pTmpBuf);
return ERROR_NOT_ENOUGH_MEMORY;
}
pTmpBuf = pTmp;
}
hr = StringCchCopy(pTmpBuf + dwUsed, dwNeeded - dwUsed, szWordBuf);
ASSERT(SUCCEEDED(hr));
dwUsed += lstrlen(szWordBuf) +1;
}
}
GlobalFree(pTmpBuf);
return uErr;
}
UINT CPolicyComponentData::ParseActionList(PARSEPROCSTRUCT * ppps,UINT * puOffsetData,
TABLEENTRY ** ppTableEntryNew,
LPCTSTR pszKeyword,BOOL * pfMore)
{
TCHAR szWordBuf[WORDBUFSIZE+1];
ACTIONLIST *pActionList;
ACTION *pActionCurrent;
UINT uOffsetActionCurrent;
DWORD dwAlloc=(DEF_SUGGESTBUF_SIZE * sizeof(TCHAR));
DWORD dwUsed = sizeof(ACTION) + sizeof(UINT);
UINT uErr=ERROR_SUCCESS,nIndex;
BOOL fContinue = TRUE;
TABLEENTRY *pTmp;
KEYWORDINFO pActionlistTypeCmpList[] = { {szKEYNAME,KYWD_ID_KEYNAME},
{szVALUENAME,KYWD_ID_VALUENAME},{szVALUE,KYWD_ID_VALUE},
{szEND,KYWD_ID_END},{NULL,0} };
KEYWORDINFO pActionlistCmpList[] = { {pszKeyword,KYWD_ID_ACTIONLIST},
{NULL,0} };
BOOL fHasKeyName=FALSE,fHasValueName=FALSE;
if (!(pActionList = (ACTIONLIST *) GlobalAlloc(GPTR,dwAlloc)))
return ERROR_NOT_ENOUGH_MEMORY;
pActionCurrent = pActionList->Action;
uOffsetActionCurrent = sizeof(UINT);
// get the next word
while ((uErr == ERROR_SUCCESS) && fContinue &&
GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
pActionlistTypeCmpList,&nIndex,pfMore,&uErr)) {
switch (nIndex) {
case KYWD_ID_KEYNAME:
if (fHasKeyName) {
DisplayKeywordError(IDS_ParseErr_DUPLICATE_KEYNAME,
NULL,NULL);
uErr = ERROR_ALREADY_DISPLAYED;
break;
}
// get the next word, which is the key name
if (!GetNextSectionWord(szWordBuf,
ARRAYSIZE(szWordBuf),NULL,NULL,pfMore,&uErr))
break;
// store the key name away
if (!AddActionListString(szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),
(BYTE **)&pActionList,
&pActionCurrent->uOffsetKeyName,&dwAlloc,&dwUsed)) {
uErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
fHasKeyName = TRUE;
pActionCurrent = (ACTION *) ((BYTE *) pActionList + uOffsetActionCurrent);
break;
case KYWD_ID_VALUENAME:
if (fHasValueName) {
DisplayKeywordError(IDS_ParseErr_DUPLICATE_KEYNAME,
NULL,NULL);
uErr = ERROR_ALREADY_DISPLAYED;
break;
}
// get the next word, which is the value name
if (!GetNextSectionWord(szWordBuf,
ARRAYSIZE(szWordBuf),NULL,NULL,pfMore,&uErr))
break;
// store the value name away
if (!AddActionListString(szWordBuf,(lstrlen(szWordBuf)+1) * sizeof(TCHAR),
(BYTE **)&pActionList,
&pActionCurrent->uOffsetValueName,&dwAlloc,&dwUsed)) {
uErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
fHasValueName = TRUE;
pActionCurrent = (ACTION *) ((BYTE *) pActionList + uOffsetActionCurrent);
break;
case KYWD_ID_VALUE:
if (!fHasValueName) {
DisplayKeywordError(IDS_ParseErr_NO_VALUENAME,
NULL,NULL);
uErr = ERROR_ALREADY_DISPLAYED;
break;
}
// call worker function to get value and value type
uErr=ParseValue_W(ppps,szWordBuf,ARRAYSIZE(szWordBuf),
&pActionCurrent->dwValue,&pActionCurrent->dwFlags,pfMore);
if (uErr != ERROR_SUCCESS)
break;
// if value is string, add it to buffer
if (!pActionCurrent->dwFlags && !AddActionListString(szWordBuf,
(lstrlen(szWordBuf)+1) * sizeof(TCHAR),(BYTE **)&pActionList,
&pActionCurrent->uOffsetValue,&dwAlloc,&dwUsed)) {
uErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
pActionCurrent = (ACTION *) ((BYTE *) pActionList + uOffsetActionCurrent);
// done with this action in the list, get ready for the next one
pActionList->nActionItems++;
fHasValueName = fHasKeyName = FALSE;
uOffsetActionCurrent = dwUsed;
// make room for next ACTION struct
if (!AddActionListString(NULL,sizeof(ACTION),(BYTE **)&pActionList,
&pActionCurrent->uOffsetNextAction,&dwAlloc,&dwUsed)) {
uErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
pActionCurrent = (ACTION *) ((BYTE *) pActionList + uOffsetActionCurrent);
break;
case KYWD_ID_END:
if (fHasKeyName || fHasValueName) {
DisplayKeywordError(IDS_ParseErr_NO_VALUENAME,
NULL,NULL);
uErr = ERROR_ALREADY_DISPLAYED;
break;
}
// make sure word following "END" is "ACTIONLIST"
if (!GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
pActionlistCmpList,NULL,pfMore,&uErr)) {
break;
}
// commit the action list we've built to table entry
pTmp=(TABLEENTRY *)AddDataToEntry(ppps->pTableEntry,
(BYTE *)pActionList,dwUsed,puOffsetData,NULL);
if (!pTmp) {
uErr=ERROR_NOT_ENOUGH_MEMORY;
} else {
*ppTableEntryNew = pTmp;
uErr = ERROR_SUCCESS;
fContinue = FALSE;
}
break;
}
}
GlobalFree(pActionList);
return uErr;
}
UINT CPolicyComponentData::ParseItemList(PARSEPROCSTRUCT * ppps,UINT * puOffsetData,
BOOL * pfMore)
{
// ptr to location to put the offset to next DROPDOWNINFO struct in chain
UINT * puLastOffsetPtr = puOffsetData;
TABLEENTRY * pTableEntryOld, *pTmp;
int nItemIndex=-1;
BOOL fHasItemName = FALSE,fHasActionList=FALSE,fHasValue=FALSE,fFirst=TRUE;
DROPDOWNINFO * pddi;
TCHAR szWordBuf[WORDBUFSIZE+1];
UINT uErr=ERROR_SUCCESS,nIndex;
KEYWORDINFO pItemlistTypeCmpList[] = { {szNAME,KYWD_ID_NAME},
{szACTIONLIST,KYWD_ID_ACTIONLIST},{szVALUE,KYWD_ID_VALUE},
{szEND,KYWD_ID_END},{szDEFAULT,KYWD_ID_DEFAULT},{NULL,0} };
KEYWORDINFO pItemlistCmpList[] = { {szITEMLIST,KYWD_ID_ITEMLIST},
{NULL,0} };
// get the next word
while ((uErr == ERROR_SUCCESS) &&
GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
pItemlistTypeCmpList,&nIndex,pfMore,&uErr)) {
switch (nIndex) {
case KYWD_ID_NAME:
// if this is the first keyword after a prior item
// (e.g., item and value flags both set) reset for next one
if (fHasItemName && fHasValue) {
fHasValue = fHasActionList= fHasItemName = FALSE;
puLastOffsetPtr = &pddi->uOffsetNextDropdowninfo;
}
if (fHasItemName) {
DisplayKeywordError(IDS_ParseErr_DUPLICATE_ITEMNAME,
NULL,NULL);
uErr = ERROR_ALREADY_DISPLAYED;
break;
}
// get the next word, which is the item name
if (!GetNextSectionWord(szWordBuf,
ARRAYSIZE(szWordBuf),NULL,NULL,pfMore,&uErr))
break;
// add room for a DROPDOWNINFO struct at end of buffer
pTableEntryOld=ppps->pTableEntry;
pTmp=(TABLEENTRY *)AddDataToEntry(ppps->pTableEntry,
NULL,sizeof(DROPDOWNINFO),puLastOffsetPtr,NULL);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
// adjust pointer to offset, in case table moved
puLastOffsetPtr = (UINT *) (((BYTE *) puLastOffsetPtr) +
((BYTE *) ppps->pTableEntry - (BYTE *) pTableEntryOld));
pddi = (DROPDOWNINFO *)
((BYTE *) ppps->pTableEntry + *puLastOffsetPtr);
// store the key name away
pTableEntryOld=ppps->pTableEntry;
pTmp=(TABLEENTRY *)AddDataToEntry(ppps->pTableEntry,
(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1)*sizeof(TCHAR),&pddi->uOffsetItemName,
NULL);
if (!pTmp)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmp;
// adjust pointer to offset, in case table moved
puLastOffsetPtr = (UINT *) (((BYTE *) puLastOffsetPtr) +
((BYTE *) ppps->pTableEntry - (BYTE *) pTableEntryOld));
pddi = (DROPDOWNINFO *)
((BYTE *) ppps->pTableEntry + *puLastOffsetPtr);
nItemIndex++;
fHasItemName = TRUE;
break;
case KYWD_ID_DEFAULT:
if (nItemIndex<0) {
DisplayKeywordError(IDS_ParseErr_NO_ITEMNAME,
NULL,NULL);
uErr = ERROR_ALREADY_DISPLAYED;
break;
}
( (SETTINGS *) ppps->pTableEntry)->dwFlags |= DF_USEDEFAULT;
( (DROPDOWNINFO *) GETOBJECTDATAPTR(((SETTINGS *)ppps->pTableEntry)))
->uDefaultItemIndex = nItemIndex;
break;
case KYWD_ID_VALUE:
if (!fHasItemName) {
DisplayKeywordError(IDS_ParseErr_NO_ITEMNAME,
NULL,NULL);
uErr = ERROR_ALREADY_DISPLAYED;
break;
}
// call worker function to get value and value type
uErr=ParseValue_W(ppps,szWordBuf,ARRAYSIZE(szWordBuf),
&pddi->dwValue,&pddi->dwFlags,pfMore);
if (uErr != ERROR_SUCCESS)
break;
// if value is string, add it to buffer
if (!pddi->dwFlags) {
// store the key name away
TABLEENTRY * pTmpTable;
pTableEntryOld = ppps->pTableEntry;
pTmpTable = (TABLEENTRY *) AddDataToEntry(ppps->pTableEntry,
(BYTE *)szWordBuf,(lstrlen(szWordBuf)+1)*sizeof(TCHAR),&pddi->uOffsetValue,
NULL);
if (!pTmpTable)
return ERROR_NOT_ENOUGH_MEMORY;
ppps->pTableEntry = pTmpTable;
// adjust pointer to offset, in case table moved
puLastOffsetPtr = (UINT *) (((BYTE *) puLastOffsetPtr) +
((BYTE *) ppps->pTableEntry - (BYTE *) pTableEntryOld));
pddi = (DROPDOWNINFO *)
((BYTE *) ppps->pTableEntry + *puLastOffsetPtr);
}
fHasValue = TRUE;
break;
case KYWD_ID_ACTIONLIST:
if (!fHasItemName) {
DisplayKeywordError(IDS_ParseErr_NO_ITEMNAME,
NULL,NULL);
uErr = ERROR_ALREADY_DISPLAYED;
break;
}
if (fHasActionList) {
DisplayKeywordError(IDS_ParseErr_DUPLICATE_ACTIONLIST,
NULL,NULL);
uErr = ERROR_ALREADY_DISPLAYED;
break;
}
pTableEntryOld=ppps->pTableEntry;
uErr=ParseActionList(ppps,&pddi->uOffsetActionList,
&ppps->pTableEntry,szACTIONLIST,pfMore);
if (uErr != ERROR_SUCCESS)
return uErr;
// adjust pointer to offset, in case table moved
puLastOffsetPtr = (UINT *) (((BYTE *) puLastOffsetPtr) +
((BYTE *) ppps->pTableEntry - (BYTE *) pTableEntryOld));
pddi = (DROPDOWNINFO *)
((BYTE *) ppps->pTableEntry + *puLastOffsetPtr);
fHasActionList = TRUE;
break;
case KYWD_ID_END:
if (!fHasItemName) {
DisplayKeywordError(IDS_ParseErr_NO_ITEMNAME,
NULL,NULL);
uErr = ERROR_ALREADY_DISPLAYED;
break;
}
if (!fHasValue) {
DisplayKeywordError(IDS_ParseErr_NO_VALUE,
NULL,NULL);
uErr = ERROR_ALREADY_DISPLAYED;
break;
}
// make sure word following "END" is "ITEMLIST"
if (!GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
pItemlistCmpList,NULL,pfMore,&uErr)) {
break;
}
return ERROR_SUCCESS;
break;
}
}
return uErr;
}
BOOL CPolicyComponentData::AddActionListString(TCHAR * pszData,DWORD cbData,BYTE ** ppBase,UINT * puOffset,
DWORD * pdwAlloc,DWORD *pdwUsed)
{
DWORD dwNeeded = *pdwUsed + cbData, dwAdd;
dwAdd = dwNeeded % sizeof(DWORD);
dwNeeded += dwAdd;
// realloc if necessary
if (dwNeeded > *pdwAlloc) {
while (*pdwAlloc < dwNeeded)
{
*pdwAlloc += SUGGESTBUF_INCREMENT;
}
BYTE *pNewBase = (BYTE *) GlobalReAlloc(*ppBase,*pdwAlloc,GMEM_MOVEABLE | GMEM_ZEROINIT);
if ( pNewBase == NULL )
{
return FALSE;
}
puOffset = (UINT *)(pNewBase + ((BYTE *)puOffset - *ppBase));
*ppBase = pNewBase;
}
*puOffset = *pdwUsed;
if (pszData) memcpy(*ppBase + *puOffset,pszData,cbData);
*pdwUsed = dwNeeded;
return TRUE;
}
BYTE * CPolicyComponentData::AddDataToEntry(TABLEENTRY * pTableEntry,
BYTE * pData,UINT cbData,
UINT * puOffsetData,DWORD * pdwBufSize)
{
TABLEENTRY * pTemp;
DWORD dwNeeded,dwOldSize = pTableEntry->dwSize, dwNewDataSize, dwAdd;
// puOffsetData points to location that holds the offset to the
// new data-- size we're adding this to the end of the table, the
// offset will be the current size of the table. Set this offset
// in *puOffsetData. Also, notice we touch *puOffsetData BEFORE
// the realloc, in case puOffsetData points into the region being
// realloced and the block of memory moves.
//
*puOffsetData = pTableEntry->dwSize;
// reallocate entry buffer if necessary
dwNewDataSize = cbData;
dwAdd = dwNewDataSize % sizeof(DWORD);
dwNewDataSize += dwAdd;
dwNeeded = pTableEntry->dwSize + dwNewDataSize;
if (!(pTemp = (TABLEENTRY *) GlobalReAlloc(pTableEntry,
dwNeeded,GMEM_ZEROINIT | GMEM_MOVEABLE)))
return NULL;
pTableEntry = pTemp;
pTableEntry->dwSize = dwNeeded;
if (pData) memcpy((BYTE *)pTableEntry + dwOldSize,pData,cbData);
if (pdwBufSize) *pdwBufSize = pTableEntry->dwSize;
return (BYTE *) pTableEntry;
}
/*******************************************************************
NAME: CompareKeyword
SYNOPSIS: Compares a specified buffer to a list of valid keywords.
If it finds a match, the index of the match in the list
is returned in *pnListIndex. Otherwise an error message
is displayed.
EXIT: Returns TRUE if a keyword match is found, FALSE otherwise.
If TRUE, *pnListIndex contains matching index.
********************************************************************/
BOOL CPolicyComponentData::CompareKeyword(TCHAR * szWord,KEYWORDINFO *pKeywordList,
UINT * pnListIndex)
{
KEYWORDINFO * pKeywordInfo = pKeywordList;
while (pKeywordInfo->pWord) {
if (!lstrcmpi(szWord,pKeywordInfo->pWord)) {
if (pnListIndex)
*pnListIndex = pKeywordInfo->nID;
return TRUE;
}
pKeywordInfo ++;
}
DisplayKeywordError(IDS_ParseErr_UNEXPECTED_KEYWORD,
szWord,pKeywordList);
return FALSE;
}
/*******************************************************************
NAME: GetNextWord
SYNOPSIS: Fills input buffer with next word in file stream
NOTES: Calls GetNextChar() to get character stream. Whitespace
and comments are skipped. Quoted strings are returned
as one word (including whitespace) with the quotes removed.
EXIT: If successful, returns a pointer to the input buffer
(szBuf). *pfMore indicates if there are more words to
be read. If an error occurs, its value is returned in *puErr.
********************************************************************/
TCHAR * CPolicyComponentData::GetNextWord(TCHAR * szBuf,UINT cbBuf,BOOL * pfMore,
UINT * puErr)
{
TCHAR * pChar;
BOOL fInWord = FALSE;
BOOL fInQuote = FALSE;
BOOL fEmptyString = FALSE;
TCHAR * pWord = szBuf;
UINT cbWord = 0;
LPTSTR lpTemp;
HRESULT hr = S_OK;
// clear buffer to start with
(void) StringCchCopy(szBuf, cbBuf, g_szNull);
while (pChar = GetNextChar(pfMore,puErr)) {
// keep track of which file line we're on
if (IsEndOfLine(pChar)) m_nFileLine++;
// keep track of wheter we are inside quoted string or not
if (IsQuote(pChar) && !m_fInComment) {
if (!fInQuote)
fInQuote = TRUE; // entering quoted string
else {
fInQuote = FALSE; // leaving quoted string
if (cbWord == 0) {
// special case "" to be an empty string
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::GetNextWord: Found empty quotes")));
fEmptyString = TRUE;
}
break; // end of word
}
}
if (!fInQuote) {
// skip over lines with comments (';')
if (!m_fInComment && IsComment(pChar)) {
m_fInComment = TRUE;
}
if (m_fInComment) {
if (IsEndOfLine(pChar)) {
m_fInComment = FALSE;
}
continue;
}
if (IsWhitespace(pChar)) {
// if we haven't found word yet, skip over whitespace
if (!fInWord)
continue;
// otherwise, whitespace signals end of word
break;
}
}
// found a non-comment, non-whitespace character
if (!fInWord) fInWord = TRUE;
if (!IsQuote(pChar)) {
// add this character to word
*pWord = *pChar;
pWord++;
cbWord++;
if (cbWord >= cbBuf) {
*(pWord - 1) = TEXT('\0');
MsgBoxParam(NULL,IDS_WORDTOOLONG,szBuf,MB_ICONEXCLAMATION,MB_OK);
*puErr = ERROR_ALREADY_DISPLAYED;
goto Exit;
}
#if 0
if (IsDBCSLeadByte((BYTE) *pChar)) {
*pWord = *pChar;
pWord++;
cbWord++;
}
#endif
}
}
*pWord = '\0'; // null-terminate
// if found string a la '!!abc', then look for a string in the [strings]
// section with the key name 'abc' and use that instead. This is because
// our localization tools are brainless and require a [strings] section.
// So although template files are sectionless, we allow a [strings] section
// at the bottom.
if (IsLocalizedString(szBuf)) {
lpTemp = (LPTSTR) GlobalAlloc (GPTR, (cbBuf * sizeof(TCHAR)));
if (!lpTemp) {
*puErr = GetLastError();
return NULL;
}
if (GetString (m_pLocaleHashTable, szBuf+2, lpTemp, cbBuf) ||
GetString (m_pLanguageHashTable, szBuf+2, lpTemp, cbBuf) ||
GetString (m_pDefaultHashTable, szBuf+2, lpTemp, cbBuf))
{
hr = StringCchCopy(szBuf, cbBuf, lpTemp);
ASSERT(SUCCEEDED(hr));
GlobalFree (lpTemp);
}
else
{
DisplayKeywordError(IDS_ParseErr_STRING_NOT_FOUND,
szBuf,NULL);
*puErr=ERROR_ALREADY_DISPLAYED;
GlobalFree (lpTemp);
return NULL;
}
} else {
*puErr = ProcessIfdefs(szBuf,cbBuf,pfMore);
if (*puErr == ERROR_SUCCESS)
{
if ((szBuf[0] == TEXT('\0')) && (!fEmptyString))
{
fInWord = FALSE;
}
}
}
Exit:
if (*puErr != ERROR_SUCCESS || !fInWord) return NULL;
return szBuf;
}
/*******************************************************************
NAME: GetNextSectionWord
SYNOPSIS: Gets next word and warns if end-of-file encountered.
Optionally checks the keyword against a list of valid
keywords.
NOTES: Calls GetNextWord() to get word. This is called in
situations where we expect there to be another word
(e.g., inside a section) and it's an error if the
file ends.
********************************************************************/
TCHAR * CPolicyComponentData::GetNextSectionWord(TCHAR * szBuf,UINT cbBuf,
KEYWORDINFO * pKeywordList,
UINT *pnListIndex,
BOOL * pfMore,UINT * puErr)
{
TCHAR * pch;
if (!(pch=GetNextWord(szBuf,cbBuf,pfMore,puErr))) {
if (!*pfMore && *puErr != ERROR_ALREADY_DISPLAYED) {
DisplayKeywordError(IDS_ParseErr_UNEXPECTED_EOF,
NULL,pKeywordList);
*puErr = ERROR_ALREADY_DISPLAYED;
}
return NULL;
}
if (pKeywordList && !CompareKeyword(szBuf,pKeywordList,pnListIndex)) {
*puErr = ERROR_ALREADY_DISPLAYED;
return NULL;
}
return pch;
}
/*******************************************************************
NAME: GetNextSectionNumericWord
SYNOPSIS: Gets next word and converts string to number. Warns if
not a numeric value
********************************************************************/
UINT CPolicyComponentData::GetNextSectionNumericWord(UINT * pnVal)
{
UINT uErr;
TCHAR szWordBuf[WORDBUFSIZE];
BOOL fMore;
if (!GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
NULL,NULL,&fMore,&uErr))
return uErr;
if (!StringToNum(szWordBuf,pnVal)) {
DisplayKeywordError(IDS_ParseErr_NOT_NUMERIC,szWordBuf,
NULL);
return ERROR_ALREADY_DISPLAYED;
}
return ERROR_SUCCESS;
}
/*******************************************************************
NAME: GetNextChar
SYNOPSIS: Returns a pointer to the next character from the
file stream.
********************************************************************/
TCHAR * CPolicyComponentData::GetNextChar(BOOL * pfMore,UINT * puErr)
{
TCHAR * pCurrentChar;
*puErr = ERROR_SUCCESS;
if (m_pFilePtr > m_pFileEnd) {
*pfMore = FALSE;
return NULL;
}
pCurrentChar = m_pFilePtr;
m_pFilePtr = CharNext(m_pFilePtr);
*pfMore = TRUE;
return pCurrentChar;
}
/*******************************************************************
NAME: GetString
SYNOPSIS: Returns the display string
********************************************************************/
BOOL CPolicyComponentData::GetString (LPHASHTABLE lpHashTable,
LPTSTR lpStringName,
LPTSTR lpResult, DWORD dwSize)
{
LPTSTR lpTemp, lpDest;
DWORD dwCCH, dwIndex;
BOOL bFoundQuote = FALSE;
TCHAR cTestChar;
if (!lpHashTable)
{
return FALSE;
}
if (!m_bRetrieveString)
{
lpResult = TEXT('\0');
return TRUE;
}
dwCCH = lstrlen (lpStringName);
lpTemp = FindHashEntry (lpHashTable, lpStringName, dwCCH);
if (!lpTemp)
{
return FALSE;
}
lpTemp += dwCCH;
while (*lpTemp == TEXT(' '))
lpTemp++;
if (*lpTemp == TEXT('='))
{
lpTemp++;
if (*lpTemp == TEXT('\"'))
{
lpTemp++;
bFoundQuote = TRUE;
}
lpDest = lpResult;
dwIndex = 0;
while (*lpTemp && (dwIndex < dwSize))
{
*lpDest = *lpTemp;
lpDest++;
lpTemp++;
dwIndex++;
}
if (dwIndex == dwSize)
{
lpDest--;
*lpDest = TEXT('\0');
MsgBoxParam(NULL,IDS_STRINGTOOLONG,lpResult,MB_ICONEXCLAMATION,MB_OK);
}
else
{
*lpDest = TEXT('\0');
}
if (bFoundQuote)
{
lpTemp = lpResult + lstrlen (lpResult) - 1;
if (*lpTemp == TEXT('\"'))
{
*lpTemp = TEXT('\0');
}
}
//
// Replace any \n combinations with a CR LF
//
lpTemp = lpResult;
while (*lpTemp)
{
if ((*lpTemp == TEXT('\\')) && (*(lpTemp + 1) == TEXT('n')))
{
*lpTemp = TEXT('\r');
lpTemp++;
*lpTemp = TEXT('\n');
}
lpTemp++;
}
return TRUE;
}
return FALSE;
}
VOID CPolicyComponentData::FillHashTable(LPHASHTABLE lpTable, LPTSTR lpStrings)
{
LPTSTR lpTemp, lpStart;
lpTemp = lpStrings;
while (*lpTemp)
{
lpStart = lpTemp;
while ((*lpTemp) && (*lpTemp != TEXT(' ')) && (*lpTemp != TEXT('=')))
{
lpTemp++;
}
if (!(*lpTemp))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::FillHashTable: Found end of line when expected a equal sign. Line found: %s"), lpStart));
return;
}
// The string will not be longer than 2^32 characters
ASSERT( (lpTemp - lpStart) <= 0xffffffff );
DWORD entryLength = (DWORD)(lpTemp - lpStart);
AddHashEntry (lpTable, lpStart, entryLength);
while (*lpTemp)
{
lpTemp++;
}
lpTemp++;
}
}
//
// CreateStringArray takes a string section and converts it to a array of strings.
// Each string is null terminated and the entire array is double null terminated at
// the end. This function is very similary to GetPrivateProfileSection, but considerably
// faster to execute.
//
LPTSTR CPolicyComponentData::CreateStringArray(LPTSTR lpStrings)
{
LPTSTR lpStrArray, lpSrc, lpDest;
DWORD dwIndex = 0;
TCHAR chLetter = 0;
lpStrArray = (LPTSTR) GlobalAlloc (GPTR, (m_pFileEnd - lpStrings + 1) * sizeof(WCHAR));
if (!lpStrArray)
{
return NULL;
}
lpSrc = lpStrings;
lpDest = lpStrArray;
while (lpSrc <= m_pFileEnd)
{
if (dwIndex == 0)
{
//
// Strip the white space off of the front of the line
//
while (*lpSrc == TEXT(' '))
{
lpSrc++;
}
//
// If we found a square bracket open, that is the beginning of a different
// string section. Exit now.
//
if (*lpSrc == TEXT('['))
{
break;
}
//
// If we found a semi-colon, this line is commented out
//
if (*lpSrc == TEXT(';'))
{
while (*lpSrc != TEXT('\r'))
{
lpSrc++;
}
lpSrc += 2;
}
}
if ((dwIndex == 0) && (*lpSrc == TEXT('\r')))
{
//
// Found a blank line
//
lpSrc += 2;
}
else
{
//
// Handle CR / LF combinations. Two cases:
// 1) If the line ends with a backslash, then the user has more text on the
// next line down (a continuation)
// 2) If the line does not end with a backslash, then that is the end of a
// string variable. Null terminate the string.
//
if (*lpSrc == TEXT('\r'))
{
//
// If the previous character was a backsash, we back the destination
// pointer up by 1 so that the backslash is removed.
//
if (chLetter == TEXT('\\'))
{
lpDest--;
}
else
{
*lpDest = TEXT('\0');
lpDest++;
dwIndex = 0;
}
lpSrc += 2;
}
else
{
chLetter = *lpDest = *lpSrc;
lpDest++;
lpSrc++;
dwIndex++;
}
}
}
return lpStrArray;
}
LPTSTR CPolicyComponentData::FindSection (LPTSTR lpSection)
{
LPTSTR lpTemp = m_pFilePtr;
DWORD dwColumn = 0;
DWORD dwStrLen = lstrlen (lpSection);
while (lpTemp < m_pFileEnd)
{
if ((*lpTemp == TEXT('[')) && (dwColumn == 0))
{
if (CompareString (LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpTemp, dwStrLen,
lpSection, dwStrLen) == CSTR_EQUAL)
{
return lpTemp;
}
}
dwColumn++;
if (*lpTemp == TEXT('\n'))
{
dwColumn = 0;
}
lpTemp++;
}
return NULL;
}
BOOL CPolicyComponentData::IsComment(TCHAR * pBuf)
{
return (*pBuf == TEXT(';'));
}
BOOL CPolicyComponentData::IsQuote(TCHAR * pBuf)
{
return (*pBuf == TEXT('\"'));
}
BOOL CPolicyComponentData::IsEndOfLine(TCHAR * pBuf)
{
return (*pBuf == TEXT('\r')); // CR
}
BOOL CPolicyComponentData::IsWhitespace(TCHAR * pBuf)
{
return ( *pBuf == TEXT(' ') // space
|| *pBuf == TEXT('\r') // CR
|| *pBuf == TEXT('\n') // LF
|| *pBuf == TEXT('\t') // tab
|| *pBuf == 0x001A // EOF
|| *pBuf == 0xFEFF // Unicode marker
);
}
BOOL CPolicyComponentData::IsLocalizedString(TCHAR * pBuf)
{
return (*pBuf == TEXT('!') && *(pBuf+1) == TEXT('!'));
}
#define MSGSIZE 1024
#define FMTSIZE 512
VOID CPolicyComponentData::DisplayKeywordError(UINT uErrorID,TCHAR * szFound,
KEYWORDINFO * pExpectedList)
{
TCHAR * pMsg,*pFmt,*pErrTxt,*pTmp;
pMsg = (TCHAR *) GlobalAlloc(GPTR,(MSGSIZE * sizeof(TCHAR)));
pFmt = (TCHAR *) GlobalAlloc(GPTR,(FMTSIZE * sizeof(TCHAR)));
pErrTxt = (TCHAR *) GlobalAlloc(GPTR,(FMTSIZE * sizeof(TCHAR)));
pTmp = (TCHAR *) GlobalAlloc(GPTR,(FMTSIZE * sizeof(TCHAR)));
if (!pMsg || !pFmt || !pErrTxt || !pTmp) {
if (pMsg) GlobalFree(pMsg);
if (pFmt) GlobalFree(pFmt);
if (pErrTxt) GlobalFree(pErrTxt);
if (pTmp) GlobalFree(pTmp);
MsgBox(NULL,IDS_ErrOUTOFMEMORY,MB_ICONEXCLAMATION,MB_OK);
return;
}
LoadSz(IDS_ParseFmt_MSG_FORMAT,pFmt,FMTSIZE);
(void) StringCchPrintf(pMsg, MSGSIZE, pFmt, m_pszParseFileName, m_nFileLine,uErrorID, LoadSz(uErrorID,
pErrTxt,FMTSIZE));
if (szFound) {
LoadSz(IDS_ParseFmt_FOUND,pFmt,FMTSIZE);
(void) StringCchPrintf(pTmp, FMTSIZE, pFmt, szFound);
(void) StringCchCat(pMsg, MSGSIZE, pTmp);
}
if (pExpectedList) {
UINT nIndex=0;
LoadSz(IDS_ParseFmt_EXPECTED,pFmt,FMTSIZE);
(void) StringCchCopy(pErrTxt, FMTSIZE, g_szNull);
while (pExpectedList[nIndex].pWord) {
(void) StringCchCat(pErrTxt, FMTSIZE, pExpectedList[nIndex].pWord);
if (pExpectedList[nIndex+1].pWord) {
(void) StringCchCat(pErrTxt, FMTSIZE, TEXT(", "));
}
nIndex++;
}
(void) StringCchPrintf(pTmp, FMTSIZE, pFmt, pErrTxt);
(void) StringCchCat(pMsg, MSGSIZE, pTmp);
}
(void) StringCchCat(pMsg, MSGSIZE, LoadSz(IDS_ParseFmt_FATAL, pTmp, FMTSIZE));
DebugMsg((DM_WARNING, TEXT("Keyword error: %s"), pMsg));
MsgBoxSz(NULL,pMsg,MB_ICONEXCLAMATION,MB_OK);
GlobalFree(pMsg);
GlobalFree(pFmt);
GlobalFree(pErrTxt);
GlobalFree(pTmp);
}
int CPolicyComponentData::MsgBox(HWND hWnd,UINT nResource,UINT uIcon,UINT uButtons)
{
TCHAR szMsgBuf[REGBUFLEN];
TCHAR szSmallBuf[SMALLBUF];
LoadSz(IDS_POLICY_NAME,szSmallBuf,ARRAYSIZE(szSmallBuf));
LoadSz(nResource,szMsgBuf,ARRAYSIZE(szMsgBuf));
MessageBeep(uIcon);
return (MessageBox(hWnd,szMsgBuf,szSmallBuf,uIcon | uButtons));
}
int CPolicyComponentData::MsgBoxSz(HWND hWnd,LPTSTR szText,UINT uIcon,UINT uButtons)
{
TCHAR szSmallBuf[SMALLBUF];
LoadSz(IDS_POLICY_NAME,szSmallBuf,ARRAYSIZE(szSmallBuf));
MessageBeep(uIcon);
return (MessageBox(hWnd,szText,szSmallBuf,uIcon | uButtons));
}
int CPolicyComponentData::MsgBoxParam(HWND hWnd,UINT nResource,TCHAR * szReplaceText,UINT uIcon,
UINT uButtons)
{
TCHAR szFormat[REGBUFLEN];
LPTSTR lpMsgBuf;
INT iResult;
HRESULT hr = S_OK;
DWORD dwMsgLen = lstrlen(szReplaceText) + 1 + REGBUFLEN;
lpMsgBuf = (LPTSTR) LocalAlloc (LPTR, (dwMsgLen) * sizeof(TCHAR));
if (!lpMsgBuf)
{
return 0;
}
LoadSz(nResource,szFormat,ARRAYSIZE(szFormat));
hr = StringCchPrintf(lpMsgBuf, dwMsgLen, szFormat, szReplaceText);
ASSERT(SUCCEEDED(hr));
iResult = MsgBoxSz(hWnd,lpMsgBuf,uIcon,uButtons);
LocalFree (lpMsgBuf);
return iResult;
}
LPTSTR CPolicyComponentData::LoadSz(UINT idString,LPTSTR lpszBuf,UINT cbBuf)
{
// Clear the buffer and load the string
if ( lpszBuf )
{
*lpszBuf = TEXT('\0');
LoadString( g_hInstance, idString, lpszBuf, cbBuf );
}
return lpszBuf;
}
BOOL fFilterDirectives = TRUE;
UINT nGlobalNestedLevel = 0;
// reads up through the matching directive #endif in current scope
//and sets file pointer immediately past the directive
UINT CPolicyComponentData::FindMatchingDirective(BOOL *pfMore,BOOL fElseOK)
{
TCHAR szWordBuf[WORDBUFSIZE];
UINT uErr=ERROR_SUCCESS,nNestedLevel=1;
BOOL fContinue = TRUE;
// set the flag to stop catching '#' directives in low level word-fetching
// routine
fFilterDirectives = FALSE;
// keep reading words. Keep track of how many layers of #ifdefs deep we
// are. Every time we encounter an #ifdef or #ifndef, increment the level
// count (nNestedLevel) by one. For every #endif decrement the level count.
// When the level count hits zero, we've found the matching #endif.
while (nNestedLevel > 0) {
if (!GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),NULL,NULL,
pfMore,&uErr))
break;
if (!lstrcmpi(szWordBuf,szIFDEF) || !lstrcmpi(szWordBuf,szIFNDEF) ||
!lstrcmpi(szWordBuf,szIF))
nNestedLevel ++;
else if (!lstrcmpi(szWordBuf,szENDIF)) {
nNestedLevel --;
}
else if (!lstrcmpi(szWordBuf,szELSE) && (nNestedLevel == 1)) {
if (fElseOK) {
// ignore "#else" unless it's on the same level as the #ifdef
// we're finding a match for (nNestedLevel == 1), in which
// case treat it as the matching directive
nNestedLevel --;
// increment global nesting so we expect an #endif to come along
// later to match this #else
nGlobalNestedLevel++;
} else {
// found a #else where we already had a #else in this level
DisplayKeywordError(IDS_ParseErr_UNMATCHED_DIRECTIVE,
szWordBuf,NULL);
return ERROR_ALREADY_DISPLAYED;
}
}
}
fFilterDirectives = TRUE;
return uErr;
}
// if the word in the word buffer is #ifdef, #if, #ifndef, #else or #endif,
// this function reads ahead an appropriate amount (
UINT CPolicyComponentData::ProcessIfdefs(TCHAR * pBuf,UINT cbBuf,BOOL * pfMore)
{
UINT uRet;
if (!fFilterDirectives)
return ERROR_SUCCESS;
if (!lstrcmpi(pBuf,szIFDEF)) {
// we've found an '#ifdef <something or other>, where ISV policy editors
// can understand particular keywords they make up. We don't have any
// #ifdef keywords of our own so always skip this
uRet = FindMatchingDirective(pfMore,TRUE);
if (uRet != ERROR_SUCCESS)
return uRet;
if (!GetNextWord(pBuf,cbBuf,pfMore,&uRet))
return uRet;
return ERROR_SUCCESS;
} else if (!lstrcmpi(pBuf,szIFNDEF)) {
// this is an #ifndef, and since nothing is ever ifdef'd for our policy
// editor, this always evaluates to TRUE
// keep reading this section but increment the nested level count,
// when we find the matching #endif or #else we'll be able to respond
// correctly
nGlobalNestedLevel ++;
// get next word (e.g. "abc" for #ifndef abc) and throw it away
if (!GetNextWord(pBuf,cbBuf,pfMore,&uRet))
return uRet;
// get next word and return it for real
if (!GetNextWord(pBuf,cbBuf,pfMore,&uRet))
return uRet;
return ERROR_SUCCESS;
} else if (!lstrcmpi(pBuf,szENDIF)) {
// if we ever encounter an #endif here, we must have processed
// the preceeding section. Just step over the #endif and go on
if (!nGlobalNestedLevel) {
// found an endif without a preceeding #if<xx>
DisplayKeywordError(IDS_ParseErr_UNMATCHED_DIRECTIVE,
pBuf,NULL);
return ERROR_ALREADY_DISPLAYED;
}
nGlobalNestedLevel--;
if (!GetNextWord(pBuf,cbBuf,pfMore,&uRet))
return uRet;
return ERROR_SUCCESS;
} else if (!lstrcmpi(pBuf,szIF)) {
// syntax is "#if VERSION (comparision) (version #)"
// e.g. "#if VERSION >= 2"
TCHAR szWordBuf[WORDBUFSIZE];
UINT nIndex,nVersion,nOperator;
BOOL fDirectiveTrue = FALSE;
// get the next word (must be "VERSION")
if (!GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
pVersionCmpList,&nIndex,pfMore,&uRet))
return uRet;
// get the comparison operator (>, <, ==, >=, <=)
if (!GetNextSectionWord(szWordBuf,ARRAYSIZE(szWordBuf),
pOperatorCmpList,&nOperator,pfMore,&uRet))
return uRet;
// get the version number
uRet=GetNextSectionNumericWord(&nVersion);
if (uRet != ERROR_SUCCESS)
return uRet;
// now evaluate the directive
switch (nOperator) {
case KYWD_ID_GT:
fDirectiveTrue = (CURRENT_ADM_VERSION > nVersion);
break;
case KYWD_ID_GTE:
fDirectiveTrue = (CURRENT_ADM_VERSION >= nVersion);
break;
case KYWD_ID_LT:
fDirectiveTrue = (CURRENT_ADM_VERSION < nVersion);
break;
case KYWD_ID_LTE:
fDirectiveTrue = (CURRENT_ADM_VERSION <= nVersion);
break;
case KYWD_ID_EQ:
fDirectiveTrue = (CURRENT_ADM_VERSION == nVersion);
break;
case KYWD_ID_NE:
fDirectiveTrue = (CURRENT_ADM_VERSION != nVersion);
break;
}
if (fDirectiveTrue) {
// keep reading this section but increment the nested level count,
// when we find the matching #endif or #else we'll be able to respond
// correctly
nGlobalNestedLevel ++;
} else {
// skip over this section
uRet = FindMatchingDirective(pfMore,TRUE);
if (uRet != ERROR_SUCCESS)
return uRet;
}
// get next word and return it for real
if (!GetNextWord(pBuf,cbBuf,pfMore,&uRet))
return uRet;
return ERROR_SUCCESS;
} else if (!lstrcmpi(pBuf,szELSE)) {
// found an #else, which means we took the upper branch, skip over
// the lower branch
if (!nGlobalNestedLevel) {
// found an #else without a preceeding #if<xx>
DisplayKeywordError(IDS_ParseErr_UNMATCHED_DIRECTIVE,
pBuf,NULL);
return ERROR_ALREADY_DISPLAYED;
}
nGlobalNestedLevel--;
uRet = FindMatchingDirective(pfMore,FALSE);
if (uRet != ERROR_SUCCESS)
return uRet;
if (!GetNextWord(pBuf,cbBuf,pfMore,&uRet))
return uRet;
return ERROR_SUCCESS;
}
return ERROR_SUCCESS;
}
/*******************************************************************
NAME: FreeTable
SYNOPSIS: Frees the specified table and all sub-tables of that
table.
NOTES: Walks through the table entries and calls itself to
recursively free sub-tables.
EXIT: Returns TRUE if successful, FALSE if a memory error
occurs.
********************************************************************/
BOOL CPolicyComponentData::FreeTable(TABLEENTRY * pTableEntry)
{
TABLEENTRY * pNext = pTableEntry->pNext;
// free all children
if (pTableEntry->pChild)
FreeTable(pTableEntry->pChild);
GlobalFree(pTableEntry);
if (pNext) FreeTable(pNext);
return TRUE;
}
LPTSTR CPolicyComponentData::GetStringSection (LPCTSTR lpSection, LPCTSTR lpFileName)
{
DWORD dwSize, dwRead;
LPTSTR lpStrings;
//
// Read in the default strings section
//
dwSize = STRINGS_BUF_SIZE;
lpStrings = (TCHAR *) GlobalAlloc (GPTR, dwSize * sizeof(TCHAR));
if (!lpStrings)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::GetStringSection: Failed to alloc memory for default strings with %d."),
GetLastError()));
return NULL;
}
do {
dwRead = GetPrivateProfileSection (lpSection,
lpStrings,
dwSize, lpFileName);
if (dwRead != (dwSize - 2))
{
break;
}
GlobalFree (lpStrings);
dwSize *= 2;
lpStrings = (TCHAR *) GlobalAlloc (GPTR, dwSize * sizeof(TCHAR));
if (!lpStrings)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::GetStringSection: Failed to alloc memory for Default strings with %d."),
GetLastError()));
return FALSE;
}
} while (TRUE);
if (dwRead == 0)
{
GlobalFree (lpStrings);
lpStrings = NULL;
}
return lpStrings;
}
INT CPolicyComponentData::TemplatesSortCallback (LPARAM lParam1, LPARAM lParam2,
LPARAM lColumn)
{
LPTEMPLATEENTRY lpEntry1, lpEntry2;
INT iResult;
lpEntry1 = (LPTEMPLATEENTRY) lParam1;
lpEntry2 = (LPTEMPLATEENTRY) lParam2;
if (lColumn == 0)
{
iResult = lstrcmpi (lpEntry1->lpFileName, lpEntry2->lpFileName);
}
else if (lColumn == 1)
{
if (lpEntry1->dwSize < lpEntry2->dwSize)
{
iResult = -1;
}
else if (lpEntry1->dwSize > lpEntry2->dwSize)
{
iResult = 1;
}
else
{
iResult = 0;
}
}
else
{
iResult = CompareFileTime (&lpEntry1->ftTime, &lpEntry2->ftTime);
}
return iResult;
}
BOOL CPolicyComponentData::FillADMFiles (HWND hDlg)
{
TCHAR szPath[MAX_PATH];
TCHAR szDate[20];
TCHAR szTime[20];
TCHAR szBuffer[45];
HWND hLV;
INT iItem;
LVITEM item;
FILETIME filetime;
SYSTEMTIME systime;
WIN32_FIND_DATA fd;
LPTEMPLATEENTRY lpEntry;
HANDLE hFile;
LPTSTR lpEnd, lpTemp;
HRESULT hr = S_OK;
XLastError xe;
//
// Ask for the root of the GPT so we can access the
// adm files.
//
if (m_pGPTInformation->GetFileSysPath(GPO_SECTION_ROOT, szPath,
MAX_PATH) != S_OK)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::FillADMFiles: Failed to get gpt path.")));
return FALSE;
}
//
// Create the directory
//
lpEnd = CheckSlash (szPath);
hr = StringCchCopy (lpEnd, ARRAYSIZE(szPath) - (lpEnd - szPath), g_szADM);
if (FAILED(hr))
{
xe = HRESULT_CODE(hr);
return FALSE;
}
if (!CreateNestedDirectory(szPath, NULL))
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::FillADMFiles: Failed to create adm directory.")));
return FALSE;
}
//
// Prepare the listview
//
hLV = GetDlgItem (hDlg, IDC_TEMPLATELIST);
SendMessage (hLV, WM_SETREDRAW, FALSE, 0);
ListView_DeleteAllItems(hLV);
//
// Enumerate the files
//
hr = StringCchCat (szPath, ARRAYSIZE(szPath), TEXT("\\*.adm"));
if (FAILED(hr))
{
xe = HRESULT_CODE(hr);
return FALSE;
}
hFile = FindFirstFile(szPath, &fd);
if (hFile != INVALID_HANDLE_VALUE)
{
do
{
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
lpEntry = (LPTEMPLATEENTRY) LocalAlloc (LPTR,
sizeof(TEMPLATEENTRY) + ((lstrlen(fd.cFileName) + 1) * sizeof(TCHAR)));
if (lpEntry)
{
lpEntry->lpFileName = (LPTSTR)((LPBYTE)lpEntry + sizeof(TEMPLATEENTRY));
lpEntry->dwSize = fd.nFileSizeLow / 1024;
if (lpEntry->dwSize == 0)
{
lpEntry->dwSize = 1;
}
lpEntry->ftTime.dwLowDateTime = fd.ftLastWriteTime.dwLowDateTime;
lpEntry->ftTime.dwHighDateTime = fd.ftLastWriteTime.dwHighDateTime;
hr = StringCchCopy (lpEntry->lpFileName, lstrlen(fd.cFileName) + 1, fd.cFileName);
ASSERT(SUCCEEDED(hr));
//
// Add the filename
//
lpTemp = fd.cFileName + lstrlen (fd.cFileName) - 4;
if (*lpTemp == TEXT('.'))
{
*lpTemp = TEXT('\0');
}
item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
item.iItem = 0;
item.iSubItem = 0;
item.state = 0;
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
item.pszText = fd.cFileName;
item.iImage = 0;
item.lParam = (LPARAM) lpEntry;
iItem = (INT)SendMessage (hLV, LVM_INSERTITEM, 0, (LPARAM) &item);
if (iItem == -1)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::FillADMFiles: Failed to insert item.")));
return FALSE;
}
//
// Add the size
//
hr = StringCchPrintf (szBuffer, ARRAYSIZE(szBuffer), TEXT("%dKB"), lpEntry->dwSize);
ASSERT(SUCCEEDED(hr));
item.mask = LVIF_TEXT;
item.iItem = iItem;
item.iSubItem = 1;
item.pszText = szBuffer;
SendMessage (hLV, LVM_SETITEMTEXT, iItem, (LPARAM) &item);
//
// And the last modified date
//
FileTimeToLocalFileTime (&fd.ftLastWriteTime, &filetime);
FileTimeToSystemTime (&filetime, &systime);
GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE,
&systime, NULL, szDate, 20);
GetTimeFormat (LOCALE_USER_DEFAULT, TIME_NOSECONDS,
&systime, NULL, szTime, 20);
hr = StringCchPrintf (szBuffer, ARRAYSIZE(szBuffer), TEXT("%s %s"), szDate, szTime);
ASSERT(SUCCEEDED(hr));
item.mask = LVIF_TEXT;
item.iItem = iItem;
item.iSubItem = 2;
item.pszText = szBuffer;
SendMessage (hLV, LVM_SETITEMTEXT, iItem, (LPARAM) &item);
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::FillADMFiles: Failed to allocate memory for an entry %d."),
GetLastError()));
}
}
} while (FindNextFile(hFile, &fd));
FindClose(hFile);
}
if (SendMessage(hLV, LVM_GETITEMCOUNT, 0, 0) > 0)
{
//
// Sort the listview
//
ListView_SortItems (hLV, TemplatesSortCallback, m_bTemplatesColumn);
//
// Select the first item
//
item.mask = LVIF_STATE;
item.iItem = 0;
item.iSubItem = 0;
item.state = LVIS_SELECTED | LVIS_FOCUSED;
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
SendMessage (hLV, LVM_SETITEMSTATE, 0, (LPARAM) &item);
EnableWindow (GetDlgItem (hDlg, IDC_REMOVETEMPLATES), TRUE);
}
else
{
EnableWindow (GetDlgItem (hDlg, IDC_REMOVETEMPLATES), FALSE);
SetFocus (GetDlgItem (hDlg, IDC_ADDTEMPLATES));
}
SendMessage (hLV, WM_SETREDRAW, TRUE, 0);
return TRUE;
}
BOOL CPolicyComponentData::InitializeTemplatesDlg (HWND hDlg)
{
LVCOLUMN lvc;
LVITEM item;
TCHAR szTitle[50];
INT iNameWidth;
HIMAGELIST hLarge, hSmall;
HICON hIcon;
HWND hLV;
RECT rc;
hLV = GetDlgItem (hDlg, IDC_TEMPLATELIST);
GetClientRect (hLV, &rc);
//
// Create the imagelists
//
hLarge = ImageList_Create (32, 32, ILC_MASK, 1, 1);
if (!hLarge)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::InitializeTemplatesDlg: Failed to create large imagelist.")));
return FALSE;
}
hSmall = ImageList_Create (16, 16, ILC_MASK, 1, 1);
if (!hSmall)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::InitializeTemplatesDlg: Failed to create small imagelist.")));
ImageList_Destroy (hLarge);
return FALSE;
}
//
// Add the icon
//
hIcon = (HICON) LoadImage (g_hInstance, MAKEINTRESOURCE(IDI_DOCUMENT),
IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
if ( hIcon )
{
ImageList_AddIcon (hLarge, hIcon);
DestroyIcon (hIcon);
}
hIcon = (HICON) LoadImage (g_hInstance, MAKEINTRESOURCE(IDI_DOCUMENT),
IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
if ( hIcon )
{
ImageList_AddIcon (hSmall, hIcon);
DestroyIcon (hIcon);
}
//
// Associate the imagelist with the listview.
// The listview will free this when the
// control is destroyed.
//
SendMessage (hLV, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM) hLarge);
SendMessage (hLV, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM) hSmall);
//
// Set extended LV style for whole line selection
//
SendMessage(hLV, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
//
// Insert the columns
//
LoadString (g_hInstance, IDS_NAME, szTitle, 50);
lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
lvc.fmt = LVCFMT_LEFT;
iNameWidth = (int)(rc.right * .60);
lvc.cx = iNameWidth;
lvc.pszText = szTitle;
lvc.cchTextMax = 50;
lvc.iSubItem = 0;
SendMessage (hLV, LVM_INSERTCOLUMN, 0, (LPARAM) &lvc);
LoadString (g_hInstance, IDS_SIZE, szTitle, 50);
lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
lvc.fmt = LVCFMT_RIGHT;
iNameWidth += (int)(rc.right * .15);
lvc.cx = (int)(rc.right * .15);
lvc.pszText = szTitle;
lvc.cchTextMax = 50;
lvc.iSubItem = 0;
SendMessage (hLV, LVM_INSERTCOLUMN, 1, (LPARAM) &lvc);
LoadString (g_hInstance, IDS_MODIFIED, szTitle, 50);
lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = rc.right - iNameWidth;
lvc.pszText = szTitle;
lvc.cchTextMax = 50;
lvc.iSubItem = 1;
SendMessage (hLV, LVM_INSERTCOLUMN, 2, (LPARAM) &lvc);
//
// Fill the list view with the adm files
//
FillADMFiles (hDlg);
return TRUE;
}
BOOL CPolicyComponentData::AddTemplates(HWND hDlg)
{
OPENFILENAME ofn;
LVITEM item;
INT iCount, iResult;
BOOL bResult = FALSE;
LPTSTR lpFileName, lpTemp, lpEnd, lpSrcList = NULL;
DWORD dwListLen, dwTemp, dwNextString;
TCHAR szFilter[100];
TCHAR szTitle[100];
TCHAR szFile[2*MAX_PATH];
TCHAR szInf[MAX_PATH];
TCHAR szDest[MAX_PATH];
TCHAR szSrc[2*MAX_PATH];
SHFILEOPSTRUCT fileop;
HRESULT hr = S_OK;
XLastError xe;
//
// Prompt for new files
//
LoadString (g_hInstance, IDS_POLICYFILTER, szFilter, ARRAYSIZE(szFilter));
LoadString (g_hInstance, IDS_POLICYTITLE, szTitle, ARRAYSIZE(szTitle));
ExpandEnvironmentStrings (TEXT("%SystemRoot%\\Inf"), szInf, MAX_PATH);
lpTemp = szFilter;
while (*lpTemp)
{
if (*lpTemp == TEXT('#'))
*lpTemp = TEXT('\0');
lpTemp++;
}
ZeroMemory (&ofn, sizeof(ofn));
szFile[0] = TEXT('\0');
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hDlg;
ofn.hInstance = g_hInstance;
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = 2*MAX_PATH;
ofn.lpstrInitialDir = szInf;
ofn.lpstrTitle = szTitle;
ofn.Flags = OFN_ALLOWMULTISELECT | OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_EXPLORER;
if (!GetOpenFileName (&ofn))
{
return FALSE;
}
//
// Setup the destination
//
if (m_pGPTInformation->GetFileSysPath(GPO_SECTION_ROOT, szDest,
MAX_PATH) != S_OK)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::AddTemplates: Failed to get gpt path.")));
return FALSE;
}
lpEnd = CheckSlash (szDest);
hr = StringCchCopy (lpEnd, ARRAYSIZE(szDest) - (lpEnd - szDest), g_szADM);
if (FAILED(hr))
{
xe = HRESULT_CODE(hr);
return FALSE;
}
//
// Setup up the source
//
*(szFile + ofn.nFileOffset - 1) = TEXT('\0');
hr = StringCchCopy (szSrc, ARRAYSIZE(szSrc), szFile);
if (FAILED(hr))
{
xe = HRESULT_CODE(hr);
return FALSE;
}
lpEnd = CheckSlash (szSrc);
lpFileName = szFile + lstrlen (szFile) + 1;
//
// Loop through the files copying and adding them to the list.
//
while (*lpFileName)
{
lpTemp = lpFileName + lstrlen (lpFileName) - 4;
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpTemp, -1, TEXT(".adm"), -1) == CSTR_EQUAL)
{
hr = StringCchCopy (lpEnd, ARRAYSIZE(szSrc) - (lpEnd - szSrc), lpFileName);
ASSERT(SUCCEEDED(hr));
if (lpSrcList)
{
dwTemp = dwListLen + ((lstrlen (szSrc) + 1) * sizeof(TCHAR));
lpTemp = (LPTSTR) LocalReAlloc (lpSrcList, dwTemp, LMEM_MOVEABLE | LMEM_ZEROINIT);
if (lpTemp)
{
lpSrcList = lpTemp;
dwListLen = dwTemp;
hr = StringCchCopy ((lpSrcList + dwNextString), lstrlen(szSrc) + 1, szSrc);
ASSERT(SUCCEEDED(hr));
dwNextString += lstrlen (szSrc) + 1;
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::AddTemplates: Failed to realloc memory for Src list. %d"),
GetLastError()));
}
}
else
{
dwListLen = (lstrlen (szSrc) + 2) * sizeof(TCHAR);
lpSrcList = (LPTSTR) LocalAlloc (LPTR, dwListLen);
if (lpSrcList)
{
hr = StringCchCopy (lpSrcList, dwListLen/sizeof(TCHAR), szSrc);
ASSERT(SUCCEEDED(hr));
dwNextString = lstrlen (lpSrcList) + 1;
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::AddTemplates: Failed to alloc memory for src list. %d"),
GetLastError()));
}
}
}
else
{
MsgBoxParam(hDlg, IDS_INVALIDADMFILE, lpFileName, MB_ICONERROR, MB_OK);
}
lpFileName = lpFileName + lstrlen (lpFileName) + 1;
}
if (lpSrcList)
{
fileop.hwnd = hDlg;
fileop.wFunc = FO_COPY;
fileop.pFrom = lpSrcList;
fileop.pTo = szDest;
fileop.fFlags = FOF_NOCONFIRMMKDIR;
iResult = SHFileOperation(&fileop);
if (!iResult)
{
bResult = TRUE;
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::AddTemplates: Failed to copy <%s> to <%s> with %d."),
szSrc, szDest, iResult));
}
LocalFree (lpSrcList);
if (bResult)
{
FillADMFiles (hDlg);
}
}
return bResult;
}
BOOL CPolicyComponentData::RemoveTemplates(HWND hDlg)
{
HWND hLV;
LVITEM item;
BOOL bResult = FALSE;
INT iResult, iIndex = -1;
LPTEMPLATEENTRY lpEntry;
LPTSTR lpEnd, lpTemp, lpDeleteList = NULL;
TCHAR szPath[MAX_PATH];
DWORD dwSize, dwListLen, dwTemp, dwNextString;
SHFILEOPSTRUCT fileop;
HRESULT hr = S_OK;
XLastError xe;
hLV = GetDlgItem (hDlg, IDC_TEMPLATELIST);
//
// Get the path to the adm directory
//
if (m_pGPTInformation->GetFileSysPath(GPO_SECTION_ROOT, szPath,
MAX_PATH) != S_OK)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::AddTemplates: Failed to get gpt path.")));
return FALSE;
}
lpEnd = CheckSlash (szPath);
hr = StringCchCopy (lpEnd, MAX_PATH - (lpEnd - szPath), g_szADM);
if (FAILED(hr))
{
xe = HRESULT_CODE(hr);
return bResult;
}
lpEnd = CheckSlash (szPath);
dwSize = MAX_PATH - (DWORD)(lpEnd - szPath);
//
// Build a list of selected items
//
while ((iIndex = ListView_GetNextItem (hLV, iIndex,
LVNI_ALL | LVNI_SELECTED)) != -1)
{
item.mask = LVIF_PARAM;
item.iItem = iIndex;
item.iSubItem = 0;
if (!ListView_GetItem (hLV, &item))
{
continue;
}
lpEntry = (LPTEMPLATEENTRY) item.lParam;
lstrcpyn (lpEnd, lpEntry->lpFileName, dwSize);
if (lpDeleteList)
{
dwTemp = dwListLen + ((lstrlen (szPath) + 1) * sizeof(TCHAR));
lpTemp = (LPTSTR) LocalReAlloc (lpDeleteList, dwTemp, LMEM_MOVEABLE | LMEM_ZEROINIT);
if (lpTemp)
{
lpDeleteList = lpTemp;
dwListLen = dwTemp;
hr = StringCchCopy ((lpDeleteList + dwNextString), lstrlen(szPath) + 1, szPath);
ASSERT(SUCCEEDED(hr));
dwNextString += lstrlen (szPath) + 1;
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::RemoveTemplates: Failed to realloc memory for delete list. %d"),
GetLastError()));
}
}
else
{
dwListLen = (lstrlen (szPath) + 2) * sizeof(TCHAR);
lpDeleteList = (LPTSTR) LocalAlloc (LPTR, dwListLen);
if (lpDeleteList)
{
hr = StringCchCopy (lpDeleteList, dwListLen/sizeof(WCHAR), szPath);
ASSERT(SUCCEEDED(hr));
dwNextString = lstrlen (lpDeleteList) + 1;
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::RemoveTemplates: Failed to alloc memory for delete list. %d"),
GetLastError()));
}
}
}
if (lpDeleteList)
{
fileop.hwnd = hDlg;
fileop.wFunc = FO_DELETE;
fileop.pFrom = lpDeleteList;
fileop.pTo = NULL;
fileop.fFlags = FOF_NOCONFIRMATION | FOF_SILENT;
iResult = SHFileOperation(&fileop);
if (!iResult)
{
bResult = TRUE;
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::RemoveTemplates: Failed to delete file <%s> with %d."),
szPath, iResult));
}
LocalFree (lpDeleteList);
if (bResult)
{
FillADMFiles (hDlg);
}
}
return bResult;
}
INT_PTR CALLBACK CPolicyComponentData::TemplatesDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
CPolicyComponentData * pCD;
static BOOL bTemplatesDirty;
switch (message)
{
case WM_INITDIALOG:
pCD = (CPolicyComponentData*) lParam;
SetWindowLongPtr (hDlg, DWLP_USER, (LONG_PTR) pCD);
bTemplatesDirty = FALSE;
if (!pCD->InitializeTemplatesDlg(hDlg))
{
EndDialog (hDlg, FALSE);
}
PostMessage (hDlg, WM_REFRESHDISPLAY, 0, 0);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
case IDCLOSE:
EndDialog (hDlg, bTemplatesDirty);
break;
case IDC_ADDTEMPLATES:
pCD = (CPolicyComponentData*) GetWindowLongPtr (hDlg, DWLP_USER);
if (pCD && pCD->AddTemplates(hDlg))
{
bTemplatesDirty = TRUE;
}
break;
case IDC_REMOVETEMPLATES:
pCD = (CPolicyComponentData*) GetWindowLongPtr (hDlg, DWLP_USER);
if (pCD && pCD->RemoveTemplates(hDlg))
{
bTemplatesDirty = TRUE;
}
break;
}
break;
case WM_NOTIFY:
if (((NMHDR FAR*)lParam)->code == LVN_DELETEITEM)
{
LVITEM item;
LPTEMPLATEENTRY lpEntry;
item.mask = LVIF_PARAM;
item.iItem = ((NMLISTVIEW FAR*)lParam)->iItem;
item.iSubItem = 0;
if (ListView_GetItem (GetDlgItem (hDlg, IDC_TEMPLATELIST), &item))
{
lpEntry = (LPTEMPLATEENTRY) item.lParam;
LocalFree (lpEntry);
}
}
else if (((NMHDR FAR*)lParam)->code == LVN_COLUMNCLICK)
{
pCD = (CPolicyComponentData*) GetWindowLongPtr (hDlg, DWLP_USER);
if (pCD)
{
pCD->m_bTemplatesColumn = ((NMLISTVIEW FAR*)lParam)->iSubItem;
ListView_SortItems (GetDlgItem (hDlg, IDC_TEMPLATELIST),
TemplatesSortCallback, pCD->m_bTemplatesColumn);
}
}
else
{
PostMessage (hDlg, WM_REFRESHDISPLAY, 0, 0);
}
break;
case WM_REFRESHDISPLAY:
if (ListView_GetNextItem (GetDlgItem(hDlg, IDC_TEMPLATELIST),
-1, LVNI_ALL | LVNI_SELECTED) == -1)
{
EnableWindow (GetDlgItem(hDlg, IDC_REMOVETEMPLATES), FALSE);
}
else
{
EnableWindow (GetDlgItem(hDlg, IDC_REMOVETEMPLATES), TRUE);
}
break;
case WM_HELP: // F1
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
(DWORD_PTR) (LPDWORD) aADMHelpIds);
return TRUE;
case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
(DWORD_PTR) (LPDWORD) aADMHelpIds);
return TRUE;
}
return FALSE;
}
BOOL CPolicyComponentData::AddRSOPRegistryDataNode(LPTSTR lpKeyName, LPTSTR lpValueName, DWORD dwType,
DWORD dwDataSize, LPBYTE lpData, UINT uiPrecedence, LPTSTR lpGPOName, BOOL bDeleted)
{
DWORD dwSize;
LPRSOPREGITEM lpItem;
BOOL bSystemEntry = FALSE;
HRESULT hr = S_OK;
//
// Special case some registry key / values and do not add them to the link list.
// These registry entries are specific to snapins we write and we know for sure
// they have rsop UI that will show their values.
//
if (lpKeyName)
{
const TCHAR szCerts[] = TEXT("Software\\Policies\\Microsoft\\SystemCertificates");
int iCertLen = lstrlen (szCerts);
//
// Remove all system certificates
//
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpKeyName, iCertLen, szCerts, iCertLen) == CSTR_EQUAL)
{
bSystemEntry = TRUE;
}
if ( ! bSystemEntry )
{
const TCHAR szCryptography[] = TEXT("Software\\Policies\\Microsoft\\Cryptography");
int iCryptographyLen = lstrlen (szCryptography);
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpKeyName, iCryptographyLen, szCryptography, iCryptographyLen) == CSTR_EQUAL)
{
bSystemEntry = TRUE;
}
}
//
// Hide the digial signature policies for Software Installation
//
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpKeyName, -1, TEXT("Software\\Policies\\Microsoft\\Windows\\Installer"), -1) == CSTR_EQUAL)
{
if (lpValueName)
{
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpValueName, -1, TEXT("InstallKnownPackagesOnly"), -1) == CSTR_EQUAL)
{
bSystemEntry = TRUE;
}
else if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpValueName, -1, TEXT("IgnoreSignaturePolicyForAdmins"), -1) == CSTR_EQUAL)
{
bSystemEntry = TRUE;
}
}
}
//
// Hide all the SAFER policies
//
const TCHAR szSaferKey[] = TEXT("Software\\Policies\\Microsoft\\Windows\\Safer");
int iSaferKeyLen = sizeof(szSaferKey) / sizeof(TCHAR) - 1;
if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpKeyName, iSaferKeyLen, szSaferKey, iSaferKeyLen) == CSTR_EQUAL)
{
bSystemEntry = TRUE;
}
}
if (bSystemEntry)
{
DebugMsg((DM_VERBOSE, TEXT("CPolicyComponentData::AddRSOPRegistryDataNode: Ignoring %s entry"), lpKeyName));
return TRUE;
}
//
// Calculate the size of the new registry item
//
dwSize = sizeof (RSOPREGITEM);
if (lpKeyName) {
dwSize += ((lstrlen(lpKeyName) + 1) * sizeof(TCHAR));
}
if (lpValueName) {
dwSize += ((lstrlen(lpValueName) + 1) * sizeof(TCHAR));
}
if (lpGPOName) {
dwSize += ((lstrlen(lpGPOName) + 1) * sizeof(TCHAR));
}
//
// Allocate space for it
//
lpItem = (LPRSOPREGITEM) LocalAlloc (LPTR, dwSize);
if (!lpItem) {
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::AddRSOPRegistryDataNode: Failed to allocate memory with %d"),
GetLastError()));
return FALSE;
}
//
// Fill in item
//
lpItem->dwType = dwType;
lpItem->dwSize = dwDataSize;
lpItem->uiPrecedence = uiPrecedence;
lpItem->bDeleted = bDeleted;
if (lpKeyName)
{
lpItem->lpKeyName = (LPTSTR)(((LPBYTE)lpItem) + sizeof(RSOPREGITEM));
hr = StringCchCopy (lpItem->lpKeyName, lstrlen(lpKeyName) + 1, lpKeyName);
ASSERT(SUCCEEDED(hr));
}
if (lpValueName)
{
if (lpKeyName)
{
lpItem->lpValueName = lpItem->lpKeyName + lstrlen (lpItem->lpKeyName) + 1;
}
else
{
lpItem->lpValueName = (LPTSTR)(((LPBYTE)lpItem) + sizeof(RSOPREGITEM));
}
hr = StringCchCopy (lpItem->lpValueName, lstrlen(lpValueName) + 1, lpValueName);
ASSERT(SUCCEEDED(hr));
}
if (lpGPOName)
{
if (lpValueName)
{
lpItem->lpGPOName = lpItem->lpValueName + lstrlen (lpItem->lpValueName) + 1;
}
else
{
if (lpKeyName)
{
lpItem->lpGPOName = lpItem->lpKeyName + lstrlen (lpItem->lpKeyName) + 1;
}
else
{
lpItem->lpGPOName = (LPTSTR)(((LPBYTE)lpItem) + sizeof(RSOPREGITEM));
}
}
hr = StringCchCopy (lpItem->lpGPOName, lstrlen(lpGPOName) + 1, lpGPOName);
ASSERT(SUCCEEDED(hr));
}
if (lpData)
{
lpItem->lpData = (LPBYTE) LocalAlloc (LPTR, dwDataSize);
if (!lpItem->lpData) {
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::AddRSOPRegistryDataNode: Failed to allocate memory for data with %d"),
GetLastError()));
LocalFree (lpItem);
return FALSE;
}
CopyMemory (lpItem->lpData, lpData, dwDataSize);
}
//
// Add item to link list
//
lpItem->pNext = m_pRSOPRegistryData;
m_pRSOPRegistryData = lpItem;
return TRUE;
}
VOID CPolicyComponentData::FreeRSOPRegistryData(VOID)
{
LPRSOPREGITEM lpTemp;
if (!m_pRSOPRegistryData)
{
return;
}
do {
lpTemp = m_pRSOPRegistryData->pNext;
if (m_pRSOPRegistryData->lpData)
{
LocalFree (m_pRSOPRegistryData->lpData);
}
LocalFree (m_pRSOPRegistryData);
m_pRSOPRegistryData = lpTemp;
} while (lpTemp);
}
HRESULT CPolicyComponentData::InitializeRSOPRegistryData(VOID)
{
BSTR pLanguage = NULL, pQuery = NULL;
BSTR pRegistryKey = NULL, pValueName = NULL, pValueType = NULL, pValue = NULL, pDeleted = NULL;
BSTR pPrecedence = NULL, pGPOid = NULL, pNamespace = NULL, pCommand = NULL;
IEnumWbemClassObject * pEnum = NULL;
IWbemClassObject *pObjects[2];
HRESULT hr;
ULONG ulRet;
VARIANT varRegistryKey, varValueName, varValueType, varData, varDeleted;
VARIANT varPrecedence, varGPOid, varCommand;
SAFEARRAY * pSafeArray;
IWbemLocator *pIWbemLocator = NULL;
IWbemServices *pIWbemServices = NULL;
LPTSTR lpGPOName;
DWORD dwDataSize;
LPBYTE lpData;
BSTR pValueTemp;
DebugMsg((DM_VERBOSE, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Entering")));
//
// Allocate BSTRs for the query language and for the query itself
//
pLanguage = SysAllocString (TEXT("WQL"));
if (!pLanguage)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to allocate memory for language")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
pQuery = SysAllocString (TEXT("SELECT registryKey, valueName, valueType, value, deleted, precedence, GPOID, command FROM RSOP_RegistryPolicySetting"));
if (!pQuery)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to allocate memory for query")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
//
// Allocate BSTRs for the property names we want to retreive
//
pRegistryKey = SysAllocString (TEXT("registryKey"));
if (!pRegistryKey)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to allocate memory for registryKey")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
pValueName = SysAllocString (TEXT("valueName"));
if (!pValueName)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to allocate memory for valueName")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
pValueType = SysAllocString (TEXT("valueType"));
if (!pValueType)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to allocate memory for valueType")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
pValue = SysAllocString (TEXT("value"));
if (!pValue)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to allocate memory for value")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
pDeleted = SysAllocString (TEXT("deleted"));
if (!pDeleted)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to allocate memory for deleted")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
pPrecedence = SysAllocString (TEXT("precedence"));
if (!pPrecedence)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to allocate memory for precedence")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
pGPOid = SysAllocString (TEXT("GPOID"));
if (!pGPOid)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to allocate memory for GPO id")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
pCommand = SysAllocString (TEXT("command"));
if (!pCommand)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to allocate memory for command")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
//
// Create an instance of the WMI locator service
//
hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pIWbemLocator);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: CoCreateInstance failed with 0x%x"), hr));
goto Exit;
}
//
// Allocate a BSTR for the namespace
//
pNamespace = SysAllocString (m_pszNamespace);
if (!pNamespace)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to allocate memory for namespace")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
//
// Connect to the server
//
hr = pIWbemLocator->ConnectServer(pNamespace, NULL, NULL, 0L, 0L, NULL, NULL,
&pIWbemServices);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: ConnectServer failed with 0x%x"), hr));
goto Exit;
}
// Set the proper security to encrypt the data
hr = CoSetProxyBlanket(pIWbemServices,
RPC_C_AUTHN_DEFAULT,
RPC_C_AUTHZ_DEFAULT,
COLE_DEFAULT_PRINCIPAL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
0);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: CoSetProxyBlanket failed with 0x%x"), hr));
goto Exit;
}
//
// Execute the query
//
hr = pIWbemServices->ExecQuery (pLanguage, pQuery,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL, &pEnum);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Failed to query for %s with 0x%x"),
pQuery, hr));
goto Exit;
}
//
// Loop through the results
//
while (pEnum->Next(WBEM_INFINITE, 1, pObjects, &ulRet) == S_OK)
{
//
// Check for the "data not available case"
//
if (ulRet == 0)
{
hr = S_OK;
goto Exit;
}
//
// Get the deleted flag
//
hr = pObjects[0]->Get (pDeleted, 0, &varDeleted, NULL, NULL);
if (SUCCEEDED(hr))
{
//
// Get the registry key
//
hr = pObjects[0]->Get (pRegistryKey, 0, &varRegistryKey, NULL, NULL);
if (SUCCEEDED(hr))
{
//
// Get the value name
//
hr = pObjects[0]->Get (pValueName, 0, &varValueName, NULL, NULL);
if (SUCCEEDED(hr))
{
//
// Get the value type
//
hr = pObjects[0]->Get (pValueType, 0, &varValueType, NULL, NULL);
if (SUCCEEDED(hr))
{
//
// Get the value data
//
hr = pObjects[0]->Get (pValue, 0, &varData, NULL, NULL);
if (SUCCEEDED(hr))
{
//
// Get the precedence
//
hr = pObjects[0]->Get (pPrecedence, 0, &varPrecedence, NULL, NULL);
if (SUCCEEDED(hr))
{
//
// Get the command
//
hr = pObjects[0]->Get (pCommand, 0, &varCommand, NULL, NULL);
if (SUCCEEDED(hr))
{
//
// Get the GPO ID
//
hr = pObjects[0]->Get (pGPOid, 0, &varGPOid, NULL, NULL);
if (SUCCEEDED(hr))
{
hr = GetGPOFriendlyName (pIWbemServices, varGPOid.bstrVal,
pLanguage, &lpGPOName);
if (SUCCEEDED(hr))
{
if (varValueName.vt != VT_NULL)
{
pValueTemp = varValueName.bstrVal;
}
else
{
pValueTemp = NULL;
}
if (varData.vt != VT_NULL)
{
pSafeArray = varData.parray;
dwDataSize = pSafeArray->rgsabound[0].cElements;
lpData = (LPBYTE) pSafeArray->pvData;
}
else
{
dwDataSize = 0;
lpData = NULL;
}
if ((varValueType.uintVal == REG_NONE) && pValueTemp &&
(CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
pValueTemp, -1, TEXT("**command"), -1) == CSTR_EQUAL))
{
pValueTemp = varCommand.bstrVal;
dwDataSize = 0;
lpData = NULL;
}
AddRSOPRegistryDataNode(varRegistryKey.bstrVal, pValueTemp,
varValueType.uintVal, dwDataSize, lpData,
varPrecedence.uintVal, lpGPOName,
(varDeleted.boolVal == 0) ? FALSE : TRUE);
LocalFree (lpGPOName);
}
VariantClear (&varGPOid);
}
VariantClear (&varCommand);
}
VariantClear (&varPrecedence);
}
VariantClear (&varData);
}
VariantClear (&varValueType);
}
VariantClear (&varValueName);
}
VariantClear (&varRegistryKey);
}
VariantClear (&varDeleted);
}
pObjects[0]->Release();
}
hr = S_OK;
Exit:
if (pEnum)
{
pEnum->Release();
}
if (pIWbemLocator)
{
pIWbemLocator->Release();
}
if (pIWbemServices)
{
pIWbemServices->Release();
}
if (pLanguage)
{
SysFreeString (pLanguage);
}
if (pQuery)
{
SysFreeString (pQuery);
}
if (pRegistryKey)
{
SysFreeString (pRegistryKey);
}
if (pValueType)
{
SysFreeString (pValueType);
}
if (pValueName)
{
SysFreeString (pValueName);
}
if (pDeleted)
{
SysFreeString (pDeleted);
}
if (pValue)
{
SysFreeString (pValue);
}
if (pNamespace)
{
SysFreeString (pNamespace);
}
if (pPrecedence)
{
SysFreeString (pPrecedence);
}
if (pGPOid)
{
SysFreeString (pGPOid);
}
if (pCommand)
{
SysFreeString (pCommand);
}
DebugMsg((DM_VERBOSE, TEXT("CPolicySnapIn::InitializeRSOPRegistryData: Leaving")));
return hr;
}
HRESULT CPolicyComponentData::GetGPOFriendlyName(IWbemServices *pIWbemServices,
LPTSTR lpGPOID, BSTR pLanguage,
LPTSTR *pGPOName)
{
BSTR pQuery = NULL, pName = NULL;
LPTSTR lpQuery = NULL;
IEnumWbemClassObject * pEnum = NULL;
IWbemClassObject *pObjects[2];
HRESULT hr;
ULONG ulRet;
VARIANT varGPOName;
DWORD dwGPONameLen = 0;
//
// Set the default
//
*pGPOName = NULL;
//
// Build the query
//
DWORD dwQryLen = lstrlen(lpGPOID) + 50;
lpQuery = (LPTSTR) LocalAlloc (LPTR, ( dwQryLen * sizeof(TCHAR)));
if (!lpQuery)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::GetGPOFriendlyName: Failed to allocate memory for unicode query")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
hr = StringCchPrintf (lpQuery, dwQryLen, TEXT("SELECT name, id FROM RSOP_GPO where id=\"%s\""), lpGPOID);
ASSERT(SUCCEEDED(hr));
pQuery = SysAllocString (lpQuery);
if (!pQuery)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::GetGPOFriendlyName: Failed to allocate memory for query")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
//
// Allocate BSTRs for the property names we want to retreive
//
pName = SysAllocString (TEXT("name"));
if (!pName)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::GetGPOFriendlyName: Failed to allocate memory for name")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
//
// Execute the query
//
hr = pIWbemServices->ExecQuery (pLanguage, pQuery,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL, &pEnum);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::GetGPOFriendlyName: Failed to query for %s with 0x%x"),
pQuery, hr));
goto Exit;
}
//
// Loop through the results
//
hr = pEnum->Next(WBEM_INFINITE, 1, pObjects, &ulRet);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::GetGPOFriendlyName: Failed to get first item in query results for %s with 0x%x"),
pQuery, hr));
goto Exit;
}
//
// Check for the "data not available case"
//
if (ulRet == 0)
{
hr = S_OK;
goto Exit;
}
//
// Get the name
//
hr = pObjects[0]->Get (pName, 0, &varGPOName, NULL, NULL);
pObjects[0]->Release();
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::GetGPOFriendlyName: Failed to get gponame in query results for %s with 0x%x"),
pQuery, hr));
goto Exit;
}
//
// Save the name
//
dwGPONameLen = lstrlen(varGPOName.bstrVal) + 1;
*pGPOName = (LPTSTR) LocalAlloc (LPTR, (dwGPONameLen) * sizeof(TCHAR));
if (!(*pGPOName))
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::GetGPOFriendlyName: Failed to allocate memory for GPO Name")));
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto Exit;
}
hr = StringCchCopy (*pGPOName, dwGPONameLen, varGPOName.bstrVal);
ASSERT(SUCCEEDED(hr));
VariantClear (&varGPOName);
hr = S_OK;
Exit:
if (pEnum)
{
pEnum->Release();
}
if (pQuery)
{
SysFreeString (pQuery);
}
if (lpQuery)
{
LocalFree (lpQuery);
}
if (pName)
{
SysFreeString (pName);
}
return hr;
}
//
// Note: the data in the uiPrecedence argument is really a UINT. It's declared
// as a HKEY so the hkeyRoot variable that calls this method can be used for both
// GPE and RSOP mode.
//
UINT CPolicyComponentData::ReadRSOPRegistryValue(HKEY uiPrecedence, TCHAR * pszKeyName,
TCHAR * pszValueName, LPBYTE pData,
DWORD dwMaxSize, DWORD *dwType,
LPTSTR *lpGPOName, LPRSOPREGITEM lpItem)
{
LPRSOPREGITEM lpTemp;
BOOL bDeleted = FALSE;
LPTSTR lpValueNameTemp = pszValueName;
if (!lpItem)
{
lpTemp = m_pRSOPRegistryData;
if (pszValueName)
{
INT iDelPrefixLen = lstrlen(szDELETEPREFIX);
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
pszValueName, iDelPrefixLen,
szDELETEPREFIX, iDelPrefixLen) == CSTR_EQUAL)
{
lpValueNameTemp = pszValueName+iDelPrefixLen;
bDeleted = TRUE;
}
}
//
// Find the item
//
while (lpTemp)
{
if (pszKeyName && lpValueNameTemp &&
lpTemp->lpKeyName && lpTemp->lpValueName)
{
if (bDeleted == lpTemp->bDeleted)
{
if ((uiPrecedence == 0) || (uiPrecedence == (HKEY)LongToHandle(lpTemp->uiPrecedence)))
{
if (!lstrcmpi(lpTemp->lpValueName, lpValueNameTemp) &&
!lstrcmpi(lpTemp->lpKeyName, pszKeyName))
{
break;
}
}
}
}
else if (!pszKeyName && lpValueNameTemp &&
!lpTemp->lpKeyName && lpTemp->lpValueName)
{
if (bDeleted == lpTemp->bDeleted)
{
if ((uiPrecedence == 0) || (uiPrecedence == (HKEY)LongToHandle(lpTemp->uiPrecedence)))
{
if (!lstrcmpi(lpTemp->lpValueName, lpValueNameTemp))
{
break;
}
}
}
}
else if (pszKeyName && !lpValueNameTemp &&
lpTemp->lpKeyName && !lpTemp->lpValueName)
{
if (bDeleted == lpTemp->bDeleted)
{
if ((uiPrecedence == 0) || (uiPrecedence == (HKEY)LongToHandle(lpTemp->uiPrecedence)))
{
if (!lstrcmpi(lpTemp->lpKeyName, pszKeyName))
{
break;
}
}
}
}
lpTemp = lpTemp->pNext;
}
}
else
{
//
// Read a specific item
//
lpTemp = lpItem;
}
//
// Exit now if the item wasn't found
//
if (!lpTemp)
{
return ERROR_FILE_NOT_FOUND;
}
//
// Check if the data will fit in the buffer passed in
//
if (lpTemp->dwSize > dwMaxSize)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::ReadRSOPRegistryValue: The returned data size of %d is greater than the buffer size passed in of %d for %s\\%s"),
lpTemp->dwSize, dwMaxSize, pszKeyName, pszValueName));
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// Copy the data
//
if (lpTemp->lpData)
{
CopyMemory (pData, lpTemp->lpData, lpTemp->dwSize);
}
*dwType = lpTemp->dwType;
if (lpGPOName)
{
*lpGPOName = lpTemp->lpGPOName;
}
return ERROR_SUCCESS;
}
//
// Note: the data in the uiPrecedence argument is really a UINT. It's declared
// as a HKEY so the hkeyRoot variable that calls this method can be used for both
// GPE and RSOP mode.
//
UINT CPolicyComponentData::EnumRSOPRegistryValues(HKEY uiPrecedence, TCHAR * pszKeyName,
TCHAR * pszValueName, DWORD dwMaxSize,
LPRSOPREGITEM *lpEnum)
{
LPRSOPREGITEM lpTemp;
HRESULT hr = S_OK;
if (lpEnum && *lpEnum)
{
lpTemp = (*lpEnum)->pNext;
}
else
{
lpTemp = m_pRSOPRegistryData;
}
//
// Find the next item
//
while (lpTemp)
{
if (!pszKeyName && !lpTemp->lpKeyName)
{
if (!lpTemp->bDeleted)
{
if ((uiPrecedence == 0) || (uiPrecedence == (HKEY)LongToHandle(lpTemp->uiPrecedence)))
{
break;
}
}
}
else if (pszKeyName && lpTemp->lpKeyName)
{
if (!lpTemp->bDeleted)
{
if ((uiPrecedence == 0) || (uiPrecedence == (HKEY)LongToHandle(lpTemp->uiPrecedence)))
{
if (!lstrcmpi(lpTemp->lpKeyName, pszKeyName))
{
break;
}
}
}
}
lpTemp = lpTemp->pNext;
}
//
// Exit now if an item wasn't found
//
if (!lpTemp)
{
*lpEnum = NULL;
return ERROR_NO_MORE_ITEMS;
}
if (lpTemp->lpValueName)
{
//
// Check if the value name will fit in the buffer passed in
//
if ((DWORD)(lstrlen(lpTemp->lpValueName) + 1) > dwMaxSize)
{
DebugMsg((DM_WARNING, TEXT("CPolicyComponentData::EnumRSOPRegistryValues: The valuename buffer size is too small")));
return ERROR_NOT_ENOUGH_MEMORY;
}
hr = StringCchCopy (pszValueName, dwMaxSize, lpTemp->lpValueName);
ASSERT(SUCCEEDED(hr));
}
else
{
*pszValueName = TEXT('\0');
}
//
// Save the item pointer
//
*lpEnum = lpTemp;
return ERROR_SUCCESS;
}
//
// Note: the data in the uiPrecedence argument is really a UINT. It's declared
// as a HKEY so the hkeyRoot variable that calls this method can be used for both
// GPE and RSOP mode.
//
UINT CPolicyComponentData::FindRSOPRegistryEntry(HKEY uiPrecedence, TCHAR * pszKeyName,
TCHAR * pszValueName, LPRSOPREGITEM *lpEnum)
{
LPRSOPREGITEM lpTemp;
BOOL bDeleted = FALSE;
LPTSTR lpValueNameTemp = pszValueName;
if (lpEnum && *lpEnum)
{
lpTemp = (*lpEnum)->pNext;
}
else
{
lpTemp = m_pRSOPRegistryData;
}
if (pszValueName)
{
INT iDelPrefixLen = lstrlen(szDELETEPREFIX);
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
pszValueName, iDelPrefixLen,
szDELETEPREFIX, iDelPrefixLen) == CSTR_EQUAL)
{
lpValueNameTemp = pszValueName+iDelPrefixLen;
bDeleted = TRUE;
}
}
//
// Find the next item
//
while (lpTemp)
{
if (pszKeyName && lpValueNameTemp &&
lpTemp->lpKeyName && lpTemp->lpValueName)
{
if (bDeleted == lpTemp->bDeleted)
{
if ((uiPrecedence == 0) || (uiPrecedence == (HKEY)LongToHandle(lpTemp->uiPrecedence)))
{
if (!lstrcmpi(lpTemp->lpValueName, lpValueNameTemp) &&
!lstrcmpi(lpTemp->lpKeyName, pszKeyName))
{
break;
}
}
}
}
else if (!pszKeyName && lpValueNameTemp &&
!lpTemp->lpKeyName && lpTemp->lpValueName)
{
if (bDeleted == lpTemp->bDeleted)
{
if ((uiPrecedence == 0) || (uiPrecedence == (HKEY)LongToHandle(lpTemp->uiPrecedence)))
{
if (!lstrcmpi(lpTemp->lpValueName, lpValueNameTemp))
{
break;
}
}
}
}
else if (pszKeyName && !lpValueNameTemp &&
lpTemp->lpKeyName && !lpTemp->lpValueName)
{
if (bDeleted == lpTemp->bDeleted)
{
if ((uiPrecedence == 0) || (uiPrecedence == (HKEY)LongToHandle(lpTemp->uiPrecedence)))
{
if (!lstrcmpi(lpTemp->lpKeyName, pszKeyName))
{
break;
}
}
}
}
lpTemp = lpTemp->pNext;
}
//
// Exit now if an item wasn't found
//
if (!lpTemp)
{
*lpEnum = NULL;
return ERROR_NO_MORE_ITEMS;
}
//
// Save the item pointer
//
*lpEnum = lpTemp;
return ERROR_SUCCESS;
}
VOID CPolicyComponentData::DumpRSOPRegistryData(void)
{
LPRSOPREGITEM lpTemp;
TCHAR szDebug[50];
lpTemp = m_pRSOPRegistryData;
if (m_bUserScope)
OutputDebugString (TEXT("\n\nDump of RSOP user registry data\n"));
else
OutputDebugString (TEXT("\n\nDump of RSOP computer registry data\n"));
while (lpTemp)
{
OutputDebugString (TEXT("\n\n"));
if (lpTemp->lpKeyName)
OutputDebugString (lpTemp->lpKeyName);
else
OutputDebugString (TEXT("NULL Key Name"));
OutputDebugString (TEXT("\n"));
if (lpTemp->lpValueName)
OutputDebugString (lpTemp->lpValueName);
else
OutputDebugString (TEXT("NULL Value Name"));
OutputDebugString (TEXT("\n"));
if (lpTemp->dwType == REG_DWORD)
{
(void) StringCchPrintf (szDebug, ARRAYSIZE(szDebug), TEXT("REG_DWORD\n%d\n"), *((LPDWORD)lpTemp->lpData));
OutputDebugString (szDebug);
}
else if (lpTemp->dwType == REG_SZ)
{
OutputDebugString (TEXT("REG_SZ\n"));
if (lpTemp->lpData)
OutputDebugString ((LPTSTR)lpTemp->lpData);
OutputDebugString (TEXT("\n"));
}
else if (lpTemp->dwType == REG_EXPAND_SZ)
{
OutputDebugString (TEXT("REG_EXPAND_SZ\n"));
if (lpTemp->lpData)
OutputDebugString ((LPTSTR)lpTemp->lpData);
OutputDebugString (TEXT("\n"));
}
else if (lpTemp->dwType == REG_BINARY)
{
OutputDebugString (TEXT("REG_BINARY\n"));
OutputDebugString (TEXT("<Binary data not displayed>\n"));
}
else if (lpTemp->dwType == REG_NONE)
{
OutputDebugString (TEXT("REG_NONE\n"));
}
else
{
(void) StringCchPrintf (szDebug, ARRAYSIZE(szDebug), TEXT("Unknown type: %d\n"), lpTemp->dwType);
OutputDebugString (szDebug);
}
(void) StringCchPrintf (szDebug, ARRAYSIZE(szDebug), TEXT("Precedence: %d\n"), lpTemp->uiPrecedence);
OutputDebugString(szDebug);
(void) StringCchPrintf (szDebug, ARRAYSIZE(szDebug), TEXT("Deleted: %d\n"), lpTemp->bDeleted);
OutputDebugString(szDebug);
(void) StringCchPrintf (szDebug, ARRAYSIZE(szDebug), TEXT("bFoundInADM: %d\n"), lpTemp->bFoundInADM);
OutputDebugString(szDebug);
OutputDebugString (TEXT("GPOName: "));
if (lpTemp->lpGPOName)
OutputDebugString (lpTemp->lpGPOName);
else
OutputDebugString (TEXT("NULL GPO Name"));
OutputDebugString (TEXT("\n"));
lpTemp = lpTemp->pNext;
}
OutputDebugString (TEXT("\n\n"));
}
BOOL CPolicyComponentData::FindEntryInActionList(POLICY * pPolicy, ACTIONLIST * pActionList, LPTSTR lpKeyName, LPTSTR lpValueName)
{
UINT uIndex;
ACTION * pAction = NULL;
TCHAR * pszKeyName = NULL;
TCHAR * pszValueName = NULL;
//
// Loop through each of the entries to see if they match
//
pAction = &pActionList->Action[0];
for (uIndex = 0; uIndex < pActionList->nActionItems; uIndex++)
{
if (uIndex == 0)
{
// already set up pAction
}
else
{
pAction = (ACTION *)(((LPBYTE)pActionList) + pAction->uOffsetNextAction);
}
//
// Get the value and keynames
//
pszValueName = (TCHAR *)(((LPBYTE)pActionList) + pAction->uOffsetValueName);
if (pAction->uOffsetKeyName)
{
pszKeyName = (TCHAR *)(((LPBYTE)pActionList) + pAction->uOffsetKeyName);
}
else
{
pszKeyName = (TCHAR *)(((LPBYTE)pPolicy) + pPolicy->uOffsetKeyName);
}
if (!lstrcmpi(pszKeyName, lpKeyName) && !lstrcmpi(pszValueName, lpValueName)) {
return TRUE;
}
}
return FALSE;
}
BOOL CPolicyComponentData::FindEntryInTable(TABLEENTRY * pTable, LPTSTR lpKeyName, LPTSTR lpValueName)
{
POLICY * pEntry = (POLICY *) pTable;
if ((pEntry->dwType & ETYPE_POLICY) || (pEntry->dwType & ETYPE_SETTING))
{
if (!lstrcmpi(lpKeyName, GETKEYNAMEPTR(pEntry)))
{
if ( (!(GETVALUENAMEPTR(pEntry)) || (!lstrcmpi(GETVALUENAMEPTR(pEntry), TEXT("")))) ) {
if (pEntry->dwType & STYPE_LISTBOX) {
return TRUE;
}
}
else if (!lstrcmpi(lpValueName, GETVALUENAMEPTR(pEntry)))
{
return TRUE;
}
}
// look in the actionlists
// actionslist can be at 3 places. under policy itself or under the dropdown lists below
ACTIONLIST * pActionList;
if (pEntry->dwType & ETYPE_POLICY) {
if (pEntry->uOffsetActionList_On) {
pActionList = (ACTIONLIST *)(((LPBYTE)pEntry) + pEntry->uOffsetActionList_On);
if (FindEntryInActionList(pEntry, pActionList, lpKeyName, lpValueName))
return TRUE;
}
if (pEntry->uOffsetActionList_Off) {
pActionList = (ACTIONLIST *)(((LPBYTE)pEntry) + pEntry->uOffsetActionList_Off);
if (FindEntryInActionList(pEntry, pActionList, lpKeyName, lpValueName))
return TRUE;
}
}
if (pEntry->dwType & ETYPE_SETTING) {
SETTINGS * pSettings = (SETTINGS *)pTable;
if (pSettings) {
BYTE * pObjectData = GETOBJECTDATAPTR(pSettings);
if (pObjectData) {
if ((pEntry->dwType & STYPE_MASK) == STYPE_CHECKBOX) {
if (((CHECKBOXINFO *)pObjectData)->uOffsetActionList_On) {
pActionList = (ACTIONLIST *)(((LPBYTE)pEntry) + (((CHECKBOXINFO *)pObjectData)->uOffsetActionList_On));
if (FindEntryInActionList(pEntry, pActionList, lpKeyName, lpValueName))
return TRUE;
}
if (((CHECKBOXINFO *)pObjectData)->uOffsetActionList_Off) {
pActionList = (ACTIONLIST *)(((LPBYTE)pEntry) + (((CHECKBOXINFO *)pObjectData)->uOffsetActionList_Off));
if (FindEntryInActionList(pEntry, pActionList, lpKeyName, lpValueName))
return TRUE;
}
}
if ((pEntry->dwType & STYPE_MASK) == STYPE_DROPDOWNLIST) {
DROPDOWNINFO * pddi;
pddi = (DROPDOWNINFO *) pObjectData;
while (pddi) {
if (pddi->uOffsetActionList) {
pActionList = (ACTIONLIST *)(((LPBYTE)pEntry) + pddi->uOffsetActionList);
if (FindEntryInActionList(pEntry, pActionList, lpKeyName, lpValueName))
return TRUE;
}
if (pddi->uOffsetNextDropdowninfo) {
pddi = (DROPDOWNINFO *) ( (BYTE *) pEntry + pddi->uOffsetNextDropdowninfo);
}
else {
pddi = NULL;
}
}
}
}
}
}
}
if (pEntry->pChild)
{
if (FindEntryInTable(pEntry->pChild, lpKeyName, lpValueName))
{
return TRUE;
}
}
if (pEntry->pNext)
{
if (FindEntryInTable(pEntry->pNext, lpKeyName, lpValueName))
{
return TRUE;
}
}
return FALSE;
}
VOID CPolicyComponentData::AddEntryToList (TABLEENTRY *pItem)
{
TABLEENTRY *lpTemp;
lpTemp = m_pExtraSettingsRoot->pChild;
if (!lpTemp)
{
m_pExtraSettingsRoot->pChild = pItem;
return;
}
while (lpTemp->pNext)
{
lpTemp = lpTemp->pNext;
}
lpTemp->pNext = pItem;
pItem->pPrev = lpTemp;
}
VOID CPolicyComponentData::InitializeExtraSettings (VOID)
{
LPRSOPREGITEM lpTemp;
TCHAR szValueStr[MAX_PATH];
HRESULT hr = S_OK;
lpTemp = m_pRSOPRegistryData;
while (lpTemp)
{
//
// Build REGITEM structures for every registry entry that has a precedence of 1
// and that is not found in any adm file
//
if ((lpTemp->uiPrecedence == 1) && (lpTemp->dwType != REG_NONE) && (!lpTemp->bDeleted))
{
DWORD dwBufSize = 0;
REGITEM *pTmp, *pItem;
LPTSTR lpName;
//
// Check to see if this registry entry is used by any adm policy / part
//
if (m_bUserScope)
{
if (m_pUserCategoryList)
{
lpTemp->bFoundInADM = FindEntryInTable(m_pUserCategoryList,
lpTemp->lpKeyName,
lpTemp->lpValueName);
}
}
else
{
if (m_pMachineCategoryList)
{
lpTemp->bFoundInADM = FindEntryInTable(m_pMachineCategoryList,
lpTemp->lpKeyName,
lpTemp->lpValueName);
}
}
if (!lpTemp->bFoundInADM)
{
//
// Build regitem entry
//
pItem = (REGITEM *) GlobalAlloc(GPTR, sizeof(REGITEM));
if (pItem)
{
pItem->dwSize = sizeof(REGITEM);
pItem->dwType = ETYPE_REGITEM;
pItem->lpItem = lpTemp;
dwBufSize += lstrlen (lpTemp->lpKeyName) + 1;
if (lpTemp->lpValueName && *lpTemp->lpValueName)
{
dwBufSize += lstrlen (lpTemp->lpValueName) + 1;
}
lpName = (LPTSTR) LocalAlloc (LPTR, dwBufSize * sizeof(TCHAR));
if (lpName)
{
hr = StringCchCopy (lpName, dwBufSize, lpTemp->lpKeyName);
ASSERT(SUCCEEDED(hr));
if (lpTemp->lpValueName && *lpTemp->lpValueName)
{
hr = StringCchCat (lpName, dwBufSize, TEXT("\\"));
ASSERT(SUCCEEDED(hr));
hr = StringCchCat (lpName, dwBufSize, lpTemp->lpValueName);
ASSERT(SUCCEEDED(hr));
}
//
// Add the display name
//
pTmp = (REGITEM *) AddDataToEntry((TABLEENTRY *)pItem,
(BYTE *)lpName,(lstrlen(lpName)+1) * sizeof(TCHAR),&(pItem->uOffsetName),
&dwBufSize);
if (pTmp)
{
pItem = pTmp;
//
// Add the keyname
//
pTmp = (REGITEM *) AddDataToEntry((TABLEENTRY *)pItem,
(BYTE *)lpTemp->lpKeyName,(lstrlen(lpTemp->lpKeyName)+1) * sizeof(TCHAR),&(pItem->uOffsetKeyName),
&dwBufSize);
if (pTmp)
{
pItem = pTmp;
szValueStr[0] = TEXT('\0');
if (lpTemp->dwType == REG_DWORD)
{
hr = StringCchPrintf (szValueStr, ARRAYSIZE(szValueStr), TEXT("%d"), (DWORD) *((LPDWORD)lpTemp->lpData));
ASSERT(SUCCEEDED(hr));
}
else if (lpTemp->dwType == REG_SZ)
{
lstrcpyn (szValueStr, (LPTSTR)lpTemp->lpData, ARRAYSIZE(szValueStr));
}
else if (lpTemp->dwType == REG_EXPAND_SZ)
{
lstrcpyn (szValueStr, (LPTSTR)lpTemp->lpData, ARRAYSIZE(szValueStr));
}
else if (lpTemp->dwType == REG_BINARY)
{
LoadString(g_hInstance, IDS_BINARYDATA, szValueStr, ARRAYSIZE(szValueStr));
}
else
{
LoadString(g_hInstance, IDS_UNKNOWNDATA, szValueStr, ARRAYSIZE(szValueStr));
}
//
// Add the value in string format
//
pTmp = (REGITEM *) AddDataToEntry((TABLEENTRY *)pItem,
(BYTE *)szValueStr,(lstrlen(szValueStr)+1) * sizeof(TCHAR),&(pItem->uOffsetValueStr),
&dwBufSize);
if (pTmp)
{
pItem = pTmp;
//
// Check if this is a real policy
//
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpTemp->lpKeyName, m_iSWPoliciesLen,
SOFTWARE_POLICIES, m_iSWPoliciesLen) == CSTR_EQUAL)
{
pItem->bTruePolicy = TRUE;
}
else if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpTemp->lpKeyName, m_iWinPoliciesLen,
WINDOWS_POLICIES, m_iWinPoliciesLen) == CSTR_EQUAL)
{
pItem->bTruePolicy = TRUE;
}
AddEntryToList ((TABLEENTRY *)pItem);
}
else
{
GlobalFree (pItem);
}
}
else
{
GlobalFree (pItem);
}
}
else
{
GlobalFree (pItem);
}
LocalFree (lpName);
}
else
{
GlobalFree (pItem);
}
}
}
}
lpTemp = lpTemp->pNext;
}
}
BOOL CPolicyComponentData::DoesNodeExist (LPSUPPORTEDENTRY *pList, LPTSTR lpString)
{
LPSUPPORTEDENTRY lpItem;
if (!(*pList))
{
return FALSE;
}
lpItem = *pList;
while (lpItem)
{
if (!lstrcmpi(lpItem->lpString, lpString))
{
return TRUE;
}
lpItem = lpItem->pNext;
}
return FALSE;
}
BOOL CPolicyComponentData::CheckSupportedFilter (POLICY *pPolicy)
{
LPSUPPORTEDENTRY lpItem = m_pSupportedStrings;
LPTSTR lpString = GETSUPPORTEDPTR(pPolicy);
if (!lpItem || !m_bUseSupportedOnFilter)
{
return TRUE;
}
while (lpItem)
{
if (!lpString)
{
if (lpItem->bNull)
{
return lpItem->bEnabled;
}
}
else
{
if (!lstrcmpi(lpItem->lpString, lpString))
{
return lpItem->bEnabled;
}
}
lpItem = lpItem->pNext;
}
return TRUE;
}
BOOL CPolicyComponentData::IsAnyPolicyAllowedPastFilter(TABLEENTRY * pCategory)
{
TABLEENTRY * pEntry;
INT iState;
if (!pCategory || !pCategory->pChild)
{
return FALSE;
}
pEntry = pCategory->pChild;
while (pEntry)
{
if (pEntry->dwType & ETYPE_CATEGORY)
{
if (IsAnyPolicyAllowedPastFilter(pEntry))
{
return TRUE;
}
}
else if (pEntry->dwType & ETYPE_POLICY)
{
if (CheckSupportedFilter((POLICY *) pEntry))
{
return TRUE;
}
}
pEntry = pEntry->pNext;
}
return FALSE;
}
VOID CPolicyComponentData::AddSupportedNode (LPSUPPORTEDENTRY *pList, LPTSTR lpString,
BOOL bNull)
{
LPSUPPORTEDENTRY lpItem;
DWORD dwSize;
//
// Check if this item is already in the link list first
//
if (DoesNodeExist (pList, lpString))
{
return;
}
//
// Add it to the list
//
dwSize = sizeof(SUPPORTEDENTRY);
dwSize += ((lstrlen(lpString) + 1) * sizeof(TCHAR));
lpItem = (LPSUPPORTEDENTRY) LocalAlloc (LPTR, dwSize);
if (!lpItem)
{
return;
}
lpItem->lpString = (LPTSTR)(((LPBYTE)lpItem) + sizeof(SUPPORTEDENTRY));
(void) StringCchCopy (lpItem->lpString, lstrlen(lpString) + 1, lpString);
lpItem->bEnabled = TRUE;
lpItem->bNull = bNull;
lpItem->pNext = *pList;
*pList = lpItem;
}
VOID CPolicyComponentData::FreeSupportedData(LPSUPPORTEDENTRY lpList)
{
LPSUPPORTEDENTRY lpTemp;
do {
lpTemp = lpList->pNext;
LocalFree (lpList);
lpList = lpTemp;
} while (lpTemp);
}
VOID CPolicyComponentData::InitializeSupportInfo(TABLEENTRY * pTable, LPSUPPORTEDENTRY *pList)
{
POLICY * pEntry = (POLICY *) pTable;
LPTSTR lpString;
if (pEntry->dwType & ETYPE_POLICY)
{
lpString = GETSUPPORTEDPTR(pEntry);
if (lpString)
{
AddSupportedNode (pList, lpString, FALSE);
}
}
if (pEntry->pChild)
{
InitializeSupportInfo(pEntry->pChild, pList);
}
if (pEntry->pNext)
{
InitializeSupportInfo(pEntry->pNext, pList);
}
}
///////////////////////////////////////////////////////////////////////////////
// //
// Class factory object implementation //
// //
///////////////////////////////////////////////////////////////////////////////
CPolicyComponentDataCF::CPolicyComponentDataCF(BOOL bUser, BOOL bRSOP)
{
m_cRef = 1;
InterlockedIncrement(&g_cRefThisDll);
m_bUser = bUser;
m_bRSOP = bRSOP;
}
CPolicyComponentDataCF::~CPolicyComponentDataCF()
{
InterlockedDecrement(&g_cRefThisDll);
}
///////////////////////////////////////////////////////////////////////////////
// //
// Class factory object implementation (IUnknown) //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG)
CPolicyComponentDataCF::AddRef()
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG)
CPolicyComponentDataCF::Release()
{
if (--m_cRef == 0)
{
delete this;
return 0;
}
return m_cRef;
}
STDMETHODIMP
CPolicyComponentDataCF::QueryInterface(REFIID riid, LPVOID FAR* ppv)
{
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
{
*ppv = (LPCLASSFACTORY)this;
m_cRef++;
return S_OK;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
}
///////////////////////////////////////////////////////////////////////////////
// //
// Class factory object implementation (IClassFactory) //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CPolicyComponentDataCF::CreateInstance(LPUNKNOWN pUnkOuter,
REFIID riid,
LPVOID FAR* ppvObj)
{
*ppvObj = NULL;
if (pUnkOuter)
return CLASS_E_NOAGGREGATION;
CPolicyComponentData *pComponentData = new CPolicyComponentData(m_bUser, m_bRSOP); // ref count == 1
if (!pComponentData)
return E_OUTOFMEMORY;
HRESULT hr = pComponentData->QueryInterface(riid, ppvObj);
pComponentData->Release(); // release initial ref
return hr;
}
STDMETHODIMP
CPolicyComponentDataCF::LockServer(BOOL fLock)
{
return E_NOTIMPL;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Class factory object creation (IClassFactory) //
// //
///////////////////////////////////////////////////////////////////////////////
HRESULT CreatePolicyComponentDataClassFactory (REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
HRESULT hr;
//
// Admin Templates in editing mode
//
if (IsEqualCLSID (rclsid, CLSID_PolicySnapInMachine)) {
CPolicyComponentDataCF *pComponentDataCF = new CPolicyComponentDataCF(FALSE, FALSE); // ref == 1
if (!pComponentDataCF)
return E_OUTOFMEMORY;
hr = pComponentDataCF->QueryInterface(riid, ppv);
pComponentDataCF->Release(); // release initial ref
return hr;
}
if (IsEqualCLSID (rclsid, CLSID_PolicySnapInUser)) {
CPolicyComponentDataCF *pComponentDataCF = new CPolicyComponentDataCF(TRUE, FALSE); // ref == 1
if (!pComponentDataCF)
return E_OUTOFMEMORY;
hr = pComponentDataCF->QueryInterface(riid, ppv);
pComponentDataCF->Release(); // release initial ref
return hr;
}
//
// Admin Templates in RSOP mode
//
if (IsEqualCLSID (rclsid, CLSID_RSOPolicySnapInMachine)) {
CPolicyComponentDataCF *pComponentDataCF = new CPolicyComponentDataCF(FALSE, TRUE); // ref == 1
if (!pComponentDataCF)
return E_OUTOFMEMORY;
hr = pComponentDataCF->QueryInterface(riid, ppv);
pComponentDataCF->Release(); // release initial ref
return hr;
}
if (IsEqualCLSID (rclsid, CLSID_RSOPolicySnapInUser)) {
CPolicyComponentDataCF *pComponentDataCF = new CPolicyComponentDataCF(TRUE, TRUE); // ref == 1
if (!pComponentDataCF)
return E_OUTOFMEMORY;
hr = pComponentDataCF->QueryInterface(riid, ppv);
pComponentDataCF->Release(); // release initial ref
return hr;
}
return CLASS_E_CLASSNOTAVAILABLE;
}
unsigned int CPolicySnapIn::m_cfNodeType = RegisterClipboardFormat(CCF_NODETYPE);
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicySnapIn object implementation //
// //
///////////////////////////////////////////////////////////////////////////////
CPolicySnapIn::CPolicySnapIn(CPolicyComponentData *pComponent)
{
m_cRef = 1;
InterlockedIncrement(&g_cRefThisDll);
m_pcd = pComponent;
m_pConsole = NULL;
m_pResult = NULL;
m_pHeader = NULL;
m_pConsoleVerb = NULL;
m_pDisplayHelp = NULL;
m_nColumn1Size = 350;
m_nColumn2Size = 100;
m_nColumn3Size = 200;
m_lViewMode = LVS_REPORT;
if (m_pcd->m_bRSOP)
{
m_bPolicyOnly = FALSE;
}
else
{
m_bPolicyOnly = TRUE;
}
m_dwPolicyOnlyPolicy = 2;
m_hMsgWindow = NULL;
m_uiRefreshMsg = RegisterWindowMessage (TEXT("ADM Template Reload"));
m_pCurrentPolicy = NULL;
m_hPropDlg = NULL;
LoadString(g_hInstance, IDS_NAME, m_pName, ARRAYSIZE(m_pName));
LoadString(g_hInstance, IDS_STATE, m_pState, ARRAYSIZE(m_pState));
LoadString(g_hInstance, IDS_SETTING, m_pSetting, ARRAYSIZE(m_pSetting));
LoadString(g_hInstance, IDS_GPONAME, m_pGPOName, ARRAYSIZE(m_pGPOName));
LoadString(g_hInstance, IDS_MULTIPLEGPOS, m_pMultipleGPOs, ARRAYSIZE(m_pMultipleGPOs));
LoadString(g_hInstance, IDS_ENABLED, m_pEnabled, ARRAYSIZE(m_pEnabled));
LoadString(g_hInstance, IDS_DISABLED, m_pDisabled, ARRAYSIZE(m_pDisabled));
LoadString(g_hInstance, IDS_NOTCONFIGURED, m_pNotConfigured, ARRAYSIZE(m_pNotConfigured));
}
CPolicySnapIn::~CPolicySnapIn()
{
InterlockedDecrement(&g_cRefThisDll);
if (m_pConsole != NULL)
{
m_pConsole->SetHeader(NULL);
m_pConsole->Release();
m_pConsole = NULL;
}
if (m_pHeader != NULL)
{
m_pHeader->Release();
m_pHeader = NULL;
}
if (m_pResult != NULL)
{
m_pResult->Release();
m_pResult = NULL;
}
if (m_pConsoleVerb != NULL)
{
m_pConsoleVerb->Release();
m_pConsoleVerb = NULL;
}
if (m_pDisplayHelp != NULL)
{
m_pDisplayHelp->Release();
m_pDisplayHelp = NULL;
}
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicySnapIn object implementation (IUnknown) //
// //
///////////////////////////////////////////////////////////////////////////////
HRESULT CPolicySnapIn::QueryInterface (REFIID riid, void **ppv)
{
if (IsEqualIID(riid, IID_IComponent) || IsEqualIID(riid, IID_IUnknown))
{
*ppv = (LPCOMPONENT)this;
m_cRef++;
return S_OK;
}
else if (IsEqualIID(riid, IID_IExtendContextMenu))
{
*ppv = (LPEXTENDCONTEXTMENU)this;
m_cRef++;
return S_OK;
}
else if (IsEqualIID(riid, IID_IExtendPropertySheet))
{
*ppv = (LPEXTENDPROPERTYSHEET)this;
m_cRef++;
return S_OK;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
}
ULONG CPolicySnapIn::AddRef (void)
{
return ++m_cRef;
}
ULONG CPolicySnapIn::Release (void)
{
if (--m_cRef == 0) {
delete this;
return 0;
}
return m_cRef;
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicySnapIn object implementation (IComponent) //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPolicySnapIn::Initialize(LPCONSOLE lpConsole)
{
HRESULT hr;
WNDCLASS wc;
HKEY hKey;
DWORD dwSize, dwType;
// Save the IConsole pointer
m_pConsole = lpConsole;
m_pConsole->AddRef();
hr = m_pConsole->QueryInterface(IID_IHeaderCtrl,
reinterpret_cast<void**>(&m_pHeader));
// Give the console the header control interface pointer
if (SUCCEEDED(hr))
m_pConsole->SetHeader(m_pHeader);
m_pConsole->QueryInterface(IID_IResultData,
reinterpret_cast<void**>(&m_pResult));
hr = m_pConsole->QueryConsoleVerb(&m_pConsoleVerb);
hr = m_pConsole->QueryInterface(IID_IDisplayHelp,
reinterpret_cast<void**>(&m_pDisplayHelp));
ZeroMemory (&wc, sizeof(wc));
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = ClipWndProc;
wc.cbWndExtra = sizeof(DWORD);
wc.hInstance = (HINSTANCE) g_hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.lpszClassName = TEXT("ClipClass");
if (!RegisterClass(&wc))
{
if (GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::Initialize: RegisterClass for clipclass failed with %d."),
GetLastError()));
return E_FAIL;
}
}
ZeroMemory (&wc, sizeof(wc));
wc.lpfnWndProc = MessageWndProc;
wc.cbWndExtra = sizeof(LPVOID);
wc.hInstance = (HINSTANCE) g_hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.lpszClassName = TEXT("GPMessageWindowClass");
if (!RegisterClass(&wc))
{
if (GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::Initialize: RegisterClass for message window class failed with %d."),
GetLastError()));
return E_FAIL;
}
}
m_hMsgWindow = CreateWindow (TEXT("GPMessageWindowClass"), TEXT("GP Hidden Message Window"),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 0, 0, NULL, NULL, NULL,
(LPVOID) this);
if (!m_hMsgWindow)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::Initialize: CreateWindow failed with %d."),
GetLastError()));
return E_FAIL;
}
//
// Load the user's options
//
if (RegOpenKeyEx (HKEY_CURRENT_USER, GPE_POLICIES_KEY, 0,
KEY_READ, &hKey) == ERROR_SUCCESS)
{
dwSize = sizeof(m_dwPolicyOnlyPolicy);
RegQueryValueEx (hKey, POLICYONLY_VALUE, NULL, &dwType,
(LPBYTE) &m_dwPolicyOnlyPolicy, &dwSize);
RegCloseKey (hKey);
}
if (m_dwPolicyOnlyPolicy == 0)
{
m_bPolicyOnly = FALSE;
}
else if (m_dwPolicyOnlyPolicy == 1)
{
m_bPolicyOnly = TRUE;
}
return S_OK;
}
STDMETHODIMP CPolicySnapIn::Destroy(MMC_COOKIE cookie)
{
DestroyWindow (m_hMsgWindow);
if (m_pConsole != NULL)
{
m_pConsole->SetHeader(NULL);
m_pConsole->Release();
m_pConsole = NULL;
}
if (m_pHeader != NULL)
{
m_pHeader->Release();
m_pHeader = NULL;
}
if (m_pResult != NULL)
{
m_pResult->Release();
m_pResult = NULL;
}
if (m_pConsoleVerb != NULL)
{
m_pConsoleVerb->Release();
m_pConsoleVerb = NULL;
}
if (m_pDisplayHelp != NULL)
{
m_pDisplayHelp->Release();
m_pDisplayHelp = NULL;
}
return S_OK;
}
STDMETHODIMP CPolicySnapIn::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
{
HRESULT hr = S_OK;
switch(event)
{
case MMCN_COLUMNS_CHANGED:
hr = S_OK;
break;
case MMCN_DBLCLICK:
hr = S_FALSE;
break;
case MMCN_ADD_IMAGES:
HBITMAP hbmp16x16;
HBITMAP hbmp32x32;
hbmp16x16 = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_16x16));
if (hbmp16x16)
{
hbmp32x32 = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_32x32));
if (hbmp32x32)
{
LPIMAGELIST pImageList = (LPIMAGELIST) arg;
// Set the images
pImageList->ImageListSetStrip(reinterpret_cast<LONG_PTR *>(hbmp16x16),
reinterpret_cast<LONG_PTR *>(hbmp32x32),
0, RGB(255, 0, 255));
DeleteObject(hbmp32x32);
}
DeleteObject(hbmp16x16);
}
break;
case MMCN_SHOW:
if (arg == TRUE)
{
RESULTDATAITEM resultItem;
LPPOLICYDATAOBJECT pPolicyDataObject;
TABLEENTRY * pNode, *pTemp = NULL;
MMC_COOKIE cookie;
INT i, iState;
BOOL bAdd;
//
// Get the cookie of the scope pane item
//
hr = lpDataObject->QueryInterface(IID_IPolicyDataObject, (LPVOID *)&pPolicyDataObject);
if (FAILED(hr))
return S_OK;
hr = pPolicyDataObject->GetCookie(&cookie);
pPolicyDataObject->Release(); // release initial ref
if (FAILED(hr))
return S_OK;
pNode = (TABLEENTRY *)cookie;
if (pNode)
{
pTemp = pNode->pChild;
}
//
// Prepare the view
//
m_pHeader->InsertColumn(0, m_pSetting, LVCFMT_LEFT, m_nColumn1Size);
m_pHeader->InsertColumn(1, m_pState, LVCFMT_CENTER, m_nColumn2Size);
if (m_pcd->m_bRSOP)
{
m_pHeader->InsertColumn(2, m_pGPOName, LVCFMT_CENTER, m_nColumn3Size);
}
m_pResult->SetViewMode(m_lViewMode);
//
// Add the Policies
//
while (pTemp)
{
if (pTemp->dwType == ETYPE_POLICY)
{
bAdd = TRUE;
if (m_pcd->m_bUseSupportedOnFilter)
{
bAdd = m_pcd->CheckSupportedFilter((POLICY *)pTemp);
}
if (bAdd && m_pcd->m_bShowConfigPoliciesOnly)
{
iState = GetPolicyState(pTemp, 1, NULL);
if (iState == -1)
{
bAdd = FALSE;
}
}
if (bAdd && m_bPolicyOnly)
{
if (((POLICY *) pTemp)->bTruePolicy != TRUE)
{
bAdd = FALSE;
}
}
if (bAdd)
{
resultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
resultItem.str = MMC_CALLBACK;
if (((POLICY *) pTemp)->bTruePolicy)
{
resultItem.nImage = 4;
}
else
{
resultItem.nImage = 5;
}
resultItem.nCol = 0;
resultItem.lParam = (LPARAM) pTemp;
if (SUCCEEDED(m_pResult->InsertItem(&resultItem)))
{
resultItem.mask = RDI_STR;
resultItem.str = MMC_CALLBACK;
resultItem.bScopeItem = FALSE;
resultItem.nCol = 1;
m_pResult->SetItem(&resultItem);
}
}
}
else if (pTemp->dwType == ETYPE_REGITEM)
{
bAdd = TRUE;
if (m_bPolicyOnly)
{
if (((REGITEM *) pTemp)->bTruePolicy != TRUE)
{
bAdd = FALSE;
}
}
if (((REGITEM *) pTemp)->lpItem->bFoundInADM == TRUE)
{
bAdd = FALSE;
}
if (bAdd)
{
resultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
resultItem.str = MMC_CALLBACK;
if (((REGITEM *) pTemp)->bTruePolicy)
{
resultItem.nImage = 4;
}
else
{
resultItem.nImage = 5;
}
resultItem.nCol = 0;
resultItem.lParam = (LPARAM) pTemp;
if (SUCCEEDED(m_pResult->InsertItem(&resultItem)))
{
resultItem.mask = RDI_STR;
resultItem.str = MMC_CALLBACK;
resultItem.bScopeItem = FALSE;
resultItem.nCol = 1;
m_pResult->SetItem(&resultItem);
}
}
}
pTemp = pTemp->pNext;
}
}
else
{
m_pHeader->GetColumnWidth(0, &m_nColumn1Size);
m_pHeader->GetColumnWidth(1, &m_nColumn2Size);
if (m_pcd->m_bRSOP)
{
m_pHeader->GetColumnWidth(2, &m_nColumn3Size);
}
m_pResult->GetViewMode(&m_lViewMode);
}
break;
case MMCN_SELECT:
{
LPPOLICYDATAOBJECT pPolicyDataObject;
DATA_OBJECT_TYPES type;
MMC_COOKIE cookie;
POLICY * pPolicy;
//
// See if this is one of our items.
//
hr = lpDataObject->QueryInterface(IID_IPolicyDataObject, (LPVOID *)&pPolicyDataObject);
if (FAILED(hr))
break;
pPolicyDataObject->GetType(&type);
pPolicyDataObject->GetCookie(&cookie);
pPolicyDataObject->Release();
if (m_pConsoleVerb)
{
//
// Set the default verb to open
//
m_pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN);
//
// If this is a result pane item or the root of the namespace
// nodes, enable the Properties menu item
//
if (type == CCT_RESULT)
{
if (HIWORD(arg))
{
m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
m_pConsoleVerb->SetDefaultVerb(MMC_VERB_PROPERTIES);
}
}
}
if (m_hPropDlg && (type == CCT_RESULT) && HIWORD(arg))
{
pPolicy = (POLICY *)cookie;
if (pPolicy->dwType & ETYPE_POLICY)
{
m_pCurrentPolicy = pPolicy;
SendMessage (GetParent(m_hPropDlg), PSM_QUERYSIBLINGS, 1000, 0);
}
}
}
break;
case MMCN_CONTEXTHELP:
{
if (m_pDisplayHelp)
{
LPPOLICYDATAOBJECT pPolicyDataObject;
DATA_OBJECT_TYPES type;
MMC_COOKIE cookie;
LPOLESTR pszHelpTopic;
//
// See if this is one of our items.
//
hr = lpDataObject->QueryInterface(IID_IPolicyDataObject, (LPVOID *)&pPolicyDataObject);
if (FAILED(hr))
break;
pPolicyDataObject->Release();
//
// Display the admin templates help page
//
DWORD dwHlpLen = 50;
pszHelpTopic = (LPOLESTR) CoTaskMemAlloc (dwHlpLen * sizeof(WCHAR));
if (pszHelpTopic)
{
hr = StringCchCopy (pszHelpTopic, dwHlpLen, TEXT("gpedit.chm::/adm.htm"));
ASSERT(SUCCEEDED(hr));
m_pDisplayHelp->ShowTopic (pszHelpTopic);
}
}
}
break;
default:
hr = E_UNEXPECTED;
break;
}
return hr;
}
STDMETHODIMP CPolicySnapIn::GetDisplayInfo(LPRESULTDATAITEM pResult)
{
if (pResult)
{
if (pResult->bScopeItem == TRUE)
{
if (pResult->mask & RDI_STR)
{
if (pResult->nCol == 0)
{
if (pResult->lParam == 0)
{
pResult->str = m_pcd->m_szRootName;
}
else
{
TABLEENTRY * pTableEntry;
pTableEntry = (TABLEENTRY *)(pResult->lParam);
pResult->str = GETNAMEPTR(pTableEntry);
}
}
else
{
pResult->str = L"";
}
}
if (pResult->mask & RDI_IMAGE)
{
pResult->nImage = 0;
}
}
else
{
if (pResult->mask & RDI_STR)
{
TABLEENTRY * pTableEntry;
INT iState;
LPTSTR lpGPOName = NULL;
pTableEntry = (TABLEENTRY *)(pResult->lParam);
if (pTableEntry->dwType & ETYPE_REGITEM)
{
REGITEM *pItem = (REGITEM*)pTableEntry;
if (pResult->nCol == 0)
{
pResult->str = GETNAMEPTR(pTableEntry);
if (pResult->str == NULL)
{
pResult->str = (LPOLESTR)L"";
}
}
else if (pResult->nCol == 1)
{
pResult->str = GETVALUESTRPTR(pItem);
}
else if (pResult->nCol == 2)
{
pResult->str = pItem->lpItem->lpGPOName;
}
}
else
{
iState = GetPolicyState (pTableEntry, 1, &lpGPOName);
if (pResult->nCol == 0)
{
pResult->str = GETNAMEPTR(pTableEntry);
if (pResult->str == NULL)
{
pResult->str = (LPOLESTR)L"";
}
}
else if (pResult->nCol == 1)
{
if (iState == 1)
{
pResult->str = m_pEnabled;
}
else if (iState == 0)
{
pResult->str = m_pDisabled;
}
else
{
pResult->str = m_pNotConfigured;
}
}
else if (pResult->nCol == 2)
{
pResult->str = lpGPOName;
}
}
}
}
}
return S_OK;
}
STDMETHODIMP CPolicySnapIn::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT *ppDataObject)
{
return m_pcd->QueryDataObject(cookie, type, ppDataObject);
}
STDMETHODIMP CPolicySnapIn::GetResultViewType(MMC_COOKIE cookie, LPOLESTR *ppViewType,
long *pViewOptions)
{
return S_FALSE;
}
STDMETHODIMP CPolicySnapIn::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
{
HRESULT hr = S_FALSE;
LPPOLICYDATAOBJECT pPolicyDataObjectA, pPolicyDataObjectB;
MMC_COOKIE cookie1, cookie2;
if (lpDataObjectA == NULL || lpDataObjectB == NULL)
return E_POINTER;
//
// QI for the private GPTDataObject interface
//
if (FAILED(lpDataObjectA->QueryInterface(IID_IPolicyDataObject,
(LPVOID *)&pPolicyDataObjectA)))
{
return S_FALSE;
}
if (FAILED(lpDataObjectB->QueryInterface(IID_IPolicyDataObject,
(LPVOID *)&pPolicyDataObjectB)))
{
pPolicyDataObjectA->Release();
return S_FALSE;
}
pPolicyDataObjectA->GetCookie(&cookie1);
pPolicyDataObjectB->GetCookie(&cookie2);
if (cookie1 == cookie2)
{
hr = S_OK;
}
pPolicyDataObjectA->Release();
pPolicyDataObjectB->Release();
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicySnapIn:: object implementation (IExtendContextMenu) //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPolicySnapIn::AddMenuItems(LPDATAOBJECT piDataObject,
LPCONTEXTMENUCALLBACK pCallback,
LONG *pInsertionAllowed)
{
HRESULT hr = S_OK;
TCHAR szMenuItem[100];
TCHAR szDescription[250];
CONTEXTMENUITEM item;
LPPOLICYDATAOBJECT pPolicyDataObject;
DATA_OBJECT_TYPES type = CCT_UNINITIALIZED;
MMC_COOKIE cookie;
POLICY *pPolicy;
if (SUCCEEDED(piDataObject->QueryInterface(IID_IPolicyDataObject,
(LPVOID *)&pPolicyDataObject)))
{
pPolicyDataObject->GetType(&type);
pPolicyDataObject->GetCookie(&cookie);
pPolicyDataObject->Release();
}
if (type == CCT_SCOPE)
{
pPolicy = (POLICY *)cookie;
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW)
{
if (!m_pcd->m_bRSOP)
{
LoadString (g_hInstance, IDS_FILTERING, szMenuItem, 100);
LoadString (g_hInstance, IDS_FILTERINGDESC, szDescription, 250);
item.strName = szMenuItem;
item.strStatusBarText = szDescription;
item.lCommandID = IDM_FILTERING;
item.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_VIEW;
item.fFlags = 0;
item.fSpecialFlags = 0;
hr = pCallback->AddItem(&item);
}
}
}
return (hr);
}
STDMETHODIMP CPolicySnapIn::Command(LONG lCommandID, LPDATAOBJECT piDataObject)
{
if (lCommandID == IDM_FILTERING)
{
if (DialogBoxParam(g_hInstance,MAKEINTRESOURCE(IDD_POLICY_FILTERING),
m_pcd->m_hwndFrame, FilterDlgProc,(LPARAM) this))
{
//
// Refresh the display
//
m_pcd->m_pScope->DeleteItem (m_pcd->m_hSWPolicies, FALSE);
m_pcd->EnumerateScopePane (NULL, m_pcd->m_hSWPolicies);
}
}
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicySnapIn object implementation (IExtendPropertySheet) //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPolicySnapIn::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
LONG_PTR handle, LPDATAOBJECT lpDataObject)
{
HRESULT hr;
PROPSHEETPAGE psp;
HPROPSHEETPAGE hPage[3];
LPPOLICYDATAOBJECT pPolicyDataObject;
MMC_COOKIE cookie;
LPSETTINGSINFO lpSettingsInfo;
//
// Make sure this is one of our objects
//
if (FAILED(lpDataObject->QueryInterface(IID_IPolicyDataObject,
(LPVOID *)&pPolicyDataObject)))
{
return S_OK;
}
//
// Get the cookie
//
pPolicyDataObject->GetCookie(&cookie);
pPolicyDataObject->Release();
m_pCurrentPolicy = (POLICY *)cookie;
//
// Allocate a settings info structure
//
lpSettingsInfo = (LPSETTINGSINFO) LocalAlloc(LPTR, sizeof(SETTINGSINFO));
if (!lpSettingsInfo)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::CreatePropertyPages: Failed to allocate memory with %d."),
GetLastError()));
return S_OK;
}
lpSettingsInfo->pCS = this;
//
// Allocate a POLICYDLGINFO structure
//
lpSettingsInfo->pdi = (POLICYDLGINFO *) LocalAlloc(LPTR,sizeof(POLICYDLGINFO));
if (!lpSettingsInfo->pdi)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::CreatePropertyPages: Failed to allocate memory with %d."),
GetLastError()));
LocalFree (lpSettingsInfo);
return S_OK;
}
//
// Initialize POLICYDLGINFO
//
lpSettingsInfo->pdi->dwControlTableSize = DEF_CONTROLS * sizeof(POLICYCTRLINFO);
lpSettingsInfo->pdi->nControls = 0;
lpSettingsInfo->pdi->pEntryRoot = (lpSettingsInfo->pCS->m_pcd->m_bUserScope ?
lpSettingsInfo->pCS->m_pcd->m_pUserCategoryList :
lpSettingsInfo->pCS->m_pcd->m_pMachineCategoryList);
lpSettingsInfo->pdi->hwndApp = lpSettingsInfo->pCS->m_pcd->m_hwndFrame;
lpSettingsInfo->pdi->pControlTable = (POLICYCTRLINFO *) LocalAlloc(LPTR,
lpSettingsInfo->pdi->dwControlTableSize);
if (!lpSettingsInfo->pdi->pControlTable) {
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::CreatePropertyPages: Failed to allocate memory with %d."),
GetLastError()));
LocalFree (lpSettingsInfo->pdi);
LocalFree (lpSettingsInfo);
return S_OK;
}
//
// Initialize the common fields in the property sheet structure
//
psp.dwSize = sizeof(PROPSHEETPAGE);
psp.dwFlags = 0;
psp.hInstance = g_hInstance;
psp.lParam = (LPARAM) lpSettingsInfo;
//
// Add the pages
//
if (m_pCurrentPolicy->dwType & ETYPE_REGITEM)
{
psp.pszTemplate = MAKEINTRESOURCE(IDD_POLICY_PRECEDENCE);
psp.pfnDlgProc = PolicyPrecedenceDlgProc;
hPage[0] = CreatePropertySheetPage(&psp);
if (hPage[0])
{
hr = lpProvider->AddPage(hPage[0]);
}
}
else
{
psp.pszTemplate = MAKEINTRESOURCE(IDD_POLICY);
psp.pfnDlgProc = PolicyDlgProc;
hPage[0] = CreatePropertySheetPage(&psp);
if (hPage[0])
{
hr = lpProvider->AddPage(hPage[0]);
psp.pszTemplate = MAKEINTRESOURCE(IDD_POLICY_HELP);
psp.pfnDlgProc = PolicyHelpDlgProc;
hPage[1] = CreatePropertySheetPage(&psp);
if (hPage[1])
{
hr = lpProvider->AddPage(hPage[1]);
if (m_pcd->m_bRSOP)
{
psp.pszTemplate = MAKEINTRESOURCE(IDD_POLICY_PRECEDENCE);
psp.pfnDlgProc = PolicyPrecedenceDlgProc;
hPage[2] = CreatePropertySheetPage(&psp);
if (hPage[2])
{
hr = lpProvider->AddPage(hPage[2]);
}
}
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::CreatePropertyPages: Failed to create property sheet page with %d."),
GetLastError()));
hr = E_FAIL;
}
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::CreatePropertyPages: Failed to create property sheet page with %d."),
GetLastError()));
hr = E_FAIL;
}
}
return (hr);
}
STDMETHODIMP CPolicySnapIn::QueryPagesFor(LPDATAOBJECT lpDataObject)
{
LPPOLICYDATAOBJECT pPolicyDataObject;
DATA_OBJECT_TYPES type;
if (SUCCEEDED(lpDataObject->QueryInterface(IID_IPolicyDataObject,
(LPVOID *)&pPolicyDataObject)))
{
pPolicyDataObject->GetType(&type);
pPolicyDataObject->Release();
if (type == CCT_RESULT)
{
if (!m_hPropDlg)
return S_OK;
// There's already a propety sheet open so we'll bring it to the front.
BringWindowToTop(GetParent(m_hPropDlg));
}
}
return S_FALSE;
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicySnapIn object implementation (Internal functions) //
// //
///////////////////////////////////////////////////////////////////////////////
BOOL CPolicySnapIn::IsAnyPolicyEnabled(TABLEENTRY * pCategory)
{
TABLEENTRY * pEntry;
INT iState;
if (!pCategory || !pCategory->pChild)
{
return FALSE;
}
pEntry = pCategory->pChild;
while (pEntry)
{
if (pEntry->dwType & ETYPE_CATEGORY)
{
if (IsAnyPolicyEnabled(pEntry))
{
return TRUE;
}
}
else if (pEntry->dwType & ETYPE_POLICY)
{
iState = GetPolicyState(pEntry, 1, NULL);
if ((iState == 1) || (iState == 0))
{
return TRUE;
}
}
pEntry = pEntry->pNext;
}
return FALSE;
}
VOID CPolicySnapIn::RefreshSettingsControls(HWND hDlg)
{
BOOL fEnabled = FALSE;
INT iState;
LPTSTR lpSupported;
POLICY *pPolicy = (POLICY *)m_pCurrentPolicy;
FreeSettingsControls(hDlg);
SetDlgItemText (hDlg, IDC_POLICY, GETNAMEPTR(m_pCurrentPolicy));
if (pPolicy->bTruePolicy)
{
SendMessage (GetDlgItem(hDlg, IDC_POLICYICON), STM_SETIMAGE, IMAGE_ICON,
(LPARAM) (HANDLE) m_hPolicyIcon);
}
else
{
SendMessage (GetDlgItem(hDlg, IDC_POLICYICON), STM_SETIMAGE, IMAGE_ICON,
(LPARAM) (HANDLE) m_hPreferenceIcon);
}
lpSupported = GETSUPPORTEDPTR(pPolicy);
if (lpSupported)
{
ShowWindow (GetDlgItem(hDlg, IDC_SUPPORTEDTITLE), SW_SHOW);
ShowWindow (GetDlgItem(hDlg, IDC_SUPPORTED), SW_SHOW);
SetDlgItemText (hDlg, IDC_SUPPORTED, lpSupported);
}
else
{
SetDlgItemText (hDlg, IDC_SUPPORTED, TEXT(""));
ShowWindow (GetDlgItem(hDlg, IDC_SUPPORTEDTITLE), SW_HIDE);
ShowWindow (GetDlgItem(hDlg, IDC_SUPPORTED), SW_HIDE);
}
iState = GetPolicyState((TABLEENTRY *)m_pCurrentPolicy, 1, NULL);
if (iState == 1)
{
CheckRadioButton(hDlg, IDC_NOCONFIG, IDC_DISABLED, IDC_ENABLED);
fEnabled = TRUE;
}
else if (iState == 0)
{
CheckRadioButton(hDlg, IDC_NOCONFIG, IDC_DISABLED, IDC_DISABLED);
}
else
{
CheckRadioButton(hDlg, IDC_NOCONFIG, IDC_DISABLED, IDC_NOCONFIG);
}
if (m_pcd->m_bRSOP)
{
EnableWindow (GetDlgItem(hDlg, IDC_ENABLED), FALSE);
EnableWindow (GetDlgItem(hDlg, IDC_DISABLED), FALSE);
EnableWindow (GetDlgItem(hDlg, IDC_NOCONFIG), FALSE);
}
if (m_pCurrentPolicy->pChild) {
CreateSettingsControls(hDlg, (SETTINGS *) m_pCurrentPolicy->pChild, fEnabled);
InitializeSettingsControls(hDlg, fEnabled);
} else {
ShowScrollBar(GetDlgItem(hDlg,IDC_POLICY_SETTINGS),SB_BOTH, FALSE);
}
m_bDirty = FALSE;
PostMessage (GetParent(hDlg), PSM_UNCHANGED, (WPARAM) hDlg, 0);
SetPrevNextButtonState(hDlg);
}
HRESULT CPolicySnapIn::UpdateItemWorker (VOID)
{
HRESULTITEM hItem;
//
// Update the display
//
if (SUCCEEDED(m_pResult->FindItemByLParam((LPARAM)m_pCurrentPolicy, &hItem)))
{
if (m_pcd->m_bShowConfigPoliciesOnly)
m_pResult->DeleteItem(hItem, 0);
else
m_pResult->UpdateItem(hItem);
}
return S_OK;
}
HRESULT CPolicySnapIn::MoveFocusWorker (BOOL bPrevious)
{
HRESULTITEM hItem;
TABLEENTRY * pTemp;
HRESULT hr;
RESULTDATAITEM item;
INT iIndex = 0;
//
// Find the currently selected item's index
//
while (TRUE)
{
ZeroMemory (&item, sizeof(item));
item.mask = RDI_INDEX | RDI_PARAM;
item.nIndex = iIndex;
hr = m_pResult->GetItem (&item);
if (FAILED(hr))
{
return hr;
}
if (item.lParam == (LPARAM) m_pCurrentPolicy)
{
break;
}
iIndex++;
}
//
// Find the currently selected item's hItem
//
hr = m_pResult->FindItemByLParam((LPARAM)m_pCurrentPolicy, &hItem);
if (FAILED(hr))
{
return hr;
}
//
// Remove the focus from the original item
//
m_pResult->ModifyItemState(0, hItem, 0, LVIS_FOCUSED | LVIS_SELECTED);
m_pResult->UpdateItem(hItem);
//
// Adjust appropriately
//
if (bPrevious)
{
if (iIndex > 0)
{
iIndex--;
}
}
else
{
iIndex++;
}
//
// Get the lParam for the new item
//
ZeroMemory (&item, sizeof(item));
item.mask = RDI_INDEX | RDI_PARAM;
item.nIndex = iIndex;
hr = m_pResult->GetItem(&item);
if (FAILED(hr))
{
return hr;
}
//
// Find the hItem for the new item
//
hr = m_pResult->FindItemByLParam(item.lParam, &hItem);
if (FAILED(hr))
{
return hr;
}
//
// Save this as the currently selected item
//
m_pCurrentPolicy = (POLICY *)item.lParam;
//
// Set the focus on the new item
//
m_pResult->ModifyItemState(0, hItem, LVIS_FOCUSED | LVIS_SELECTED, 0);
m_pResult->UpdateItem(hItem);
return S_OK;
}
HRESULT CPolicySnapIn::MoveFocus (HWND hDlg, BOOL bPrevious)
{
//
// Send the move focus message to the hidden window on the main
// thread so it can use the mmc interfaces
//
SendMessage (m_hMsgWindow, WM_MOVEFOCUS, (WPARAM) bPrevious, 0);
//
// Update the display
//
SendMessage (GetParent(hDlg), PSM_QUERYSIBLINGS, 1000, 0);
return S_OK;
}
HRESULT CPolicySnapIn::SetPrevNextButtonStateWorker (HWND hDlg)
{
TABLEENTRY * pTemp;
HRESULT hr;
RESULTDATAITEM item;
INT iIndex = 0;
BOOL bPrev = FALSE, bNext = FALSE, bFound = FALSE;
//
// Loop through the items looking for Policies
//
while (TRUE)
{
ZeroMemory (&item, sizeof(item));
item.mask = RDI_INDEX | RDI_PARAM;
item.nIndex = iIndex;
hr = m_pResult->GetItem (&item);
if (FAILED(hr))
{
break;
}
if (item.lParam == (LPARAM) m_pCurrentPolicy)
{
bFound = TRUE;
}
else
{
pTemp = (TABLEENTRY *) item.lParam;
if ((pTemp->dwType & ETYPE_POLICY) || (pTemp->dwType & ETYPE_REGITEM))
{
if ((m_pcd->m_bShowConfigPoliciesOnly) && (pTemp->dwType & ETYPE_POLICY))
{
INT iState;
iState = GetPolicyState(pTemp, 1, NULL);
if ((iState == 1) || (iState == 0))
{
if (bFound)
{
bNext = TRUE;
}
else
{
bPrev = TRUE;
}
}
}
else
{
if (bFound)
{
bNext = TRUE;
}
else
{
bPrev = TRUE;
}
}
}
}
iIndex++;
}
if (!bNext && (GetFocus() == GetDlgItem(hDlg,IDC_POLICY_NEXT)))
{
SetFocus (GetNextDlgTabItem(hDlg, GetDlgItem(hDlg,IDC_POLICY_NEXT), TRUE));
}
EnableWindow (GetDlgItem(hDlg,IDC_POLICY_NEXT), bNext);
if (!bPrev && (GetFocus() == GetDlgItem(hDlg,IDC_POLICY_PREVIOUS)))
{
SetFocus (GetNextDlgTabItem(hDlg, GetDlgItem(hDlg,IDC_POLICY_PREVIOUS), FALSE));
}
EnableWindow (GetDlgItem(hDlg,IDC_POLICY_PREVIOUS), bPrev);
return S_OK;
}
HRESULT CPolicySnapIn::SetPrevNextButtonState (HWND hDlg)
{
//
// Send the SetPrevNext message to the hidden window on the main
// thread so it can use the mmc interfaces
//
SendMessage (m_hMsgWindow, WM_SETPREVNEXT, (WPARAM) hDlg, 0);
return S_OK;
}
INT_PTR CALLBACK CPolicySnapIn::PolicyDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
LPSETTINGSINFO lpSettingsInfo;
switch (message)
{
case WM_INITDIALOG:
lpSettingsInfo = (LPSETTINGSINFO) (((LPPROPSHEETPAGE)lParam)->lParam);
if (!lpSettingsInfo) {
break;
}
SetWindowLongPtr (hDlg, DWLP_USER, (LONG_PTR) lpSettingsInfo);
lpSettingsInfo->pCS->m_hPropDlg = hDlg;
lpSettingsInfo->pdi->fActive=TRUE;
lpSettingsInfo->pCS->m_hPolicyIcon = (HICON) LoadImage (g_hInstance,
MAKEINTRESOURCE(IDI_POLICY2),
IMAGE_ICON, 16, 16,
LR_DEFAULTCOLOR);
lpSettingsInfo->pCS->m_hPreferenceIcon = (HICON) LoadImage (g_hInstance,
MAKEINTRESOURCE(IDI_POLICY3),
IMAGE_ICON, 16, 16,
LR_DEFAULTCOLOR);
// now that we've stored pointer to POLICYDLGINFO struct in our extra
// window data, send WM_USER to clip window to tell it to create a
// child container window (and store the handle in our POLICYDLGINFO)
SendDlgItemMessage(hDlg,IDC_POLICY_SETTINGS,WM_USER,0,0L);
lpSettingsInfo->pCS->RefreshSettingsControls(hDlg);
lpSettingsInfo->pCS->SetKeyboardHook(hDlg);
break;
case WM_MYCHANGENOTIFY:
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr (hDlg, DWLP_USER);
if (lpSettingsInfo) {
lpSettingsInfo->pCS->m_bDirty = TRUE;
SendMessage (GetParent(hDlg), PSM_CHANGED, (WPARAM) hDlg, 0);
}
break;
case PSM_QUERYSIBLINGS:
if (wParam == 1000) {
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr (hDlg, DWLP_USER);
if (!lpSettingsInfo) {
break;
}
lpSettingsInfo->pCS->RefreshSettingsControls(hDlg);
SendMessage (GetParent(hDlg), PSM_SETTITLE, PSH_PROPTITLE,
(LPARAM)GETNAMEPTR(lpSettingsInfo->pCS->m_pCurrentPolicy));
}
break;
case WM_COMMAND:
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr (hDlg, DWLP_USER);
if (!lpSettingsInfo) {
break;
}
if ((LOWORD (wParam) == IDC_NOCONFIG) && (HIWORD (wParam) == BN_CLICKED))
{
lpSettingsInfo->pCS->InitializeSettingsControls(hDlg, FALSE);
PostMessage (hDlg, WM_MYCHANGENOTIFY, 0, 0);
}
if ((LOWORD (wParam) == IDC_ENABLED) && (HIWORD (wParam) == BN_CLICKED))
{
lpSettingsInfo->pCS->InitializeSettingsControls(hDlg, TRUE);
PostMessage (hDlg, WM_MYCHANGENOTIFY, 0, 0);
}
if ((LOWORD (wParam) == IDC_DISABLED) && (HIWORD (wParam) == BN_CLICKED))
{
lpSettingsInfo->pCS->InitializeSettingsControls(hDlg, FALSE);
PostMessage (hDlg, WM_MYCHANGENOTIFY, 0, 0);
}
if (LOWORD(wParam) == IDC_POLICY_NEXT)
{
if (SUCCEEDED(lpSettingsInfo->pCS->SaveSettings(hDlg)))
{
lpSettingsInfo->pCS->MoveFocus (hDlg, FALSE);
}
}
if (LOWORD(wParam) == IDC_POLICY_PREVIOUS)
{
if (SUCCEEDED(lpSettingsInfo->pCS->SaveSettings(hDlg)))
{
lpSettingsInfo->pCS->MoveFocus (hDlg, TRUE);
}
}
break;
case WM_NOTIFY:
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr (hDlg, DWLP_USER);
if (!lpSettingsInfo) {
break;
}
switch (((NMHDR FAR*)lParam)->code)
{
case PSN_APPLY:
{
LPPSHNOTIFY lpNotify = (LPPSHNOTIFY) lParam;
if (FAILED(lpSettingsInfo->pCS->SaveSettings(hDlg)))
{
SetWindowLongPtr (hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
return TRUE;
}
if (lpNotify->lParam)
{
lpSettingsInfo->pCS->RemoveKeyboardHook();
lpSettingsInfo->pCS->m_hPropDlg = NULL;
lpSettingsInfo->pCS->FreeSettingsControls(hDlg);
DestroyIcon(lpSettingsInfo->pCS->m_hPolicyIcon);
lpSettingsInfo->pCS->m_hPolicyIcon = NULL;
DestroyIcon(lpSettingsInfo->pCS->m_hPreferenceIcon);
lpSettingsInfo->pCS->m_hPreferenceIcon = NULL;
LocalFree (lpSettingsInfo->pdi->pControlTable);
LocalFree (lpSettingsInfo->pdi);
LocalFree (lpSettingsInfo);
SetWindowLongPtr (hDlg, DWLP_USER, (LONG_PTR) NULL);
}
SetWindowLongPtr (hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
return TRUE;
}
case PSN_RESET:
lpSettingsInfo->pCS->RemoveKeyboardHook();
lpSettingsInfo->pCS->m_hPropDlg = NULL;
SetWindowLongPtr (hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
return TRUE;
}
break;
case WM_HELP: // F1
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
(DWORD_PTR) (LPDWORD) aPolicyHelpIds);
return TRUE;
case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
(DWORD_PTR) (LPDWORD) aPolicyHelpIds);
return TRUE;
}
return FALSE;
}
INT_PTR CALLBACK CPolicySnapIn::PolicyHelpDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
LPSETTINGSINFO lpSettingsInfo;
switch (message)
{
case WM_INITDIALOG:
lpSettingsInfo = (LPSETTINGSINFO) (((LPPROPSHEETPAGE)lParam)->lParam);
if (!lpSettingsInfo) {
break;
}
SetWindowLongPtr (hDlg, DWLP_USER, (LONG_PTR) lpSettingsInfo);
wParam = 1000;
// fall through...
case PSM_QUERYSIBLINGS:
{
CPolicySnapIn * pCS;
LPTSTR lpHelpText;
if (wParam == 1000)
{
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr (hDlg, DWLP_USER);
if (!lpSettingsInfo) {
break;
}
pCS = lpSettingsInfo->pCS;
SetDlgItemText (hDlg, IDC_POLICY_TITLE, GETNAMEPTR(pCS->m_pCurrentPolicy));
if (pCS->m_pCurrentPolicy->uOffsetHelp)
{
lpHelpText = (LPTSTR) ((BYTE *) pCS->m_pCurrentPolicy + pCS->m_pCurrentPolicy->uOffsetHelp);
SetDlgItemText (hDlg, IDC_POLICY_HELP, lpHelpText);
}
else
{
SetDlgItemText (hDlg, IDC_POLICY_HELP, TEXT(""));
}
pCS->SetPrevNextButtonState(hDlg);
}
PostMessage(hDlg, WM_MYREFRESH, 0, 0);
break;
}
case WM_MYREFRESH:
{
CPolicySnapIn * pCS;
BOOL bAlone;
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr (hDlg, DWLP_USER);
pCS = lpSettingsInfo->pCS;
SendMessage(GetDlgItem(hDlg, IDC_POLICY_HELP), EM_SETSEL, -1, 0);
bAlone = !(((pCS->m_pCurrentPolicy)->pNext) ||
((pCS->m_pCurrentPolicy)->pPrev) );
if (bAlone) {
SetFocus(GetDlgItem(GetParent(hDlg), IDOK));
}
break;
}
case WM_COMMAND:
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr (hDlg, DWLP_USER);
if (!lpSettingsInfo) {
break;
}
if (LOWORD(wParam) == IDC_POLICY_NEXT)
{
lpSettingsInfo->pCS->MoveFocus (hDlg, FALSE);
}
if (LOWORD(wParam) == IDC_POLICY_PREVIOUS)
{
lpSettingsInfo->pCS->MoveFocus (hDlg, TRUE);
}
if (LOWORD(wParam) == IDCANCEL)
{
SendMessage(GetParent(hDlg), message, wParam, lParam);
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR*)lParam)->code)
{
case PSN_APPLY:
case PSN_RESET:
SetWindowLongPtr (hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
return TRUE;
case PSN_SETACTIVE:
PostMessage(hDlg, WM_MYREFRESH, 0, 0);
break;
}
break;
case WM_HELP: // F1
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
(DWORD_PTR) (LPDWORD) aExplainHelpIds);
return TRUE;
case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
(DWORD_PTR) (LPDWORD) aExplainHelpIds);
return TRUE;
}
return FALSE;
}
INT_PTR CALLBACK CPolicySnapIn::PolicyPrecedenceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
LPSETTINGSINFO lpSettingsInfo;
HRESULT hr = S_OK;
switch (message)
{
case WM_INITDIALOG:
{
RECT rc;
TCHAR szHeaderName[50];
INT iTotal = 0, iCurrent;
HWND hLV = GetDlgItem (hDlg, IDC_POLICY_PRECEDENCE);
LV_COLUMN col;
lpSettingsInfo = (LPSETTINGSINFO) (((LPPROPSHEETPAGE)lParam)->lParam);
if (!lpSettingsInfo) {
break;
}
SetWindowLongPtr (hDlg, DWLP_USER, (LONG_PTR) lpSettingsInfo);
//
// Add the columns
//
GetClientRect (hLV, &rc);
LoadString(g_hInstance, IDS_GPONAME, szHeaderName, ARRAYSIZE(szHeaderName));
col.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
col.fmt = LVCFMT_LEFT;
iCurrent = (int)(rc.right * .70);
iTotal += iCurrent;
col.cx = iCurrent;
col.pszText = szHeaderName;
col.iSubItem = 0;
ListView_InsertColumn (hLV, 0, &col);
LoadString(g_hInstance, IDS_SETTING, szHeaderName, ARRAYSIZE(szHeaderName));
col.iSubItem = 1;
col.cx = rc.right - iTotal;
col.fmt = LVCFMT_CENTER;
ListView_InsertColumn (hLV, 1, &col);
//
// Set extended LV styles
//
SendMessage(hLV, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);
}
wParam = 1000;
// fall through...
case PSM_QUERYSIBLINGS:
{
CPolicySnapIn * pCS;
INT iState;
LPTSTR lpGPOName;
UINT uiPrecedence = 1;
LVITEM item;
INT iItem, iIndex = 0;
HWND hLV = GetDlgItem (hDlg, IDC_POLICY_PRECEDENCE);
if (wParam == 1000)
{
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr (hDlg, DWLP_USER);
if (!lpSettingsInfo) {
break;
}
pCS = lpSettingsInfo->pCS;
SetDlgItemText (hDlg, IDC_POLICY_TITLE, GETNAMEPTR(pCS->m_pCurrentPolicy));
SendMessage (hLV, LVM_DELETEALLITEMS, 0, 0);
if (pCS->m_pCurrentPolicy->dwType & ETYPE_REGITEM)
{
LPRSOPREGITEM pItem = ((REGITEM*)pCS->m_pCurrentPolicy)->lpItem;
LPRSOPREGITEM lpEnum;
TCHAR szValueStr[MAX_PATH];
while (TRUE)
{
lpEnum = NULL;
if (pCS->m_pcd->FindRSOPRegistryEntry((HKEY) LongToHandle(uiPrecedence), pItem->lpKeyName,
pItem->lpValueName, &lpEnum) != ERROR_SUCCESS)
{
break;
}
//
// Add the GPO Name
//
item.mask = LVIF_TEXT | LVIF_STATE;
item.iItem = iIndex;
item.iSubItem = 0;
item.state = 0;
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
item.pszText = lpEnum->lpGPOName;
iItem = (INT)SendMessage (hLV, LVM_INSERTITEM, 0, (LPARAM) &item);
if (iItem != -1)
{
szValueStr[0] = TEXT('\0');
if (pItem->dwType == REG_DWORD)
{
hr = StringCchPrintf (szValueStr, ARRAYSIZE(szValueStr), TEXT("%d"), *((LPDWORD)pItem->lpData));
ASSERT(SUCCEEDED(hr));
}
else if (pItem->dwType == REG_SZ)
{
lstrcpyn (szValueStr, (LPTSTR)pItem->lpData, ARRAYSIZE(szValueStr));
}
else if (pItem->dwType == REG_EXPAND_SZ)
{
lstrcpyn (szValueStr, (LPTSTR)pItem->lpData, ARRAYSIZE(szValueStr));
}
else if (pItem->dwType == REG_BINARY)
{
LoadString(g_hInstance, IDS_BINARYDATA, szValueStr, ARRAYSIZE(szValueStr));
}
else
{
LoadString(g_hInstance, IDS_UNKNOWNDATA, szValueStr, ARRAYSIZE(szValueStr));
}
//
// Add the state
//
item.mask = LVIF_TEXT;
item.iItem = iItem;
item.iSubItem = 1;
item.pszText = szValueStr;
SendMessage (hLV, LVM_SETITEMTEXT, iItem, (LPARAM) &item);
}
uiPrecedence++;
iIndex++;
}
}
else
{
while (TRUE)
{
lpGPOName = NULL; // just in case we have missed a case
iState = pCS->GetPolicyState ((TABLEENTRY *)pCS->m_pCurrentPolicy, uiPrecedence, &lpGPOName);
if (iState == -1)
{
uiPrecedence++;
iState = pCS->GetPolicyState ((TABLEENTRY *)pCS->m_pCurrentPolicy, uiPrecedence, &lpGPOName);
if (iState == -1)
{
break;
}
}
//
// Add the GPO Name
//
item.mask = LVIF_TEXT | LVIF_STATE;
item.iItem = iIndex;
item.iSubItem = 0;
item.state = 0;
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
item.pszText = lpGPOName ? lpGPOName : TEXT("");
iItem = (INT)SendMessage (hLV, LVM_INSERTITEM, 0, (LPARAM) &item);
if (iItem != -1)
{
//
// Add the state
//
item.mask = LVIF_TEXT;
item.iItem = iItem;
item.iSubItem = 1;
item.pszText = (iState == 1) ? pCS->m_pEnabled : pCS->m_pDisabled;
SendMessage (hLV, LVM_SETITEMTEXT, iItem, (LPARAM) &item);
}
uiPrecedence++;
iIndex++;
}
}
//
// Select the first item
//
item.mask = LVIF_STATE;
item.iItem = 0;
item.iSubItem = 0;
item.state = LVIS_SELECTED | LVIS_FOCUSED;
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
SendMessage (hLV, LVM_SETITEMSTATE, 0, (LPARAM) &item);
pCS->SetPrevNextButtonState(hDlg);
}
break;
}
case WM_COMMAND:
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr (hDlg, DWLP_USER);
if (!lpSettingsInfo) {
break;
}
if (LOWORD(wParam) == IDC_POLICY_NEXT)
{
lpSettingsInfo->pCS->MoveFocus (hDlg, FALSE);
}
if (LOWORD(wParam) == IDC_POLICY_PREVIOUS)
{
lpSettingsInfo->pCS->MoveFocus (hDlg, TRUE);
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR*)lParam)->code)
{
case PSN_APPLY:
case PSN_RESET:
SetWindowLongPtr (hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
return TRUE;
}
break;
case WM_HELP: // F1
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, RSOP_HELP_FILE, HELP_WM_HELP,
(DWORD_PTR) (LPDWORD) aPrecedenceHelpIds);
return TRUE;
case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND) wParam, RSOP_HELP_FILE, HELP_CONTEXTMENU,
(DWORD_PTR) (LPDWORD) aPrecedenceHelpIds);
return TRUE;
}
return FALSE;
}
LRESULT CPolicySnapIn::CallNextHook(int nCode, WPARAM wParam,LPARAM lParam)
{
if (m_hKbdHook)
{
return CallNextHookEx(
m_hKbdHook,
nCode,
wParam,
lParam);
}
else
{
DebugMsg((DM_WARNING, L"CPolicySnapIn::CallNextHook m_hKbdHook is Null"));
return 0;
}
}
HWND g_hDlgActive = NULL;
LRESULT CALLBACK CPolicySnapIn::KeyboardHookProc(int nCode, WPARAM wParam,LPARAM lParam)
{
LPSETTINGSINFO lpSettingsInfo;
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr(g_hDlgActive, DWLP_USER);
if (!lpSettingsInfo)
{
DebugMsg((DM_WARNING, L"CPolicySnapIn::KeyboardHookProc:GetWindowLongPtr returned NULL"));
return 0;
}
if ( nCode < 0)
{
if (lpSettingsInfo->pCS)
{
return lpSettingsInfo->pCS->CallNextHook(nCode,
wParam,
lParam);
}
else
{
DebugMsg((DM_WARNING, L"CPolicySnapIn::KeyboardHookProc NULL CPolicySnapIn Pointer"));
return 0;
}
}
if (wParam == VK_TAB && !(lParam & 0x80000000)) { // tab key depressed
BOOL fShift = (GetKeyState(VK_SHIFT) & 0x80000000);
HWND hwndFocus = GetFocus();
HWND hChild;
POLICYDLGINFO * pdi;
int iIndex;
int iDelta;
pdi = lpSettingsInfo->pdi;
if (!pdi)
{
if (lpSettingsInfo->pCS)
{
return lpSettingsInfo->pCS->CallNextHook(nCode,
wParam,
lParam);
}
else
{
DebugMsg((DM_WARNING, L"CPolicySnapIn::KeyboardHookProc NULL CPolicySnapIn Pointer"));
return 0;
}
}
// see if the focus control is one of the setting controls
for (iIndex=0;iIndex<(int)pdi->nControls;iIndex++) {
if (pdi->pControlTable[iIndex].hwnd == hwndFocus) {
goto BreakOut;
}
hChild = GetWindow (pdi->pControlTable[iIndex].hwnd, GW_CHILD);
while (hChild) {
if (hChild == hwndFocus) {
goto BreakOut;
}
hChild = GetWindow (hChild, GW_HWNDNEXT);
}
}
BreakOut:
if (iIndex == (int) pdi->nControls)
{
if (lpSettingsInfo->pCS)
{
return lpSettingsInfo->pCS->CallNextHook(nCode,
wParam,
lParam);
}
else // no, we don't care
{
DebugMsg((DM_WARNING, L"CPolicySnapIn::KeyboardHookProc NULL CPolicySnapIn Pointer"));
return 0;
}
}
iDelta = (fShift ? -1 : 1);
// from the current setting control, scan forwards or backwards
// (depending if on shift state, this can be TAB or shift-TAB)
// to find the next control to give focus to
for (iIndex += iDelta;iIndex>=0 && iIndex<(int) pdi->nControls;
iIndex += iDelta) {
if (pdi->pControlTable[iIndex].uDataIndex !=
NO_DATA_INDEX &&
IsWindowEnabled(pdi->pControlTable[iIndex].hwnd)) {
// found it, set the focus on that control and return 1
// to eat the keystroke
SetFocus(pdi->pControlTable[iIndex].hwnd);
lpSettingsInfo->pCS->EnsureSettingControlVisible(g_hDlgActive,
pdi->pControlTable[iIndex].hwnd);
return 1;
}
}
// at first or last control in settings table, let dlg code
// handle it and give focus to next (or previous) control in dialog
}
else
{
if (lpSettingsInfo->pCS)
{
return lpSettingsInfo->pCS->CallNextHook(nCode,
wParam,
lParam);
}
else
{
DebugMsg((DM_WARNING, L"CPolicySnapIn::KeyboardHookProc NULL CPolicySnapIn Pointer"));
return 0;
}
}
return 0;
}
VOID CPolicySnapIn::SetKeyboardHook(HWND hDlg)
{
// hook the keyboard to trap TABs. If this fails for some reason,
// fail silently and go on, not critical that tabs work correctly
// (unless you have no mouse :) )
if (m_hKbdHook = SetWindowsHookEx(WH_KEYBOARD,
KeyboardHookProc,
g_hInstance,
GetCurrentThreadId()))
{
g_hDlgActive = hDlg;
}
}
VOID CPolicySnapIn::RemoveKeyboardHook(VOID)
{
if (m_hKbdHook) {
UnhookWindowsHookEx(m_hKbdHook);
g_hDlgActive = NULL;
m_hKbdHook = NULL;
}
}
INT CPolicySnapIn::GetPolicyState (TABLEENTRY *pTableEntry, UINT uiPrecedence, LPTSTR *lpGPOName)
{
DWORD dwData=0;
UINT uRet;
TCHAR * pszValueName;
TCHAR * pszKeyName;
DWORD dwFoundSettings=0, dwTemp;
BOOL fFound=FALSE,fCustomOn=FALSE, fCustomOff=FALSE;
HKEY hKeyRoot;
INT iRetVal = -1;
TABLEENTRY *pChild;
if (m_pcd->m_bRSOP)
{
hKeyRoot = (HKEY) LongToHandle(uiPrecedence);
}
else
{
if (m_pcd->m_pGPTInformation->GetRegistryKey(
(m_pcd->m_bUserScope ? GPO_SECTION_USER : GPO_SECTION_MACHINE),
&hKeyRoot) != S_OK)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::GetPolicyState: Failed to get registry key handle.")));
return -1;
}
}
//
// Get the name of the value to read, if any
//
if (((POLICY *)pTableEntry)->uOffsetValueName)
{
pszKeyName = GETKEYNAMEPTR(pTableEntry);
pszValueName = GETVALUENAMEPTR(((POLICY *)pTableEntry));
//
// First look for custom on/off values
//
if (((POLICY *)pTableEntry)->uOffsetValue_On)
{
fCustomOn = TRUE;
if (CompareCustomValue(hKeyRoot,pszKeyName,pszValueName,
(STATEVALUE *) ((BYTE *) pTableEntry + ((POLICY *)
pTableEntry)->uOffsetValue_On),&dwFoundSettings,lpGPOName)) {
dwData = 1;
fFound =TRUE;
}
}
if (!fFound && ((POLICY *)pTableEntry)->uOffsetValue_Off)
{
fCustomOff = TRUE;
if (CompareCustomValue(hKeyRoot,pszKeyName,pszValueName,
(STATEVALUE *) ((BYTE *) pTableEntry + ((POLICY *)
pTableEntry)->uOffsetValue_Off),&dwFoundSettings,lpGPOName)) {
dwData = 0;
fFound = TRUE;
}
}
//
// Look for standard values if custom values have not been specified
//
if (!fCustomOn && !fCustomOff && ReadStandardValue(hKeyRoot, pszKeyName, pszValueName,
pTableEntry, &dwData, &dwFoundSettings, lpGPOName))
{
fFound = TRUE;
}
if (fFound)
{
if (dwData)
iRetVal = 1;
else
iRetVal = 0;
}
}
else if ((((POLICY *)pTableEntry)->uOffsetActionList_On) &&
CheckActionList((POLICY *)pTableEntry, hKeyRoot, TRUE, lpGPOName))
{
iRetVal = 1;
}
else if ((((POLICY *)pTableEntry)->uOffsetActionList_Off) &&
CheckActionList((POLICY *)pTableEntry, hKeyRoot, FALSE, lpGPOName))
{
iRetVal = 0;
}
else
{
BOOL bDisabled = TRUE;
//
// Process settings underneath this policy (if any)
//
if (pTableEntry->pChild) {
dwFoundSettings = 0;
pChild = pTableEntry->pChild;
while (pChild) {
dwTemp = 0;
LoadSettings(pChild, hKeyRoot, &dwTemp, lpGPOName);
dwFoundSettings |= dwTemp;
if ((dwTemp & FS_PRESENT) && (!(dwTemp & FS_DISABLED))) {
bDisabled = FALSE;
}
pChild = pChild->pNext;
}
if (dwFoundSettings) {
if (bDisabled)
iRetVal = 0;
else
iRetVal = 1;
}
}
}
if (!m_pcd->m_bRSOP)
{
RegCloseKey (hKeyRoot);
}
return iRetVal;
}
BOOL CPolicySnapIn::CheckActionList (POLICY * pPolicy, HKEY hKeyRoot, BOOL bActionListOn, LPTSTR *lpGPOName)
{
UINT uIndex;
ACTIONLIST * pActionList;
ACTION * pAction;
TCHAR szValue[MAXSTRLEN];
DWORD dwValue;
TCHAR szNewValueName[MAX_PATH+1];
TCHAR * pszKeyName;
TCHAR * pszValueName;
TCHAR * pszValue;
//
// Get the correct action list
//
if (bActionListOn)
{
pActionList = (ACTIONLIST *)(((LPBYTE)pPolicy) + pPolicy->uOffsetActionList_On);
}
else
{
pActionList = (ACTIONLIST *)(((LPBYTE)pPolicy) + pPolicy->uOffsetActionList_Off);
}
//
// Loop through each of the entries to see if they match
//
for (uIndex = 0; uIndex < pActionList->nActionItems; uIndex++)
{
if (uIndex == 0)
{
pAction = &pActionList->Action[0];
}
else
{
pAction = (ACTION *)(((LPBYTE)pActionList) + pAction->uOffsetNextAction);
}
//
// Get the value and keynames
//
pszValueName = (TCHAR *)(((LPBYTE)pActionList) + pAction->uOffsetValueName);
if (pAction->uOffsetKeyName)
{
pszKeyName = (TCHAR *)(((LPBYTE)pActionList) + pAction->uOffsetKeyName);
}
else
{
pszKeyName = (TCHAR *)(((LPBYTE)pPolicy) + pPolicy->uOffsetKeyName);
}
//
// Add prefixes if appropriate
//
PrependValueName(pszValueName, pAction->dwFlags,
szNewValueName, ARRAYSIZE(szNewValueName));
if (pAction->dwFlags & VF_ISNUMERIC)
{
if (ReadRegistryDWordValue(hKeyRoot, pszKeyName,
szNewValueName, &dwValue, lpGPOName) != ERROR_SUCCESS)
{
return FALSE;
}
if (dwValue != pAction->dwValue)
{
return FALSE;
}
}
else if (pAction->dwFlags & VF_DELETE)
{
//
// See if this is a value that's marked for deletion
// (valuename is prepended with "**del."
//
if ((ReadRegistryStringValue(hKeyRoot, pszKeyName, szNewValueName,
szValue,ARRAYSIZE(szValue),lpGPOName)) != ERROR_SUCCESS) {
return FALSE;
}
}
else
{
if (ReadRegistryStringValue(hKeyRoot, pszKeyName, szNewValueName,
szValue, ARRAYSIZE(szValue),lpGPOName) != ERROR_SUCCESS)
{
return FALSE;
}
pszValue = (TCHAR *)(((LPBYTE)pActionList) + pAction->uOffsetValue);
if (lstrcmpi(szValue,pszValue) != 0)
{
return FALSE;
}
}
}
return TRUE;
}
UINT CPolicySnapIn::LoadSettings(TABLEENTRY * pTableEntry,HKEY hkeyRoot,
DWORD * pdwFound, LPTSTR *lpGPOName)
{
UINT uRet = ERROR_SUCCESS;
TCHAR * pszValueName = NULL;
TCHAR * pszKeyName = NULL;
DWORD dwData=0,dwFlags,dwFoundSettings=0;
TCHAR szData[MAXSTRLEN];
BOOL fCustomOn=FALSE,fCustomOff=FALSE,fFound=FALSE;
BYTE * pObjectData = GETOBJECTDATAPTR(((SETTINGS *)pTableEntry));
TCHAR szNewValueName[MAX_PATH+1];
// get the name of the key to read
if (((SETTINGS *) pTableEntry)->uOffsetKeyName) {
pszKeyName = GETKEYNAMEPTR(((SETTINGS *) pTableEntry));
}
else return ERROR_NOT_ENOUGH_MEMORY;
// get the name of the value to read
if (((SETTINGS *) pTableEntry)->uOffsetValueName) {
pszValueName = GETVALUENAMEPTR(((SETTINGS *) pTableEntry));
}
else return ERROR_NOT_ENOUGH_MEMORY;
switch (pTableEntry->dwType & STYPE_MASK) {
case STYPE_EDITTEXT:
case STYPE_COMBOBOX:
dwFlags = ( (SETTINGS *) pTableEntry)->dwFlags;
// add prefixes if appropriate
PrependValueName(pszValueName,dwFlags,
szNewValueName,ARRAYSIZE(szNewValueName));
if ((uRet = ReadRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,szData,ARRAYSIZE(szData),lpGPOName)) == ERROR_SUCCESS) {
// set flag that we found setting in registry/policy file
if (pdwFound)
*pdwFound |= FS_PRESENT;
} else if (!(dwFlags & VF_DELETE)) {
// see if this key is marked as deleted
PrependValueName(pszValueName,VF_DELETE,
szNewValueName,ARRAYSIZE(szNewValueName));
if ((uRet = ReadRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,szData,ARRAYSIZE(szData) * sizeof(TCHAR),lpGPOName)) == ERROR_SUCCESS) {
// set flag that we found setting marked as deleted in
// policy file
if (pdwFound)
*pdwFound |= FS_DELETED;
}
}
return ERROR_SUCCESS;
break;
case STYPE_CHECKBOX:
if (!pObjectData) {
return ERROR_INVALID_PARAMETER;
}
// first look for custom on/off values
if (((CHECKBOXINFO *) pObjectData)->uOffsetValue_On) {
fCustomOn = TRUE;
if (CompareCustomValue(hkeyRoot,pszKeyName,pszValueName,
(STATEVALUE *) ((BYTE *) pTableEntry + ((CHECKBOXINFO *)
pObjectData)->uOffsetValue_On),&dwFoundSettings, lpGPOName)) {
dwData = 1;
fFound = TRUE;
}
}
if (!fFound && ((CHECKBOXINFO *) pObjectData)->uOffsetValue_Off) {
fCustomOff = TRUE;
if (CompareCustomValue(hkeyRoot,pszKeyName,pszValueName,
(STATEVALUE *) ((BYTE *) pTableEntry + ((CHECKBOXINFO *)
pObjectData)->uOffsetValue_Off),&dwFoundSettings, lpGPOName)) {
dwData = 0;
fFound = TRUE;
}
}
// look for standard values if custom values have not been specified
if (!fFound &&
ReadStandardValue(hkeyRoot,pszKeyName,pszValueName,
pTableEntry,&dwData,&dwFoundSettings, lpGPOName)) {
fFound = TRUE;
}
if (fFound) {
// set flag that we found setting in registry
if (pdwFound) {
*pdwFound |= dwFoundSettings;
if (dwData == 0) {
*pdwFound |= FS_DISABLED;
}
}
}
return ERROR_SUCCESS;
break;
case STYPE_NUMERIC:
if (ReadStandardValue(hkeyRoot,pszKeyName,pszValueName,
pTableEntry,&dwData,&dwFoundSettings,lpGPOName)) {
// set flag that we found setting in registry
if (pdwFound)
*pdwFound |= dwFoundSettings;
}
break;
case STYPE_DROPDOWNLIST:
if (ReadCustomValue(hkeyRoot,pszKeyName,pszValueName,
szData,ARRAYSIZE(szData),&dwData,&dwFlags, lpGPOName)) {
BOOL fMatch = FALSE;
if (dwFlags & VF_DELETE) {
// set flag that we found setting marked as deleted
// in policy file
if (pdwFound)
*pdwFound |= FS_DELETED;
return ERROR_SUCCESS;
}
// walk the list of DROPDOWNINFO structs (one for each state),
// and see if the value we found matches the value for the state
if ( ((SETTINGS *) pTableEntry)->uOffsetObjectData) {
DROPDOWNINFO * pddi = (DROPDOWNINFO *)
GETOBJECTDATAPTR( ((SETTINGS *) pTableEntry));
UINT nIndex = 0;
do {
if (dwFlags == pddi->dwFlags) {
if (pddi->dwFlags & VF_ISNUMERIC) {
if (dwData == pddi->dwValue)
fMatch = TRUE;
} else if (!pddi->dwFlags) {
if (!lstrcmpi(szData,(TCHAR *)((BYTE *)pTableEntry +
pddi->uOffsetValue)))
fMatch = TRUE;
}
}
if (!pddi->uOffsetNextDropdowninfo || fMatch)
break;
pddi = (DROPDOWNINFO *) ( (BYTE *) pTableEntry +
pddi->uOffsetNextDropdowninfo);
nIndex++;
} while (!fMatch);
if (fMatch) {
// set flag that we found setting in registry
if (pdwFound)
*pdwFound |= FS_PRESENT;
}
}
}
break;
case STYPE_LISTBOX:
return LoadListboxData(pTableEntry,hkeyRoot,
pszKeyName,pdwFound, NULL, lpGPOName);
break;
}
return ERROR_SUCCESS;
}
UINT CPolicySnapIn::LoadListboxData(TABLEENTRY * pTableEntry,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,DWORD * pdwFound, HGLOBAL * phGlobal, LPTSTR *lpGPOName)
{
HKEY hKey = NULL;
UINT nIndex=0,nLen;
TCHAR szValueName[MAX_PATH+1],szValueData[MAX_PATH+1];
DWORD cbValueName,cbValueData;
DWORD dwType,dwAlloc=1024 * sizeof(TCHAR),dwUsed=0;
HGLOBAL hBuf;
TCHAR * pBuf;
SETTINGS * pSettings = (SETTINGS *) pTableEntry;
LISTBOXINFO * pListboxInfo = (LISTBOXINFO *)
GETOBJECTDATAPTR(pSettings);
BOOL fFoundValues=FALSE,fFoundDelvals=FALSE;
UINT uRet=ERROR_SUCCESS;
LPRSOPREGITEM lpItem = NULL;
BOOL bMultiple;
HRESULT hr = S_OK;
DWORD dwBufLen = 0;
if (m_pcd->m_bRSOP)
{
//
// If this is an additive listbox, we want to pick up entries from
// any GPO, not just the GPOs of precedence 1, so set hkeyRoot to 0
//
if ((pSettings->dwFlags & DF_ADDITIVE) && (hkeyRoot == (HKEY) 1))
{
hkeyRoot = (HKEY) 0;
}
}
else
{
if (RegOpenKeyEx(hkeyRoot,pszCurrentKeyName,0,KEY_READ,&hKey) != ERROR_SUCCESS)
return ERROR_SUCCESS; // nothing to do
}
// allocate a temp buffer to read entries into
if (!(hBuf = GlobalAlloc(GHND,dwAlloc)) ||
!(pBuf = (TCHAR *) GlobalLock(hBuf))) {
if (hBuf)
GlobalFree(hBuf);
uRet = ERROR_NOT_ENOUGH_MEMORY;
goto CPolicySnapin_LoadListBoxData_exit;
}
while (TRUE) {
cbValueName=ARRAYSIZE(szValueName);
cbValueData=ARRAYSIZE(szValueData) * sizeof(TCHAR);
if (m_pcd->m_bRSOP)
{
uRet = m_pcd->EnumRSOPRegistryValues(hkeyRoot, pszCurrentKeyName,
szValueName, cbValueName,
&lpItem);
if (uRet == ERROR_SUCCESS)
{
//
// Check if the GPO name is changing
//
bMultiple = FALSE;
if (lpGPOName && *lpGPOName && lpItem->lpGPOName && (hkeyRoot == 0))
{
if (lstrcmpi(*lpGPOName, lpItem->lpGPOName))
{
bMultiple = TRUE;
}
}
uRet = m_pcd->ReadRSOPRegistryValue(hkeyRoot, pszCurrentKeyName,
szValueName, (LPBYTE)szValueData,
cbValueData, &dwType, lpGPOName,
lpItem);
if (bMultiple)
{
*lpGPOName = m_pMultipleGPOs;
}
}
}
else
{
uRet=RegEnumValue(hKey,nIndex,szValueName,&cbValueName,NULL,
&dwType,(LPBYTE)szValueData,&cbValueData);
}
// stop if we're out of items
if (uRet != ERROR_SUCCESS && uRet != ERROR_MORE_DATA)
break;
nIndex++;
if (szValueName[0] == TEXT('\0')) {
// if the value is empty, it is the key creation code
continue;
}
// if valuename prefixed with '**', it's a control code, ignore it
if (szValueName[0] == TEXT('*') && szValueName[1] == TEXT('*')) {
// if we found **delvals., then some sort of listbox stuff
// is going on, remember that we found this code
if (!lstrcmpi(szValueName,szDELVALS))
fFoundDelvals = TRUE;
continue;
}
// only process this item if enum was successful
// (so we'll skip items with weird errors like ERROR_MORE_DATA and
// but keep going with the enum)
if (uRet == ERROR_SUCCESS) {
TCHAR * pszData;
// if there's no value name prefix scheme specified (e.g.
// value names are "abc1", "abc2", etc), and the explicit valuename
// flag isn't set where we remember the value name as well as
// the data for every value, then we need the value name to
// be the same as the value data ("thing.exe=thing.exe").
if (!(pSettings->dwFlags & DF_EXPLICITVALNAME) &&
!(pListboxInfo->uOffsetPrefix) && !(pListboxInfo->uOffsetValue)) {
if (dwType != (DWORD)((pSettings->dwFlags & DF_EXPANDABLETEXT) ? REG_EXPAND_SZ : REG_SZ) ||
lstrcmpi(szValueName,szValueData))
continue; // skip this value if val name != val data
}
//
// If there is a valueprefix, only pick up values that start
// with that prefix
//
if (pListboxInfo->uOffsetPrefix) {
LPTSTR lpPrefix = (LPTSTR)((LPBYTE)pTableEntry + pListboxInfo->uOffsetPrefix);
INT iPrefixLen = lstrlen(lpPrefix);
if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpPrefix, iPrefixLen, szValueName,
iPrefixLen) != CSTR_EQUAL) {
continue;
}
}
// if explicit valuenames used, then copy the value name into
// buffer
if (pSettings->dwFlags & DF_EXPLICITVALNAME) {
nLen = lstrlen(szValueName) + 1;
dwBufLen = dwUsed+nLen+4;
if (!(pBuf=ResizeBuffer(pBuf,hBuf,(dwBufLen) * sizeof(TCHAR),&dwAlloc)))
{
uRet = ERROR_NOT_ENOUGH_MEMORY;
goto CPolicySnapin_LoadListBoxData_exit;
}
hr = StringCchCopy(pBuf+dwUsed, dwBufLen - dwUsed, szValueName);
ASSERT(SUCCEEDED(hr));
dwUsed += nLen;
}
// for default listbox type, value data is the actual "data"
// and value name either will be the same as the data or
// some prefix + "1", "2", etc. If there's a data value to
// write for each entry, then the "data" is the value name
// (e.g. "Larry = abc", "Dave = abc"), etc. If explicit value names
// are turned on, then both the value name and data are stored
// and editable
// copy value data into buffer
if (pListboxInfo->uOffsetValue) {
// data value set, use value name for data
pszData = szValueName;
} else pszData = szValueData;
nLen = lstrlen(pszData) + 1;
dwBufLen = dwUsed+nLen+4;
if (!(pBuf=ResizeBuffer(pBuf,hBuf,(dwBufLen) * sizeof(TCHAR),&dwAlloc)))
{
uRet = ERROR_NOT_ENOUGH_MEMORY;
goto CPolicySnapin_LoadListBoxData_exit;
}
hr = StringCchCopy(pBuf+dwUsed, dwBufLen - dwUsed, pszData);
ASSERT(SUCCEEDED(hr));
dwUsed += nLen;
fFoundValues=TRUE;
//
// Add the GPO name if this is RSOP mode
//
if (m_pcd->m_bRSOP)
{
nLen = lstrlen(lpItem->lpGPOName) + 1;
dwBufLen = dwUsed+nLen+4;
if (!(pBuf=ResizeBuffer(pBuf,hBuf,(dwBufLen) * sizeof(TCHAR),&dwAlloc)))
{
uRet = ERROR_NOT_ENOUGH_MEMORY;
goto CPolicySnapin_LoadListBoxData_exit;
}
hr = StringCchCopy(pBuf+dwUsed, dwBufLen - dwUsed, lpItem->lpGPOName);
ASSERT(SUCCEEDED(hr));
dwUsed += nLen;
}
}
}
// doubly null-terminate the buffer... safe to do this because we
// tacked on the extra "+4" in the ResizeBuffer calls above
*(pBuf+dwUsed) = TEXT('\0');
dwUsed++;
uRet = ERROR_SUCCESS;
if (fFoundValues) {
// set flag that we found setting in registry/policy file
if (pdwFound)
*pdwFound |= FS_PRESENT;
} else {
if (fFoundDelvals && pdwFound) {
*pdwFound |= FS_DELETED;
}
}
GlobalUnlock(hBuf);
if ((uRet == ERROR_SUCCESS) && phGlobal)
{
*phGlobal = hBuf;
}
else
{
GlobalFree(hBuf);
}
CPolicySnapin_LoadListBoxData_exit:
if (hKey)
{
RegCloseKey(hKey);
}
return uRet;
}
BOOL CPolicySnapIn::ReadCustomValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
TCHAR * pszValue,UINT cbValue,DWORD * pdwValue,DWORD * pdwFlags,LPTSTR *lpGPOName)
{
HKEY hKey;
DWORD dwType,dwSize=cbValue * sizeof(TCHAR);
BOOL fSuccess = FALSE;
TCHAR szNewValueName[MAX_PATH+1];
*pdwValue=0;
*pszValue = TEXT('\0');
if (m_pcd->m_bRSOP)
{
if (m_pcd->ReadRSOPRegistryValue(hkeyRoot, pszKeyName, pszValueName, (LPBYTE)pszValue,
dwSize, &dwType, lpGPOName, NULL) == ERROR_SUCCESS)
{
if (dwType == REG_SZ)
{
// value returned in pszValueName
*pdwFlags = 0;
fSuccess = TRUE;
}
else if (dwType == REG_DWORD || dwType == REG_BINARY)
{
// copy value to *pdwValue
memcpy(pdwValue,pszValue,sizeof(DWORD));
*pdwFlags = VF_ISNUMERIC;
fSuccess = TRUE;
}
}
else
{
// see if this is a value that's marked for deletion
// (valuename is prepended with "**del."
PrependValueName(pszValueName,VF_DELETE,
szNewValueName,ARRAYSIZE(szNewValueName));
if (m_pcd->ReadRSOPRegistryValue(hkeyRoot, pszKeyName, szNewValueName, (LPBYTE)pszValue,
dwSize, &dwType, lpGPOName, NULL) == ERROR_SUCCESS)
{
fSuccess=TRUE;
*pdwFlags = VF_DELETE;
}
else
{
// see if this is a soft value
// (valuename is prepended with "**soft."
PrependValueName(pszValueName,VF_SOFT,
szNewValueName,ARRAYSIZE(szNewValueName));
if (m_pcd->ReadRSOPRegistryValue(hkeyRoot, pszKeyName, szNewValueName, (LPBYTE)pszValue,
dwSize, &dwType, lpGPOName, NULL) == ERROR_SUCCESS)
{
fSuccess=TRUE;
*pdwFlags = VF_SOFT;
}
}
}
}
else
{
if (RegOpenKeyEx(hkeyRoot,pszKeyName,0,KEY_READ,&hKey) == ERROR_SUCCESS) {
if (RegQueryValueEx(hKey,pszValueName,NULL,&dwType,(LPBYTE) pszValue,
&dwSize) == ERROR_SUCCESS) {
if (dwType == REG_SZ) {
// value returned in pszValueName
*pdwFlags = 0;
fSuccess = TRUE;
} else if (dwType == REG_DWORD || dwType == REG_BINARY) {
// copy value to *pdwValue
memcpy(pdwValue,pszValue,sizeof(DWORD));
*pdwFlags = VF_ISNUMERIC;
fSuccess = TRUE;
}
} else {
// see if this is a value that's marked for deletion
// (valuename is prepended with "**del."
PrependValueName(pszValueName,VF_DELETE,
szNewValueName,ARRAYSIZE(szNewValueName));
if (RegQueryValueEx(hKey,szNewValueName,NULL,&dwType,(LPBYTE) pszValue,
&dwSize) == ERROR_SUCCESS) {
fSuccess=TRUE;
*pdwFlags = VF_DELETE;
} else {
// see if this is a soft value
// (valuename is prepended with "**soft."
PrependValueName(pszValueName,VF_SOFT,
szNewValueName,ARRAYSIZE(szNewValueName));
if (RegQueryValueEx(hKey,szNewValueName,NULL,&dwType,(LPBYTE) pszValue,
&dwSize) == ERROR_SUCCESS) {
fSuccess=TRUE;
*pdwFlags = VF_SOFT;
}
}
}
RegCloseKey(hKey);
}
}
return fSuccess;
}
BOOL CPolicySnapIn::CompareCustomValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
STATEVALUE * pStateValue,DWORD * pdwFound, LPTSTR *lpGPOName)
{
TCHAR szValue[MAXSTRLEN];
DWORD dwValue;
TCHAR szNewValueName[MAX_PATH+1];
// add prefixes if appropriate
PrependValueName(pszValueName,pStateValue->dwFlags,
szNewValueName,ARRAYSIZE(szNewValueName));
if (pStateValue->dwFlags & VF_ISNUMERIC) {
if ((ReadRegistryDWordValue(hkeyRoot,pszKeyName,
szNewValueName,&dwValue,lpGPOName) == ERROR_SUCCESS) &&
dwValue == pStateValue->dwValue) {
*pdwFound = FS_PRESENT;
return TRUE;
}
} else if (pStateValue->dwFlags & VF_DELETE) {
// see if this is a value that's marked for deletion
// (valuename is prepended with "**del."
if ((ReadRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,szValue,ARRAYSIZE(szValue),lpGPOName)) == ERROR_SUCCESS) {
*pdwFound = FS_DELETED;
return TRUE;
}
} else {
if ((ReadRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,szValue,ARRAYSIZE(szValue),lpGPOName)) == ERROR_SUCCESS &&
!lstrcmpi(szValue,pStateValue->szValue)) {
*pdwFound = FS_PRESENT;
return TRUE;
}
}
return FALSE;
}
BOOL CPolicySnapIn::ReadStandardValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
TABLEENTRY * pTableEntry,DWORD * pdwData,DWORD * pdwFound, LPTSTR *lpGPOName)
{
UINT uRet;
TCHAR szNewValueName[MAX_PATH+1];
// add prefixes if appropriate
PrependValueName(pszValueName,((SETTINGS *) pTableEntry)->dwFlags,
szNewValueName,ARRAYSIZE(szNewValueName));
if ( ((SETTINGS *) pTableEntry)->dwFlags & DF_TXTCONVERT) {
// read numeric value as text if specified
TCHAR szNum[11];
uRet = ReadRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,szNum,ARRAYSIZE(szNum),lpGPOName);
if (uRet == ERROR_SUCCESS) {
StringToNum(szNum, (UINT *)pdwData);
*pdwFound = FS_PRESENT;
return TRUE;
}
} else {
// read numeric value as binary
uRet = ReadRegistryDWordValue(hkeyRoot,pszKeyName,
szNewValueName,pdwData, lpGPOName);
if (uRet == ERROR_SUCCESS) {
*pdwFound = FS_PRESENT;
return TRUE;
}
}
// see if this settings has been marked as 'deleted'
TCHAR szVal[MAX_PATH+1];
*pdwData = 0;
PrependValueName(pszValueName,VF_DELETE,szNewValueName,
ARRAYSIZE(szNewValueName));
uRet=ReadRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,szVal,ARRAYSIZE(szVal),lpGPOName);
if (uRet == ERROR_SUCCESS) {
*pdwFound = FS_DELETED;
return TRUE;
}
return FALSE;
}
// adds the special prefixes "**del." and "**soft." if writing to a policy file,
// and VF_DELETE/VF_SOFT flags are set
VOID CPolicySnapIn::PrependValueName(TCHAR * pszValueName,DWORD dwFlags,TCHAR * pszNewValueName,
UINT cbNewValueName)
{
UINT nValueNameLen = lstrlen(pszValueName) + 1;
HRESULT hr = S_OK;
(void) StringCchCopy(pszNewValueName, cbNewValueName, g_szNull);
if (cbNewValueName < nValueNameLen) // check length of buffer, just in case
return;
// prepend special prefixes for "delete" or "soft" values
if ((dwFlags & VF_DELETE) && (cbNewValueName > nValueNameLen +
ARRAYSIZE(szDELETEPREFIX))) {
(void) StringCchCopy(pszNewValueName, cbNewValueName, szDELETEPREFIX);
} else if ((dwFlags & VF_SOFT) && (cbNewValueName > nValueNameLen +
ARRAYSIZE(szSOFTPREFIX))) {
(void) StringCchCopy(pszNewValueName, cbNewValueName, szSOFTPREFIX);
}
(void) StringCchCat(pszNewValueName, cbNewValueName, pszValueName);
}
UINT CPolicySnapIn::WriteRegistryDWordValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
DWORD dwValue)
{
HKEY hKey;
UINT uRet;
if (!pszKeyName || !pszValueName)
return ERROR_INVALID_PARAMETER;
// create the key with appropriate name
if ( (uRet = RegCreateKey(hkeyRoot,pszKeyName,&hKey))
!= ERROR_SUCCESS)
return uRet;
uRet = RegSetValueEx(hKey,pszValueName,0,REG_DWORD,
(LPBYTE) &dwValue,sizeof(dwValue));
RegCloseKey(hKey);
return uRet;
}
UINT CPolicySnapIn::ReadRegistryDWordValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
DWORD * pdwValue, LPTSTR *lpGPOName)
{
HKEY hKey;
UINT uRet;
DWORD dwType,dwSize = sizeof(DWORD);
if (!pszKeyName || !pszValueName)
return ERROR_INVALID_PARAMETER;
*pdwValue = 0;
if (m_pcd->m_bRSOP)
{
uRet = m_pcd->ReadRSOPRegistryValue(hkeyRoot, pszKeyName, pszValueName, (LPBYTE) pdwValue, 4,
&dwType, lpGPOName, NULL);
}
else
{
// open appropriate key
if ( (uRet = RegOpenKeyEx(hkeyRoot,pszKeyName,0,KEY_READ,&hKey))
!= ERROR_SUCCESS)
return uRet;
uRet = RegQueryValueEx(hKey,pszValueName,0,&dwType,
(LPBYTE) pdwValue,&dwSize);
RegCloseKey(hKey);
}
return uRet;
}
UINT CPolicySnapIn::WriteRegistryStringValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
TCHAR * pszValue, BOOL bExpandable)
{
HKEY hKey;
UINT uRet;
if (!pszKeyName || !pszValueName)
return ERROR_INVALID_PARAMETER;
// create the key with appropriate name
if ( (uRet = RegCreateKey(hkeyRoot,pszKeyName,&hKey))
!= ERROR_SUCCESS)
return uRet;
uRet = RegSetValueEx(hKey,pszValueName,0,
bExpandable ? REG_EXPAND_SZ : REG_SZ,
(LPBYTE) pszValue,(lstrlen(pszValue)+1) * sizeof(TCHAR));
RegCloseKey(hKey);
return uRet;
}
UINT CPolicySnapIn::ReadRegistryStringValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
TCHAR * pszValue,UINT cbValue, LPTSTR *lpGPOName)
{
HKEY hKey;
UINT uRet;
DWORD dwType;
DWORD dwSize = cbValue * sizeof(TCHAR);
if (!pszKeyName || !pszValueName)
return ERROR_INVALID_PARAMETER;
if (m_pcd->m_bRSOP)
{
uRet = m_pcd->ReadRSOPRegistryValue(hkeyRoot, pszKeyName, pszValueName, (LPBYTE) pszValue,
dwSize, &dwType, lpGPOName, NULL);
}
else
{
// create the key with appropriate name
if ( (uRet = RegOpenKeyEx(hkeyRoot,pszKeyName,0,KEY_READ,&hKey))
!= ERROR_SUCCESS)
return uRet;
uRet = RegQueryValueEx(hKey,pszValueName,0,&dwType,
(LPBYTE) pszValue,&dwSize);
RegCloseKey(hKey);
}
return uRet;
}
UINT CPolicySnapIn::DeleteRegistryValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName)
{
HKEY hKey;
UINT uRet;
if (!pszKeyName || !pszValueName)
return ERROR_INVALID_PARAMETER;
// create the key with appropriate name
if ( (uRet = RegOpenKeyEx(hkeyRoot,pszKeyName,0,KEY_WRITE,&hKey))
!= ERROR_SUCCESS)
return uRet;
uRet = RegDeleteValue(hKey,pszValueName);
RegCloseKey(hKey);
return uRet;
}
UINT CPolicySnapIn::WriteCustomValue_W(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
TCHAR * pszValue,DWORD dwValue,DWORD dwFlags,BOOL fErase)
{
UINT uRet=ERROR_SUCCESS;
TCHAR szNewValueName[MAX_PATH+1];
// first: "clean house" by deleting both the specified value name,
// and the value name with the delete (**del.) prefix.
// Then write the appropriate version back out if need be
PrependValueName(pszValueName,VF_DELETE,szNewValueName,
ARRAYSIZE(szNewValueName));
DeleteRegistryValue(hkeyRoot,pszKeyName,szNewValueName);
// add prefixes if appropriate
PrependValueName(pszValueName,(dwFlags & ~VF_DELETE),szNewValueName,
ARRAYSIZE(szNewValueName));
DeleteRegistryValue(hkeyRoot,pszKeyName,szNewValueName);
if (fErase) {
// just need to delete value, done above
uRet = ERROR_SUCCESS;
RegCleanUpValue (hkeyRoot, pszKeyName, pszValueName);
} else if (dwFlags & VF_DELETE) {
// need to delete value (done above) and mark as deleted if writing
// to policy file
uRet = ERROR_SUCCESS;
PrependValueName(pszValueName,VF_DELETE,szNewValueName,
ARRAYSIZE(szNewValueName));
uRet=WriteRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName, (TCHAR *)szNOVALUE, FALSE);
} else {
if (dwFlags & VF_ISNUMERIC) {
uRet=WriteRegistryDWordValue(hkeyRoot,pszKeyName,
szNewValueName,dwValue);
} else {
uRet = WriteRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,pszValue,
(dwFlags & DF_EXPANDABLETEXT) ? TRUE : FALSE);
}
}
return uRet;
}
UINT CPolicySnapIn::WriteCustomValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
STATEVALUE * pStateValue,BOOL fErase)
{
// pull info out of STATEVALUE struct and call worker function
return WriteCustomValue_W(hkeyRoot,pszKeyName,pszValueName,
pStateValue->szValue,pStateValue->dwValue,pStateValue->dwFlags,
fErase);
}
// writes a numeric value given root key, key name and value name. The specified
// value is removed if fErase is TRUE. Normally if the data (dwData) is zero
// the value will be deleted, but if fWriteZero is TRUE then the value will
// be written as zero if the data is zero.
UINT CPolicySnapIn::WriteStandardValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
TABLEENTRY * pTableEntry,DWORD dwData,BOOL fErase,BOOL fWriteZero)
{
UINT uRet=ERROR_SUCCESS;
TCHAR szNewValueName[MAX_PATH+1];
HRESULT hr = S_OK;
// first: "clean house" by deleting both the specified value name,
// and the value name with the delete (**del.) prefix (if writing to policy
// file). Then write the appropriate version back out if need be
PrependValueName(pszValueName,VF_DELETE,szNewValueName,
ARRAYSIZE(szNewValueName));
DeleteRegistryValue(hkeyRoot,pszKeyName,szNewValueName);
DeleteRegistryValue(hkeyRoot,pszKeyName,pszValueName);
if (fErase) {
// just need to delete value, done above
uRet = ERROR_SUCCESS;
RegCleanUpValue (hkeyRoot, pszKeyName, pszValueName);
} else if ( ((SETTINGS *) pTableEntry)->dwFlags & DF_TXTCONVERT) {
// if specified, save value as text
TCHAR szNum[11];
hr = StringCchPrintf(szNum, ARRAYSIZE(szNum), TEXT("%lu"),dwData);
ASSERT(SUCCEEDED(hr));
if (!dwData && !fWriteZero) {
// if value is 0, delete the value (done above), and mark
// it as deleted if writing to policy file
PrependValueName(pszValueName,VF_DELETE,szNewValueName,
ARRAYSIZE(szNewValueName));
uRet=WriteRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,(TCHAR *)szNOVALUE, FALSE);
} else {
PrependValueName(pszValueName,((SETTINGS *)pTableEntry)->dwFlags,
szNewValueName,ARRAYSIZE(szNewValueName));
uRet = WriteRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,szNum, FALSE);
}
} else {
if (!dwData && !fWriteZero) {
// if value is 0, delete the value (done above), and mark
// it as deleted if writing to policy file
PrependValueName(pszValueName,VF_DELETE,szNewValueName,
ARRAYSIZE(szNewValueName));
uRet=WriteRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,(TCHAR *)szNOVALUE, FALSE);
} else {
// save value as binary
PrependValueName(pszValueName,((SETTINGS *)pTableEntry)->dwFlags,
szNewValueName,ARRAYSIZE(szNewValueName));
uRet=WriteRegistryDWordValue(hkeyRoot,pszKeyName,
szNewValueName,dwData);
return 0;
}
}
return uRet;
}
TCHAR * CPolicySnapIn::ResizeBuffer(TCHAR * pBuf,HGLOBAL hBuf,DWORD dwNeeded,DWORD * pdwCurSize)
{
TCHAR * pNew;
if (dwNeeded <= *pdwCurSize) return pBuf; // nothing to do
*pdwCurSize = dwNeeded;
GlobalUnlock(hBuf);
if (!GlobalReAlloc(hBuf,dwNeeded,GHND))
return NULL;
if (!(pNew = (TCHAR *) GlobalLock(hBuf))) return NULL;
return pNew;
}
/*******************************************************************
NAME: MessageWndProc
SYNOPSIS: Window proc for GPMessageWndProc window
********************************************************************/
LRESULT CALLBACK CPolicySnapIn::MessageWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
SetWindowLongPtr (hWnd, GWLP_USERDATA, (LONG_PTR)((CREATESTRUCT *) lParam)->lpCreateParams);
break;
case WM_MOVEFOCUS:
{
CPolicySnapIn * pPS;
pPS = (CPolicySnapIn *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
if (pPS)
{
pPS->MoveFocusWorker ((BOOL)wParam);
}
}
break;
case WM_UPDATEITEM:
{
CPolicySnapIn * pPS;
pPS = (CPolicySnapIn *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
if (pPS)
{
pPS->UpdateItemWorker ();
}
}
break;
case WM_SETPREVNEXT:
{
CPolicySnapIn * pPS;
pPS = (CPolicySnapIn *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
if (pPS)
{
pPS->SetPrevNextButtonStateWorker ((HWND) wParam);
}
}
break;
default:
{
CPolicySnapIn * pPS;
pPS = (CPolicySnapIn *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
if (pPS)
{
if (message == pPS->m_uiRefreshMsg)
{
if ((DWORD) lParam == GetCurrentProcessId())
{
if (!pPS->m_hPropDlg)
{
pPS->m_pcd->m_pScope->DeleteItem (pPS->m_pcd->m_hSWPolicies, FALSE);
pPS->m_pcd->LoadTemplates();
pPS->m_pcd->EnumerateScopePane (NULL, pPS->m_pcd->m_hSWPolicies);
}
}
}
}
return (DefWindowProc(hWnd, message, wParam, lParam));
}
}
return (0);
}
/*******************************************************************
NAME: ClipWndProc
SYNOPSIS: Window proc for ClipClass window
********************************************************************/
LRESULT CALLBACK CPolicySnapIn::ClipWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message) {
case WM_CREATE:
if (!((CREATESTRUCT *) lParam)->lpCreateParams) {
// this is the clip window in the dialog box.
SetScrollRange(hWnd,SB_VERT,0,0,TRUE);
SetScrollRange(hWnd,SB_HORZ,0,0,TRUE);
} else {
// this is the container window
// store away the dialog box HWND (the grandparent of this
// window) because the pointer to instance data we need lives
// in the dialog's window data
SetWindowLong(hWnd,0,WT_SETTINGS);
}
break;
case WM_USER:
{
HWND hwndParent = GetParent(hWnd);
LPSETTINGSINFO lpSettingsInfo;
POLICYDLGINFO * pdi;
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr(hwndParent, DWLP_USER);
if (!lpSettingsInfo)
return FALSE;
pdi = lpSettingsInfo->pdi;
if (!pdi)
return FALSE;
if (!lpSettingsInfo->hFontDlg)
lpSettingsInfo->hFontDlg = (HFONT) SendMessage(GetParent(hWnd),WM_GETFONT,0,0L);
// make a container window that is clipped by this windows
if (!(pdi->hwndSettings=CreateWindow(TEXT("ClipClass"),(TCHAR *) g_szNull,
WS_CHILD | WS_VISIBLE,0,0,400,400,hWnd,NULL,g_hInstance,
(LPVOID) hWnd)))
return FALSE;
SetWindowLong(hWnd,0,WT_CLIP);
return TRUE;
}
break;
case WM_VSCROLL:
case WM_HSCROLL:
if (GetWindowLong(hWnd,0) == WT_CLIP)
{
LPSETTINGSINFO lpSettingsInfo;
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr(GetParent(hWnd), DWLP_USER);
if (!lpSettingsInfo)
return FALSE;
lpSettingsInfo->pCS->ProcessScrollBar(hWnd,wParam,
(message == WM_VSCROLL) ? TRUE : FALSE);
}
else goto defproc;
return 0;
case WM_COMMAND:
if (GetWindowLong(hWnd,0) == WT_SETTINGS) {
LPSETTINGSINFO lpSettingsInfo;
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr(GetParent(GetParent(hWnd)), DWLP_USER);
if (!lpSettingsInfo)
break;
lpSettingsInfo->pCS->ProcessCommand(hWnd,wParam,(HWND) lParam, lpSettingsInfo->pdi);
}
break;
case WM_GETDLGCODE:
if (GetWindowLong(hWnd,0) == WT_CLIP) {
SetWindowLongPtr(GetParent(hWnd),DWLP_MSGRESULT,DLGC_WANTTAB |
DLGC_WANTALLKEYS);
return DLGC_WANTTAB | DLGC_WANTALLKEYS;
}
break;
case WM_SETFOCUS:
// if clip window gains keyboard focus, transfer focus to first
// control owned by settings window
if (GetWindowLong(hWnd,0) == WT_CLIP) {
HWND hwndParent = GetParent(hWnd);
POLICYDLGINFO * pdi;
INT nIndex;
BOOL fForward=TRUE;
HWND hwndPrev = GetDlgItem(hwndParent,IDC_POLICY_PREVIOUS);
HWND hwndNext = GetDlgItem(hwndParent,IDC_POLICY_NEXT);
HWND hwndOK = GetDlgItem(GetParent(hwndParent),IDOK);
int iDelta;
LPSETTINGSINFO lpSettingsInfo;
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr(GetParent(hWnd), DWLP_USER);
if (!lpSettingsInfo)
return FALSE;
pdi = lpSettingsInfo->pdi;
if (!pdi)
return FALSE;
// if Previous Policy button lost focus, then we're going backwards
// in tab order; otherwise we're going forwards
if ( (HWND) wParam == hwndPrev)
fForward = FALSE;
else if ( (HWND) wParam == hwndNext)
fForward = FALSE;
else if ( (HWND) wParam == hwndOK)
fForward = FALSE;
// find the first control that has a data index (e.g. is
// not static text) and give it focus
if (pdi->nControls) {
if (fForward) { // search from start of table forwards
nIndex = 0;
iDelta = 1;
} else { // search from end of table backwards
nIndex = pdi->nControls-1;
iDelta = -1;
}
for (;nIndex>=0 && nIndex<(int)pdi->nControls;nIndex += iDelta) {
if (pdi->pControlTable[nIndex].uDataIndex !=
NO_DATA_INDEX &&
IsWindowEnabled(pdi->pControlTable[nIndex].hwnd)) {
SetFocus(pdi->pControlTable[nIndex].hwnd);
lpSettingsInfo->pCS->EnsureSettingControlVisible(hwndParent,
pdi->pControlTable[nIndex].hwnd);
return FALSE;
}
}
}
// only get here if there are no setting windows that can
// receive keyboard focus. Give keyboard focus to the
// next guy in line. This is the "OK" button, unless we
// shift-tabbed to get here from the "OK" button in which
// case the tree window is the next guy in line
if (fForward) {
if (IsWindowEnabled (hwndPrev))
SetFocus(hwndPrev);
else if (IsWindowEnabled (hwndNext))
SetFocus(hwndNext);
else
SetFocus(hwndOK);
} else {
if (IsDlgButtonChecked (hwndParent, IDC_ENABLED) == BST_CHECKED) {
SetFocus (GetDlgItem(hwndParent,IDC_ENABLED));
} else if (IsDlgButtonChecked (hwndParent, IDC_DISABLED) == BST_CHECKED) {
SetFocus (GetDlgItem(hwndParent,IDC_DISABLED));
} else {
SetFocus (GetDlgItem(hwndParent,IDC_NOCONFIG));
}
}
return FALSE;
}
break;
default:
defproc:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (0);
}
/*******************************************************************
NAME: ProcessCommand
SYNOPSIS: WM_COMMAND handler for ClipClass window
********************************************************************/
VOID CPolicySnapIn::ProcessCommand(HWND hWnd,WPARAM wParam,HWND hwndCtrl, POLICYDLGINFO * pdi)
{
// get instance-specific struct from dialog
UINT uID = GetWindowLong(hwndCtrl,GWL_ID);
if ( (uID >= IDD_SETTINGCTRL) && (uID < IDD_SETTINGCTRL+pdi->nControls)) {
POLICYCTRLINFO * pPolicyCtrlInfo= &pdi->pControlTable[uID - IDD_SETTINGCTRL];
switch (pPolicyCtrlInfo->dwType) {
case STYPE_CHECKBOX:
SendMessage(hwndCtrl,BM_SETCHECK,
!(SendMessage(hwndCtrl,BM_GETCHECK,0,0)),0);
break;
case STYPE_LISTBOX:
ShowListbox(hwndCtrl,pPolicyCtrlInfo->pSetting);
break;
default:
// nothing to do
break;
}
if ((HIWORD(wParam) == BN_CLICKED) ||
(HIWORD(wParam) == EN_CHANGE) ||
(HIWORD(wParam) == CBN_SELCHANGE) ||
(HIWORD(wParam) == CBN_EDITCHANGE))
{
PostMessage (GetParent(GetParent(hWnd)), WM_MYCHANGENOTIFY, 0, 0);
}
}
}
// scrolls the control window into view if it's not visible
VOID CPolicySnapIn::EnsureSettingControlVisible(HWND hDlg,HWND hwndCtrl)
{
// get the clip window, which owns the scroll bar
HWND hwndClip = GetDlgItem(hDlg,IDC_POLICY_SETTINGS);
POLICYDLGINFO * pdi;
UINT nPos = GetScrollPos(hwndClip,SB_VERT),ySettingWindowSize,yClipWindowSize;
UINT nExtra;
int iMin,iMax=0;
WINDOWPLACEMENT wp;
RECT rcCtrl;
LPSETTINGSINFO lpSettingsInfo;
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr(hDlg, DWLP_USER);
if (!lpSettingsInfo)
return;
pdi = lpSettingsInfo->pdi;
if (!pdi)
return;
// find the scroll range
GetScrollRange(hwndClip,SB_VERT,&iMin,&iMax);
if (!iMax) // no scroll bar, nothing to do
return;
// find the y size of the settings window that contains the settings controls
// (this is clipped by the clip window in the dialog, scroll bar moves the
// setting window up and down behind the clip window)
wp.length = sizeof(wp);
if (!GetWindowPlacement(pdi->hwndSettings,&wp))
return; // unlikely to fail, but just bag out if it does rather than do something wacky
ySettingWindowSize=wp.rcNormalPosition.bottom-wp.rcNormalPosition.top;
// find y size of clip window
if (!GetWindowPlacement(hwndClip,&wp))
return; // unlikely to fail, but just bag out if it does rather than do something wacky
yClipWindowSize=wp.rcNormalPosition.bottom-wp.rcNormalPosition.top;
nExtra = ySettingWindowSize - yClipWindowSize;
// if setting window is smaller than clip window, there should be no
// scroll bar so we should never get here. Check just in case though...
if (ySettingWindowSize < yClipWindowSize)
return;
// get y position of control to be made visible
if (!GetWindowPlacement(hwndCtrl,&wp))
return;
rcCtrl = wp.rcNormalPosition;
rcCtrl.bottom = min ((int) ySettingWindowSize,rcCtrl.bottom + SC_YPAD);
rcCtrl.top = max ((int) 0,rcCtrl.top - SC_YPAD);
// if bottom of control is out of view, scroll the settings window up
if ((float) rcCtrl.bottom >
(float) (yClipWindowSize + ( (float) nPos/(float)iMax) * (ySettingWindowSize -
yClipWindowSize))) {
UINT nNewPos = (UINT)
( ((float) (nExtra - (ySettingWindowSize - rcCtrl.bottom)) / (float) nExtra) * iMax);
SetScrollPos(hwndClip,SB_VERT,nNewPos,TRUE);
ProcessScrollBar(hwndClip,MAKELPARAM(SB_THUMBTRACK,nNewPos), TRUE);
return;
}
// if top of control is out of view, scroll the settings window down
if ((float) rcCtrl.top <
(float) ( (float) nPos/(float)iMax) * nExtra) {
UINT nNewPos = (UINT)
( ((float) rcCtrl.top / (float) nExtra) * iMax);
SetScrollPos(hwndClip,SB_VERT,nNewPos,TRUE);
ProcessScrollBar(hwndClip,MAKELPARAM(SB_THUMBTRACK,nNewPos), TRUE);
return;
}
}
VOID CPolicySnapIn::ProcessScrollBar(HWND hWnd,WPARAM wParam,BOOL bVert)
{
UINT nPos = GetScrollPos(hWnd,bVert ? SB_VERT : SB_HORZ);
RECT rcParent,rcChild;
POLICYDLGINFO * pdi;
LPSETTINGSINFO lpSettingsInfo;
// get instance-specific struct from dialog
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr(GetParent(hWnd), DWLP_USER);
if (!lpSettingsInfo)
return;
pdi = lpSettingsInfo->pdi;
if (!pdi)
return;
if (LOWORD(wParam) == SB_ENDSCROLL)
return;
switch (LOWORD(wParam)) {
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
nPos = HIWORD(wParam);
break;
case SB_TOP:
nPos = 0;
break;
case SB_BOTTOM:
nPos = 100;
break;
case SB_LINEUP:
if (nPos >= 10)
nPos -= 10;
else
nPos = 0;
break;
case SB_LINEDOWN:
if (nPos <= 90)
nPos += 10;
else
nPos = 100;
break;
case SB_PAGEUP:
if (nPos >= 30)
nPos -= 30;
else
nPos = 0;
break;
case SB_PAGEDOWN:
if (nPos <= 70)
nPos += 30;
else
nPos = 100;
break;
}
SetScrollPos(hWnd,bVert ? SB_VERT : SB_HORZ,nPos,TRUE);
GetClientRect(hWnd,&rcParent);
GetClientRect(pdi->hwndSettings,&rcChild);
if (bVert)
{
SetWindowPos(pdi->hwndSettings,NULL,0,-(int) ((( (float)
(rcChild.bottom-rcChild.top)-(rcParent.bottom-rcParent.top))
/100.0) * (float) nPos),rcChild.right,rcChild.bottom,SWP_NOZORDER |
SWP_NOSIZE);
}
else
{
SetWindowPos(pdi->hwndSettings,NULL,-(int) ((( (float)
(rcChild.right-rcChild.left)-(rcParent.right-rcParent.left))
/100.0) * (float) nPos),rcChild.top, rcChild.right,rcChild.bottom,SWP_NOZORDER |
SWP_NOSIZE);
}
}
/*******************************************************************
NAME: FreeSettingsControls
SYNOPSIS: Frees all settings controls
********************************************************************/
VOID CPolicySnapIn::FreeSettingsControls(HWND hDlg)
{
UINT nIndex;
HGLOBAL hData;
POLICYDLGINFO * pdi;
LPSETTINGSINFO lpSettingsInfo;
// get instance-specific struct from dialog
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr(hDlg, DWLP_USER);
if (!lpSettingsInfo)
return;
pdi = lpSettingsInfo->pdi;
if (!pdi)
return;
for (nIndex=0;nIndex<pdi->nControls;nIndex++) {
if (pdi->pControlTable[nIndex].dwType == STYPE_LISTBOX)
{
hData = (HGLOBAL) GetWindowLongPtr (pdi->pControlTable[nIndex].hwnd,
GWLP_USERDATA);
if (hData)
{
GlobalFree (hData);
}
}
DestroyWindow(pdi->pControlTable[nIndex].hwnd);
}
pdi->pCurrentSettings = NULL;
pdi->nControls = 0;
SetScrollRange(pdi->hwndSettings,SB_VERT,0,0,TRUE);
SetScrollRange(pdi->hwndSettings,SB_HORZ,0,0,TRUE);
}
/*******************************************************************
NAME: CreateSettingsControls
SYNOPSIS: Creates controls in settings window
NOTES: Looks at a table of SETTINGS structs to determine
type of control to create and type-specific information.
For some types, more than one control can be created
(for instance, edit fields get a static control with
the title followed by an edit field control).
ENTRY: hDlg - owner dialog
hTable - table of SETTINGS structs containing setting
control information
********************************************************************/
BOOL CPolicySnapIn::CreateSettingsControls(HWND hDlg,SETTINGS * pSetting,BOOL fEnable)
{
LPBYTE pObjectData;
POLICYDLGINFO * pdi;
UINT xMax=0,yStart=SC_YSPACING,nHeight,nWidth,yMax,xWindowMax;
HWND hwndControl,hwndBuddy,hwndParent;
RECT rcParent;
DWORD dwType, dwStyle;
UINT uEnable = (fEnable ? 0 : WS_DISABLED);
WINDOWPLACEMENT wp;
LPSETTINGSINFO lpSettingsInfo;
// get instance-specific struct from dialog
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr(hDlg, DWLP_USER);
if (!lpSettingsInfo)
return FALSE;
pdi = lpSettingsInfo->pdi;
if (!pdi)
return FALSE;
wp.length = sizeof(wp);
if (!GetWindowPlacement(GetDlgItem(hDlg,IDC_POLICY_SETTINGS),&wp))
return FALSE;
xWindowMax = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
pdi->pCurrentSettings = pSetting;
while (pSetting) {
pObjectData = GETOBJECTDATAPTR(pSetting);
dwType = pSetting->dwType & STYPE_MASK;
nWidth = 0;
nHeight = 0;
switch (dwType) {
case STYPE_TEXT:
// create static text control
if (!(hwndControl = CreateSetting(pdi,(TCHAR *) szSTATIC,
(TCHAR *) (GETNAMEPTR(pSetting)),0,SSTYLE_STATIC | uEnable,0,
yStart,0,15,STYPE_TEXT,NO_DATA_INDEX,0, lpSettingsInfo->hFontDlg)))
return FALSE;
AdjustWindowToText(hwndControl,(TCHAR *) (GETNAMEPTR(pSetting))
,SC_XSPACING,yStart,0,&nWidth,&nHeight, lpSettingsInfo->hFontDlg);
yStart += nHeight + SC_YSPACING;
nWidth += SC_XSPACING;
break;
case STYPE_CHECKBOX:
// create checkbox control
if (!(hwndControl = CreateSetting(pdi,(TCHAR *) szBUTTON,
(TCHAR *) (GETNAMEPTR(pSetting)),0,SSTYLE_CHECKBOX | uEnable,
0,yStart,200,nHeight,STYPE_CHECKBOX,pSetting->uDataIndex,
pSetting, lpSettingsInfo->hFontDlg)))
return FALSE;
nWidth = 20;
AdjustWindowToText(hwndControl,(TCHAR *) (GETNAMEPTR(pSetting))
,SC_XSPACING,yStart,0,&nWidth,&nHeight, lpSettingsInfo->hFontDlg);
yStart += nHeight + SC_YSPACING;
nWidth += SC_XSPACING;
break;
case STYPE_EDITTEXT:
case STYPE_COMBOBOX:
// create static text with setting name
if (!(hwndControl = CreateSetting(pdi,(TCHAR *) szSTATIC,
GETNAMEPTR(pSetting),0,SSTYLE_STATIC | uEnable,0,0,0,0,
STYPE_TEXT,NO_DATA_INDEX,0, lpSettingsInfo->hFontDlg)))
return FALSE;
AdjustWindowToText(hwndControl,
GETNAMEPTR(pSetting),SC_XSPACING,yStart,SC_YPAD,
&nWidth,&nHeight, lpSettingsInfo->hFontDlg);
nWidth += SC_XSPACING + 5;
if (nWidth + SC_EDITWIDTH> xWindowMax) {
// if next control will stick out of settings window,
// put it on the next line
if (nWidth > xMax)
xMax = nWidth;
yStart += nHeight + SC_YCONTROLWRAP;
nWidth = SC_XINDENT;
} else {
SetWindowPos(hwndControl,NULL,SC_XSPACING,(yStart + SC_YTEXTDROP),0,0,SWP_NOZORDER | SWP_NOSIZE);
}
// create edit field or combo box control
if (dwType == STYPE_EDITTEXT) {
hwndControl = CreateSetting(pdi,(TCHAR *) szEDIT,(TCHAR *) g_szNull,
WS_EX_CLIENTEDGE,SSTYLE_EDITTEXT | uEnable,nWidth,yStart,SC_EDITWIDTH,nHeight,
STYPE_EDITTEXT,pSetting->uDataIndex,pSetting, lpSettingsInfo->hFontDlg);
} else {
dwStyle = SSTYLE_COMBOBOX | uEnable;
if (pSetting->dwFlags & DF_NOSORT) {
dwStyle &= ~CBS_SORT;
}
hwndControl = CreateSetting(pdi,(TCHAR *) szCOMBOBOX,(TCHAR *)g_szNull,
WS_EX_CLIENTEDGE,dwStyle,nWidth,yStart,SC_EDITWIDTH,nHeight*6,
STYPE_COMBOBOX,pSetting->uDataIndex,pSetting, lpSettingsInfo->hFontDlg);
}
if (!hwndControl) return FALSE;
// limit the text length appropriately
if (dwType == STYPE_COMBOBOX) {
SendMessage(hwndControl,CB_LIMITTEXT,
(WPARAM) ((POLICYCOMBOBOXINFO *) pObjectData)->nMaxLen,0L);
} else {
SendMessage(hwndControl,EM_SETLIMITTEXT,
(WPARAM) ((EDITTEXTINFO *) pObjectData)->nMaxLen,0L);
}
if (dwType == STYPE_COMBOBOX &&
((POLICYCOMBOBOXINFO *) pObjectData)->uOffsetSuggestions)
InsertComboboxItems(hwndControl,(TCHAR *) ((LPBYTE)pSetting +
((POLICYCOMBOBOXINFO *) pObjectData)->uOffsetSuggestions));
yStart += (UINT) ((float) nHeight*1.3) + SC_YSPACING;
nWidth += SC_EDITWIDTH;
break;
case STYPE_NUMERIC:
// create static text for setting
if (!(hwndControl = CreateSetting(pdi,(TCHAR *) szSTATIC,
GETNAMEPTR(pSetting),0,
SSTYLE_STATIC | uEnable,0,0,0,0,STYPE_TEXT,NO_DATA_INDEX,0, lpSettingsInfo->hFontDlg)))
return FALSE;
AdjustWindowToText(hwndControl,
GETNAMEPTR(pSetting),SC_XSPACING,(yStart + SC_YTEXTDROP),SC_YPAD,
&nWidth,&nHeight, lpSettingsInfo->hFontDlg);
nWidth += SC_XSPACING + 5;
// create edit field
if (!(hwndBuddy = CreateSetting(pdi,(TCHAR *) szEDIT,
(TCHAR *) g_szNull,WS_EX_CLIENTEDGE,SSTYLE_EDITTEXT | uEnable,nWidth,yStart,SC_UPDOWNWIDTH,
nHeight,STYPE_NUMERIC,pSetting->uDataIndex,pSetting, lpSettingsInfo->hFontDlg)))
return FALSE;
//SendMessage(hwndBuddy,EM_LIMITTEXT,4,0);
nWidth += SC_UPDOWNWIDTH;
// create spin (up-down) control if specifed
if (((NUMERICINFO *)pObjectData)->uSpinIncrement) {
UDACCEL udAccel = {0,0};
UINT nMax,nMin;
if (!(hwndControl = CreateSetting(pdi,(TCHAR *) szUPDOWN,
(TCHAR *) g_szNull,WS_EX_CLIENTEDGE,SSTYLE_UPDOWN | UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_UNSIGNED | uEnable,nWidth,yStart,SC_UPDOWNWIDTH2,
nHeight,STYPE_TEXT | STYPE_NUMERIC,NO_DATA_INDEX,0, lpSettingsInfo->hFontDlg)))
return FALSE;
nWidth += SC_UPDOWNWIDTH2;
nMax = ((NUMERICINFO *) pObjectData)->uMaxValue;
nMin = ((NUMERICINFO *) pObjectData)->uMinValue;
udAccel.nInc = ((NUMERICINFO *) pObjectData)->uSpinIncrement;
SendMessage(hwndControl,UDM_SETBUDDY,(WPARAM) hwndBuddy,0L);
SendMessage(hwndControl,UDM_SETRANGE32,(WPARAM) nMin,(LPARAM) nMax);
SendMessage(hwndControl,UDM_SETACCEL,1,(LPARAM) &udAccel);
}
yStart += nHeight + SC_YSPACING;
break;
case STYPE_DROPDOWNLIST:
// create text description
if (!(hwndControl = CreateSetting(pdi,(TCHAR *) szSTATIC,
GETNAMEPTR(pSetting),0,
SSTYLE_STATIC | uEnable,0,0,0,0,STYPE_TEXT,NO_DATA_INDEX,0, lpSettingsInfo->hFontDlg)))
return FALSE;
AdjustWindowToText(hwndControl,
GETNAMEPTR(pSetting),SC_XSPACING,yStart,SC_YPAD,&nWidth,&nHeight, lpSettingsInfo->hFontDlg);
nWidth += SC_XLEADING + 5;
if (nWidth + SC_EDITWIDTH> xWindowMax) {
// if next control will stick out of settings window,
// put it on the next line
if (nWidth > xMax)
xMax = nWidth;
yStart += nHeight + SC_YCONTROLWRAP;
nWidth = SC_XINDENT;
} else {
SetWindowPos(hwndControl,NULL,SC_XSPACING,(yStart + SC_YTEXTDROP),0,0,SWP_NOZORDER | SWP_NOSIZE);
}
dwStyle = SSTYLE_DROPDOWNLIST | uEnable;
if (pSetting->dwFlags & DF_NOSORT) {
dwStyle &= ~CBS_SORT;
}
// create drop down listbox
hwndControl = CreateSetting(pdi,(TCHAR *) szCOMBOBOX,(TCHAR *) g_szNull,
WS_EX_CLIENTEDGE,dwStyle,nWidth,yStart,SC_EDITWIDTH,nHeight*6,
STYPE_DROPDOWNLIST,pSetting->uDataIndex,pSetting, lpSettingsInfo->hFontDlg);
if (!hwndControl) return FALSE;
nWidth += SC_EDITWIDTH;
{
// insert dropdown list items into control
UINT uOffset = pSetting->uOffsetObjectData,nIndex=0;
DROPDOWNINFO * pddi;
int iSel;
while (uOffset) {
pddi = (DROPDOWNINFO *) ( (LPBYTE) pSetting + uOffset);
iSel=(int)SendMessage(hwndControl,CB_ADDSTRING,0,(LPARAM)
((LPBYTE) pSetting + pddi->uOffsetItemName));
if (iSel<0) return FALSE;
SendMessage(hwndControl,CB_SETITEMDATA,iSel,nIndex);
nIndex++;
uOffset = pddi->uOffsetNextDropdowninfo;
}
}
yStart += (UINT) ((float) nHeight*1.3) + 1;
break;
case STYPE_LISTBOX:
{
TCHAR szShow[50];
// create static text with description
if (!(hwndControl = CreateSetting(pdi,(TCHAR *) szSTATIC,
GETNAMEPTR(pSetting),0,
SSTYLE_STATIC | uEnable,0,0,0,0,STYPE_TEXT,NO_DATA_INDEX,0, lpSettingsInfo->hFontDlg)))
return FALSE;
AdjustWindowToText(hwndControl,GETNAMEPTR(pSetting),SC_XSPACING,yStart,
SC_YPAD,&nWidth,&nHeight, lpSettingsInfo->hFontDlg);
nWidth += SC_XLEADING;
if (nWidth + LISTBOX_BTN_WIDTH> xWindowMax) {
// if next control will stick out of settings window,
// put it on the next line
if (nWidth > xMax)
xMax = nWidth;
yStart += nHeight + SC_YCONTROLWRAP;
nWidth = SC_XINDENT;
} else {
SetWindowPos(hwndControl,NULL,SC_XSPACING,(yStart + SC_YTEXTDROP),0,0,SWP_NOZORDER | SWP_NOSIZE);
}
// create pushbutton to show listbox contents
LoadString(g_hInstance, IDS_LISTBOX_SHOW, szShow, ARRAYSIZE(szShow));
hwndControl = CreateSetting(pdi,(TCHAR *) szBUTTON,szShow,0,
SSTYLE_LBBUTTON | uEnable,nWidth+5,yStart,
LISTBOX_BTN_WIDTH,nHeight,STYPE_LISTBOX,
pSetting->uDataIndex,pSetting, lpSettingsInfo->hFontDlg);
if (!hwndControl) return FALSE;
SetWindowLongPtr(hwndControl,GWLP_USERDATA,0);
nWidth += LISTBOX_BTN_WIDTH + SC_XLEADING;
yStart += nHeight+1;
}
}
if (nWidth > xMax)
xMax = nWidth;
pSetting = (SETTINGS *) pSetting->pNext;
}
yMax = yStart - 1;
SetWindowPos(pdi->hwndSettings,NULL,0,0,xMax,yMax,SWP_NOZORDER);
hwndParent = GetParent(pdi->hwndSettings);
GetClientRect(hwndParent,&rcParent);
if (yMax > (UINT) rcParent.bottom-rcParent.top) {
SetScrollRange(hwndParent,SB_VERT,0,100,TRUE);
SetScrollPos(hwndParent,SB_VERT,0,TRUE);
ShowScrollBar(hwndParent,SB_VERT, TRUE);
} else {
SetScrollRange(hwndParent,SB_VERT,0,0,TRUE);
ShowScrollBar(hwndParent,SB_VERT, FALSE);
}
if (xMax > (UINT) rcParent.right-rcParent.left) {
SetScrollRange(hwndParent,SB_HORZ,0,100,TRUE);
SetScrollPos(hwndParent,SB_HORZ,0,TRUE);
ShowScrollBar(hwndParent,SB_HORZ, TRUE);
} else {
SetScrollRange(hwndParent,SB_HORZ,0,0,TRUE);
ShowScrollBar(hwndParent,SB_HORZ, FALSE);
}
return TRUE;
}
VOID CPolicySnapIn::InsertComboboxItems(HWND hwndControl,TCHAR * pSuggestionList)
{
while (*pSuggestionList) {
SendMessage(hwndControl,CB_ADDSTRING,0,(LPARAM) pSuggestionList);
pSuggestionList += lstrlen(pSuggestionList) + 1;
}
}
/*******************************************************************
NAME: CreateSettings
SYNOPSIS: Creates a control and add it to the table of settings
controls
********************************************************************/
HWND CPolicySnapIn::CreateSetting(POLICYDLGINFO * pdi,TCHAR * pszClassName,TCHAR * pszWindowName,
DWORD dwExStyle,DWORD dwStyle,int x,int y,int cx,int cy,DWORD dwType,UINT uIndex,
SETTINGS * pSetting, HFONT hFontDlg)
{
HWND hwndControl;
if (!(hwndControl = CreateWindowEx(WS_EX_NOPARENTNOTIFY | dwExStyle,
pszClassName,pszWindowName,dwStyle,x,y,cx,cy,pdi->hwndSettings,NULL,
g_hInstance,NULL))) return NULL;
if (!SetWindowData(pdi,hwndControl,dwType,uIndex,pSetting)) {
DestroyWindow(hwndControl);
return NULL;
}
SendMessage(hwndControl,WM_SETFONT,(WPARAM) hFontDlg,MAKELPARAM(TRUE,0));
return hwndControl;
}
BOOL CPolicySnapIn::SetWindowData(POLICYDLGINFO * pdi,HWND hwndControl,DWORD dwType,
UINT uDataIndex,SETTINGS * pSetting)
{
POLICYCTRLINFO PolicyCtrlInfo;
int iCtrl;
PolicyCtrlInfo.hwnd = hwndControl;
PolicyCtrlInfo.dwType = dwType;
PolicyCtrlInfo.uDataIndex = uDataIndex;
PolicyCtrlInfo.pSetting = pSetting;
iCtrl = AddControlHwnd(pdi,&PolicyCtrlInfo);
if (iCtrl < 0) return FALSE;
SetWindowLong(hwndControl,GWL_ID,iCtrl + IDD_SETTINGCTRL);
return TRUE;
}
int CPolicySnapIn::AddControlHwnd(POLICYDLGINFO * pdi,POLICYCTRLINFO * pPolicyCtrlInfo)
{
int iRet;
DWORD dwNeeded;
POLICYCTRLINFO * pTemp;
// grow table if necessary
dwNeeded = (pdi->nControls+1) * sizeof(POLICYCTRLINFO);
if (dwNeeded > pdi->dwControlTableSize) {
pTemp = (POLICYCTRLINFO *) LocalReAlloc(pdi->pControlTable,
dwNeeded,LMEM_ZEROINIT | LMEM_MOVEABLE);
if (!pTemp) return (-1);
pdi->pControlTable = pTemp;
pdi->dwControlTableSize = dwNeeded;
}
pdi->pControlTable[pdi->nControls] = *pPolicyCtrlInfo;
iRet = (int) pdi->nControls;
(pdi->nControls)++;
return iRet;
}
BOOL CPolicySnapIn::AdjustWindowToText(HWND hWnd,TCHAR * szText,UINT xStart,UINT yStart,
UINT yPad,UINT * pnWidth,UINT * pnHeight, HFONT hFontDlg)
{
SIZE size;
if (GetTextSize(hWnd,szText,&size, hFontDlg))
{
*pnHeight =size.cy + yPad;
*pnWidth += size.cx;
SetWindowPos(hWnd,NULL,xStart,yStart,*pnWidth,*pnHeight,SWP_NOZORDER);
}
return FALSE;
}
BOOL CPolicySnapIn::GetTextSize(HWND hWnd,TCHAR * szText,SIZE * pSize, HFONT hFontDlg)
{
HDC hDC;
BOOL fRet;
if (!(hDC = GetDC(hWnd))) return FALSE;
SelectObject(hDC, hFontDlg);
fRet=GetTextExtentPoint(hDC,szText,lstrlen(szText),pSize);
ReleaseDC(hWnd,hDC);
return fRet;
}
//*************************************************************
//
// SaveSettings()
//
// Purpose: Saves the results of the settings
//
// Parameters:
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
HRESULT CPolicySnapIn::SaveSettings(HWND hDlg)
{
UINT nIndex;
POLICYDLGINFO * pdi;
LPSETTINGSINFO lpSettingsInfo;
SETTINGS * pSetting;
HKEY hKeyRoot;
DWORD dwTemp;
UINT uRet = ERROR_SUCCESS, uPolicyState;
int iSel, iIndex;
LPTSTR lpBuffer;
BOOL fTranslated;
NUMERICINFO * pNumericInfo;
HRESULT hr;
LPBYTE pObjectData;
BOOL fErase;
DROPDOWNINFO * pddi;
GUID guidRegistryExt = REGISTRY_EXTENSION_GUID;
GUID guidSnapinMach = CLSID_PolicySnapInMachine;
GUID guidSnapinUser = CLSID_PolicySnapInUser;
GUID ClientGUID;
LPTSTR lpClientGUID;
TCHAR szFormat[100];
TCHAR szMsg[150];
BOOL bFoundNone; // used in the listbox case alone
//
// Check for RSOP mode
//
if (m_pcd->m_bRSOP)
{
DebugMsg((DM_VERBOSE, TEXT("CPolicySnapIn::SaveSettings: Running in RSOP mode, nothing to save.")));
return S_OK;
}
//
// Check the dirty bit
//
if (!m_bDirty)
{
DebugMsg((DM_VERBOSE, TEXT("CPolicySnapIn::SaveSettings: No changes detected. Exiting successfully.")));
return S_OK;
}
// get instance-specific struct from dialog
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr(hDlg, DWLP_USER);
if (!lpSettingsInfo)
return E_FAIL;
pdi = lpSettingsInfo->pdi;
if (!pdi)
return E_FAIL;
if (m_pcd->m_pGPTInformation->GetRegistryKey(
(m_pcd->m_bUserScope ? GPO_SECTION_USER : GPO_SECTION_MACHINE),
&hKeyRoot) != S_OK)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::SaveSettings: Failed to get registry key handle.")));
return S_FALSE;
}
//
// Get the policy state
//
if (IsDlgButtonChecked (hDlg, IDC_NOCONFIG) == BST_CHECKED)
{
uPolicyState = BST_INDETERMINATE;
}
else if (IsDlgButtonChecked (hDlg, IDC_ENABLED) == BST_CHECKED)
{
uPolicyState = BST_CHECKED;
}
else
{
uPolicyState = BST_UNCHECKED;
}
if (uPolicyState == BST_INDETERMINATE)
{
fErase = TRUE;
}
else
{
fErase = FALSE;
}
//
// Validate the state of the parts
//
for (nIndex=0;nIndex<pdi->nControls;nIndex++)
{
pSetting = pdi->pControlTable[nIndex].pSetting;
if (pdi->pControlTable[nIndex].uDataIndex != NO_DATA_INDEX)
{
switch (pdi->pControlTable[nIndex].dwType)
{
case STYPE_CHECKBOX:
if (BST_CHECKED == uPolicyState)
{
pObjectData = GETOBJECTDATAPTR(pSetting);
if (!pObjectData)
{
return E_INVALIDARG;
}
}
break;
case STYPE_EDITTEXT:
case STYPE_COMBOBOX:
if (uPolicyState == BST_CHECKED)
{
dwTemp = (DWORD)SendMessage(pdi->pControlTable[nIndex].hwnd,
WM_GETTEXTLENGTH,0,0);
if (!dwTemp)
{
if (pSetting->dwFlags & DF_REQUIRED)
{
m_pcd->MsgBoxParam(hDlg,IDS_ENTRYREQUIRED,GETNAMEPTR(pSetting),
MB_ICONINFORMATION,MB_OK);
RegCloseKey (hKeyRoot);
return E_FAIL;
}
}
}
break;
case STYPE_NUMERIC:
if (uPolicyState == BST_CHECKED)
{
if (pSetting->dwFlags & DF_REQUIRED)
{
dwTemp = (DWORD)SendMessage(pdi->pControlTable[nIndex].hwnd,
WM_GETTEXTLENGTH,0,0);
if (!dwTemp)
{
if (pSetting->dwFlags & DF_REQUIRED)
{
m_pcd->MsgBoxParam(hDlg,IDS_ENTRYREQUIRED,GETNAMEPTR(pSetting),
MB_ICONINFORMATION,MB_OK);
RegCloseKey (hKeyRoot);
return E_FAIL;
}
}
}
uRet=GetDlgItemInt(pdi->hwndSettings,nIndex+IDD_SETTINGCTRL,
&fTranslated,FALSE);
if (!fTranslated)
{
m_pcd->MsgBoxParam(hDlg,IDS_INVALIDNUM,
GETNAMEPTR(pSetting),MB_ICONINFORMATION,
MB_OK);
SetFocus(pdi->pControlTable[nIndex].hwnd);
SendMessage(pdi->pControlTable[nIndex].hwnd,
EM_SETSEL,0,-1);
RegCloseKey (hKeyRoot);
return E_FAIL;
}
}
break;
case STYPE_DROPDOWNLIST:
if (uPolicyState == BST_CHECKED)
{
iSel = (int)SendMessage(pdi->pControlTable[nIndex].hwnd,
CB_GETCURSEL,0,0L);
iSel = (int)SendMessage(pdi->pControlTable[nIndex].hwnd,
CB_GETITEMDATA,iSel,0L);
if (iSel < 0)
{
m_pcd->MsgBoxParam(hDlg,IDS_ENTRYREQUIRED,GETNAMEPTR(pSetting),
MB_ICONINFORMATION,MB_OK);
SetFocus(pdi->pControlTable[nIndex].hwnd);
RegCloseKey (hKeyRoot);
return E_FAIL;
}
}
else
{
iSel = 0;
}
pddi = (DROPDOWNINFO *) GETOBJECTDATAPTR(pSetting);
iIndex = 0;
// walk the chain of DROPDOWNINFO structs to find the entry that
// we want to write. (for value n, find the nth struct)
while (iIndex < iSel)
{
// selected val is higher than # of structs in chain,
// should never happen but check just in case...
if (!pddi->uOffsetNextDropdowninfo)
{
RegCloseKey (hKeyRoot);
return ERROR_NOT_ENOUGH_MEMORY;
}
pddi = (DROPDOWNINFO *)
((LPBYTE) pSetting + pddi->uOffsetNextDropdowninfo);
iIndex++;
}
break;
case STYPE_LISTBOX:
HGLOBAL hData = (HGLOBAL)GetWindowLongPtr (pdi->pControlTable[nIndex].hwnd, GWLP_USERDATA);
BOOL bEnabled;
WCHAR *pszData;
bFoundNone = FALSE;
bEnabled = (uPolicyState == BST_INDETERMINATE) ? FALSE : TRUE;
if ((bEnabled) && (!hData))
{
bFoundNone = TRUE;
}
else if (bEnabled)
{
pszData = (TCHAR *)GlobalLock (hData);
GlobalUnlock(hData);
// if there are no items at all
if (!(*pszData))
{
bFoundNone = TRUE;
}
pszData = NULL;
}
// if the policy is enabled and no values are set
if ((uPolicyState == BST_CHECKED) && (bFoundNone))
{
m_pcd->MsgBoxParam(hDlg,IDS_ENTRYREQUIRED,GETNAMEPTR(pSetting),
MB_ICONINFORMATION,MB_OK);
SetFocus(pdi->pControlTable[nIndex].hwnd);
RegCloseKey (hKeyRoot);
return E_FAIL;
}
break;
}
}
}
//
// Save the overall policy state
//
if (uPolicyState != BST_INDETERMINATE)
{
if (uPolicyState == BST_CHECKED)
dwTemp = 1;
else
dwTemp = 0;
if (dwTemp && m_pCurrentPolicy->uOffsetValue_On)
{
uRet= WriteCustomValue(hKeyRoot,GETKEYNAMEPTR(m_pCurrentPolicy),GETVALUENAMEPTR(m_pCurrentPolicy),
(STATEVALUE *) ((LPBYTE) m_pCurrentPolicy + m_pCurrentPolicy->uOffsetValue_On),
fErase);
}
else if (!dwTemp && m_pCurrentPolicy->uOffsetValue_Off)
{
uRet= WriteCustomValue(hKeyRoot,GETKEYNAMEPTR(m_pCurrentPolicy),GETVALUENAMEPTR(m_pCurrentPolicy),
(STATEVALUE *) ((LPBYTE) m_pCurrentPolicy + m_pCurrentPolicy->uOffsetValue_Off),
fErase);
}
else
{
if (m_pCurrentPolicy->uOffsetValueName)
{
uRet=WriteStandardValue(hKeyRoot,GETKEYNAMEPTR(m_pCurrentPolicy),GETVALUENAMEPTR(m_pCurrentPolicy),
(TABLEENTRY *)m_pCurrentPolicy,dwTemp,fErase,FALSE);
}
else
{
uRet = ERROR_SUCCESS;
}
}
if (uRet == ERROR_SUCCESS)
{
uRet = ProcessCheckboxActionLists(hKeyRoot,(TABLEENTRY *)m_pCurrentPolicy,
GETKEYNAMEPTR(m_pCurrentPolicy),dwTemp,FALSE, !dwTemp, TRUE);
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::SaveSettings: Failed to set registry value with %d."), uRet));
}
}
else
{
if (m_pCurrentPolicy->uOffsetValueName)
{
uRet=WriteStandardValue(hKeyRoot,GETKEYNAMEPTR(m_pCurrentPolicy),GETVALUENAMEPTR(m_pCurrentPolicy),
(TABLEENTRY *)m_pCurrentPolicy,0,TRUE,FALSE);
}
if (uRet == ERROR_SUCCESS)
{
uRet = ProcessCheckboxActionLists(hKeyRoot,(TABLEENTRY *)m_pCurrentPolicy,
GETKEYNAMEPTR(m_pCurrentPolicy),0,TRUE,FALSE, TRUE);
}
}
//
// Save the state of the parts
//
for (nIndex=0;nIndex<pdi->nControls;nIndex++)
{
pSetting = pdi->pControlTable[nIndex].pSetting;
if (pdi->pControlTable[nIndex].uDataIndex != NO_DATA_INDEX)
{
switch (pdi->pControlTable[nIndex].dwType)
{
case STYPE_CHECKBOX:
dwTemp = (DWORD)SendMessage(pdi->pControlTable[nIndex].hwnd,BM_GETCHECK,0,0L);
pObjectData = GETOBJECTDATAPTR(pSetting);
if (!pObjectData)
{
if (BST_CHECKED == uPolicyState)
{
return E_INVALIDARG;
}
else
{
break;
}
}
if (dwTemp && ((CHECKBOXINFO *) pObjectData)->uOffsetValue_On)
{
uRet= WriteCustomValue(hKeyRoot,
GETKEYNAMEPTR(pSetting),
GETVALUENAMEPTR(pSetting),
(STATEVALUE *) ((LPBYTE) pSetting + ((CHECKBOXINFO *) pObjectData)->uOffsetValue_On),
fErase);
}
else if (!dwTemp && ((CHECKBOXINFO *) pObjectData)->uOffsetValue_Off)
{
uRet= WriteCustomValue(hKeyRoot,GETKEYNAMEPTR(pSetting),
GETVALUENAMEPTR(pSetting),
(STATEVALUE *) ((LPBYTE) pSetting + ((CHECKBOXINFO *) pObjectData)->uOffsetValue_Off),
fErase);
}
else
{
uRet=WriteStandardValue(hKeyRoot,
GETKEYNAMEPTR(pSetting),
GETVALUENAMEPTR(pSetting),
(TABLEENTRY *)pSetting,
dwTemp,
fErase,
FALSE);
}
if (uRet == ERROR_SUCCESS)
{
uRet = ProcessCheckboxActionLists(hKeyRoot,(TABLEENTRY *)pSetting,
GETKEYNAMEPTR(pSetting),
dwTemp,
fErase,
(uPolicyState == BST_UNCHECKED),
FALSE);
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::SaveSettings: Failed to set registry value with %d."), uRet));
}
break;
case STYPE_EDITTEXT:
case STYPE_COMBOBOX:
if (uPolicyState == BST_CHECKED)
{
dwTemp = (DWORD)SendMessage(pdi->pControlTable[nIndex].hwnd,
WM_GETTEXTLENGTH,0,0);
if (!dwTemp)
{
if (pSetting->dwFlags & DF_REQUIRED)
{
m_pcd->MsgBoxParam(hDlg,IDS_ENTRYREQUIRED,GETNAMEPTR(pSetting),
MB_ICONINFORMATION,MB_OK);
RegCloseKey (hKeyRoot);
return E_FAIL;
}
}
lpBuffer = (LPTSTR) LocalAlloc (LPTR, (dwTemp + 1) * sizeof(TCHAR));
if (lpBuffer)
{
SendMessage(pdi->pControlTable[nIndex].hwnd,WM_GETTEXT,
(dwTemp+1),(LPARAM) lpBuffer);
uRet = WriteCustomValue_W(hKeyRoot,
GETKEYNAMEPTR(pSetting),
GETVALUENAMEPTR(pSetting),
lpBuffer, 0, pSetting->dwFlags, FALSE);
if (uRet != ERROR_SUCCESS)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::SaveSettings: Failed to set registry value with %d."), uRet));
}
LocalFree (lpBuffer);
}
else
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::SaveSettings: Failed to allocate memory with %d."),
GetLastError()));
}
}
else
{
WriteCustomValue_W(hKeyRoot,GETKEYNAMEPTR(pSetting),GETVALUENAMEPTR(pSetting),
(LPTSTR)g_szNull,0,
(uPolicyState == BST_UNCHECKED) ? VF_DELETE : 0,
fErase);
}
break;
case STYPE_NUMERIC:
if (uPolicyState == BST_CHECKED)
{
if (pSetting->dwFlags & DF_REQUIRED)
{
dwTemp = (DWORD)SendMessage(pdi->pControlTable[nIndex].hwnd,
WM_GETTEXTLENGTH,0,0);
if (!dwTemp)
{
if (pSetting->dwFlags & DF_REQUIRED)
{
m_pcd->MsgBoxParam(hDlg,IDS_ENTRYREQUIRED,GETNAMEPTR(pSetting),
MB_ICONINFORMATION,MB_OK);
RegCloseKey (hKeyRoot);
return E_FAIL;
}
}
}
uRet=GetDlgItemInt(pdi->hwndSettings,nIndex+IDD_SETTINGCTRL,
&fTranslated,FALSE);
// validate for max and min
pNumericInfo = (NUMERICINFO *) GETOBJECTDATAPTR(pSetting);
if (pNumericInfo && uRet < pNumericInfo->uMinValue)
{
LoadString(g_hInstance, IDS_NUMBERTOOSMALL, szFormat, ARRAYSIZE(szFormat));
hr = StringCchPrintf(szMsg, ARRAYSIZE(szMsg), szFormat, uRet, pNumericInfo->uMinValue, pNumericInfo->uMinValue, uRet);
ASSERT(SUCCEEDED(hr));
m_pcd->MsgBoxSz(hDlg,szMsg, MB_ICONINFORMATION, MB_OK);
uRet = pNumericInfo->uMinValue;
}
if (pNumericInfo && uRet > pNumericInfo->uMaxValue)
{
LoadString(g_hInstance, IDS_NUMBERTOOLARGE, szFormat, ARRAYSIZE(szFormat));
hr = StringCchPrintf (szMsg, ARRAYSIZE(szMsg), szFormat, uRet, pNumericInfo->uMaxValue, pNumericInfo->uMaxValue, uRet);
ASSERT(SUCCEEDED(hr));
m_pcd->MsgBoxSz(hDlg,szMsg, MB_ICONINFORMATION, MB_OK);
uRet = pNumericInfo->uMaxValue;
}
}
else
{
uRet = 0;
}
uRet=WriteStandardValue(hKeyRoot,GETKEYNAMEPTR(pSetting),
GETVALUENAMEPTR(pSetting),
(TABLEENTRY *)pSetting,uRet,
fErase,(uPolicyState == BST_UNCHECKED) ? FALSE : TRUE);
if (uRet != ERROR_SUCCESS)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::SaveSettings: Failed to set registry value with %d."), uRet));
}
break;
case STYPE_DROPDOWNLIST:
if (uPolicyState == BST_CHECKED)
{
iSel = (int)SendMessage(pdi->pControlTable[nIndex].hwnd,
CB_GETCURSEL,0,0L);
iSel = (int)SendMessage(pdi->pControlTable[nIndex].hwnd,
CB_GETITEMDATA,iSel,0L);
if (iSel < 0)
{
m_pcd->MsgBoxParam(hDlg,IDS_ENTRYREQUIRED,GETNAMEPTR(pSetting),
MB_ICONINFORMATION,MB_OK);
SetFocus(pdi->pControlTable[nIndex].hwnd);
RegCloseKey (hKeyRoot);
return E_FAIL;
}
}
else
{
iSel = 0;
}
pddi = (DROPDOWNINFO *) GETOBJECTDATAPTR(pSetting);
iIndex = 0;
// walk the chain of DROPDOWNINFO structs to find the entry that
// we want to write. (for value n, find the nth struct)
while (iIndex < iSel) {
// selected val is higher than # of structs in chain,
// should never happen but check just in case...
if (!pddi->uOffsetNextDropdowninfo)
{
RegCloseKey (hKeyRoot);
return ERROR_NOT_ENOUGH_MEMORY;
}
pddi = (DROPDOWNINFO *)
((LPBYTE) pSetting + pddi->uOffsetNextDropdowninfo);
iIndex++;
}
uRet=WriteCustomValue_W(hKeyRoot,GETKEYNAMEPTR(pSetting),GETVALUENAMEPTR(pSetting),
(LPTSTR) ((LPBYTE)pSetting+pddi->uOffsetValue),pddi->dwValue,
pddi->dwFlags | ((uPolicyState == BST_UNCHECKED) ? VF_DELETE : 0),
fErase);
if (uRet == ERROR_SUCCESS && pddi->uOffsetActionList) {
uRet=WriteActionList(hKeyRoot,(ACTIONLIST *) ( (LPBYTE)
pSetting + pddi->uOffsetActionList),GETKEYNAMEPTR(pSetting),
fErase, (uPolicyState == BST_UNCHECKED));
}
if (uRet != ERROR_SUCCESS)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::SaveSettings: Failed to set registry value with %d."), uRet));
}
break;
case STYPE_LISTBOX:
bFoundNone = FALSE;
SaveListboxData((HGLOBAL)GetWindowLongPtr (pdi->pControlTable[nIndex].hwnd, GWLP_USERDATA),
pSetting, hKeyRoot, GETKEYNAMEPTR(pSetting), fErase,
((uPolicyState == BST_INDETERMINATE) ? FALSE : TRUE),
(uPolicyState == BST_CHECKED), &bFoundNone);
// if the policy is enabled and no values are set
if ((uPolicyState == BST_CHECKED) && (bFoundNone)) {
m_pcd->MsgBoxParam(hDlg,IDS_ENTRYREQUIRED,GETNAMEPTR(pSetting),
MB_ICONINFORMATION,MB_OK);
SetFocus(pdi->pControlTable[nIndex].hwnd);
RegCloseKey (hKeyRoot);
return E_FAIL;
}
break;
}
if (pSetting->uOffsetClientExt)
{
lpClientGUID = (LPTSTR) ((BYTE *) pSetting + pSetting->uOffsetClientExt);
StringToGuid (lpClientGUID, &ClientGUID);
m_pcd->m_pGPTInformation->PolicyChanged(!m_pcd->m_bUserScope, TRUE, &ClientGUID,
m_pcd->m_bUserScope ? &guidSnapinUser
: &guidSnapinMach );
}
}
}
hr = m_pcd->m_pGPTInformation->PolicyChanged(!m_pcd->m_bUserScope, TRUE, &guidRegistryExt,
m_pcd->m_bUserScope ? &guidSnapinUser
: &guidSnapinMach );
if (FAILED(hr))
{
LPTSTR lpError;
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
0, hr, 0, (LPTSTR) &lpError, 0, NULL))
{
m_pcd->MsgBoxParam(hDlg,IDS_POLICYCHANGEDFAILED,lpError,
MB_ICONERROR, MB_OK);
LocalFree (lpError);
}
}
if (m_pCurrentPolicy->uOffsetClientExt)
{
lpClientGUID = (LPTSTR) ((BYTE *) m_pCurrentPolicy + m_pCurrentPolicy->uOffsetClientExt);
StringToGuid (lpClientGUID, &ClientGUID);
m_pcd->m_pGPTInformation->PolicyChanged(!m_pcd->m_bUserScope, TRUE, &ClientGUID,
m_pcd->m_bUserScope ? &guidSnapinUser
: &guidSnapinMach );
}
RegCloseKey (hKeyRoot);
SendMessage (m_hMsgWindow, WM_UPDATEITEM, 0, 0);
if (SUCCEEDED(hr))
{
m_bDirty = FALSE;
PostMessage (GetParent(hDlg), PSM_UNCHANGED, (WPARAM) hDlg, 0);
}
return S_OK;
}
VOID CPolicySnapIn::DeleteOldListboxData(SETTINGS * pSetting, HKEY hkeyRoot,
TCHAR * pszCurrentKeyName)
{
HGLOBAL hData = NULL;
LPTSTR lpData;
HKEY hKey;
TCHAR szValueName[MAX_PATH+1];
INT nItem=1;
LISTBOXINFO * pListboxInfo = (LISTBOXINFO *) GETOBJECTDATAPTR(pSetting);
HRESULT hr = S_OK;
//
// Open the target registry key
//
if (RegOpenKeyEx (hkeyRoot, pszCurrentKeyName, 0, KEY_WRITE, &hKey) != ERROR_SUCCESS)
{
return;
}
//
// Load the old listbox data
//
if (LoadListboxData((TABLEENTRY *) pSetting, hkeyRoot,
pszCurrentKeyName, NULL, &hData, NULL) == ERROR_SUCCESS)
{
if (hData)
{
//
// Delete the listbox's old data
//
if ((lpData = (LPTSTR) GlobalLock(hData)))
{
while (*lpData) {
if (pSetting->dwFlags & DF_EXPLICITVALNAME)
{
// if explicit valuename flag set, entries are stored
// <value name>\0<value>\0....<value name>\0<value>\0\0
// otherwise, entries are stored
// <value>\0<value>\0....<value>\0
RegDeleteValue (hKey, lpData);
lpData += lstrlen(lpData) +1;
lpData += lstrlen(lpData) +1;
}
else
{
//
// Value name is either same as the data, or a prefix
// with a number
//
if (!pListboxInfo->uOffsetPrefix)
{
// if no prefix set, then name = data
RegDeleteValue (hKey, lpData);
lpData += lstrlen(lpData) +1;
}
else
{
// value name is "<prefix><n>" where n=1,2,etc.
hr = StringCchPrintf(szValueName, ARRAYSIZE(szValueName), TEXT("%s%lu"),(TCHAR *) ((LPBYTE)pSetting +
pListboxInfo->uOffsetPrefix),nItem);
ASSERT(SUCCEEDED(hr));
RegDeleteValue (hKey, szValueName);
lpData += lstrlen(lpData) +1;
nItem++;
}
}
}
GlobalUnlock(hData);
}
GlobalFree (hData);
}
}
RegCloseKey (hKey);
}
UINT CPolicySnapIn::SaveListboxData(HGLOBAL hData,SETTINGS * pSetting,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,BOOL fErase,BOOL fMarkDeleted, BOOL bEnabled, BOOL * bFoundNone)
{
UINT uOffset,uRet,nItem=1;
HKEY hKey;
TCHAR * pszData,* pszName;
TCHAR szValueName[MAX_PATH+1];
DWORD cbValueName, dwDisp;
LISTBOXINFO * pListboxInfo = (LISTBOXINFO *) GETOBJECTDATAPTR(pSetting);
HRESULT hr = S_OK;
// these checks need to be done first before any other operations are done
if ((bEnabled) && (!hData)) {
*bFoundNone = TRUE;
return ERROR_INVALID_PARAMETER;
}
if (bEnabled) {
pszData = (TCHAR *)GlobalLock (hData);
// if there are no items at all
if (!(*pszData)) {
*bFoundNone = TRUE;
GlobalUnlock(hData);
return ERROR_INVALID_PARAMETER;
}
GlobalUnlock(hData);
pszData = NULL;
}
*bFoundNone = FALSE;
if (fErase)
{
RegDelnode (hkeyRoot, pszCurrentKeyName);
RegCleanUpValue (hkeyRoot, pszCurrentKeyName, TEXT("some value that won't exist"));
return ERROR_SUCCESS;
}
if (pSetting->dwFlags & DF_ADDITIVE)
{
DeleteOldListboxData(pSetting, hkeyRoot, pszCurrentKeyName);
}
else
{
RegDelnode (hkeyRoot, pszCurrentKeyName);
}
uRet = RegCreateKeyEx (hkeyRoot,pszCurrentKeyName,0,NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
&hKey, &dwDisp);
if (uRet != ERROR_SUCCESS)
return uRet;
uRet=ERROR_SUCCESS;
if (fMarkDeleted)
{
//
// Write a control code that will cause
// all values under that key to be deleted when client downloads from the file.
// Don't do this if listbox is additive (DF_ADDITIVE), in that case whatever
// we write here will be dumped in along with existing values
//
if (!(pSetting->dwFlags & DF_ADDITIVE))
{
uRet=WriteRegistryStringValue(hkeyRoot,pszCurrentKeyName,
(TCHAR *) szDELVALS,
(TCHAR *) szNOVALUE, FALSE);
}
}
if (hData) {
pszData = (TCHAR *)GlobalLock (hData);
while (*pszData && (uRet == ERROR_SUCCESS))
{
UINT nLen = lstrlen(pszData)+1;
if (pSetting->dwFlags & DF_EXPLICITVALNAME)
{
// value name specified for each item
pszName = pszData; // value name
pszData += nLen; // now pszData points to value data
nLen = lstrlen(pszData)+1;
}
else
{
// value name is either same as the data, or a prefix
// with a number
if (!pListboxInfo->uOffsetPrefix) {
// if no prefix set, then name = data
pszName = pszData;
} else {
// value name is "<prefix><n>" where n=1,2,etc.
hr = StringCchPrintf(szValueName, ARRAYSIZE(szValueName), TEXT("%s%lu"),(TCHAR *) ((LPBYTE)pSetting +
pListboxInfo->uOffsetPrefix),nItem);
ASSERT(SUCCEEDED(hr));
pszName = szValueName;
nItem++;
}
}
uRet=RegSetValueEx(hKey,pszName,0,
(pSetting->dwFlags & DF_EXPANDABLETEXT) ?
REG_EXPAND_SZ : REG_SZ, (LPBYTE) pszData,
(lstrlen(pszData) + 1) * sizeof(TCHAR));
pszData += nLen;
}
GlobalUnlock (hData);
}
RegCloseKey(hKey);
return uRet;
}
UINT CPolicySnapIn::ProcessCheckboxActionLists(HKEY hkeyRoot,TABLEENTRY * pTableEntry,
TCHAR * pszCurrentKeyName,DWORD dwData,
BOOL fErase, BOOL fMarkAsDeleted,
BOOL bPolicy)
{
UINT uOffsetActionList_On,uOffsetActionList_Off,uRet=ERROR_SUCCESS;
if (bPolicy)
{
POLICY * pPolicy = (POLICY *) pTableEntry;
uOffsetActionList_On = pPolicy->uOffsetActionList_On;
uOffsetActionList_Off = pPolicy->uOffsetActionList_Off;
}
else
{
LPBYTE pObjectData = GETOBJECTDATAPTR(((SETTINGS *)pTableEntry));
if (!pObjectData) {
return ERROR_INVALID_PARAMETER;
}
uOffsetActionList_On = ((CHECKBOXINFO *) pObjectData)
->uOffsetActionList_On;
uOffsetActionList_Off = ((CHECKBOXINFO *) pObjectData)
->uOffsetActionList_Off;
}
if (dwData)
{
if (uOffsetActionList_On)
{
uRet = WriteActionList(hkeyRoot,(ACTIONLIST *)
((LPBYTE) pTableEntry + uOffsetActionList_On),
pszCurrentKeyName,fErase,fMarkAsDeleted);
}
}
else
{
if (uOffsetActionList_Off)
{
uRet = WriteActionList(hkeyRoot,(ACTIONLIST *)
((LPBYTE) pTableEntry + uOffsetActionList_Off),
pszCurrentKeyName,fErase,FALSE);
}
else
{
if (uOffsetActionList_On)
{
uRet = WriteActionList(hkeyRoot,(ACTIONLIST *)
((LPBYTE) pTableEntry + uOffsetActionList_On),
pszCurrentKeyName,fErase,TRUE);
}
}
}
return uRet;
}
UINT CPolicySnapIn::WriteActionList(HKEY hkeyRoot,ACTIONLIST * pActionList,
LPTSTR pszCurrentKeyName,BOOL fErase, BOOL fMarkAsDeleted)
{
UINT nCount;
LPTSTR pszValueName;
LPTSTR pszValue=NULL;
UINT uRet;
ACTION * pAction = pActionList->Action;
for (nCount=0;nCount < pActionList->nActionItems; nCount++)
{
//
// Not every action in the list has to have a key name. But if one
// is specified, use it and it becomes the current key name for the
// list until we encounter another one.
//
if (pAction->uOffsetKeyName)
{
pszCurrentKeyName = (LPTSTR) ((LPBYTE)pActionList + pAction->uOffsetKeyName);
}
//
// Every action must have a value name, enforced at parse time
//
pszValueName = (LPTSTR) ((LPBYTE)pActionList + pAction->uOffsetValueName);
//
// String values have a string elsewhere in buffer
//
if (!pAction->dwFlags && pAction->uOffsetValue)
{
pszValue = (LPTSTR) ((LPBYTE)pActionList + pAction->uOffsetValue);
}
//
// Write the value in list
//
uRet=WriteCustomValue_W(hkeyRoot,pszCurrentKeyName,pszValueName,
pszValue,pAction->dwValue,
pAction->dwFlags | (fMarkAsDeleted ? VF_DELETE : 0),
fErase);
if (uRet != ERROR_SUCCESS)
{
return uRet;
}
pAction = (ACTION*) ((LPBYTE) pActionList + pAction->uOffsetNextAction);
}
return ERROR_SUCCESS;
}
/*******************************************************************
NAME: FindComboboxItemData
SYNOPSIS: Returns the index of item in combobox whose item data
is equal to nData. Returns -1 if no items have data
which matches.
********************************************************************/
int CPolicySnapIn::FindComboboxItemData(HWND hwndControl,UINT nData)
{
UINT nIndex;
for (nIndex=0;nIndex<(UINT) SendMessage(hwndControl,CB_GETCOUNT,0,0L);
nIndex++) {
if ((UINT) SendMessage(hwndControl,CB_GETITEMDATA,nIndex,0L) == nData)
return (int) nIndex;
}
return -1;
}
//*************************************************************
//
// InitializeSettingsControls()
//
// Purpose: Initializes the settings controls
//
// Parameters:
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
HRESULT CPolicySnapIn::InitializeSettingsControls(HWND hDlg, BOOL fEnable)
{
UINT nIndex;
POLICYDLGINFO * pdi;
LPSETTINGSINFO lpSettingsInfo;
SETTINGS * pSetting;
HKEY hKeyRoot;
DWORD dwTemp, dwData, dwFlags, dwFoundSettings;
UINT uRet;
int iSel;
HGLOBAL hData;
LPTSTR lpBuffer;
BOOL fTranslated, fFound;
NUMERICINFO * pNumericInfo;
TCHAR szBuffer[MAXSTRLEN];
TCHAR szNewValueName[MAX_PATH+1];
BOOL bChangeableState;
HRESULT hr = S_OK;
// get instance-specific struct from dialog
lpSettingsInfo = (LPSETTINGSINFO) GetWindowLongPtr(hDlg, DWLP_USER);
if (!lpSettingsInfo)
return E_FAIL;
pdi = lpSettingsInfo->pdi;
if (!pdi)
return E_FAIL;
if (m_pcd->m_bRSOP)
{
hKeyRoot = (HKEY) 1;
}
else
{
if (m_pcd->m_pGPTInformation->GetRegistryKey(
(m_pcd->m_bUserScope ? GPO_SECTION_USER : GPO_SECTION_MACHINE),
&hKeyRoot) != S_OK)
{
DebugMsg((DM_WARNING, TEXT("CPolicySnapIn::InitializeSettingsControls: Failed to get registry key handle.")));
return S_FALSE;
}
}
for (nIndex=0;nIndex<pdi->nControls;nIndex++)
{
pSetting = pdi->pControlTable[nIndex].pSetting;
if (pdi->pControlTable[nIndex].uDataIndex != NO_DATA_INDEX)
{
switch (pdi->pControlTable[nIndex].dwType)
{
case STYPE_CHECKBOX:
if (fEnable)
{
CHECKBOXINFO * pcbi = (CHECKBOXINFO *) GETOBJECTDATAPTR(pSetting);
//
// First look for custom on/off values
//
dwTemp = 0;
fFound = FALSE;
dwFoundSettings = 0;
if (pcbi->uOffsetValue_On)
{
if (CompareCustomValue(hKeyRoot,GETKEYNAMEPTR(pSetting),GETVALUENAMEPTR(pSetting),
(STATEVALUE *) ((BYTE *) pSetting + pcbi->uOffsetValue_On),
&dwFoundSettings, NULL))
{
dwTemp = 1;
fFound = TRUE;
}
}
if (!fFound && pcbi->uOffsetValue_Off)
{
if (CompareCustomValue(hKeyRoot,GETKEYNAMEPTR(pSetting),GETVALUENAMEPTR(pSetting),
(STATEVALUE *) ((BYTE *) pSetting+ pcbi->uOffsetValue_Off),
&dwFoundSettings, NULL))
{
dwTemp = 0;
fFound = TRUE;
}
}
//
// Look for standard values if custom values have not been specified
//
if (!fFound &&
ReadStandardValue(hKeyRoot,GETKEYNAMEPTR(pSetting),GETVALUENAMEPTR(pSetting),
(TABLEENTRY*)pSetting,&dwTemp,&dwFoundSettings,NULL))
{
fFound = TRUE;
}
//
// If still not found, check for the def checked flag
//
if (!fFound)
{
if (pSetting->dwFlags & DF_USEDEFAULT)
{
fFound = TRUE;
dwTemp = 1;
}
}
if (fFound && dwTemp)
{
SendMessage(pdi->pControlTable[nIndex].hwnd,BM_SETCHECK,BST_CHECKED,0L);
}
else
{
SendMessage(pdi->pControlTable[nIndex].hwnd,BM_SETCHECK,BST_UNCHECKED,0L);
}
}
else
{
SendMessage(pdi->pControlTable[nIndex].hwnd,BM_SETCHECK,BST_UNCHECKED,0L);
}
break;
case STYPE_EDITTEXT:
case STYPE_COMBOBOX:
szBuffer[0] = TEXT('\0');
if (fEnable)
{
uRet = ReadRegistryStringValue(hKeyRoot,
GETKEYNAMEPTR(pSetting),
GETVALUENAMEPTR(pSetting),
szBuffer, ARRAYSIZE(szBuffer),NULL);
//
// Use default text if it exists
//
if (uRet != ERROR_SUCCESS)
{
if (pSetting->dwFlags & DF_USEDEFAULT)
{
LPTSTR pszDefaultText;
EDITTEXTINFO * peti = ((EDITTEXTINFO *) GETOBJECTDATAPTR(pSetting));
pszDefaultText = (LPTSTR) ((LPBYTE)pSetting + peti->uOffsetDefText);
hr = StringCchCopy (szBuffer, ARRAYSIZE(szBuffer), pszDefaultText);
ASSERT(SUCCEEDED(hr));
}
}
}
SendMessage (pdi->pControlTable[nIndex].hwnd, WM_SETTEXT,
0, (LPARAM) szBuffer);
break;
case STYPE_NUMERIC:
if (fEnable)
{
if (ReadStandardValue(hKeyRoot,GETKEYNAMEPTR(pSetting),GETVALUENAMEPTR(pSetting),
(TABLEENTRY*)pSetting,&dwTemp,&dwFoundSettings,NULL) &&
(!(dwFoundSettings & FS_DELETED)))
{
SetDlgItemInt(pdi->hwndSettings,nIndex+IDD_SETTINGCTRL,
dwTemp,FALSE);
}
else
{
if (pSetting->dwFlags & DF_USEDEFAULT)
{
NUMERICINFO * pni = (NUMERICINFO *)GETOBJECTDATAPTR(pSetting);
SetDlgItemInt(pdi->hwndSettings,nIndex+IDD_SETTINGCTRL,
pni->uDefValue,FALSE);
}
}
}
else
{
SendMessage(pdi->pControlTable[nIndex].hwnd,WM_SETTEXT,0,(LPARAM) g_szNull);
}
break;
case STYPE_DROPDOWNLIST:
if (fEnable)
{
dwData = 0;
dwFlags = 0;
if (ReadCustomValue(hKeyRoot,GETKEYNAMEPTR(pSetting),
GETVALUENAMEPTR(pSetting),
szBuffer,ARRAYSIZE(szBuffer),
&dwData,&dwFlags, NULL) && (!(dwFlags & VF_DELETE)))
{
BOOL fMatch = FALSE;
//
// Walk the list of DROPDOWNINFO structs (one for each state),
// and see if the value we found matches the value for the state
//
if (pSetting->uOffsetObjectData)
{
DROPDOWNINFO * pddi = (DROPDOWNINFO *) GETOBJECTDATAPTR(pSetting);
iSel = 0;
do {
if (dwFlags == pddi->dwFlags)
{
if (pddi->dwFlags & VF_ISNUMERIC)
{
if (dwData == pddi->dwValue)
fMatch = TRUE;
}
else if (!pddi->dwFlags)
{
if (!lstrcmpi(szBuffer,(TCHAR *)((BYTE *)pSetting +
pddi->uOffsetValue)))
fMatch = TRUE;
}
}
if (!pddi->uOffsetNextDropdowninfo || fMatch)
break;
pddi = (DROPDOWNINFO *) ( (BYTE *) pSetting +
pddi->uOffsetNextDropdowninfo);
iSel++;
} while (!fMatch);
if (fMatch) {
SendMessage (pdi->pControlTable[nIndex].hwnd,
CB_SETCURSEL,
FindComboboxItemData(pdi->pControlTable[nIndex].hwnd, iSel),0);
}
}
}
else
{
if (pSetting->dwFlags & DF_USEDEFAULT)
{
DROPDOWNINFO * pddi = (DROPDOWNINFO *)GETOBJECTDATAPTR(pSetting);
if ( pddi )
{
SendMessage (pdi->pControlTable[nIndex].hwnd, CB_SETCURSEL,
FindComboboxItemData(pdi->pControlTable[nIndex].hwnd, pddi->uDefaultItemIndex),0);
}
}
}
}
else
{
SendMessage(pdi->pControlTable[nIndex].hwnd,CB_SETCURSEL,(UINT) -1,0L);
}
break;
case STYPE_LISTBOX:
hData = (HGLOBAL) GetWindowLongPtr (pdi->pControlTable[nIndex].hwnd, GWLP_USERDATA);
if (fEnable)
{
if (!hData)
{
if (LoadListboxData((TABLEENTRY *) pSetting, hKeyRoot,
GETKEYNAMEPTR(pSetting),NULL,
&hData, NULL) == ERROR_SUCCESS)
{
SetWindowLongPtr (pdi->pControlTable[nIndex].hwnd, GWLP_USERDATA, (LONG_PTR)hData);
}
}
}
else
{
if (hData)
{
GlobalFree (hData);
SetWindowLongPtr (pdi->pControlTable[nIndex].hwnd, GWLP_USERDATA, 0);
}
}
break;
}
}
//
// Decide if the part should be enabled or not
//
// Special case text, numeric and listbox controls.
// When the policy is disabled, text controls should still be enabled.
// Numeric controls are special because they use the NO_DATA_INDEX
// flag, so we need to check for those. Listbox controls are special
// in RSOP only.
//
bChangeableState = TRUE;
if (pdi->pControlTable[nIndex].uDataIndex == NO_DATA_INDEX)
{
if (pdi->pControlTable[nIndex].dwType != (STYPE_TEXT | STYPE_NUMERIC))
{
bChangeableState = FALSE;
}
}
if (pdi->pControlTable[nIndex].dwType == STYPE_LISTBOX)
{
if (m_pcd->m_bRSOP)
{
bChangeableState = FALSE;
}
}
if (bChangeableState)
{
if (m_pcd->m_bRSOP && (STYPE_EDITTEXT == pdi->pControlTable[nIndex].dwType) )
{
EnableWindow(pdi->pControlTable[nIndex].hwnd, TRUE);
SendMessage( pdi->pControlTable[nIndex].hwnd, EM_SETREADONLY, TRUE, 0);
}
else
EnableWindow(pdi->pControlTable[nIndex].hwnd, (m_pcd->m_bRSOP ? FALSE :fEnable));
}
else
EnableWindow(pdi->pControlTable[nIndex].hwnd,TRUE);
}
if (!m_pcd->m_bRSOP)
{
RegCloseKey (hKeyRoot);
}
return S_OK;
}
VOID CPolicySnapIn::ShowListbox(HWND hParent,SETTINGS * pSettings)
{
LISTBOXDLGINFO ListboxDlgInfo;
ListboxDlgInfo.pCS = this;
ListboxDlgInfo.pSettings = pSettings;
ListboxDlgInfo.hData = (HGLOBAL)GetWindowLongPtr (hParent, GWLP_USERDATA);
if (DialogBoxParam(g_hInstance,MAKEINTRESOURCE(IDD_POLICY_SHOWLISTBOX),hParent,
ShowListboxDlgProc,(LPARAM) &ListboxDlgInfo))
{
SetWindowLongPtr (hParent, GWLP_USERDATA, (LONG_PTR) ListboxDlgInfo.hData);
}
}
INT_PTR CALLBACK CPolicySnapIn::ShowListboxDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
switch (uMsg) {
case WM_INITDIALOG:
{
LISTBOXDLGINFO * pLBInfo = (LISTBOXDLGINFO *)lParam;
//
// Store away pointer to ListboxDlgInfo in window data
//
SetWindowLongPtr(hDlg,DWLP_USER,lParam);
if (!pLBInfo->pCS->InitShowlistboxDlg(hDlg)) {
pLBInfo->pCS->m_pcd->MsgBox(hDlg,IDS_ErrOUTOFMEMORY,MB_ICONEXCLAMATION,MB_OK);
EndDialog(hDlg,FALSE);
}
}
return TRUE;
case WM_COMMAND:
switch (wParam) {
case IDOK:
{
LISTBOXDLGINFO * pListboxDlgInfo =
(LISTBOXDLGINFO *) GetWindowLongPtr(hDlg,DWLP_USER);
if (!pListboxDlgInfo->pCS->m_pcd->m_bRSOP)
{
if (!pListboxDlgInfo->pCS->ProcessShowlistboxDlg(hDlg)) {
pListboxDlgInfo->pCS->m_pcd->MsgBox(hDlg,IDS_ErrOUTOFMEMORY,MB_ICONEXCLAMATION,MB_OK);
return FALSE;
}
}
EndDialog(hDlg,TRUE);
}
break;
case IDCANCEL:
EndDialog(hDlg,FALSE);
break;
case IDC_POLICY_ADD:
{
LISTBOXDLGINFO * pListboxDlgInfo =
(LISTBOXDLGINFO *) GetWindowLongPtr(hDlg,DWLP_USER);
pListboxDlgInfo->pCS->ListboxAdd(GetDlgItem(hDlg,IDC_POLICY_LISTBOX), (BOOL)
pListboxDlgInfo->pSettings->dwFlags & DF_EXPLICITVALNAME,
(BOOL)( ((LISTBOXINFO *)
GETOBJECTDATAPTR(pListboxDlgInfo->pSettings))->
uOffsetPrefix));
}
break;
case IDC_POLICY_REMOVE:
{
LISTBOXDLGINFO * pListboxDlgInfo =
(LISTBOXDLGINFO *) GetWindowLongPtr(hDlg,DWLP_USER);
pListboxDlgInfo->pCS->ListboxRemove(hDlg,GetDlgItem(hDlg,IDC_POLICY_LISTBOX));
}
break;
}
break;
case WM_NOTIFY:
if (wParam == IDC_POLICY_LISTBOX) {
if (((NMHDR FAR*)lParam)->code == LVN_ITEMCHANGED) {
LISTBOXDLGINFO * pListboxDlgInfo =
(LISTBOXDLGINFO *) GetWindowLongPtr(hDlg,DWLP_USER);
if (!pListboxDlgInfo->pCS->m_pcd->m_bRSOP)
{
pListboxDlgInfo->pCS->EnableShowListboxButtons(hDlg);
}
}
}
break;
}
return FALSE;
}
BOOL CPolicySnapIn::InitShowlistboxDlg(HWND hDlg)
{
LISTBOXDLGINFO * pListboxDlgInfo;
SETTINGS * pSettings;
LV_COLUMN lvc;
RECT rcListbox;
UINT uColWidth,uOffsetData;
HWND hwndListbox;
BOOL fSuccess=TRUE;
LONG lStyle;
TCHAR szBuffer[SMALLBUF];
LPTSTR lpData;
pListboxDlgInfo = (LISTBOXDLGINFO *)GetWindowLongPtr (hDlg, DWLP_USER);
if (!pListboxDlgInfo)
return FALSE;
pSettings = pListboxDlgInfo->pSettings;
hwndListbox = GetDlgItem(hDlg,IDC_POLICY_LISTBOX);
//
// Turn off the header if we don't need it
//
if (!m_pcd->m_bRSOP)
{
if (!(pSettings->dwFlags & DF_EXPLICITVALNAME))
{
lStyle = GetWindowLong (hwndListbox, GWL_STYLE);
lStyle |= LVS_NOCOLUMNHEADER;
SetWindowLong (hwndListbox, GWL_STYLE, lStyle);
}
}
SendMessage(hwndListbox, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);
//
// Set the setting title in the dialog
//
SetDlgItemText(hDlg,IDC_POLICY_TITLE,GETNAMEPTR(pSettings));
GetClientRect(hwndListbox,&rcListbox);
uColWidth = rcListbox.right-rcListbox.left;
if (m_pcd->m_bRSOP)
{
if (pSettings->dwFlags & DF_EXPLICITVALNAME)
{
uColWidth /= 3;
}
else
{
uColWidth /= 2;
}
}
else
{
if (pSettings->dwFlags & DF_EXPLICITVALNAME)
{
uColWidth /= 2;
}
}
if (pSettings->dwFlags & DF_EXPLICITVALNAME) {
//
// add a 2nd column to the listview control
//
LoadString(g_hInstance,IDS_VALUENAME,szBuffer,ARRAYSIZE(szBuffer));
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = uColWidth-1;
lvc.pszText = szBuffer;
lvc.cchTextMax = lstrlen(lvc.pszText)+1;
lvc.iSubItem = 0;
ListView_InsertColumn(hwndListbox,0,&lvc);
}
//
// Add a column to the listview control
//
LoadString(g_hInstance,IDS_VALUE,szBuffer,ARRAYSIZE(szBuffer));
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = uColWidth;
lvc.pszText = szBuffer;
lvc.cchTextMax = lstrlen(lvc.pszText)+1;
lvc.iSubItem = (pSettings->dwFlags & DF_EXPLICITVALNAME ? 1 : 0);
ListView_InsertColumn(hwndListbox,lvc.iSubItem,&lvc);
if (m_pcd->m_bRSOP)
{
//
// Add the GPO Name column to the listview control
//
LoadString(g_hInstance,IDS_GPONAME,szBuffer,ARRAYSIZE(szBuffer));
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = uColWidth;
lvc.pszText = szBuffer;
lvc.cchTextMax = lstrlen(lvc.pszText)+1;
lvc.iSubItem = (pSettings->dwFlags & DF_EXPLICITVALNAME ? 2 : 1);
ListView_InsertColumn(hwndListbox,lvc.iSubItem,&lvc);
}
if (m_pcd->m_bRSOP)
{
EnableWindow(GetDlgItem(hDlg,IDC_POLICY_REMOVE), FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_POLICY_ADD), FALSE);
}
else
{
EnableShowListboxButtons(hDlg);
}
if (pListboxDlgInfo->hData)
{
//
// Insert the items from user's data buffer into the listbox
//
if ((lpData = (LPTSTR) GlobalLock(pListboxDlgInfo->hData)))
{
while (*lpData && fSuccess) {
LV_ITEM lvi;
lvi.pszText=lpData;
lvi.mask = LVIF_TEXT;
lvi.iItem=-1;
lvi.iSubItem=0;
lvi.cchTextMax = lstrlen(lpData)+1;
fSuccess=((lvi.iItem=ListView_InsertItem(hwndListbox,&lvi)) >= 0);
lpData += lstrlen(lpData) +1;
// if explicit valuename flag set, entries are stored
// <value name>\0<value>\0....<value name>\0<value>\0\0
// otherwise, entries are stored
// <value>\0<value>\0....<value>\0
if (pSettings->dwFlags & DF_EXPLICITVALNAME) {
if (fSuccess) {
if (*lpData) {
lvi.iSubItem=1;
lvi.pszText=lpData;
lvi.cchTextMax = lstrlen(lpData)+1;
fSuccess=(ListView_SetItem(hwndListbox,&lvi) >= 0);
}
lpData += lstrlen(lpData) +1;
}
}
if (m_pcd->m_bRSOP) {
if (fSuccess) {
if (*lpData) {
lvi.iSubItem=(pSettings->dwFlags & DF_EXPLICITVALNAME) ? 2 : 1;
lvi.pszText=lpData;
lvi.cchTextMax = lstrlen(lpData)+1;
fSuccess=(ListView_SetItem(hwndListbox,&lvi) >= 0);
}
lpData += lstrlen(lpData) +1;
}
}
}
GlobalUnlock(pListboxDlgInfo->hData);
}
else
{
fSuccess = FALSE;
}
}
return fSuccess;
}
BOOL CPolicySnapIn::ProcessShowlistboxDlg(HWND hDlg)
{
LISTBOXDLGINFO * pListboxDlgInfo = (LISTBOXDLGINFO *)
GetWindowLongPtr(hDlg,DWLP_USER); // get pointer to struct from window data
DWORD dwAlloc=1024 * sizeof(TCHAR),dwUsed=0;
HGLOBAL hBuf;
TCHAR * pBuf;
HWND hwndListbox = GetDlgItem(hDlg,IDC_POLICY_LISTBOX);
LV_ITEM lvi;
UINT nLen;
int nCount;
TCHAR pszText[MAX_PATH+1];
HRESULT hr = S_OK;
DWORD dwBufLen;
// allocate a temp buffer to read entries into
if (!(hBuf = GlobalAlloc(GHND,dwAlloc)) ||
!(pBuf = (TCHAR *) GlobalLock(hBuf))) {
if (hBuf)
GlobalFree(hBuf);
return FALSE;
}
lvi.mask = LVIF_TEXT;
lvi.iItem=0;
lvi.pszText = pszText;
lvi.cchTextMax = ARRAYSIZE(pszText);
nCount = ListView_GetItemCount(hwndListbox);
// retrieve the items out of listbox, pack into temp buffer
for (;lvi.iItem<nCount;lvi.iItem ++) {
lvi.iSubItem = 0;
if (ListView_GetItem(hwndListbox,&lvi)) {
nLen = lstrlen(lvi.pszText) + 1;
dwBufLen = dwUsed+nLen+4;
if (!(pBuf=ResizeBuffer(pBuf,hBuf,(dwBufLen) * sizeof(TCHAR),&dwAlloc)))
return ERROR_NOT_ENOUGH_MEMORY;
hr = StringCchCopy(pBuf+dwUsed, dwBufLen - dwUsed, lvi.pszText);
ASSERT(SUCCEEDED(hr));
dwUsed += nLen;
}
if (pListboxDlgInfo->pSettings->dwFlags & DF_EXPLICITVALNAME) {
lvi.iSubItem = 1;
if (ListView_GetItem(hwndListbox,&lvi)) {
nLen = lstrlen(lvi.pszText) + 1;
dwBufLen = dwUsed+nLen+4;
if (!(pBuf=ResizeBuffer(pBuf,hBuf,(dwBufLen) * sizeof(TCHAR),&dwAlloc)))
return ERROR_NOT_ENOUGH_MEMORY;
hr = StringCchCopy(pBuf+dwUsed, dwBufLen - dwUsed, lvi.pszText);
ASSERT(SUCCEEDED(hr));
dwUsed += nLen;
}
}
}
// doubly null-terminate the buffer... safe to do this because we
// tacked on the extra "+4" in the ResizeBuffer calls above
*(pBuf+dwUsed) = TEXT('\0');
dwUsed ++;
GlobalUnlock(hBuf);
if (pListboxDlgInfo->hData)
{
GlobalFree (pListboxDlgInfo->hData);
}
pListboxDlgInfo->hData = hBuf;
return TRUE;
}
VOID CPolicySnapIn::EnableShowListboxButtons(HWND hDlg)
{
BOOL fEnable;
// enable Remove button if there are any items selected
fEnable = (ListView_GetNextItem(GetDlgItem(hDlg,IDC_POLICY_LISTBOX),
-1,LVNI_SELECTED) >= 0);
EnableWindow(GetDlgItem(hDlg,IDC_POLICY_REMOVE),fEnable);
}
VOID CPolicySnapIn::ListboxRemove(HWND hDlg,HWND hwndListbox)
{
int nItem;
while ( (nItem=ListView_GetNextItem(hwndListbox,-1,LVNI_SELECTED))
>= 0) {
ListView_DeleteItem(hwndListbox,nItem);
}
EnableShowListboxButtons(hDlg);
}
VOID CPolicySnapIn::ListboxAdd(HWND hwndListbox, BOOL fExplicitValName,BOOL fValuePrefix)
{
ADDITEMINFO AddItemInfo;
LV_ITEM lvi;
ZeroMemory(&AddItemInfo,sizeof(AddItemInfo));
AddItemInfo.pCS = this;
AddItemInfo.fExplicitValName = fExplicitValName;
AddItemInfo.fValPrefix = fValuePrefix;
AddItemInfo.hwndListbox = hwndListbox;
//
// Bring up the appropriate add dialog-- one edit field ("type the thing
// to add") normally, two edit fields ("type the name of the thing, type
// the value of the thing") if the explicit value style is used
//
if (!DialogBoxParam(g_hInstance,MAKEINTRESOURCE((fExplicitValName ? IDD_POLICY_LBADD2 :
IDD_POLICY_LBADD)),hwndListbox,ListboxAddDlgProc,(LPARAM) &AddItemInfo))
return; // user cancelled
// add the item to the listbox
lvi.mask = LVIF_TEXT;
lvi.iItem=lvi.iSubItem=0;
lvi.pszText=(fExplicitValName ? AddItemInfo.szValueName :
AddItemInfo.szValueData);
lvi.cchTextMax = lstrlen(lvi.pszText)+1;
if ((lvi.iItem=ListView_InsertItem(hwndListbox,&lvi))<0) {
// if add fails, display out of memory error
m_pcd->MsgBox(hwndListbox,IDS_ErrOUTOFMEMORY,MB_ICONEXCLAMATION,MB_OK);
return;
}
if (fExplicitValName) {
lvi.iSubItem=1;
lvi.pszText=AddItemInfo.szValueData;
lvi.cchTextMax = lstrlen(lvi.pszText)+1;
if (ListView_SetItem(hwndListbox,&lvi) < 0) {
m_pcd->MsgBox(hwndListbox,IDS_ErrOUTOFMEMORY,MB_ICONEXCLAMATION,MB_OK);
return;
}
}
}
INT_PTR CALLBACK CPolicySnapIn::ListboxAddDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
switch (uMsg) {
case WM_INITDIALOG:
{
ADDITEMINFO * pAddItemInfo = (ADDITEMINFO *)lParam;
// store away pointer to additeminfo in window data
SetWindowLongPtr(hDlg,DWLP_USER,lParam);
SendDlgItemMessage(hDlg,IDC_POLICY_VALUENAME,EM_LIMITTEXT,MAX_PATH,0L);
SendDlgItemMessage(hDlg,IDC_POLICY_VALUEDATA,EM_LIMITTEXT,MAX_PATH,0L);
if (!pAddItemInfo->fExplicitValName) {
ShowWindow (GetDlgItem (hDlg, IDC_POLICY_VALUENAME), SW_HIDE);
}
}
break;
case WM_COMMAND:
switch (wParam) {
case IDOK:
{
ADDITEMINFO * pAddItemInfo = (ADDITEMINFO *)
GetWindowLongPtr(hDlg,DWLP_USER);
GetDlgItemText(hDlg,IDC_POLICY_VALUENAME,
pAddItemInfo->szValueName,
ARRAYSIZE(pAddItemInfo->szValueName));
GetDlgItemText(hDlg,IDC_POLICY_VALUEDATA,
pAddItemInfo->szValueData,
ARRAYSIZE(pAddItemInfo->szValueData));
// if explicit value names used, value name must
// not be empty, and it must be unique
if (pAddItemInfo->fExplicitValName) {
LV_FINDINFO lvfi;
int iSel;
if (!lstrlen(pAddItemInfo->szValueName)) {
// can't be empty
pAddItemInfo->pCS->m_pcd->MsgBox(hDlg,IDS_EMPTYVALUENAME,
MB_ICONINFORMATION,MB_OK);
SetFocus(GetDlgItem(hDlg,IDC_POLICY_VALUENAME));
return FALSE;
}
lvfi.flags = LVFI_STRING;
lvfi.psz = pAddItemInfo->szValueName;
iSel=ListView_FindItem(pAddItemInfo->hwndListbox,
-1,&lvfi);
if (iSel >= 0) {
// value name already used
pAddItemInfo->pCS->m_pcd->MsgBox(hDlg,IDS_VALUENAMENOTUNIQUE,
MB_ICONINFORMATION,MB_OK);
SetFocus(GetDlgItem(hDlg,IDC_POLICY_VALUENAME));
SendDlgItemMessage(hDlg,IDC_POLICY_VALUENAME,
EM_SETSEL,0,-1);
return FALSE;
}
} else if (!pAddItemInfo->fValPrefix) {
// if value name == value data, then value data
// must be unique
LV_FINDINFO lvfi;
int iSel;
if (!lstrlen(pAddItemInfo->szValueData)) {
// can't be empty
pAddItemInfo->pCS->m_pcd->MsgBox(hDlg,IDS_EMPTYVALUEDATA,
MB_ICONINFORMATION,MB_OK);
SetFocus(GetDlgItem(hDlg,IDC_POLICY_VALUEDATA));
return FALSE;
}
lvfi.flags = LVFI_STRING;
lvfi.psz = pAddItemInfo->szValueData;
iSel=ListView_FindItem(pAddItemInfo->hwndListbox,
-1,&lvfi);
if (iSel >= 0) {
// value name already used
pAddItemInfo->pCS->m_pcd->MsgBox(hDlg,IDS_VALUEDATANOTUNIQUE,
MB_ICONINFORMATION,MB_OK);
SetFocus(GetDlgItem(hDlg,IDC_POLICY_VALUEDATA));
SendDlgItemMessage(hDlg,IDC_POLICY_VALUEDATA,
EM_SETSEL,0,-1);
return FALSE;
}
}
else
{
if (!lstrlen(pAddItemInfo->szValueData)) {
// can't be empty
pAddItemInfo->pCS->m_pcd->MsgBox(hDlg,IDS_EMPTYVALUEDATA,
MB_ICONINFORMATION,MB_OK);
SetFocus(GetDlgItem(hDlg,IDC_POLICY_VALUEDATA));
return FALSE;
}
}
EndDialog(hDlg,TRUE);
}
break;
case IDCANCEL:
EndDialog(hDlg,FALSE);
break;
}
break;
}
return FALSE;
}
void CPolicySnapIn::InitializeFilterDialog (HWND hDlg)
{
INT iIndex;
RECT rect;
LV_COLUMN lvcol;
LONG lWidth;
DWORD dwCount = 0;
HWND hList = GetDlgItem(hDlg, IDC_FILTERLIST);
LPSUPPORTEDENTRY lpTemp;
LVITEM item;
//
// Count the number of Supported On strings
//
lpTemp = m_pcd->m_pSupportedStrings;
while (lpTemp)
{
lpTemp = lpTemp->pNext;
dwCount++;
}
//
// Decide on the column width
//
GetClientRect(hList, &rect);
if (dwCount > (DWORD)ListView_GetCountPerPage(hList))
{
lWidth = (rect.right - rect.left) - GetSystemMetrics(SM_CYHSCROLL);
}
else
{
lWidth = rect.right - rect.left;
}
//
// Insert the first column
//
memset(&lvcol, 0, sizeof(lvcol));
lvcol.mask = LVCF_FMT | LVCF_WIDTH;
lvcol.fmt = LVCFMT_LEFT;
lvcol.cx = lWidth;
ListView_InsertColumn(hList, 0, &lvcol);
//
// Turn on some listview features
//
SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP | LVS_EX_CHECKBOXES);
//
// Insert the Supported On strings
//
lpTemp = m_pcd->m_pSupportedStrings;
while (lpTemp)
{
ZeroMemory (&item, sizeof(item));
item.mask = LVIF_TEXT | LVIF_PARAM;
item.iItem = 0;
item.pszText = lpTemp->lpString;
item.lParam = (LPARAM) lpTemp;
iIndex = ListView_InsertItem (hList, &item);
if (iIndex > -1)
{
ZeroMemory (&item, sizeof(item));
item.mask = LVIF_STATE;
item.state = lpTemp->bEnabled ? INDEXTOSTATEIMAGEMASK(2) : INDEXTOSTATEIMAGEMASK(1);
item.stateMask = LVIS_STATEIMAGEMASK;
SendMessage (hList, LVM_SETITEMSTATE, (WPARAM)iIndex, (LPARAM)&item);
}
lpTemp = lpTemp->pNext;
}
//
// Select the first item
//
item.mask = LVIF_STATE;
item.iItem = 0;
item.iSubItem = 0;
item.state = LVIS_SELECTED | LVIS_FOCUSED;
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
SendMessage (hList, LVM_SETITEMSTATE, 0, (LPARAM) &item);
//
// Initialize the checkboxes
//
if (m_pcd->m_bUseSupportedOnFilter)
{
CheckDlgButton (hDlg, IDC_SUPPORTEDOPTION, BST_CHECKED);
}
else
{
EnableWindow (GetDlgItem (hDlg, IDC_SUPPORTEDONTITLE), FALSE);
EnableWindow (GetDlgItem (hDlg, IDC_FILTERLIST), FALSE);
EnableWindow (GetDlgItem (hDlg, IDC_SELECTALL), FALSE);
EnableWindow (GetDlgItem (hDlg, IDC_DESELECTALL), FALSE);
}
if (m_pcd->m_bShowConfigPoliciesOnly)
{
CheckDlgButton (hDlg, IDC_SHOWCONFIG, BST_CHECKED);
}
if ((m_dwPolicyOnlyPolicy == 0) || (m_dwPolicyOnlyPolicy == 1))
{
if (m_dwPolicyOnlyPolicy == 1)
{
CheckDlgButton (hDlg, IDC_SHOWPOLICIES, BST_CHECKED);
}
EnableWindow (GetDlgItem (hDlg, IDC_SHOWPOLICIES), FALSE);
}
else
{
if (m_bPolicyOnly)
{
CheckDlgButton (hDlg, IDC_SHOWPOLICIES, BST_CHECKED);
}
}
}
INT_PTR CALLBACK CPolicySnapIn::FilterDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
CPolicySnapIn * pCS;
switch (uMsg)
{
case WM_INITDIALOG:
pCS = (CPolicySnapIn *) lParam;
SetWindowLongPtr (hDlg, DWLP_USER, (LONG_PTR) pCS);
if (pCS)
{
pCS->InitializeFilterDialog(hDlg);
}
break;
case WM_COMMAND:
switch (wParam)
{
case IDC_SUPPORTEDOPTION:
if (IsDlgButtonChecked (hDlg, IDC_SUPPORTEDOPTION) == BST_CHECKED)
{
EnableWindow (GetDlgItem (hDlg, IDC_SUPPORTEDONTITLE), TRUE);
EnableWindow (GetDlgItem (hDlg, IDC_FILTERLIST), TRUE);
EnableWindow (GetDlgItem (hDlg, IDC_SELECTALL), TRUE);
EnableWindow (GetDlgItem (hDlg, IDC_DESELECTALL), TRUE);
}
else
{
EnableWindow (GetDlgItem (hDlg, IDC_SUPPORTEDONTITLE), FALSE);
EnableWindow (GetDlgItem (hDlg, IDC_FILTERLIST), FALSE);
EnableWindow (GetDlgItem (hDlg, IDC_SELECTALL), FALSE);
EnableWindow (GetDlgItem (hDlg, IDC_DESELECTALL), FALSE);
}
break;
case IDC_SELECTALL:
{
LVITEM item;
ZeroMemory (&item, sizeof(item));
item.mask = LVIF_STATE;
item.state = INDEXTOSTATEIMAGEMASK(2);
item.stateMask = LVIS_STATEIMAGEMASK;
SendMessage (GetDlgItem (hDlg, IDC_FILTERLIST), LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&item);
}
break;
case IDC_DESELECTALL:
{
LVITEM item;
ZeroMemory (&item, sizeof(item));
item.mask = LVIF_STATE;
item.state = INDEXTOSTATEIMAGEMASK(1);
item.stateMask = LVIS_STATEIMAGEMASK;
SendMessage (GetDlgItem (hDlg, IDC_FILTERLIST), LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&item);
}
break;
case IDOK:
{
LVITEM item;
INT iIndex = 0;
LPSUPPORTEDENTRY lpItem;
pCS = (CPolicySnapIn *) GetWindowLongPtr(hDlg,DWLP_USER);
if (!pCS)
{
break;
}
if (IsDlgButtonChecked (hDlg, IDC_SUPPORTEDOPTION) == BST_CHECKED)
{
pCS->m_pcd->m_bUseSupportedOnFilter = TRUE;
while (TRUE)
{
ZeroMemory (&item, sizeof(item));
item.mask = LVIF_PARAM | LVIF_STATE;
item.iItem = iIndex;
item.stateMask = LVIS_STATEIMAGEMASK;
if (!ListView_GetItem (GetDlgItem (hDlg, IDC_FILTERLIST), &item))
{
break;
}
lpItem = (LPSUPPORTEDENTRY) item.lParam;
if (lpItem)
{
if (item.state == INDEXTOSTATEIMAGEMASK(2))
{
lpItem->bEnabled = TRUE;
}
else
{
lpItem->bEnabled = FALSE;
}
}
iIndex++;
}
}
else
{
pCS->m_pcd->m_bUseSupportedOnFilter = FALSE;
}
if (IsDlgButtonChecked (hDlg, IDC_SHOWCONFIG) == BST_CHECKED)
{
pCS->m_pcd->m_bShowConfigPoliciesOnly = TRUE;
}
else
{
pCS->m_pcd->m_bShowConfigPoliciesOnly = FALSE;
}
if (IsDlgButtonChecked (hDlg, IDC_SHOWPOLICIES) == BST_CHECKED)
{
pCS->m_bPolicyOnly = TRUE;
}
else
{
pCS->m_bPolicyOnly = FALSE;
}
EndDialog(hDlg,TRUE);
}
break;
case IDCANCEL:
EndDialog(hDlg,FALSE);
break;
}
break;
case WM_NOTIFY:
pCS = (CPolicySnapIn *) GetWindowLongPtr (hDlg, DWLP_USER);
if (!pCS) {
break;
}
switch (((NMHDR FAR*)lParam)->code)
{
case LVN_ITEMACTIVATE:
{
LPNMITEMACTIVATE pItem = (LPNMITEMACTIVATE) lParam;
LPSUPPORTEDENTRY lpItem;
LVITEM item;
HWND hLV = GetDlgItem(hDlg, IDC_FILTERLIST);
ZeroMemory (&item, sizeof(item));
item.mask = LVIF_STATE | LVIF_PARAM;
item.iItem = pItem->iItem;
item.stateMask = LVIS_STATEIMAGEMASK;
if (!ListView_GetItem (hLV, &item))
{
break;
}
lpItem = (LPSUPPORTEDENTRY) item.lParam;
if (!lpItem)
{
break;
}
if (lpItem)
{
if (item.state == INDEXTOSTATEIMAGEMASK(2))
{
item.state = INDEXTOSTATEIMAGEMASK(1);
}
else
{
item.state = INDEXTOSTATEIMAGEMASK(2);
}
item.mask = LVIF_STATE;
SendMessage (hLV, LVM_SETITEMSTATE, (WPARAM)pItem->iItem, (LPARAM)&item);
}
}
}
break;
case WM_HELP: // F1
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
(DWORD_PTR) (LPSTR) aFilteringHelpIds);
break;
case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
(DWORD_PTR) (LPSTR) aFilteringHelpIds);
return (TRUE);
}
return FALSE;
}
unsigned int CPolicyDataObject::m_cfNodeType = RegisterClipboardFormat(CCF_NODETYPE);
unsigned int CPolicyDataObject::m_cfNodeTypeString = RegisterClipboardFormat(CCF_SZNODETYPE);
unsigned int CPolicyDataObject::m_cfDisplayName = RegisterClipboardFormat(CCF_DISPLAY_NAME);
unsigned int CPolicyDataObject::m_cfCoClass = RegisterClipboardFormat(CCF_SNAPIN_CLASSID);
unsigned int CPolicyDataObject::m_cfDescription = RegisterClipboardFormat(L"CCF_DESCRIPTION");
unsigned int CPolicyDataObject::m_cfHTMLDetails = RegisterClipboardFormat(L"CCF_HTML_DETAILS");
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicyDataObject implementation //
// //
///////////////////////////////////////////////////////////////////////////////
CPolicyDataObject::CPolicyDataObject(CPolicyComponentData *pComponent)
{
m_cRef = 1;
InterlockedIncrement(&g_cRefThisDll);
m_pcd = pComponent;
m_pcd->AddRef();
m_type = CCT_UNINITIALIZED;
m_cookie = -1;
}
CPolicyDataObject::~CPolicyDataObject()
{
m_pcd->Release();
InterlockedDecrement(&g_cRefThisDll);
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicyDataObject object implementation (IUnknown) //
// //
///////////////////////////////////////////////////////////////////////////////
HRESULT CPolicyDataObject::QueryInterface (REFIID riid, void **ppv)
{
if (IsEqualIID(riid, IID_IPolicyDataObject))
{
*ppv = (LPPOLICYDATAOBJECT)this;
m_cRef++;
return S_OK;
}
else if (IsEqualIID(riid, IID_IDataObject) ||
IsEqualIID(riid, IID_IUnknown))
{
*ppv = (LPDATAOBJECT)this;
m_cRef++;
return S_OK;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
}
ULONG CPolicyDataObject::AddRef (void)
{
return ++m_cRef;
}
ULONG CPolicyDataObject::Release (void)
{
if (--m_cRef == 0) {
delete this;
return 0;
}
return m_cRef;
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicyDataObject object implementation (IDataObject) //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPolicyDataObject::GetDataHere(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium)
{
HRESULT hr = DV_E_CLIPFORMAT;
TCHAR szBuffer[300];
// Based on the CLIPFORMAT write data to the stream
const CLIPFORMAT cf = lpFormatetc->cfFormat;
if(cf == m_cfNodeType)
{
hr = CreateNodeTypeData(lpMedium);
}
else if(cf == m_cfNodeTypeString)
{
hr = CreateNodeTypeStringData(lpMedium);
}
else if (cf == m_cfDisplayName)
{
hr = CreateDisplayName(lpMedium);
}
else if (cf == m_cfCoClass)
{
hr = CreateCoClassID(lpMedium);
}
else if (cf == m_cfDescription)
{
hr = DV_E_TYMED;
if (lpMedium->tymed == TYMED_ISTREAM)
{
ULONG ulWritten;
if (m_cookie)
{
TABLEENTRY * pEntry = (TABLEENTRY *) m_cookie;
if (pEntry->dwType & ETYPE_POLICY)
{
POLICY * pPolicy = (POLICY *) m_cookie;
IStream *lpStream = lpMedium->pstm;
if (lpStream)
{
if (pPolicy->uOffsetHelp)
{
LPTSTR sz = (LPTSTR)((BYTE *)pPolicy + pPolicy->uOffsetHelp);
hr = lpStream->Write(sz, lstrlen(sz) * sizeof(TCHAR), &ulWritten);
}
if (!pPolicy->bTruePolicy)
{
LoadString (g_hInstance, IDS_PREFERENCE, szBuffer, ARRAYSIZE(szBuffer));
hr = lpStream->Write(szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &ulWritten);
}
}
}
else if (pEntry->dwType & ETYPE_CATEGORY)
{
CATEGORY * pCat = (CATEGORY *) m_cookie;
if (pCat->uOffsetHelp)
{
LPTSTR sz = (LPTSTR)((BYTE *)pCat + pCat->uOffsetHelp);
IStream *lpStream = lpMedium->pstm;
if (lpStream)
{
hr = lpStream->Write(sz, lstrlen(sz) * sizeof(TCHAR), &ulWritten);
}
}
}
else if (pEntry->dwType == (ETYPE_ROOT | ETYPE_REGITEM))
{
IStream *lpStream = lpMedium->pstm;
LoadString (g_hInstance, IDS_EXSETROOT_DESC, szBuffer, ARRAYSIZE(szBuffer));
if (lpStream)
{
hr = lpStream->Write(szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &ulWritten);
}
}
else if (pEntry->dwType == ETYPE_REGITEM)
{
IStream *lpStream = lpMedium->pstm;
LoadString (g_hInstance, IDS_EXSET_DESC, szBuffer, ARRAYSIZE(szBuffer));
if (lpStream)
{
REGITEM * pItem = (REGITEM *) m_cookie;
hr = lpStream->Write(szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &ulWritten);
if (!pItem->bTruePolicy)
{
LoadString (g_hInstance, IDS_PREFERENCE, szBuffer, ARRAYSIZE(szBuffer));
hr = lpStream->Write(szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &ulWritten);
}
}
}
}
else
{
LoadString (g_hInstance, IDS_POLICY_DESC, szBuffer, ARRAYSIZE(szBuffer));
IStream *lpStream = lpMedium->pstm;
if (lpStream)
{
hr = lpStream->Write(szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &ulWritten);
}
}
}
}
else if (cf == m_cfHTMLDetails)
{
hr = DV_E_TYMED;
if (lpMedium->tymed == TYMED_ISTREAM)
{
ULONG ulWritten;
if (m_cookie)
{
POLICY * pPolicy = (POLICY *) m_cookie;
if ((pPolicy->dwType & ETYPE_POLICY) || (pPolicy->dwType == ETYPE_REGITEM))
{
IStream *lpStream = lpMedium->pstm;
if(lpStream)
{
LPTSTR sz = GETSUPPORTEDPTR(pPolicy);
hr = lpStream->Write(g_szDisplayProperties, lstrlen(g_szDisplayProperties) * sizeof(TCHAR), &ulWritten);
if ((pPolicy->dwType & ETYPE_POLICY) && sz)
{
LoadString (g_hInstance, IDS_SUPPORTEDDESC, szBuffer, ARRAYSIZE(szBuffer));
hr = lpStream->Write(szBuffer, lstrlen(szBuffer) * sizeof(TCHAR), &ulWritten);
hr = lpStream->Write(sz, lstrlen(sz) * sizeof(TCHAR), &ulWritten);
}
}
}
}
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// //
// CPolicyDataObject object implementation (Internal functions) //
// //
///////////////////////////////////////////////////////////////////////////////
HRESULT CPolicyDataObject::Create(LPVOID pBuffer, INT len, LPSTGMEDIUM lpMedium)
{
HRESULT hr = DV_E_TYMED;
// Do some simple validation
if (pBuffer == NULL || lpMedium == NULL)
return E_POINTER;
// Make sure the type medium is HGLOBAL
if (lpMedium->tymed == TYMED_HGLOBAL)
{
// Create the stream on the hGlobal passed in
LPSTREAM lpStream;
hr = CreateStreamOnHGlobal(lpMedium->hGlobal, FALSE, &lpStream);
if (SUCCEEDED(hr))
{
// Write to the stream the number of bytes
unsigned long written;
hr = lpStream->Write(pBuffer, len, &written);
// Because we told CreateStreamOnHGlobal with 'FALSE',
// only the stream is released here.
// Note - the caller (i.e. snap-in, object) will free the HGLOBAL
// at the correct time. This is according to the IDataObject specification.
lpStream->Release();
}
}
return hr;
}
HRESULT CPolicyDataObject::CreateNodeTypeData(LPSTGMEDIUM lpMedium)
{
LPRESULTITEM lpResultItem = (LPRESULTITEM) m_cookie;
if (m_cookie == -1)
return E_UNEXPECTED;
// Create the node type object in GUID format
if (m_pcd->m_bUserScope)
return Create((LPVOID)&NODEID_PolicyRootUser, sizeof(GUID), lpMedium);
else
return Create((LPVOID)&NODEID_PolicyRootMachine, sizeof(GUID), lpMedium);
}
HRESULT CPolicyDataObject::CreateNodeTypeStringData(LPSTGMEDIUM lpMedium)
{
TCHAR szNodeType[50];
if (m_cookie == -1)
return E_UNEXPECTED;
szNodeType[0] = TEXT('\0');
if (m_pcd->m_bUserScope)
StringFromGUID2 (NODEID_PolicyRootUser, szNodeType, 50);
else
StringFromGUID2 (NODEID_PolicyRootMachine, szNodeType, 50);
// Create the node type object in GUID string format
return Create((LPVOID)szNodeType, ((lstrlenW(szNodeType)+1) * sizeof(WCHAR)), lpMedium);
}
HRESULT CPolicyDataObject::CreateDisplayName(LPSTGMEDIUM lpMedium)
{
WCHAR szDisplayName[100] = {0};
LoadStringW (g_hInstance, IDS_POLICY_NAME, szDisplayName, 100);
return Create((LPVOID)szDisplayName, (lstrlenW(szDisplayName) + 1) * sizeof(WCHAR), lpMedium);
}
HRESULT CPolicyDataObject::CreateCoClassID(LPSTGMEDIUM lpMedium)
{
// Create the CoClass information
if (m_pcd->m_bUserScope)
return Create((LPVOID)&CLSID_PolicySnapInUser, sizeof(CLSID), lpMedium);
else
return Create((LPVOID)&CLSID_PolicySnapInMachine, sizeof(CLSID), lpMedium);
}
const TCHAR szViewDescript [] = TEXT("MMCViewExt 1.0 Object");
const TCHAR szViewGUID [] = TEXT("{B708457E-DB61-4C55-A92F-0D4B5E9B1224}");
const TCHAR szThreadingModel[] = TEXT("Apartment");
HRESULT RegisterPolicyExtension (REFGUID clsid, UINT uiStringId, REFGUID RootNodeID,
REFGUID ExtNodeId, LPTSTR lpSnapInNameIndirect)
{
TCHAR szSnapInKey[50];
TCHAR szSubKey[200];
TCHAR szSnapInName[100];
TCHAR szGUID[50];
DWORD dwDisp;
LONG lResult;
HKEY hKey;
HRESULT hr = S_OK;
//
// First register the extension
//
StringFromGUID2 (clsid, szSnapInKey, 50);
//
// Register SnapIn in HKEY_CLASSES_ROOT
//
LoadString (g_hInstance, uiStringId, szSnapInName, 100);
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), TEXT("CLSID\\%s"), szSnapInKey);
ASSERT(SUCCEEDED(hr));
lResult = RegCreateKeyEx (HKEY_CLASSES_ROOT, szSubKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
&hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) {
return SELFREG_E_CLASS;
}
RegSetValueEx (hKey, NULL, 0, REG_SZ, (LPBYTE)szSnapInName,
(lstrlen(szSnapInName) + 1) * sizeof(TCHAR));
RegCloseKey (hKey);
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), TEXT("CLSID\\%s\\InProcServer32"), szSnapInKey);
ASSERT(SUCCEEDED(hr));
lResult = RegCreateKeyEx (HKEY_CLASSES_ROOT, szSubKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
&hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) {
return SELFREG_E_CLASS;
}
RegSetValueEx (hKey, NULL, 0, REG_EXPAND_SZ, (LPBYTE)g_szSnapInLocation,
(lstrlen(g_szSnapInLocation) + 1) * sizeof(TCHAR));
RegSetValueEx (hKey, TEXT("ThreadingModel"), 0, REG_SZ, (LPBYTE)szThreadingModel,
(lstrlen(szThreadingModel) + 1) * sizeof(TCHAR));
RegCloseKey (hKey);
//
// Register SnapIn with MMC
//
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), TEXT("Software\\Microsoft\\MMC\\SnapIns\\%s"), szSnapInKey);
ASSERT(SUCCEEDED(hr));
lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, szSubKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
&hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) {
return SELFREG_E_CLASS;
}
RegSetValueEx (hKey, TEXT("NameString"), 0, REG_SZ, (LPBYTE)szSnapInName,
(lstrlen(szSnapInName) + 1) * sizeof(TCHAR));
RegSetValueEx (hKey, TEXT("NameStringIndirect"), 0, REG_SZ, (LPBYTE)lpSnapInNameIndirect,
(lstrlen(lpSnapInNameIndirect) + 1) * sizeof(TCHAR));
RegCloseKey (hKey);
StringFromGUID2 (RootNodeID, szGUID, 50);
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), TEXT("Software\\Microsoft\\MMC\\SnapIns\\%s\\NodeTypes\\%s"),
szSnapInKey, szGUID);
ASSERT(SUCCEEDED(hr));
lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, szSubKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
&hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) {
return SELFREG_E_CLASS;
}
RegCloseKey (hKey);
//
// Register in the NodeTypes key
//
StringFromGUID2 (RootNodeID, szGUID, 50);
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), TEXT("Software\\Microsoft\\MMC\\NodeTypes\\%s"), szGUID);
ASSERT(SUCCEEDED(hr));
lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, szSubKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
&hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) {
return SELFREG_E_CLASS;
}
RegCloseKey (hKey);
//
// Register for the view extension
//
hr = StringCchCat (szSubKey, ARRAYSIZE(szSubKey), TEXT("\\Extensions\\View"));
ASSERT(SUCCEEDED(hr));
lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, szSubKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
&hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) {
return SELFREG_E_CLASS;
}
RegSetValueEx (hKey, szViewGUID, 0, REG_SZ, (LPBYTE)szViewDescript,
(lstrlen(szViewDescript) + 1) * sizeof(TCHAR));
RegCloseKey (hKey);
//
// Register as an extension for various nodes
//
StringFromGUID2 (ExtNodeId, szGUID, 50);
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), TEXT("Software\\Microsoft\\MMC\\NodeTypes\\%s\\Extensions\\NameSpace"), szGUID);
ASSERT(SUCCEEDED(hr));
lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, szSubKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
&hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) {
return SELFREG_E_CLASS;
}
RegSetValueEx (hKey, szSnapInKey, 0, REG_SZ, (LPBYTE)szSnapInName,
(lstrlen(szSnapInName) + 1) * sizeof(TCHAR));
RegCloseKey (hKey);
return S_OK;
}
HRESULT RegisterPolicy(void)
{
HRESULT hr;
hr = RegisterPolicyExtension (CLSID_PolicySnapInMachine, IDS_POLICY_NAME_MACHINE,
NODEID_PolicyRootMachine, NODEID_MachineRoot, TEXT("@gptext.dll,-20"));
if (hr == S_OK)
{
hr = RegisterPolicyExtension (CLSID_PolicySnapInUser, IDS_POLICY_NAME_USER,
NODEID_PolicyRootUser, NODEID_UserRoot, TEXT("@gptext.dll,-21"));
}
if (hr == S_OK)
{
hr = RegisterPolicyExtension (CLSID_RSOPolicySnapInMachine, IDS_POLICY_NAME_MACHINE,
NODEID_RSOPolicyRootMachine, NODEID_RSOPMachineRoot, TEXT("@gptext.dll,-20"));
}
if (hr == S_OK)
{
hr = RegisterPolicyExtension (CLSID_RSOPolicySnapInUser, IDS_POLICY_NAME_USER,
NODEID_RSOPolicyRootUser, NODEID_RSOPUserRoot, TEXT("@gptext.dll,-21"));
}
return hr;
}
HRESULT UnregisterPolicyExtension (REFGUID clsid, REFGUID RootNodeID, REFGUID ExtNodeId)
{
TCHAR szSnapInKey[50];
TCHAR szSubKey[200];
TCHAR szGUID[50];
LONG lResult;
HKEY hKey;
DWORD dwDisp;
HRESULT hr = S_OK;
//
// First unregister the extension
//
StringFromGUID2 (clsid, szSnapInKey, 50);
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), TEXT("CLSID\\%s"), szSnapInKey);
ASSERT(SUCCEEDED(hr));
RegDelnode (HKEY_CLASSES_ROOT, szSubKey);
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), TEXT("Software\\Microsoft\\MMC\\SnapIns\\%s"), szSnapInKey);
ASSERT(SUCCEEDED(hr));
RegDelnode (HKEY_LOCAL_MACHINE, szSubKey);
StringFromGUID2 (RootNodeID, szGUID, 50);
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), TEXT("Software\\Microsoft\\MMC\\NodeTypes\\%s"), szGUID);
ASSERT(SUCCEEDED(hr));
RegDelnode (HKEY_LOCAL_MACHINE, szSubKey);
StringFromGUID2 (ExtNodeId, szGUID, 50);
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), TEXT("Software\\Microsoft\\MMC\\NodeTypes\\%s\\Extensions\\NameSpace"), szGUID);
ASSERT(SUCCEEDED(hr));
lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, szSubKey, 0,
KEY_WRITE, &hKey);
if (lResult == ERROR_SUCCESS) {
RegDeleteValue (hKey, szSnapInKey);
RegCloseKey (hKey);
}
return S_OK;
}
HRESULT UnregisterPolicy(void)
{
HRESULT hr;
hr = UnregisterPolicyExtension (CLSID_PolicySnapInMachine, NODEID_PolicyRootMachine,
NODEID_Machine);
if (hr == S_OK)
{
hr = UnregisterPolicyExtension (CLSID_PolicySnapInUser, NODEID_PolicyRootUser,
NODEID_User);
}
if (hr == S_OK)
{
hr = UnregisterPolicyExtension (CLSID_RSOPolicySnapInMachine, NODEID_RSOPolicyRootMachine,
NODEID_RSOPMachineRoot);
}
if (hr == S_OK)
{
hr = UnregisterPolicyExtension (CLSID_RSOPolicySnapInUser, NODEID_RSOPolicyRootUser,
NODEID_RSOPUserRoot);
}
return hr;
}
VOID LoadMessage (DWORD dwID, LPTSTR lpBuffer, DWORD dwSize)
{
HINSTANCE hInstActiveDS;
HINSTANCE hInstWMI;
if (!FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dwID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
lpBuffer, dwSize, NULL))
{
hInstActiveDS = LoadLibrary (TEXT("activeds.dll"));
if (hInstActiveDS)
{
if (!FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
hInstActiveDS, dwID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
lpBuffer, dwSize, NULL))
{
hInstWMI = LoadLibrary (TEXT("wmiutils.dll"));
if (hInstWMI)
{
if (!FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
hInstWMI, dwID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
lpBuffer, dwSize, NULL))
{
DebugMsg((DM_WARNING, TEXT("LoadMessage: Failed to query error message text for %d due to error %d"),
dwID, GetLastError()));
(void) StringCchPrintf (lpBuffer, dwSize, TEXT("%d (0x%x)"), dwID, dwID);
}
FreeLibrary (hInstWMI);
}
}
FreeLibrary (hInstActiveDS);
}
}
}
//*************************************************************
//
// ErrorDlgProc()
//
// Purpose: Dialog box procedure for errors
//
// Parameters:
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
INT_PTR CALLBACK ErrorDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
TCHAR szError[MAX_PATH];
LPGPOERRORINFO lpEI = (LPGPOERRORINFO) lParam;
HICON hIcon;
hIcon = LoadIcon (NULL, IDI_INFORMATION);
if (hIcon)
{
SendDlgItemMessage (hDlg, IDC_ERROR_ICON, STM_SETICON, (WPARAM)hIcon, 0);
}
SetDlgItemText (hDlg, IDC_ERRORTEXT, lpEI->lpMsg);
if (lpEI->lpDetails) {
// if details is provided use that
SetDlgItemText (hDlg, IDC_DETAILSTEXT, lpEI->lpDetails);
}
else {
szError[0] = TEXT('\0');
if (lpEI->dwError)
{
LoadMessage (lpEI->dwError, szError, ARRAYSIZE(szError));
}
if (szError[0] == TEXT('\0'))
{
LoadString (g_hInstance, IDS_NONE, szError, ARRAYSIZE(szError));
}
SetDlgItemText (hDlg, IDC_DETAILSTEXT, szError);
}
// this is the only way I know to remove focus from the details
PostMessage(hDlg, WM_MYREFRESH, 0, 0);
return TRUE;
}
case WM_MYREFRESH:
{
SetFocus(GetDlgItem(hDlg, IDCLOSE));
}
case WM_COMMAND:
if (LOWORD(wParam) == IDCLOSE || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return TRUE;
}
break;
case WM_HELP: // F1
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
(ULONG_PTR) (LPSTR) aErrorHelpIds);
break;
case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
(ULONG_PTR) (LPSTR) aErrorHelpIds);
return (TRUE);
}
return FALSE;
}
//*************************************************************
//
// ReportError()
//
// Purpose: Displays an error message to the user
//
// Parameters: hParent - Parent window handle
// dwError - Error number
// idMsg - Error message id
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 7/18/95 ericflo Created
//
//*************************************************************
BOOL ReportAdmError (HWND hParent, DWORD dwError, UINT idMsg, ...)
{
GPOERRORINFO ei;
TCHAR szMsg[MAX_PATH];
TCHAR szErrorMsg[2*MAX_PATH+40];
va_list marker;
HRESULT hr = S_OK;
//
// Load the error message
//
if (!LoadString (g_hInstance, idMsg, szMsg, MAX_PATH))
{
return FALSE;
}
//
// Plug in the arguments
//
va_start(marker, idMsg);
if (idMsg == IDS_RSOP_ADMFAILED) {
ei.lpDetails = va_arg(marker, LPTSTR);
(void) StringCchCopy(szErrorMsg, ARRAYSIZE(szErrorMsg), szMsg);
}
else {
va_start(marker, idMsg);
(void) StringCchVPrintf(szErrorMsg, ARRAYSIZE(szErrorMsg), szMsg, marker);
}
va_end(marker);
//
// Display the message
//
ei.dwError = dwError;
ei.lpMsg = szErrorMsg;
DialogBoxParam (g_hInstance, MAKEINTRESOURCE(IDD_ERROR_ADMTEMPLATES), hParent,
ErrorDlgProc, (LPARAM) &ei);
return TRUE;
}
LPHASHTABLE CreateHashTable (void)
{
LPHASHTABLE lpTable;
lpTable = (LPHASHTABLE)LocalAlloc (LPTR, sizeof(LPHASHTABLE) * HASH_BUCKET_COUNT);
return lpTable;
}
VOID FreeHashTable (LPHASHTABLE lpTable)
{
INT i;
LPHASHENTRY lpItem, lpNext;
for (i = 0; i < HASH_BUCKET_COUNT; i++)
{
lpItem = lpTable->lpEntries[i];
while (lpItem)
{
lpNext = lpItem->pNext;
LocalFree (lpItem);
lpItem = lpNext;
}
}
LocalFree (lpTable);
}
ULONG CalculateHashInfo(LPTSTR lpName, DWORD dwChars, DWORD *pdwHashValue)
{
DWORD dwHash = 314159269;
DWORD dwIndex;
CharLowerBuff (lpName, dwChars);
for (dwIndex = 0; dwIndex < dwChars; dwIndex++)
{
dwHash ^= (dwHash<<11) + (dwHash<<5) + (dwHash>>2) + (unsigned int) lpName[dwIndex];
}
dwHash = (dwHash & 0x7FFFFFFF);
*pdwHashValue = dwHash;
return (dwHash % HASH_BUCKET_COUNT);
}
BOOL AddHashEntry (LPHASHTABLE lpTable, LPTSTR lpName, DWORD dwChars)
{
DWORD dwHashValue, dwBucket;
LPHASHENTRY lpTemp, lpItem;
dwBucket = CalculateHashInfo(lpName, dwChars, &dwHashValue);
lpItem = (LPHASHENTRY) LocalAlloc (LPTR, sizeof(HASHENTRY));
if (!lpItem)
{
return FALSE;
}
lpItem->dwHashValue = dwHashValue;
lpItem->dwVariableLength = dwChars;
lpItem->lpStringEntry = lpName;
lpTemp = lpTable->lpEntries[dwBucket];
if (lpTemp)
{
while (lpTemp->pNext)
{
lpTemp = lpTemp->pNext;
}
lpTemp->pNext = lpItem;
}
else
{
lpTable->lpEntries[dwBucket] = lpItem;
}
return TRUE;
}
LPTSTR FindHashEntry (LPHASHTABLE lpTable, LPTSTR lpName, DWORD dwChars)
{
DWORD dwHashValue, dwBucket;
LPHASHENTRY lpTemp, lpItem;
dwBucket = CalculateHashInfo(lpName, dwChars, &dwHashValue);
lpTemp = lpTable->lpEntries[dwBucket];
if (lpTemp)
{
while (lpTemp)
{
if ((lpTemp->dwHashValue == dwHashValue) && (lpTemp->dwVariableLength == dwChars))
{
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
lpTemp->lpStringEntry, dwChars,
lpName, dwChars) == CSTR_EQUAL)
{
return lpTemp->lpStringEntry;
}
}
lpTemp = lpTemp->pNext;
}
}
return NULL;
}
#if DBG
VOID DumpHashTableDetails (LPHASHTABLE lpTable)
{
INT i;
DWORD dwCount = 0;
LPHASHENTRY lpItem, lpNext;
for (i = 0; i < HASH_BUCKET_COUNT; i++)
{
dwCount = 0;
lpItem = lpTable->lpEntries[i];
while (lpItem)
{
dwCount++;
lpItem = lpItem->pNext;
}
DebugMsg((DM_VERBOSE, TEXT("Hash Bucket %d has %d entries"), i, dwCount));
}
}
#endif