//+---------------------------------------------------------------------------
//
//  Microsoft Windows
//  Copyright (C) Microsoft Corporation 1996-2001.
//
//  File:       wmihooks.cpp
//
//  Contents:   implementation of CWMIRsop
//
//----------------------------------------------------------------------------
#include <stdafx.h>
#include <wmihooks.h>
#include "util.h"

WCHAR const QUERY_LANG[]            = L"WQL";
WCHAR const WMI_CLASS[]             = L"__CLASS";
WCHAR const RSOP_NAME_SPACE[]       = L"root\\rsop\\computer";
WCHAR const RSOP_PREC_ONE_QUERY[]   = L"select * from RSOP_SecuritySettings where precedence=1";
WCHAR const RSOP_ALL_QUERY[]        = L"select * from RSOP_SecuritySettings";
WCHAR const RSOP_STATUS[]           = L"Status";
WCHAR const RSOP_ERROR[]            = L"ErrorCode";
WCHAR const RSOP_PRECEDENCE[]       = L"precedence";
WCHAR const RSOP_GPOID[]            = L"GPOID";
WCHAR const RSOP_KEYNAME[]          = L"KeyName";
WCHAR const RSOP_SETTING[]          = L"Setting";
WCHAR const RSOP_USERRIGHT[]        = L"UserRight";
WCHAR const RSOP_ACCOUNTLIST[]      = L"AccountList";
WCHAR const RSOP_EVENTLOG_TYPE[]    = L"Type";

//String Constants for RSOP_classNames
WCHAR const RSOP_SEC_NUM[]          = TEXT("RSOP_SecuritySettingNumeric");
WCHAR const RSOP_SEC_BOOL[]         = TEXT("RSOP_SecuritySettingBoolean");
WCHAR const RSOP_SCE_STRING[]       = TEXT("RSOP_SecuritySettingString");
WCHAR const RSOP_AUDIT[]            = TEXT("RSOP_AuditPolicy");
WCHAR const RSOP_EVENT_NUM[]        = TEXT("RSOP_SecurityEventLogSettingNumeric");
WCHAR const RSOP_EVENT_BOOL[]       = TEXT("RSOP_SecurityEventLogSettingBoolean");
WCHAR const RSOP_REG_VAL[]          = TEXT("RSOP_RegistryValue");
WCHAR const RSOP_USER_RIGHT[]       = TEXT("RSOP_UserPrivilegeRight");
WCHAR const RSOP_RGROUPS[]          = TEXT("RSOP_RestrictedGroup");
WCHAR const RSOP_SERVICE[]          = TEXT("RSOP_SystemService");
WCHAR const RSOP_FILE[]             = TEXT("RSOP_File");
WCHAR const RSOP_REG[]              = TEXT("RSOP_RegistryKey");

//KeyNames
WCHAR const MIN_PASS_AGE[]          = TEXT("MinimumPasswordAge");
WCHAR const MAX_PASS_AGE[]          = TEXT("MaximumPasswordAge");
WCHAR const MIN_PASS_LEN[]          = TEXT("MinimumPasswordLength");
WCHAR const PASS_HIS_SIZE[]         = TEXT("PasswordHistorySize");
WCHAR const REQUIRE_LOGON_TO_CHANGE_PASS[] = TEXT("RequireLogonToChangePassword");
WCHAR const LOCKOUT_COUNT[]         = TEXT("LockoutBadCount");
WCHAR const RESET_LOCKOUT_COUNT[]   = TEXT("ResetLockoutCount");
WCHAR const LOCKOUT_DURATION[]      = TEXT("LockoutDuration");
WCHAR const MAX_TICKET_AGE[]        = TEXT("MaxTicketAge");
WCHAR const MAX_RENEW_AGE[]         = TEXT("MaxRenewAge");
WCHAR const MAX_SERVICE_AGE[]       = TEXT("MaxServiceAge");
WCHAR const MAX_CLOCK_SKEW[]        = TEXT("MaxClockSkew");
WCHAR const VALIDATE_CLIENT[]       = TEXT("TicketValidateClient");
WCHAR const PASS_COMPLEX[]          = TEXT("PasswordComplexity");
WCHAR const FORCE_LOGOFF[]          = TEXT("ForceLogOffWhenHourExpire");
WCHAR const ENABLE_ADMIN[]         = TEXT("EnableAdminAccount");
WCHAR const ENABLE_GUEST[]         = TEXT("EnableGuestAccount");
WCHAR const LSA_ANON_LOOKUP[]       = TEXT("LSAAnonymousNameLookup");
WCHAR const CLEAR_TEXT_PASS[]       = TEXT("ClearTextPassword");
WCHAR const AUDIT_SYSTEM_EVENTS[]   = TEXT("AuditSystemEvents");
WCHAR const AUDIT_LOGON_EVENTS[]    = TEXT("AuditLogonEvents");
WCHAR const AUDIT_OBJECT_ACCESS[]   = TEXT("AuditObjectAccess");
WCHAR const AUDIT_PRIVILEGE_USE[]   = TEXT("AuditPrivilegeUse");
WCHAR const AUDIT_POLICY_CHANGE[]   = TEXT("AuditPolicyChange");
WCHAR const AUDIT_ACCOUNT_MANAGE[]  = TEXT("AuditAccountManage");
WCHAR const AUDIT_PROCESS_TRAKING[] = TEXT("AuditProcessTracking");
WCHAR const AUDIT_DS_ACCESS[]       = TEXT("AuditDSAccess");
WCHAR const AUDIT_ACCOUNT_LOGON[]   = TEXT("AuditAccountLogon");

WCHAR const MAX_LOG_SIZE[]          = TEXT("MaximumLogSize");
WCHAR const AUDIT_LOG_RETENTION_PERIOD[] = TEXT ("AuditLogRetentionPeriod");
WCHAR const RETENTION_DAYS[]        = TEXT ("RetentionDays");
WCHAR const RESTRICT_GUEST_ACCESS[] = TEXT ("RestrictGuestAccess");
WCHAR const NEW_GUEST_NAME[]        = TEXT ("NewGuestName");
WCHAR const NEW_ADMINISTRATOR_NAME[] = TEXT ("NewAdministratorName");

VOID FreeRI(PRSOP_INFO ptr)
{
    if(ptr)
    {
        if(ptr->pszGPOID)
            LocalFree(ptr->pszGPOID);
        LocalFree(ptr);
    }
}


VOID InitWMI_SEC_PROFILE_INFO(PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    memset(pProfileInfo,0,sizeof(SCE_PROFILE_INFO));
    pProfileInfo->MinimumPasswordAge = SCE_NO_VALUE;
    pProfileInfo->MaximumPasswordAge = SCE_NO_VALUE;
    pProfileInfo->MinimumPasswordLength = SCE_NO_VALUE;
    pProfileInfo->PasswordComplexity = SCE_NO_VALUE;
    pProfileInfo->PasswordHistorySize = SCE_NO_VALUE;
    pProfileInfo->LockoutBadCount = SCE_NO_VALUE;
    pProfileInfo->ResetLockoutCount = SCE_NO_VALUE;
    pProfileInfo->LockoutDuration = SCE_NO_VALUE;
    pProfileInfo->RequireLogonToChangePassword = SCE_NO_VALUE;
    pProfileInfo->ForceLogoffWhenHourExpire = SCE_NO_VALUE;
    pProfileInfo->NewAdministratorName = 0;
    pProfileInfo->NewGuestName = 0;
    pProfileInfo->EnableAdminAccount = SCE_NO_VALUE;
    pProfileInfo->EnableGuestAccount = SCE_NO_VALUE;
    pProfileInfo->LSAAnonymousNameLookup = SCE_NO_VALUE;
    pProfileInfo->ClearTextPassword = SCE_NO_VALUE;
    pProfileInfo->AuditDSAccess = SCE_NO_VALUE;
    pProfileInfo->AuditAccountLogon = SCE_NO_VALUE;
    pProfileInfo->MaximumLogSize[0] = SCE_NO_VALUE;
    pProfileInfo->MaximumLogSize[1] = SCE_NO_VALUE;
    pProfileInfo->MaximumLogSize[2] = SCE_NO_VALUE;
    pProfileInfo->AuditLogRetentionPeriod[0] = SCE_NO_VALUE;
    pProfileInfo->AuditLogRetentionPeriod[1] = SCE_NO_VALUE;
    pProfileInfo->AuditLogRetentionPeriod[2] = SCE_NO_VALUE;
    pProfileInfo->RetentionDays[0] = SCE_NO_VALUE;
    pProfileInfo->RetentionDays[1] = SCE_NO_VALUE;
    pProfileInfo->RetentionDays[2] = SCE_NO_VALUE;
    pProfileInfo->RestrictGuestAccess[0] = SCE_NO_VALUE;
    pProfileInfo->RestrictGuestAccess[1] = SCE_NO_VALUE;
    pProfileInfo->RestrictGuestAccess[2] = SCE_NO_VALUE;
    pProfileInfo->AuditSystemEvents = SCE_NO_VALUE;
    pProfileInfo->AuditLogonEvents = SCE_NO_VALUE;
    pProfileInfo->AuditObjectAccess = SCE_NO_VALUE;
    pProfileInfo->AuditPrivilegeUse = SCE_NO_VALUE;
    pProfileInfo->AuditPolicyChange = SCE_NO_VALUE;
    pProfileInfo->AuditAccountManage = SCE_NO_VALUE;
    pProfileInfo->AuditProcessTracking = SCE_NO_VALUE;

    pProfileInfo->pInfo=NULL;
    pProfileInfo->pRIMinimumPasswordAge=NULL;
    pProfileInfo->pRIMaximumPasswordAge=NULL;
    pProfileInfo->pRIMinimumPasswordLength=NULL;
    pProfileInfo->pRIPasswordComplexity=NULL;
    pProfileInfo->pRIPasswordHistorySize=NULL;
    pProfileInfo->pRILockoutBadCount=NULL;
    pProfileInfo->pRIResetLockoutCount=NULL;
    pProfileInfo->pRILockoutDuration=NULL;
    pProfileInfo->pRIRequireLogonToChangePassword=NULL;
    pProfileInfo->pRIForceLogoffWhenHourExpire=NULL;
    pProfileInfo->pRIEnableAdminAccount=NULL;
    pProfileInfo->pRIEnableGuestAccount=NULL;
    pProfileInfo->pRILSAAnonymousNameLookup=NULL;
    pProfileInfo->pRINewAdministratorName=NULL;
    pProfileInfo->pRINewGuestName=NULL;
    pProfileInfo->pRIClearTextPassword=NULL;
    pProfileInfo->pRIMaxTicketAge=NULL;
    pProfileInfo->pRIMaxRenewAge=NULL;
    pProfileInfo->pRIMaxServiceAge=NULL;
    pProfileInfo->pRIMaxClockSkew=NULL;
    pProfileInfo->pRITicketValidateClient=NULL;
    pProfileInfo->pRIAuditSystemEvents=NULL;
    pProfileInfo->pRIAuditLogonEvents=NULL;
    pProfileInfo->pRIAuditObjectAccess=NULL;
    pProfileInfo->pRIAuditPrivilegeUse=NULL;
    pProfileInfo->pRIAuditPolicyChange=NULL;
    pProfileInfo->pRIAuditAccountManage=NULL;
    pProfileInfo->pRIAuditProcessTracking=NULL;
    pProfileInfo->pRIAuditDSAccess=NULL;
    pProfileInfo->pRIAuditAccountLogon=NULL;
    pProfileInfo->pRIMaximumLogSize[0]=NULL;
    pProfileInfo->pRIMaximumLogSize[1]=NULL;
    pProfileInfo->pRIMaximumLogSize[2]=NULL;
    pProfileInfo->pRIAuditLogRetentionPeriod[0]=NULL;
    pProfileInfo->pRIAuditLogRetentionPeriod[1]=NULL;
    pProfileInfo->pRIAuditLogRetentionPeriod[2]=NULL;
    pProfileInfo->pRIRetentionDays[0]=NULL;
    pProfileInfo->pRIRetentionDays[1]=NULL;
    pProfileInfo->pRIRetentionDays[2]=NULL;
    pProfileInfo->pRIRestrictGuestAccess[0]=NULL;
    pProfileInfo->pRIRestrictGuestAccess[1]=NULL;
    pProfileInfo->pRIRestrictGuestAccess[2]=NULL;
}

VOID FreeList(list<PRSOP_INFO> * li)
{
    for(list<PRSOP_INFO>::iterator i = li->begin();
                                               i != li->end();
                                               ++i )
    {
        FreeRI(*i);
    }
    li->erase(li->begin(),li->end());
}

VOID FreeVector(vector<PRSOP_INFO> * li)
{
    for(vector<PRSOP_INFO>::iterator i = li->begin();
                                               i != li->end();
                                               ++i )
    {
        FreeRI(*i);
    }
    li->erase(li->begin(),li->end());
}

VOID FreeWMI_SCE_PROFILE_INFO(PWMI_SCE_PROFILE_INFO pProfileInfo)
{
   if (!pProfileInfo) {
      return;
   }
    //TODO
    //Use the code to Free SCE_PROFILE_INFO
    FreeRI(pProfileInfo->pInfo);
    FreeRI(pProfileInfo->pRIMinimumPasswordAge);
    FreeRI(pProfileInfo->pRIMaximumPasswordAge);
    FreeRI(pProfileInfo->pRIMinimumPasswordLength);
    FreeRI(pProfileInfo->pRIPasswordComplexity);
    FreeRI(pProfileInfo->pRIPasswordHistorySize);
    FreeRI(pProfileInfo->pRILockoutBadCount);
    FreeRI(pProfileInfo->pRIResetLockoutCount);
    FreeRI(pProfileInfo->pRILockoutDuration);
    FreeRI(pProfileInfo->pRIRequireLogonToChangePassword);
    FreeRI(pProfileInfo->pRIForceLogoffWhenHourExpire);
    FreeRI(pProfileInfo->pRIEnableAdminAccount);
    FreeRI(pProfileInfo->pRIEnableGuestAccount);
    FreeRI(pProfileInfo->pRILSAAnonymousNameLookup);
    FreeRI(pProfileInfo->pRINewAdministratorName);
    FreeRI(pProfileInfo->pRINewGuestName);
    FreeRI(pProfileInfo->pRIClearTextPassword);
    FreeRI(pProfileInfo->pRIMaxTicketAge);
    FreeRI(pProfileInfo->pRIMaxRenewAge);
    FreeRI(pProfileInfo->pRIMaxServiceAge);
    FreeRI(pProfileInfo->pRIMaxClockSkew);
    FreeRI(pProfileInfo->pRITicketValidateClient);
    FreeRI(pProfileInfo->pRIAuditSystemEvents);
    FreeRI(pProfileInfo->pRIAuditLogonEvents);
    FreeRI(pProfileInfo->pRIAuditObjectAccess);
    FreeRI(pProfileInfo->pRIAuditPrivilegeUse);
    FreeRI(pProfileInfo->pRIAuditPolicyChange);
    FreeRI(pProfileInfo->pRIAuditAccountManage);
    FreeRI(pProfileInfo->pRIAuditProcessTracking);
    FreeRI(pProfileInfo->pRIAuditDSAccess);
    FreeRI(pProfileInfo->pRIAuditAccountLogon);
    FreeRI(pProfileInfo->pRIMaximumLogSize[0]);
    FreeRI(pProfileInfo->pRIMaximumLogSize[1]);
    FreeRI(pProfileInfo->pRIMaximumLogSize[2]);
    FreeRI(pProfileInfo->pRIAuditLogRetentionPeriod[0]);
    FreeRI(pProfileInfo->pRIAuditLogRetentionPeriod[1]);
    FreeRI(pProfileInfo->pRIAuditLogRetentionPeriod[2]);
    FreeRI(pProfileInfo->pRIRetentionDays[0]);
    FreeRI(pProfileInfo->pRIRetentionDays[1]);
    FreeRI(pProfileInfo->pRIRetentionDays[2]);
    FreeRI(pProfileInfo->pRIRestrictGuestAccess[0]);
    FreeRI(pProfileInfo->pRIRestrictGuestAccess[1]);
    FreeRI(pProfileInfo->pRIRestrictGuestAccess[2]);

    FreeList(&(pProfileInfo->listRIInfPrivilegeAssignedTo));
    FreeList(&(pProfileInfo->listRIGroupMemebership));
    FreeList(&(pProfileInfo->listRIServices));
    FreeVector(&(pProfileInfo->vecRIFiles));
    FreeVector(&(pProfileInfo->vecRIReg));

    SceFreeProfileMemory(pProfileInfo);
}

CWMIRsop::~CWMIRsop() {
   if (m_vecAllRSOPCache) {
      for(vector<PWMI_SCE_PROFILE_INFO>::iterator i = m_vecAllRSOPCache->begin();
                                                  i != m_vecAllRSOPCache->end();
                                                  ++i )
      {
         PWMI_SCE_PROFILE_INFO pProfileInfo = *i;
         FreeWMI_SCE_PROFILE_INFO(pProfileInfo);
      }
   }

   delete m_vecAllRSOPCache;
   m_vecAllRSOPCache = NULL;    // be extra carefull because the old code is not to delete it at all.

   if (m_pSvc) {
      m_pSvc->Release();
   }
}

HRESULT CWMIRsop::Initialize()
{
    HRESULT hr = S_OK;
    IWbemLocator *pLoc = NULL;

    //Already initialized
    if(m_pSvc)
        return hr;

    if (!m_pRSOPInformation) 
    {
       return E_FAIL;
    }


    hr = CoCreateInstance(CLSID_WbemLocator,
                          0,
                          CLSCTX_INPROC_SERVER,
                          IID_IWbemLocator,
                          (LPVOID *) &pLoc);
    if (FAILED(hr))
    {
        return hr;
    }


    const int cchMaxLength = 512;
    WCHAR szNameSpace[cchMaxLength];//LPOLESTR pszNameSpace = (LPOLESTR) LocalAlloc (LPTR, cchMaxLength * sizeof (WCHAR));

    hr = m_pRSOPInformation->GetNamespace (
               GPO_SECTION_MACHINE,
               szNameSpace,
               cchMaxLength);
    szNameSpace[cchMaxLength - 1] = L'\0';

       if (SUCCEEDED(hr)) 
       {
          BSTR bstrNameSpace = SysAllocString (szNameSpace);
          if (bstrNameSpace) 
          {
             hr = pLoc->ConnectServer(bstrNameSpace,
                                      NULL,
                                      NULL,
                                      0,
                                      NULL,
                                      0,
                                      0,
                                      &m_pSvc
                                      );

             SysFreeString(bstrNameSpace);
          }
          else
              hr = E_OUTOFMEMORY;
       }

    if (SUCCEEDED(hr))
    {
        // Set the proxy so that impersonation of the client occurs.
        hr = CoSetProxyBlanket(m_pSvc,
                          RPC_C_AUTHN_WINNT,
                          RPC_C_AUTHZ_NONE,
                          NULL,
                          RPC_C_AUTHN_LEVEL_CALL,
                          RPC_C_IMP_LEVEL_IMPERSONATE,
                          NULL,
                          EOAC_NONE);
    }

    pLoc->Release();
    return hr;   // Program successfully completed.
}

HRESULT CWMIRsop::EnumeratePrecedenceOne(IEnumWbemClassObject **ppEnum)
{
    HRESULT hr = m_pSvc->ExecQuery(_bstr_t(QUERY_LANG),
                           _bstr_t(RSOP_PREC_ONE_QUERY),
                           WBEM_FLAG_FORWARD_ONLY,
                           NULL,
                           ppEnum);

    return hr;
}

HRESULT CWMIRsop::EnumerateAll(IEnumWbemClassObject **ppEnum)
{
    HRESULT hr = m_pSvc->ExecQuery(_bstr_t(QUERY_LANG),
                           _bstr_t(RSOP_ALL_QUERY),
                           WBEM_FLAG_FORWARD_ONLY,
                           NULL,
                           ppEnum);

    return hr;
}

HRESULT CWMIRsop::GetNextInstance(IEnumWbemClassObject *pEnum,
                          IWbemClassObject** rsopInstance)
{
    HRESULT hr = WBEM_S_FALSE;
    ULONG returnedNum = 0;
    if(pEnum)
    {
        hr = pEnum->Next(WBEM_INFINITE,
                         1,
                         rsopInstance,
                         &returnedNum);
        if( FAILED(hr) )
            return hr;

        if (returnedNum == 0)
            hr = WBEM_S_FALSE;
    }
    return hr;
}

HRESULT CWMIRsop::GetClass(IWbemClassObject* rsopInstance,
                   LPWSTR *ppClass)
{
    PTSTR pszClassName;
    VARIANT value;

    HRESULT hr = rsopInstance->Get(_bstr_t(WMI_CLASS),
                           0,
                           &value,
                           NULL,
                           NULL);

    if(FAILED(hr) || value.vt != VT_BSTR || value.bstrVal == NULL)
        return hr;

    pszClassName = (PTSTR) V_BSTR(&value);
    ULONG uLen = wcslen(pszClassName);
    *ppClass = (LPWSTR)LocalAlloc(LPTR, (uLen + 1) * sizeof(WCHAR));
    if( *ppClass == NULL )
    {
       VariantClear(&value);
       return E_OUTOFMEMORY;
    }
    wcscpy(*ppClass,pszClassName);
    VariantClear(&value);
    return hr;
}

HRESULT CWMIRsop::GetRSOPInfo(IWbemClassObject *rsopInstance,
                        PRSOP_INFO pInfo)
{

    HRESULT hr = S_OK;
    PTSTR pszGPOID = 0;
    UINT status = 0;
    UINT precedence = 0;
    VARIANT value;

    //Get Status
    hr = rsopInstance->Get(_bstr_t(RSOP_STATUS),
                           0,
                           &value,
                           NULL,
                           NULL);

    if(FAILED(hr))
        return hr;

    pInfo->status = (ULONG) V_UINT(&value);
    VariantClear(&value);

    //Get Error
    hr = rsopInstance->Get(_bstr_t(RSOP_ERROR),
                           0,
                           &value,
                           NULL,
                           NULL);

    if(FAILED(hr))
        return hr;

    pInfo->error = (ULONG) V_UINT(&value);
    VariantClear(&value);

    //Get Precedence
    hr = rsopInstance->Get(_bstr_t(RSOP_PRECEDENCE),
                    0,
                    &value,
                    NULL,
                    NULL);

    if(FAILED(hr))
        return hr;

    pInfo->precedence = (ULONG) V_UINT(&value);
    VariantClear(&value);

    //Get GPOID
    hr =    rsopInstance->Get(_bstr_t(RSOP_GPOID),
                              0,
                              &value,
                              NULL,
                              NULL);

    if(FAILED(hr) || value.vt != VT_BSTR || (value.vt == VT_BSTR && value.bstrVal == NULL) )
        return hr;

    pszGPOID = (PTSTR) V_BSTR(&value);
    ULONG uLen = wcslen(pszGPOID);
    pInfo->pszGPOID = (LPWSTR)LocalAlloc(LPTR, (uLen + 1) * sizeof(WCHAR));
    if( pInfo->pszGPOID == NULL )
    {
       VariantClear(&value);
       return E_OUTOFMEMORY;
    }
    wcscpy(pInfo->pszGPOID, pszGPOID);
    VariantClear(&value);

    return hr;
}

HRESULT CWMIRsop::GetPrecedenceOneRSOPInfo(PWMI_SCE_PROFILE_INFO *ppProfileInfo)
{
    HRESULT hr = S_OK;
    IWbemClassObject *rsopInstance = NULL;
    IEnumWbemClassObject *pEnumObject = NULL;
    PWMI_SCE_PROFILE_INFO pTempProfileInfo = NULL;
    PRSOP_INFO pInfo = NULL;

    hr = Initialize();
    if( FAILED(hr) )
        goto exit_gracefully;

    hr = EnumeratePrecedenceOne(&pEnumObject);
    if( FAILED(hr) )
        goto exit_gracefully;

    pTempProfileInfo = new WMI_SCE_PROFILE_INFO;
    if( !pTempProfileInfo )
    {
        hr = E_OUTOFMEMORY;
        goto exit_gracefully;
    }
    InitWMI_SEC_PROFILE_INFO(pTempProfileInfo);

    //Get each instance
    while( ((hr = GetNextInstance(pEnumObject, &rsopInstance)) != WBEM_S_FALSE) && !FAILED(hr) )
    {
        pInfo = (PRSOP_INFO)LocalAlloc(LPTR, sizeof(RSOP_INFO));
        if(pInfo == NULL)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }

        //Get RSOP_INFO
        hr = GetRSOPInfo(rsopInstance, pInfo);
        if( FAILED(hr) )
            goto exit_gracefully;

        hr = AddInstance(rsopInstance,
                         pInfo,
                         pTempProfileInfo);
        if( FAILED(hr) )
            goto exit_gracefully;
        rsopInstance->Release();
        rsopInstance = NULL;
        pInfo = NULL;
    }


exit_gracefully:
    if(FAILED(hr))
    {
        if (rsopInstance)
            rsopInstance->Release();    // if while loop somehow terminate to here, rsopInstance is never released there
        if(pEnumObject)
            pEnumObject->Release();

        FreeRI(pInfo);
        //Free pTempProfileInfo
        FreeWMI_SCE_PROFILE_INFO(pTempProfileInfo);
        pTempProfileInfo = NULL;
    }
    *ppProfileInfo = pTempProfileInfo;
    return hr;
}

PWMI_SCE_PROFILE_INFO SearchProfileInList(vector<PWMI_SCE_PROFILE_INFO> *vecInfo,
                                          PRSOP_INFO pInfo)
{

    for(vector<PWMI_SCE_PROFILE_INFO>::iterator i = vecInfo->begin();
                                               i != vecInfo->end();
                                               ++i )
    {
        PWMI_SCE_PROFILE_INFO pProfileInfo = *i;
        if(_wcsicmp(pProfileInfo->pInfo->pszGPOID,pInfo->pszGPOID) == 0 )
            return pProfileInfo;
    }
    return NULL;
}

//Function Object Used for sorting vector
struct less_mag : public binary_function<PWMI_SCE_PROFILE_INFO, PWMI_SCE_PROFILE_INFO, bool> {
    bool operator()(PWMI_SCE_PROFILE_INFO x, PWMI_SCE_PROFILE_INFO y)
    { return x->pInfo->precedence < y->pInfo->precedence; }
};

HRESULT CWMIRsop::GetAllRSOPInfo(vector<PWMI_SCE_PROFILE_INFO> *vecInfo)
{
    HRESULT hr = S_OK;
    IWbemClassObject *rsopInstance = NULL;
    IEnumWbemClassObject *pEnumObject = NULL;
    PRSOP_INFO pInfo = NULL;
    PWMI_SCE_PROFILE_INFO pProfileInfo = NULL;

    if (NULL == vecInfo) {
       return E_INVALIDARG;
    }

    //
    // If we've alrady cached the info from WMI then just return it
    // don't try and get it again
    //
    if (m_vecAllRSOPCache) 
    {
       for(vector<PWMI_SCE_PROFILE_INFO>::iterator i = m_vecAllRSOPCache->begin();
                                               i != m_vecAllRSOPCache->end();
                                               ++i )
       {
          vecInfo->push_back(*i);
       }
       return S_OK;
    }

    hr = Initialize();
    if( FAILED(hr) )
        goto exit_gracefully;

    hr = EnumerateAll(&pEnumObject);
    if( FAILED(hr) )
        goto exit_gracefully;

    //Get each instance
    while( ((hr = GetNextInstance(pEnumObject, &rsopInstance)) != WBEM_S_FALSE) && !FAILED(hr) )
    {
        pInfo = (PRSOP_INFO)LocalAlloc(LPTR, sizeof(RSOP_INFO));
        if(pInfo == NULL)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }

        //Get RSOP_INFO
        hr = GetRSOPInfo(rsopInstance, pInfo);
        if( FAILED(hr) )
            goto exit_gracefully;

        pProfileInfo = SearchProfileInList(vecInfo,pInfo);
        if(!pProfileInfo)
        {
            pProfileInfo = new WMI_SCE_PROFILE_INFO;
            if(!pProfileInfo)
            {
                hr = E_OUTOFMEMORY;
                goto exit_gracefully;
            }
            InitWMI_SEC_PROFILE_INFO(pProfileInfo);
            pProfileInfo->pInfo = (PRSOP_INFO)LocalAlloc(LPTR,sizeof(RSOP_INFO));
            if(!pProfileInfo->pInfo)
            {
                hr = E_OUTOFMEMORY;
                goto exit_gracefully;
            }
            pProfileInfo->pInfo->pszGPOID = (LPWSTR)LocalAlloc(LPTR, (wcslen(pInfo->pszGPOID)+1)*sizeof(WCHAR));
            if(!pProfileInfo->pInfo->pszGPOID)
            {
                hr = E_OUTOFMEMORY;
                goto exit_gracefully;
            }
            wcscpy(pProfileInfo->pInfo->pszGPOID,pInfo->pszGPOID);
            vecInfo->push_back(pProfileInfo);
        }

        if( pProfileInfo->pInfo->precedence < pInfo->precedence )
            pProfileInfo->pInfo->precedence = pInfo->precedence;

        hr = AddInstance(rsopInstance,
                         pInfo,
                         pProfileInfo);
        if(FAILED(hr))
            goto exit_gracefully;
        rsopInstance->Release();
        rsopInstance = NULL;
        pInfo = NULL;
    }

    sort(vecInfo->begin(),vecInfo->end(),less_mag());

    m_vecAllRSOPCache = new vector<PWMI_SCE_PROFILE_INFO>;
    if (m_vecAllRSOPCache) 
    {
       for(vector<PWMI_SCE_PROFILE_INFO>::iterator i = vecInfo->begin();
                                               i != vecInfo->end();
                                               ++i )
       {
          m_vecAllRSOPCache->push_back(*i);
       }
    }

exit_gracefully:
    if(FAILED(hr))
    {
        FreeRI(pInfo);
        //Free the vector
        for(vector<PWMI_SCE_PROFILE_INFO>::iterator i = vecInfo->begin();
                                               i != vecInfo->end();
                                               ++i )
        {
            PWMI_SCE_PROFILE_INFO pProfileInfo = *i;
            FreeWMI_SCE_PROFILE_INFO(pProfileInfo);
        }
    }
    if(pEnumObject)
        pEnumObject->Release();
    if(rsopInstance)
        rsopInstance->Release();

    return hr;
}

HRESULT CWMIRsop::AddNumericSetting(IWbemClassObject *rsopInstance,
                            PRSOP_INFO pInfo,
                            PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    HRESULT hr = S_OK;
    VARIANT bKeyName;
    PTSTR keyName;
    VARIANT bSettingValue;
    DWORD settingValue;

   _TRACE (1, L"Entering CWMIRsop::AddNumericSetting\n");
    hr = rsopInstance->Get((BSTR)RSOP_KEYNAME,
                          0,
                          &bKeyName,
                          NULL,
                          NULL);
    if( FAILED(hr) || bKeyName.vt != VT_BSTR || bKeyName.bstrVal == NULL)
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)RSOP_SETTING,
                          0,
                          &bSettingValue,
                          NULL,
                          NULL);
    if( FAILED(hr) )
        goto exit_gracefully;


    keyName = V_BSTR(&bKeyName);
    settingValue = V_UINT(&bSettingValue);

    if(!_wcsicmp(keyName, MIN_PASS_AGE))
    {
        pProfileInfo->MinimumPasswordAge = settingValue;
        pProfileInfo->pRIMinimumPasswordAge = pInfo;
    }
    else if(!_wcsicmp(keyName, MAX_PASS_AGE))
    {
        pProfileInfo->MaximumPasswordAge = settingValue;
        pProfileInfo->pRIMaximumPasswordAge = pInfo;
    }
    else if(!_wcsicmp(keyName, MIN_PASS_LEN))
    {
        pProfileInfo->MinimumPasswordLength = settingValue;
        pProfileInfo->pRIMinimumPasswordLength = pInfo;
    }
    else if(!_wcsicmp(keyName, PASS_HIS_SIZE))
    {
        pProfileInfo->PasswordHistorySize = settingValue;
        pProfileInfo->pRIPasswordHistorySize = pInfo;
    }
    else if(!_wcsicmp(keyName, LOCKOUT_COUNT))
    {
        pProfileInfo->LockoutBadCount = settingValue;
        pProfileInfo->pRILockoutBadCount = pInfo;
    }
    else if(!_wcsicmp(keyName, RESET_LOCKOUT_COUNT))
    {
        pProfileInfo->ResetLockoutCount = settingValue;
        pProfileInfo->pRIResetLockoutCount = pInfo;
    }
    else if(!_wcsicmp(keyName, LOCKOUT_DURATION))
    {
        pProfileInfo->LockoutDuration = settingValue;
        pProfileInfo->pRILockoutDuration = pInfo;
    }
    else if(!_wcsicmp(keyName, MAX_TICKET_AGE))
    {
        if(!pProfileInfo->pKerberosInfo)
        {
            pProfileInfo->pKerberosInfo =
                (PSCE_KERBEROS_TICKET_INFO) LocalAlloc(LPTR, sizeof(SCE_KERBEROS_TICKET_INFO));
            if(pProfileInfo->pKerberosInfo == NULL)
            {
                hr = E_OUTOFMEMORY;
                goto exit_gracefully;
            }
        }
        pProfileInfo->pKerberosInfo->MaxTicketAge = settingValue;
        pProfileInfo->pRIMaxTicketAge = pInfo;
    }
    else if(!_wcsicmp(keyName, MAX_RENEW_AGE))
    {
        if(!pProfileInfo->pKerberosInfo)
        {
            pProfileInfo->pKerberosInfo =
                (PSCE_KERBEROS_TICKET_INFO) LocalAlloc(LPTR, sizeof(SCE_KERBEROS_TICKET_INFO));
            if(pProfileInfo->pKerberosInfo == NULL)
            {
                hr = E_OUTOFMEMORY;
                goto exit_gracefully;
            }
        }
        pProfileInfo->pKerberosInfo->MaxRenewAge = settingValue;
        pProfileInfo->pRIMaxRenewAge = pInfo;
    }
    else if(!_wcsicmp(keyName, MAX_SERVICE_AGE))
    {
        if(!pProfileInfo->pKerberosInfo)
        {
            pProfileInfo->pKerberosInfo =
                (PSCE_KERBEROS_TICKET_INFO) LocalAlloc(LPTR, sizeof(SCE_KERBEROS_TICKET_INFO));
            if(pProfileInfo->pKerberosInfo == NULL)
            {
                hr = E_OUTOFMEMORY;
                goto exit_gracefully;
            }
        }
        pProfileInfo->pKerberosInfo->MaxServiceAge = settingValue;
        pProfileInfo->pRIMaxServiceAge = pInfo;
    }
    else if(!_wcsicmp(keyName, MAX_CLOCK_SKEW))
    {
        if(!pProfileInfo->pKerberosInfo)
        {
            pProfileInfo->pKerberosInfo =
                (PSCE_KERBEROS_TICKET_INFO) LocalAlloc(LPTR, sizeof(SCE_KERBEROS_TICKET_INFO));
            if(pProfileInfo->pKerberosInfo == NULL)
            {
                hr = E_OUTOFMEMORY;
                goto exit_gracefully;
            }
        }
        pProfileInfo->pKerberosInfo->MaxClockSkew = settingValue;
        pProfileInfo->pRIMaxClockSkew = pInfo;
    }
    else
    {
        _ASSERT (FALSE); // key name not accounted for
    }


exit_gracefully:
    VariantClear(&bKeyName);
    VariantClear(&bSettingValue);

   _TRACE (-1,L"Leaving CWMIRsop::AddNumericSetting\n");
    return hr;
}

HRESULT CWMIRsop::AddEventLogNumericSetting(IWbemClassObject *rsopInstance,
                            PRSOP_INFO pInfo,
                            PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    VARIANT bKeyName;
    VARIANT bSettingValue;
    VARIANT bType;

   _TRACE (1, L"Entering CWMIRsop::AddEventLogNumericSetting\n");
    HRESULT hr = rsopInstance->Get((BSTR)RSOP_KEYNAME,
                          0,
                          &bKeyName,
                          NULL,
                          NULL);
    if( FAILED(hr) || bKeyName.vt != VT_BSTR || bKeyName.bstrVal == NULL)
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)RSOP_SETTING,
                          0,
                          &bSettingValue,
                          NULL,
                          NULL);
    if( FAILED(hr) )
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)RSOP_EVENTLOG_TYPE,
                          0,
                          &bType,
                          NULL,
                          NULL);
    if( FAILED(hr) )
        goto exit_gracefully;


   PTSTR keyName = V_BSTR(&bKeyName);
   DWORD settingValue = V_UINT(&bSettingValue);
   PTSTR typeValue = V_BSTR(&bType);

   unsigned long ulType = wcstoul (typeValue, L'\0', 10);
	ASSERT (ulType <= 2);
	if ( ulType <= 2 )
	{
      if ( !_wcsicmp(keyName, MAX_LOG_SIZE) )
      {
			pProfileInfo->MaximumLogSize[ulType] = settingValue;
			pProfileInfo->pRIMaximumLogSize[ulType] = pInfo;
		}
      else if ( !_wcsicmp(keyName, AUDIT_LOG_RETENTION_PERIOD) )
      {
			pProfileInfo->AuditLogRetentionPeriod[ulType] = settingValue;
			pProfileInfo->pRIAuditLogRetentionPeriod[ulType] = pInfo;
		}
      else if ( !_wcsicmp(keyName, RETENTION_DAYS) )
      {
			pProfileInfo->RetentionDays[ulType] = settingValue;
			pProfileInfo->pRIRetentionDays[ulType] = pInfo;
		}
      else
      {
         _ASSERT (FALSE); // key name not accounted for
      }
   }
	else
	   hr = E_FAIL;

exit_gracefully:
    VariantClear (&bKeyName);
    VariantClear (&bSettingValue);
    VariantClear (&bType);
   _TRACE (-1,L"Leaving CWMIRsop::AddEventLogNumericSetting\n");
    return hr;
}

HRESULT CWMIRsop::AddEventLogBooleanSetting(IWbemClassObject *rsopInstance,
                            PRSOP_INFO pInfo,
                            PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    HRESULT hr = S_OK;
    VARIANT bKeyName;
    PTSTR keyName = 0;
    VARIANT bSettingValue;
   DWORD settingValue;
    BOOL boolVal = FALSE;
    VARIANT bType;
    PTSTR   typeValue = 0;

   _TRACE (1, L"Entering CWMIRsop::AddEventLogBooleanSetting\n");
    hr = rsopInstance->Get((BSTR)RSOP_KEYNAME,
                          0,
                          &bKeyName,
                          NULL,
                          NULL);
    if( FAILED(hr) || bKeyName.vt != VT_BSTR || bKeyName.bstrVal == NULL)
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)RSOP_SETTING,
                          0,
                          &bSettingValue,
                          NULL,
                          NULL);
    if( FAILED(hr) )
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)RSOP_EVENTLOG_TYPE,
                          0,
                          &bType,
                          NULL,
                          NULL);
    if( FAILED(hr) )
        goto exit_gracefully;


    keyName = V_BSTR(&bKeyName);
    boolVal = V_BOOL(&bSettingValue);
    settingValue = (boolVal)? 1:0;
    typeValue = V_BSTR(&bType);


   unsigned long ulType = wcstoul (typeValue, L'\0', 10);
	ASSERT (ulType <= 2);
	if ( ulType <= 2 )
	{
      if ( !_wcsicmp(keyName, RESTRICT_GUEST_ACCESS) )
      {
			pProfileInfo->RestrictGuestAccess[ulType] = settingValue;
			pProfileInfo->pRIRestrictGuestAccess[ulType] = pInfo;
		}
      else
      {
         _ASSERT (FALSE); // key name not accounted for
      }
   }
	else
	   hr = E_FAIL;

exit_gracefully:
    VariantClear (&bKeyName);
    VariantClear (&bSettingValue);
    VariantClear (&bType);
   _TRACE (-1,L"Leaving CWMIRsop::AddEventLogBooleanSetting\n");
    return hr;
}

HRESULT CWMIRsop::AddBooleanSetting(IWbemClassObject *rsopInstance,
                          PRSOP_INFO pInfo,
                          PWMI_SCE_PROFILE_INFO pProfileInfo)
{

    VARIANT bKeyName;
    PTSTR keyName;
    VARIANT bSettingValue;
    BOOL boolVal;
    DWORD settingValue;
    HRESULT hr = S_OK;

    _TRACE (1, L"Entering CWMIRsop::AddBooleanSetting\n");

    hr = rsopInstance->Get((BSTR)RSOP_KEYNAME,
                           0,
                           &bKeyName,
                           NULL,
                           NULL);
    if(FAILED(hr) || bKeyName.vt != VT_BSTR || bKeyName.bstrVal == NULL)
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)RSOP_SETTING,
                           0,
                           &bSettingValue,
                           NULL,
                           NULL);
    if(FAILED(hr))
        goto exit_gracefully;

    keyName = (PTSTR) V_BSTR(&bKeyName);

    boolVal = V_BOOL(&bSettingValue);

    settingValue = (boolVal)? 1:0;

    if(!_wcsicmp(keyName, PASS_COMPLEX))
    {
        pProfileInfo->PasswordComplexity = settingValue;
        pProfileInfo->pRIPasswordComplexity = pInfo;
    }
    else if(!_wcsicmp(keyName, FORCE_LOGOFF))
    {
        pProfileInfo->ForceLogoffWhenHourExpire = settingValue;
        pProfileInfo->pRIForceLogoffWhenHourExpire = pInfo;
    }
    else if(!_wcsicmp(keyName, ENABLE_ADMIN))
    {
        pProfileInfo->EnableAdminAccount = settingValue;
        pProfileInfo->pRIEnableAdminAccount = pInfo;
    }
    else if(!_wcsicmp(keyName, ENABLE_GUEST))
    {
        pProfileInfo->EnableGuestAccount = settingValue;
        pProfileInfo->pRIEnableGuestAccount = pInfo;
    }
    else if(!_wcsicmp(keyName, LSA_ANON_LOOKUP))
    {
        pProfileInfo->LSAAnonymousNameLookup = settingValue;
        pProfileInfo->pRILSAAnonymousNameLookup = pInfo;
    }
    else if(!_wcsicmp(keyName, CLEAR_TEXT_PASS))
    {
        pProfileInfo->ClearTextPassword = settingValue;
        pProfileInfo->pRIClearTextPassword = pInfo;
    }
    else if (!_wcsicmp(keyName, REQUIRE_LOGON_TO_CHANGE_PASS))
    {
        pProfileInfo->RequireLogonToChangePassword = settingValue;
        pProfileInfo->pRIRequireLogonToChangePassword = pInfo;
    }
    else if(!_wcsicmp(keyName, VALIDATE_CLIENT))
    {
        if(!pProfileInfo->pKerberosInfo)
        {
            pProfileInfo->pKerberosInfo =
                (PSCE_KERBEROS_TICKET_INFO) LocalAlloc(LPTR, sizeof(SCE_KERBEROS_TICKET_INFO));
            if(pProfileInfo->pKerberosInfo == NULL)
            {
                hr = E_OUTOFMEMORY;
                goto exit_gracefully;
            }
        }
        pProfileInfo->pKerberosInfo->TicketValidateClient = settingValue;
        pProfileInfo->pRITicketValidateClient = pInfo;
    }
    else
    {
       _ASSERT (FALSE); // key name not accounted for
    }
exit_gracefully:
    VariantClear(&bKeyName);
    VariantClear(&bSettingValue);
   _TRACE (-1,L"Leaving CWMIRsop::AddBooleanSetting\n");
    return hr;
}


HRESULT CWMIRsop::AddAuditSetting(IWbemClassObject *rsopInstance,
                          PRSOP_INFO pInfo,
                          PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    VARIANT bCategoryName;
    PTSTR categoryName;
    VARIANT vSuccessVal;
    VARIANT vFailVal;
    BOOL successVal;
    BOOL failVal;
    DWORD settingVal = 0;
    HRESULT hr = S_OK;

   _TRACE (1, L"Entering CWMIRsop::AddAuditSetting\n");

    hr = rsopInstance->Get(_bstr_t(TEXT("Category")),
                0,
                &bCategoryName,
                NULL,
                NULL
                );

    if(FAILED(hr) || bCategoryName.vt != VT_BSTR || bCategoryName.bstrVal == NULL)
        goto exit_gracefully;

    hr = rsopInstance->Get(_bstr_t(TEXT("Success")),
                0,
                &vSuccessVal,
                NULL,
                NULL
                );
    if(FAILED(hr))
        goto exit_gracefully;

    hr = rsopInstance->Get(_bstr_t(TEXT("Failure")),
            0,
            &vFailVal,
            NULL,
            NULL
            );
    if(FAILED(hr))
        goto exit_gracefully;



    categoryName = (PTSTR) V_BSTR(&bCategoryName);

    successVal = V_BOOL(&vSuccessVal);

    failVal = V_BOOL(&vFailVal);

    if (successVal) 
        settingVal |= 1;
    if (failVal) 
        settingVal |= 2;

    if(!_wcsicmp(categoryName, AUDIT_SYSTEM_EVENTS))
    {
        pProfileInfo->AuditSystemEvents = settingVal;
        pProfileInfo->pRIAuditSystemEvents = pInfo;
    }
    else if(!_wcsicmp(categoryName, AUDIT_LOGON_EVENTS))
    {
        pProfileInfo->AuditLogonEvents = settingVal;
        pProfileInfo->pRIAuditLogonEvents = pInfo;
    }
    else if(!_wcsicmp(categoryName, AUDIT_OBJECT_ACCESS))
    {
        pProfileInfo->AuditObjectAccess = settingVal;
        pProfileInfo->pRIAuditObjectAccess = pInfo;
    }
    else if (!_wcsicmp(categoryName, AUDIT_PRIVILEGE_USE))
    {
        pProfileInfo->AuditPrivilegeUse = settingVal;
        pProfileInfo->pRIAuditPrivilegeUse = pInfo;
    }
    else if(!_wcsicmp(categoryName, AUDIT_POLICY_CHANGE))
    {
        pProfileInfo->AuditPolicyChange = settingVal;
        pProfileInfo->pRIAuditPolicyChange = pInfo;
    }
    else if(!_wcsicmp(categoryName, AUDIT_ACCOUNT_MANAGE))
    {
        pProfileInfo->AuditAccountManage = settingVal;
        pProfileInfo->pRIAuditAccountManage = pInfo;
    }
    else if(!_wcsicmp(categoryName, AUDIT_PROCESS_TRAKING))
    {
        pProfileInfo->AuditProcessTracking = settingVal;
        pProfileInfo->pRIAuditProcessTracking = pInfo;
    }
    else if(!_wcsicmp(categoryName, AUDIT_DS_ACCESS))
    {
        pProfileInfo->AuditDSAccess = settingVal;
        pProfileInfo->pRIAuditDSAccess = pInfo;
    }
    else if(!_wcsicmp(categoryName, AUDIT_ACCOUNT_LOGON))
    {
        pProfileInfo->AuditAccountLogon = settingVal;
        pProfileInfo->pRIAuditAccountLogon = pInfo;
    }
    else
    {
      _ASSERT (FALSE); // key name not accounted for
    }

exit_gracefully:

    VariantClear(&bCategoryName);
    VariantClear(&vSuccessVal);
    VariantClear(&vFailVal);
   _TRACE (-1,L"Leaving CWMIRsop::AddAuditSetting\n");

    return hr;
}


HRESULT CWMIRsop::AddUserRightSetting(
                    IWbemClassObject *rsopInstance,
                    PRSOP_INFO pInfo,
                    PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    VARIANT bUserRight;
    PTSTR userRight = NULL;
    VARIANT vAccountList;
   HRESULT hr = S_OK;

   _TRACE (1, L"Entering CWMIRsop::AddUserRightSetting\n");

    hr = rsopInstance->Get(_bstr_t(RSOP_USERRIGHT),
                      0,
                      &bUserRight,
                      NULL,
                      NULL);
    if( FAILED(hr) || bUserRight.vt != VT_BSTR || bUserRight.bstrVal == NULL )
        goto exit_gracefully;

    hr = rsopInstance->Get(_bstr_t(RSOP_ACCOUNTLIST),
                      0,
                      &vAccountList,
                      NULL,
                      NULL);
    if( FAILED(hr) )
        goto exit_gracefully;

    DWORD len;
    len  = wcslen((PTSTR) V_BSTR(&bUserRight));
     userRight = (PTSTR) LocalAlloc(LPTR, (len+1) * sizeof(WCHAR) );
    if(!userRight)
    {
        hr = E_OUTOFMEMORY;
        goto exit_gracefully;
    }
    wcscpy(userRight, (PTSTR) V_BSTR(&bUserRight));



    PSCE_PRIVILEGE_ASSIGNMENT head;
    head = pProfileInfo->OtherInfo.scp.u.pInfPrivilegeAssignedTo;

    if (!head)
    {
        head = (pProfileInfo->OtherInfo.scp.u.pInfPrivilegeAssignedTo =
            (PSCE_PRIVILEGE_ASSIGNMENT) LocalAlloc(LPTR, sizeof(SCE_PRIVILEGE_ASSIGNMENT)));
        if(!head)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
    }
    else
    {
        PSCE_PRIVILEGE_ASSIGNMENT current;
        current = (PSCE_PRIVILEGE_ASSIGNMENT) LocalAlloc(LPTR, sizeof(SCE_PRIVILEGE_ASSIGNMENT));
        if(!current)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
        current->Next = head;
        head = current;
        pProfileInfo->OtherInfo.scp.u.pInfPrivilegeAssignedTo = head;
    }

    head->Name = userRight;
    userRight = NULL;

    if(V_VT(&vAccountList) != VT_NULL)
    {
        SAFEARRAY* ptempArray;
        ptempArray = NULL;
        BSTR tempString;
        long lowerBoundray=0, upperBoundray=0, loopCount=0;
        ptempArray = V_ARRAY(&vAccountList);

        if ( FAILED(SafeArrayGetLBound(ptempArray, 1, &lowerBoundray)) ) lowerBoundray = 0;
        if ( FAILED(SafeArrayGetUBound(ptempArray, 1, &upperBoundray)) ) upperBoundray = 0;

        PSCE_NAME_LIST nameHead = head->AssignedTo;
        for (loopCount = lowerBoundray; loopCount <= upperBoundray; loopCount++)
        {
            hr = SafeArrayGetElement(ptempArray,
                                    &loopCount,
                                    &tempString);

            if ( FAILED(hr) ) goto exit_gracefully;

            if(!nameHead)
            {
                nameHead =
                    (head->AssignedTo = (PSCE_NAME_LIST) LocalAlloc(LPTR, sizeof(SCE_NAME_LIST)));
                if(!nameHead)
                {
                    hr = E_OUTOFMEMORY;
                    goto exit_gracefully;
                }
            }
            else
            {
                PSCE_NAME_LIST currentName =
                    (PSCE_NAME_LIST) LocalAlloc(LPTR, sizeof(SCE_NAME_LIST));
                if(!currentName)
                {
                    hr = E_OUTOFMEMORY;
                    goto exit_gracefully;
                }

                currentName->Next = nameHead;
                nameHead = currentName;
                head->AssignedTo = nameHead;
            }

            DWORD nameLen = wcslen((PTSTR) tempString);
            nameHead->Name = (PTSTR) LocalAlloc(LPTR, (nameLen+1) *sizeof(WCHAR) );
            if(!nameHead->Name)
            {
                hr = E_OUTOFMEMORY;
                goto exit_gracefully;
            }
            wcscpy(nameHead->Name, (PTSTR) tempString);
        }
    }

        //Set other info
    pProfileInfo->listRIInfPrivilegeAssignedTo.push_front(pInfo);


exit_gracefully:
    if(FAILED(hr) && (userRight != NULL))
    {
        LocalFree(userRight);
    }
    VariantClear(&bUserRight);
    VariantClear(&vAccountList);
   _TRACE (-1,L"Leaving CWMIRsop::AddUserRightSetting\n");
    return hr;
}

HRESULT CWMIRsop::AddRegValSetting(IWbemClassObject *rsopInstance,
                           PRSOP_INFO pInfo,
                           PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    VARIANT bKeyName;
    PTSTR keyName;
    VARIANT vSettingValue;
    VARIANT vType;
    PTSTR settingValue;
    DWORD type;
    HRESULT hr = S_OK;

    _TRACE (1, L"Entering CWMIRsop::AddRegValSetting\n");

    hr  = rsopInstance->Get(_bstr_t(TEXT("Path")),
                            0,
                            &bKeyName,
                            NULL,
                            NULL);
    if(FAILED(hr) || bKeyName.vt != VT_BSTR || bKeyName.bstrVal == NULL )
        goto exit_gracefully;

    hr = rsopInstance->Get(_bstr_t(TEXT("Data")),
                            0,
                            &vSettingValue,
                            NULL,
                            NULL);
    if(FAILED(hr) || vSettingValue.vt != VT_BSTR || vSettingValue.bstrVal == NULL )
        goto exit_gracefully;

    hr = rsopInstance->Get(_bstr_t(TEXT("Type")),
                            0,
                            &vType,
                            NULL,
                            NULL);
    if(FAILED(hr))
        goto exit_gracefully;


    DWORD len;
    len = wcslen((PTSTR) V_BSTR(&bKeyName));
    keyName = (PTSTR) LocalAlloc(LPTR, (len+1) *sizeof(WCHAR));
    if(!keyName)
    {
        hr = E_OUTOFMEMORY;
        goto exit_gracefully;
    }

    wcscpy(keyName,(PTSTR) V_BSTR(&bKeyName));

    len = wcslen((PTSTR) V_BSTR(&vSettingValue));
    settingValue = (PTSTR) LocalAlloc(LPTR, (len+1) *sizeof(WCHAR));
    if(!settingValue)
    {
        hr = E_OUTOFMEMORY;
        goto exit_gracefully;
    }

    wcscpy(settingValue,(PTSTR) V_BSTR(&vSettingValue));

    type = (DWORD) V_I4(&vType);


    DWORD arrayIndex;
    if ((arrayIndex = pProfileInfo->RegValueCount) == 0)
    {
        pProfileInfo->aRegValues =
            (PSCE_REGISTRY_VALUE_INFO) LocalAlloc(LPTR, sizeof(SCE_REGISTRY_VALUE_INFO)* m_cRegValueSize);
        if(!pProfileInfo->aRegValues)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
    }

    //double the array preserving the content
    if( arrayIndex >= m_cRegValueSize )
    {
        PSCE_REGISTRY_VALUE_INFO temp = (PSCE_REGISTRY_VALUE_INFO) LocalAlloc(LPTR, sizeof(SCE_REGISTRY_VALUE_INFO)* m_cRegValueSize * 2);
        if(!temp)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
        memcpy(temp,pProfileInfo->aRegValues,sizeof(SCE_REGISTRY_VALUE_INFO)*arrayIndex);
        LocalFree(pProfileInfo->aRegValues);
        pProfileInfo->aRegValues = temp;
        m_cRegValueSize *= 2;
    }

    pProfileInfo->aRegValues[arrayIndex].FullValueName = keyName;
    pProfileInfo->aRegValues[arrayIndex].Value = settingValue;
    pProfileInfo->aRegValues[arrayIndex].ValueType = type;
    pProfileInfo->RegValueCount += 1;

        //Store RSOP_INFO
    pProfileInfo->vecRIRegValues.push_back(pInfo);


exit_gracefully:

    VariantClear(&bKeyName);
    VariantClear(&vSettingValue);
    VariantClear(&vType);

   _TRACE (-1,L"Leaving CWMIRsop::AddRegValSetting\n");
    return hr;

}

HRESULT CWMIRsop::AddRestrictedGroupSetting(IWbemClassObject *rsopInstance,
                                    PRSOP_INFO pInfo,
                                    PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    VARIANT bRGroup;
    PTSTR RGroup;
    VARIANT vMembers;
    HRESULT hr = S_OK;

    _TRACE (1, L"Entering CWMIRsop::AddRestrictedGroupSetting\n");

    hr = rsopInstance->Get(_bstr_t(TEXT("GroupName")),
                0,
                &bRGroup,
                NULL,
                NULL
                );
    if(FAILED(hr) || bRGroup.vt != VT_BSTR || bRGroup.bstrVal == NULL )
        goto exit_gracefully;

    hr = rsopInstance->Get(_bstr_t(TEXT("Members")),
                0,
                &vMembers,
                NULL,
                NULL
                );
    if(FAILED(hr))
        goto exit_gracefully;


    DWORD len;
    len = wcslen((PTSTR) V_BSTR(&bRGroup));
    RGroup = (PTSTR) LocalAlloc(LPTR, (len+1) * sizeof(WCHAR));
    if(!RGroup)
    {
        hr = E_OUTOFMEMORY;
        goto exit_gracefully;
    }
    wcscpy(RGroup, (PTSTR) V_BSTR(&bRGroup));

    PSCE_GROUP_MEMBERSHIP head;
    head = pProfileInfo->pGroupMembership;

    if (!head)
    {
        head = (pProfileInfo->pGroupMembership =
            (PSCE_GROUP_MEMBERSHIP) LocalAlloc(LPTR, sizeof(SCE_GROUP_MEMBERSHIP)));
        if(!head)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
    }
    else
    {
        PSCE_GROUP_MEMBERSHIP current =
            (PSCE_GROUP_MEMBERSHIP) LocalAlloc(LPTR, sizeof(SCE_GROUP_MEMBERSHIP));
        if(!current)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
        current->Next = head;
        head = current;
        pProfileInfo->pGroupMembership = head;
    }

    head->GroupName = RGroup;

    if(V_VT(&vMembers) != VT_NULL)
    {
        SAFEARRAY* ptempArray = NULL;
        BSTR tempString;
        long lowerBoundray=0, upperBoundray=0, loopCount=0;
        ptempArray = V_ARRAY(&vMembers);

        if ( FAILED(SafeArrayGetLBound(ptempArray, 1, &lowerBoundray)) ) lowerBoundray = 0;
        if ( FAILED(SafeArrayGetUBound(ptempArray, 1, &upperBoundray)) ) upperBoundray = 0;

        PSCE_NAME_LIST nameHead = head->pMembers;
        for (loopCount = lowerBoundray; loopCount <= upperBoundray; loopCount++){

            hr = SafeArrayGetElement(ptempArray,
                                &loopCount,
                                &tempString);

            if ( FAILED(hr) ) goto exit_gracefully;

            if(!nameHead)
            {
                nameHead =
                    (head->pMembers = (PSCE_NAME_LIST) LocalAlloc(LPTR, sizeof(SCE_NAME_LIST)));
                if(!nameHead)
                {
                    hr = E_OUTOFMEMORY;
                    goto exit_gracefully;
                }
            }
            else
            {
                PSCE_NAME_LIST currentName =
                    (PSCE_NAME_LIST) LocalAlloc(LPTR, sizeof(SCE_NAME_LIST));
                if(!currentName)
                {
                    hr = E_OUTOFMEMORY;
                    goto exit_gracefully;
                }
                currentName->Next = nameHead;
                nameHead = currentName;
                head->pMembers = nameHead;
            }

            DWORD nameLen = wcslen((PTSTR) tempString);
            nameHead->Name = (PTSTR) LocalAlloc(LPTR, (nameLen+1) *sizeof(WCHAR) );
            if ( !(nameHead->Name) ) {

                hr = E_OUTOFMEMORY;
                goto exit_gracefully;
            }
            wcscpy(nameHead->Name, (PTSTR) tempString);
        }
    }

        //Add RSOP info
    pProfileInfo->listRIGroupMemebership.push_front(pInfo);


exit_gracefully:
    VariantClear(&bRGroup);
    VariantClear(&vMembers);
   _TRACE (-1,L"Leaving CWMIRsop::AddRestrictedGroupSetting\n");
    return hr;
}

HRESULT CWMIRsop::AddServiceSetting(IWbemClassObject *rsopInstance,
                            PRSOP_INFO pInfo,
                            PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    VARIANT bServiceName;
    PTSTR serviceName;
    VARIANT vSDDL;
    VARIANT vStartup;
    PSECURITY_DESCRIPTOR SDDL = NULL;
    DWORD startup;
    HRESULT hr = S_OK;


   _TRACE (1, L"Entering CWMIRsop::AddServiceSetting\n");

    hr = rsopInstance->Get(_bstr_t(TEXT("Service")),
                           0,
                           &bServiceName,
                           NULL,
                           NULL);
    if(FAILED(hr) || bServiceName.vt != VT_BSTR || bServiceName.bstrVal == NULL )
        goto exit_gracefully;

    hr = rsopInstance->Get(_bstr_t(TEXT("SDDLString")),
                           0,
                           &vSDDL,
                           NULL,
                           NULL);
    if(FAILED(hr))
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)(TEXT("StartupMode")),
                           0,
                           &vStartup,
                           NULL,
                           NULL);
    if(FAILED(hr))
        goto exit_gracefully;


    DWORD len;
    len = wcslen((PTSTR) V_BSTR(&bServiceName));
    serviceName = (PTSTR) LocalAlloc(LPTR, (len+1) *sizeof(WCHAR));
    if(!serviceName)
    {
        hr = E_OUTOFMEMORY;
        goto exit_gracefully;
    }
    wcscpy(serviceName,(PTSTR) V_BSTR(&bServiceName));

    ULONG sdLen;
    sdLen = 0;
    if( !ConvertStringSecurityDescriptorToSecurityDescriptor(
        (PTSTR) V_BSTR(&vSDDL),
        SDDL_REVISION_1,
        &SDDL,
        &sdLen
        ) )
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto exit_gracefully;
    }


    startup = (DWORD) V_I4(&vStartup);


    PSCE_SERVICES head;
    head = pProfileInfo->pServices;

    if (!head)
    {
        head = (pProfileInfo->pServices =
            (PSCE_SERVICES) LocalAlloc(LPTR, sizeof(SCE_SERVICES)));
        if(!head)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
    }
    else
    {
        PSCE_SERVICES current =
            (PSCE_SERVICES) LocalAlloc(LPTR, sizeof(SCE_SERVICES));
        if(!current)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }

        current->Next = head;
        head = current;
        pProfileInfo->pServices = head;
    }

    head->ServiceName = serviceName;
    head->General.pSecurityDescriptor = SDDL;
    head->Startup = (BYTE) startup; //no data loss value is <= 4

    //Add RSOP info
    pProfileInfo->listRIServices.push_front(pInfo);

exit_gracefully:
    VariantClear(&bServiceName);
    VariantClear(&vSDDL);
    VariantClear(&vStartup);
   _TRACE (-1,L"Leaving CWMIRsop::AddServiceSetting\n");

    return hr;
}

HRESULT CWMIRsop::AddFileSetting(IWbemClassObject *rsopInstance,
                            PRSOP_INFO pInfo,
                            PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    VARIANT bFileName;
    PTSTR fileName = NULL;
    VARIANT vSDDL;
    VARIANT vMode;
    PSECURITY_DESCRIPTOR SDDL = NULL;
    DWORD mode = 0;

   _TRACE (1, L"Entering CWMIRsop::AddFileSetting\n");

    HRESULT hr = S_OK;


    hr = rsopInstance->Get((BSTR)(TEXT("Path")),
                0,
                &bFileName,
                NULL,
                NULL
                );
    if(FAILED(hr) || bFileName.vt != VT_BSTR || bFileName.bstrVal == NULL )
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)(TEXT("Mode")),
                0,
                &vMode,
                NULL,
                NULL
                );
    if(FAILED(hr))
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)(TEXT("SDDLString")),
                0,
                &vSDDL,
                NULL,
                NULL
                );
    if(FAILED(hr))
        goto exit_gracefully;


    DWORD len;
    len = wcslen((PTSTR) V_BSTR(&bFileName));
    fileName = (PTSTR) LocalAlloc(LPTR, len * sizeof(TCHAR) + 2);
    if(!fileName)
    {
        hr = E_OUTOFMEMORY;
        goto exit_gracefully;
    }
    wcscpy(fileName, (PTSTR) V_BSTR(&bFileName));


    mode = (DWORD) V_I4(&vMode);


    if (mode != 1)
    {

        ULONG sdLen = 0;
        if( !ConvertStringSecurityDescriptorToSecurityDescriptor(
            (PTSTR) V_BSTR(&vSDDL),
            SDDL_REVISION_1,
            &SDDL,
            &sdLen
            ))
        {

            hr = HRESULT_FROM_WIN32(GetLastError());
            goto exit_gracefully;
        }
    }


    PSCE_OBJECT_ARRAY head;
    head = pProfileInfo->pFiles.pAllNodes;

    if(!head)
    {
        head =  (pProfileInfo->pFiles.pAllNodes =
            (PSCE_OBJECT_ARRAY) LocalAlloc(LPTR, sizeof(SCE_OBJECT_ARRAY)));
        if(!head)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
        head->pObjectArray =
            (PSCE_OBJECT_SECURITY*) LocalAlloc(LPTR, sizeof(PSCE_OBJECT_SECURITY)*m_cFileSize);
        if(!head->pObjectArray)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
    }
    else if(head->Count >= m_cFileSize)
    {
        PSCE_OBJECT_SECURITY* temp = (PSCE_OBJECT_SECURITY*) LocalAlloc(LPTR, sizeof(PSCE_OBJECT_SECURITY)*m_cFileSize*2);
        if(!temp)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
        memcpy(temp,head->pObjectArray,head->Count *sizeof(PSCE_OBJECT_SECURITY));
        LocalFree(head->pObjectArray);
        head->pObjectArray = temp;
        m_cFileSize *=2;
    }

    DWORD index;
    index = head->Count;

    head->pObjectArray[index] =
        (PSCE_OBJECT_SECURITY) LocalAlloc(LPTR, sizeof(SCE_OBJECT_SECURITY));
    if(!head->pObjectArray[index])
    {
        hr = E_OUTOFMEMORY;
        goto exit_gracefully;
    }
    head->pObjectArray[index]->Name = fileName;
    head->pObjectArray[index]->pSecurityDescriptor = SDDL;
    head->pObjectArray[index]->Status = (BYTE) mode;
    head->Count++;

    //SET RSOP INFO
    pProfileInfo->vecRIFiles.push_back(pInfo);

exit_gracefully:
    VariantClear(&bFileName);
    VariantClear(&vMode);
    if(mode != 1){
        VariantClear(&vSDDL);
    }
   _TRACE (-1,L"Leaving CWMIRsop::AddFileSetting\n");

    return hr;
}


HRESULT CWMIRsop::AddRegSetting(IWbemClassObject *rsopInstance,
                        PRSOP_INFO pInfo,
                        PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    PTSTR gpoID = NULL;
    VARIANT bFileName;
    PTSTR fileName = NULL;
    VARIANT vSDDL;
    VARIANT vMode;
    PSECURITY_DESCRIPTOR SDDL = NULL;
    DWORD mode = 0;
    static DWORD multiplier = 1;

    HRESULT hr = S_OK;

   _TRACE (1, L"Entering CWMIRsop::AddRegSetting\n");

    hr = rsopInstance->Get((BSTR)(TEXT("Path")),
                0,
                &bFileName,
                NULL,
                NULL
                );
    if(FAILED(hr) || bFileName.vt != VT_BSTR || bFileName.bstrVal == NULL )
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)(TEXT("Mode")),
                0,
                &vMode,
                NULL,
                NULL
                );
    if(FAILED(hr))
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)(TEXT("SDDLString")),
                0,
                &vSDDL,
                NULL,
                NULL
                );
    if(FAILED(hr))
        goto exit_gracefully;



    DWORD len;
    len = wcslen((PTSTR) V_BSTR(&bFileName));
    fileName = (PTSTR) LocalAlloc(LPTR, len * sizeof(TCHAR) + 2);
    if(!fileName)
    {
        hr = E_OUTOFMEMORY;
        goto exit_gracefully;
    }
    wcscpy(fileName, (PTSTR) V_BSTR(&bFileName));

    mode = (DWORD) V_I4(&vMode);


    if (mode != 1)
    {

        ULONG sdLen = 0;
        if( !ConvertStringSecurityDescriptorToSecurityDescriptor(
            (PTSTR) V_BSTR(&vSDDL),
            SDDL_REVISION_1,
            &SDDL,
            &sdLen
            ))
        {

            hr = HRESULT_FROM_WIN32(GetLastError());
            goto exit_gracefully;
        }
    }


    PSCE_OBJECT_ARRAY head;
    head = pProfileInfo->pRegistryKeys.pAllNodes;

    if(!head){
        head = (pProfileInfo->pRegistryKeys.pAllNodes =
            (PSCE_OBJECT_ARRAY) LocalAlloc(LPTR, sizeof(SCE_OBJECT_ARRAY)));
        if(!head)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
        head->pObjectArray =
            (PSCE_OBJECT_SECURITY*) LocalAlloc(LPTR, sizeof(PSCE_OBJECT_SECURITY)*m_cRegArrayCount);
        if(!head->pObjectArray)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
    }
    else if(head->Count >= m_cRegArrayCount){
        PSCE_OBJECT_SECURITY* temp = head->pObjectArray;
        head->pObjectArray =
            (PSCE_OBJECT_SECURITY*) LocalAlloc(LPTR, sizeof(PSCE_OBJECT_SECURITY)*m_cRegArrayCount*2);
        if(!head->pObjectArray)
        {
            hr = E_OUTOFMEMORY;
            goto exit_gracefully;
        }
        memcpy(head->pObjectArray,temp,head->Count *sizeof(PSCE_OBJECT_SECURITY));
        LocalFree(temp);
        m_cRegArrayCount *= 2;
    }

   //
   // Can't initialize at declaration since this is skipped by gotos
   //
    DWORD index;
   index = head->Count;

    head->pObjectArray[index] =
        (PSCE_OBJECT_SECURITY) LocalAlloc(LPTR, sizeof(SCE_OBJECT_SECURITY));
   if (head->pObjectArray[index]) {
    head->pObjectArray[index]->Name = fileName;
    head->pObjectArray[index]->pSecurityDescriptor = SDDL;
    head->pObjectArray[index]->Status = (BYTE) mode;
    head->Count++;
   }
    //add rsop info
    pProfileInfo->vecRIReg.push_back(pInfo);


exit_gracefully:
    VariantClear(&bFileName);
    VariantClear(&vMode);
    if(mode != 1){
        VariantClear(&vSDDL);
    }

   _TRACE (-1, L"Leaving CWMIRsop::AddRegSetting\n");
    return hr;
}


HRESULT CWMIRsop::AddStringSetting (IWbemClassObject *rsopInstance,
                              PRSOP_INFO pInfo,
                              PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    HRESULT hr = S_OK;
    VARIANT bKeyName;
    PWSTR   keyName = 0;
    VARIANT bSettingValue;
    PWSTR   settingValue = 0;

   _TRACE (1, L"Entering CWMIRsop::AddStringSetting\n");
    hr = rsopInstance->Get((BSTR)RSOP_KEYNAME,
                          0,
                          &bKeyName,
                          NULL,
                          NULL);
    if( FAILED(hr) || bKeyName.vt != VT_BSTR || bKeyName.bstrVal == NULL)
        goto exit_gracefully;

    hr = rsopInstance->Get((BSTR)RSOP_SETTING,
                          0,
                          &bSettingValue,
                          NULL,
                          NULL);
    if( FAILED(hr) || bSettingValue.vt != VT_BSTR || bSettingValue.bstrVal == NULL)
        goto exit_gracefully;


    keyName = V_BSTR(&bKeyName);
    settingValue = V_BSTR(&bSettingValue);

    if (!_wcsicmp(keyName, NEW_GUEST_NAME))
    {
        if ( 0 != pProfileInfo->NewGuestName )
        {
            LocalFree (pProfileInfo->NewGuestName);
            pProfileInfo->NewGuestName = 0;
        }

        size_t len = wcslen (settingValue);
        pProfileInfo->NewGuestName = (PWSTR) LocalAlloc (LPTR, (len + 1) * sizeof (TCHAR));
        if ( pProfileInfo->NewGuestName )
        {
            wcscpy (pProfileInfo->NewGuestName, settingValue);
        }
        else
            hr = E_OUTOFMEMORY;

        pProfileInfo->pRINewGuestName = pInfo;
    }
    else if (!_wcsicmp(keyName, NEW_ADMINISTRATOR_NAME))
    {
        if ( 0 != pProfileInfo->NewAdministratorName )
        {
            LocalFree (pProfileInfo->NewAdministratorName);
            pProfileInfo->NewAdministratorName = 0;
        }

        size_t len = wcslen (settingValue);
        pProfileInfo->NewAdministratorName = (PWSTR) LocalAlloc (LPTR, (len + 1) * sizeof (TCHAR));
        if ( pProfileInfo->NewAdministratorName )
        {
            wcscpy (pProfileInfo->NewAdministratorName, settingValue);
        }
        else
            hr = E_OUTOFMEMORY;

        pProfileInfo->pRINewAdministratorName = pInfo;
    }
    else
    {
       _ASSERT (FALSE); // key name not accounted for
    }


exit_gracefully:
    VariantClear(&bKeyName);
    VariantClear(&bSettingValue);

   _TRACE (-1,L"Leaving CWMIRsop::AddStringSetting\n");
    return hr;
}


HRESULT CWMIRsop::AddInstance(IWbemClassObject *rsopInstance,
                    PRSOP_INFO pInfo,
                    PWMI_SCE_PROFILE_INFO pProfileInfo)
{
    HRESULT hr = S_OK;
    LPWSTR className = NULL;

    _TRACE (1, L"Entering CWMIRsop::AddInstance\n");

    //Get RSOP_Class Name
    hr = GetClass(rsopInstance, &className);
    if( FAILED(hr) )
        goto exit_gracefully;


    if(!_wcsicmp(className, RSOP_SEC_NUM))
    {
        hr = AddNumericSetting(rsopInstance,
                               pInfo,
                               pProfileInfo);
    }
    else if(!_wcsicmp(className, RSOP_SEC_BOOL))
    {
        hr = AddBooleanSetting(rsopInstance,
                               pInfo,
                               pProfileInfo);
    }
    else if(!_wcsicmp(className, RSOP_SCE_STRING))
    {
       hr = AddStringSetting(rsopInstance,pInfo,pProfileInfo);
    }
    else if(!_wcsicmp(className, RSOP_AUDIT))
    {
        hr = AddAuditSetting(rsopInstance,pInfo,pProfileInfo);
    }
    else if(!_wcsicmp(className, RSOP_EVENT_NUM))
    {
        hr = AddEventLogNumericSetting (rsopInstance, pInfo, pProfileInfo);
    }
    else if(!_wcsicmp(className, RSOP_EVENT_BOOL))
    {
        hr = AddEventLogBooleanSetting(rsopInstance,pInfo,pProfileInfo);
    }
    else if(!_wcsicmp(className, RSOP_REG_VAL))
    {
        hr = AddRegValSetting(rsopInstance,pInfo,pProfileInfo);
    }
    else if(!_wcsicmp(className, RSOP_USER_RIGHT))
    {
        hr = AddUserRightSetting(rsopInstance,pInfo,pProfileInfo);
    }
    else if(!_wcsicmp(className, RSOP_RGROUPS))
    {
        hr = AddRestrictedGroupSetting(rsopInstance,pInfo,pProfileInfo);
    }
    else if(!_wcsicmp(className, RSOP_SERVICE))
    {
        hr = AddServiceSetting(rsopInstance,pInfo,pProfileInfo);
    }
    else if(!_wcsicmp(className, RSOP_FILE))
    {
        hr = AddFileSetting(rsopInstance,pInfo,pProfileInfo);
    }
    else if(!_wcsicmp(className, RSOP_REG))
    {
        hr = AddRegSetting(rsopInstance,pInfo,pProfileInfo);
    }
    else
    {
        _ASSERT (FALSE); // class not accounted for
    }
exit_gracefully:
    _TRACE (-1,L"Exiting CWMIRsop::AddInstance\n");
    LocalFree(className);
return hr;
}

HRESULT
CWMIRsop::GetGPOFriendlyName (PWSTR lpGPOID, PWSTR *pGPOName)
{
    BSTR pQuery = NULL, pName = NULL;
    LPTSTR lpQuery = NULL;
    IEnumWbemClassObject * pEnum = NULL;
    IWbemClassObject *pObjects[2];
    HRESULT hr;
    ULONG ulRet;
    VARIANT varGPOName;

    //
    // Set the default
    //

    *pGPOName = NULL;

    //
    // Build the query
    //

    lpQuery = (LPTSTR) LocalAlloc (LPTR, ((lstrlen(lpGPOID) + 50) * sizeof(TCHAR)));

    if (!lpQuery)
    {
        _TRACE (0, L"CWMIRsop::GetGPOFriendlyName: Failed to allocate memory for unicode query");
        hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
        goto Exit;
    }

    wsprintf (lpQuery, TEXT("SELECT name, id FROM RSOP_GPO where id=\"%s\""), lpGPOID);


    pQuery = SysAllocString (lpQuery);

    if (!pQuery)
    {
        _TRACE (0, L"CWMIRsop::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)
    {
       _TRACE (0, L"CWMIRsop::GetGPOFriendlyName: Failed to allocate memory for name");
        hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
        goto Exit;
    }


    //
    // Execute the query
    //

    hr = m_pSvc->ExecQuery (_bstr_t(QUERY_LANG), pQuery,
                            WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
                            NULL, &pEnum);


    if (FAILED(hr))
    {
        _TRACE (0, L"CWMIRsop::GetGPOFriendlyName: Failed to query for %s with 0x%x\n",
                  pQuery, hr);
        goto Exit;
    }


    //
    // Loop through the results
    //

    hr = pEnum->Next(WBEM_INFINITE, 1, pObjects, &ulRet);

    if (FAILED(hr))
    {
        _TRACE (0, L"CWMIRsop::GetGPOFriendlyName: Failed to get first item in query results for %s with 0x%x\n",
                  pQuery, hr);
        goto Exit;
    }


    //
    // Check for the "data not available case"
    //

    if (ulRet == 0)
    {
        hr = S_OK;
        goto Exit;
    }


    //
    // Get the name
    //

    VariantInit(&varGPOName);
    hr = pObjects[0]->Get (pName, 0, &varGPOName, NULL, NULL);

    if (FAILED(hr))
    {
        _TRACE (0, L"CWMIRsop::GetGPOFriendlyName: Failed to get gponame in query results for %s with 0x%x\n",
                  pQuery, hr);
        goto Exit;
    }


    //
    // Save the name
    //

    *pGPOName = (LPTSTR) LocalAlloc (LPTR, (lstrlen(varGPOName.bstrVal) + 1) * sizeof(TCHAR));

    if (!(*pGPOName))
    {
        _TRACE (0, L"CWMIRsop::GetGPOFriendlyName: Failed to allocate memory for GPO Name");
        hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
        goto Exit;
    }

    lstrcpy (*pGPOName, varGPOName.bstrVal);

    hr = S_OK;

Exit:
    VariantClear (&varGPOName);

    if (pEnum)
    {
        pEnum->Release();
    }

    if (pQuery)
    {
        SysFreeString (pQuery);
    }

    if (lpQuery)
    {
        LocalFree (lpQuery);
    }

    if (pName)
    {
        SysFreeString (pName);
    }

    return hr;
}