/******************************************************************
   Copyright (C) 2000 Microsoft Corp.

   Terminal.CPP -- WMI provider class implementation

   Generated by Microsoft WMI Code Generation Engine
  
   TO DO: - See individual function headers
          - When linking, make sure you link to framedyd.lib & 
            msvcrtd.lib (debug) or framedyn.lib & msvcrt.lib (retail).

   Description: 
   
  
  
******************************************************************/
#include "stdafx.h"
#include <fwcommon.h>
#include "Terminal.h"
#include "registry.h"
#include "smartptr.h"
#include <windows.h>
#include "cfgbkend_i.c"


#define TS_PATH TEXT("SYSTEM\\ControlSet\\Control\\Terminal Server")
#define TS_LOGON_PATH TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon")
#define TERMINAL_SERVICE_PARAM_DISCOVERY  TEXT("SYSTEM\\CurrentControlSet\\Services\\TermService\\Parameters")
#define TERMINAL_SERVICE_PARAM_DISCOVERY_SERVERS  TEXT("SYSTEM\\CurrentControlSet\\Services\\TermService\\Parameters\\LicenseServers")


extern TCHAR tchErrorMessage[ 80 ];



// TO DO: Replace "NameSpace" with the appropriate namespace for your
//        provider instance.  For instance:  "root\\default or "root\\cimv2".
//===================================================================


// Property names
//===============


// Property names
//===============

const static WCHAR* pErrorClass = L"\\\\.\\root\\cimv2:TerminalServiceSettingError";


CStackClass::CStackClass ( )
{
    HRESULT hr;

    m_pCfg = NULL;
    m_pCfgComp = NULL;

    hr = CoGetClassObject(CLSID_CfgComp, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void **)&m_pCfg); 
    
    TRC2((TB, "StackClass@Constructor: CoGetClassObject of IClassFactory ret 0x%x", hr));

    if( SUCCEEDED ( hr ) && m_pCfg != NULL )
    {           
        hr = m_pCfg->CreateInstance(NULL, IID_ICfgComp, (void **)&m_pCfgComp); 
        
        TRC2((TB, "StackClass@Constructor: CoCreateInstance of ICfgComp ret 0x%x", hr));
        
        if( SUCCEEDED ( hr ) && m_pCfgComp != NULL )
        {            
            hr = m_pCfgComp->Initialize( );
        }
        else
        {
            m_pCfgComp = NULL;
        }        
    }   
    else
    {
        m_pCfgComp = NULL;
        m_pCfg = NULL;
    }
}


//=--------------------
/******************************************************************************************************
*
*DESCRIPTION :     CWin32_TSProvider class is a base class from which all other classes are derived.
*                  The destructor releases the CfgBkEnd interface pointer.
*                  
********************************************************************************************************/

CStackClass::~CStackClass ()
{
    if ( NULL != m_pCfgComp )
    {
        m_pCfgComp->Release();
       
        TRC2((TB, "StackClass@Destructor for ICfgComp: succeeded"));        
    }    
    if ( NULL != m_pCfg )
    {
        m_pCfg->Release();
       
        TRC2((TB, "StackClass@Destructor for IClassFactory: succeeded"));       
    }
}



//------------------------




/*****************************************************************************
 *
 *  FUNCTION    :   CWin32_TerminalServiceSetting::CWin32_TerminalServiceSetting
 *                  This class reads and sets the Server Settings such as Terminal
 *                  server mode, license type, active desktop state, temp folders,
 *                  logon and Help.
 *
 *****************************************************************************/
CWin32_TerminalServiceSetting::CWin32_TerminalServiceSetting (LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) : Provider( lpwszName, lpwszNameSpace )
{
   
    if ( g_hInstance != NULL)
    {

        TRC2((TB, "CWin32_TerminalServiceSetting_ctor"));       

        _tcscpy(m_szServerName, _T("ServerName"));

        _tcscpy(m_szMode, _T("TerminalServerMode"));

        _tcscpy(m_szLicensingName, _T("LicensingName"));

        _tcscpy(m_szLicensingDescription, _T("LicensingDescription"));

        _tcscpy(m_szActiveDesktop, _T("ActiveDesktop"));

        _tcscpy(m_szUserPerm, _T("UserPermission"));

        _tcscpy(m_szDeleteTempFolders, _T("DeleteTempFolders"));

        _tcscpy(m_szUseTempFolders, _T("UseTempFolders"));

        _tcscpy(m_szLogons, _T("Logons"));

        _tcscpy(m_szHelp, _T("Help"));

        _tcscpy(m_szValue, _T("Value"));

        _tcscpy(m_szPropertyName, _T("PropertyName"));
        
        _tcscpy(m_szChangeMode, _T("ChangeMode"));

        _tcscpy(m_szLicensingType, _T("LicensingType"));

        _tcscpy(m_szSetPolicyPropertyName, _T("SetPolicyPropertyName"));

        _tcscpy(m_szAllowTSConnections, _T("AllowTSConnections"));

        _tcscpy(m_szSetAllowTSConnections, _T("SetAllowTSConnections"));

        _tcscpy(m_szSingleSession, _T("SingleSession"));

        _tcscpy(m_szSetSingleSession, _T("SetSingleSession"));

        _tcscpy(m_szProfilePath, _T("ProfilePath"));

        _tcscpy(m_szHomeDirectory, _T("HomeDirectory"));

        _tcscpy(m_szSetProfilePath, _T("SetProfilePath"));

        _tcscpy(m_szSetHomeDirectory, _T("SetHomeDirectory"));

        _tcscpy(m_szDirectConnectLicenseServers, _T("DirectConnectLicenseServers"));

        _tcscpy(m_szAddDirectConnectLicenseServer, _T("AddDirectConnectLicenseServer"));

        _tcscpy(m_szDeleteDirectConnectLicenseServer, _T("DeleteDirectConnectLicenseServer"));

        _tcscpy(m_szLicenseServerName, _T("LicenseServerName"));
        
    }        
    RegGetMachinePolicy(&m_gpPolicy);
                                                                                                                       
}

//=-------------
/*****************************************************************************
 *
 *  FUNCTION    :   CWin32_TerminalServiceSetting::~CWin32_TerminalServiceSetting
 *****************************************************************************/
CWin32_TerminalServiceSetting::~CWin32_TerminalServiceSetting ()
{
}
//=-------------
/*****************************************************************************
*
*  FUNCTION    :    CWin32_TerminalServiceSetting::EnumerateInstances
*
*  DESCRIPTION :    Returns all the instances of this class.
*
*  INPUTS      :    A pointer to the MethodContext for communication with WinMgmt.
*                   A long that contains the flags described in 
*                   IWbemServices::CreateInstanceEnumAsync.  Note that the following
*                   flags are handled by (and filtered out by) WinMgmt:
*                   WBEM_FLAG_DEEP, WBEM_FLAG_SHALLOW, WBEM_FLAG_RETURN_IMMEDIATELY, 
*                   WBEM_FLAG_FORWARD_ONLY, WBEM_FLAG_BIDIRECTIONAL
*
*  RETURNS     :    WBEM_S_NO_ERROR if successful
*
*  COMMENTS    :    All instances on the machine are returned here and
*                   all properties that this class knows how to populate must 
*                   be filled in.  If there are no instances, return 
*                   WBEM_S_NO_ERROR.  
*****************************************************************************/

HRESULT CWin32_TerminalServiceSetting::EnumerateInstances (MethodContext* pMethodContext, long lFlags )
{
    HRESULT hr = WBEM_E_INVALID_PARAMETER;        
    
    CInstance* pInstance = CreateNewInstance(pMethodContext);

    if( pInstance != NULL )
    {        

        TRC2((TB, "TerminalServiceSetting@EnumerateInstances: CreateNewInstance succeeded"));  
        
        hr = LoadPropertyValues(pInstance, BIT_ALL_PROPERTIES);

        if( SUCCEEDED( hr ))
        {
            hr = pInstance->Commit();            
            
        } 
        pInstance->Release( );
    }

    return hr ;
}
//=---------
/*****************************************************************************
*
*  FUNCTION    :    CWin32_TerminalServiceSetting::GetObject
*
*  DESCRIPTION :    Find a single instance based on the key property, the TerminalName. 
*
*  INPUTS      :    A pointer to a CInstance object containing the key properties. 
*                   A long that contains the flags described in 
*                   IWbemServices::GetObjectAsync.  
*
*  RETURNS     :    WBEM_S_NO_ERROR if the instance can be found
*                   WBEM_E_NOT_FOUND if the instance described by the key properties 
*                   could not be found
*                   WBEM_E_FAILED if the instance could be found but another error 
*                   occurred. 
*
*****************************************************************************/

HRESULT CWin32_TerminalServiceSetting::GetObject ( CInstance* pInstance, long lFlags, CFrameworkQuery &Query )
{
    

    HRESULT hr = WBEM_S_NO_ERROR;
    DWORD dwMode = 0;                  // Mode
    BOOL bActivate ;
    DWORD dwStatus = 0;
    CRegistry oRegObject;
    DWORD dwData = 0;
    DWORD dwRequiredProperties = 0;


    if( Query.IsPropertyRequired(m_szServerName))
       dwRequiredProperties |= BIT_SERVERNAME;
 
    if (Query.IsPropertyRequired(m_szMode))
       dwRequiredProperties |= BIT_MODE;

    if (Query.IsPropertyRequired(m_szActiveDesktop))
       dwRequiredProperties |= BIT_ACTIVEDESKTOP;

    if (Query.IsPropertyRequired(m_szDeleteTempFolders))
       dwRequiredProperties |= BIT_DELETETEMPDIRS;

    if (Query.IsPropertyRequired(m_szLicensingType))
       dwRequiredProperties |= BIT_LICENSING;

    if (Query.IsPropertyRequired(m_szLicensingName))
       dwRequiredProperties |= BIT_LICENSING;

    if (Query.IsPropertyRequired(m_szLicensingDescription))
       dwRequiredProperties |= BIT_LICENSING;

    if (Query.IsPropertyRequired(m_szLogons))
       dwRequiredProperties |= BIT_LOGONS;

    if (Query.IsPropertyRequired(m_szUserPerm))
       dwRequiredProperties |= BIT_USERPERM;

    if (Query.IsPropertyRequired(m_szUseTempFolders))
       dwRequiredProperties |= BIT_PERSESSIONTEMPDIR;

    if (Query.IsPropertyRequired(m_szHelp))
       dwRequiredProperties |= BIT_HELP;

    if (Query.IsPropertyRequired(m_szAllowTSConnections))
       dwRequiredProperties |= BIT_ALLOWTSCONNECTIONS;

    if (Query.IsPropertyRequired(m_szSingleSession))
        dwRequiredProperties |= BIT_SINGLESESSION;

    if (Query.IsPropertyRequired(m_szProfilePath))
        dwRequiredProperties |= BIT_PROFILEPATH;

    if (Query.IsPropertyRequired(m_szHomeDirectory))
        dwRequiredProperties |= BIT_HOMEDIRECTORY;

    if (Query.IsPropertyRequired(m_szDirectConnectLicenseServers))
        dwRequiredProperties |= BIT_DIRECTCONNECTLICENSESERVERS;

    hr = LoadPropertyValues(pInstance, dwRequiredProperties);


    return S_OK ;
}
//=---------

/*****************************************************************************
*
*  FUNCTION    :    CWin32_TerminalServiceSetting::ExecQuery
*
*  DESCRIPTION :    The method context is passed for use in the creation of 
*                   instances that satisfy the query, and a CFrameworkQuery 
*                   which describes the query.  Create and populate all 
*                   instances which satisfy the query.  You may return more 
*                   instances or more properties than are requested and WinMgmt 
*                   will post filter out any that do not apply.
*
*  INPUTS      :    A pointer to the MethodContext for communication with WinMgmt.
*                   A query object describing the query to satisfy.
*                   A long that contains the flags described in 
*                   IWbemServices::CreateInstanceEnumAsync.  Note that the following
*                   flags are handled by (and filtered out by) WinMgmt:
*                       WBEM_FLAG_FORWARD_ONLY
*                       WBEM_FLAG_BIDIRECTIONAL
*                       WBEM_FLAG_ENSURE_LOCATABLE
*
*  RETURNS     :    WBEM_E_PROVIDER_NOT_CAPABLE if queries not supported for 
*                       this class or if the query is too complex for this class
*                       to interpret.  The framework will call the EnumerateInstances
*                       function instead and let Winmgmt post filter.
*                   WBEM_E_FAILED if the query failed
*                   WBEM_S_NO_ERROR if query was successful 
*
*  COMMENTS    : TO DO: Most providers will not need to implement this method.  If you don't, WinMgmt 
*                       will call your enumerate function to get all the instances and perform the 
*                       filtering for you.  Unless you expect SIGNIFICANT savings from implementing 
*                       queries, you should remove this method.  You should also remove this method
*                       if you are implementing a 'method only' provider.
*
*****************************************************************************/
HRESULT CWin32_TerminalServiceSetting::ExecQuery (MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags)
{

    HRESULT hr = WBEM_E_NOT_FOUND;
    DWORD dwRequiredProperties = 0;
    CHStringArray asNames;
    DWORD dwMode = 0;
    DWORD dwStatus = 0;
	CStackClass StackObj;

	if( StackObj.m_pCfgComp == NULL)
	{
		return WBEM_E_ILLEGAL_NULL;
	}  	

    // Method 2
    Query.GetValuesForProp(m_szServerName, asNames);

    BOOL bGetAllInstances = asNames.GetSize() == 0;

    // Method 1
    if (Query.IsPropertyRequired(m_szServerName))
        dwRequiredProperties |= BIT_SERVERNAME;

    if (Query.IsPropertyRequired(m_szMode))
       dwRequiredProperties |= BIT_MODE;

    if (Query.IsPropertyRequired(m_szActiveDesktop))
       dwRequiredProperties |= BIT_ACTIVEDESKTOP;

    if (Query.IsPropertyRequired(m_szDeleteTempFolders))
       dwRequiredProperties |= BIT_DELETETEMPDIRS;

    if (Query.IsPropertyRequired(m_szLicensingType))
       dwRequiredProperties |= BIT_LICENSING;

    if (Query.IsPropertyRequired(m_szLogons))
       dwRequiredProperties |= BIT_LOGONS;

    if (Query.IsPropertyRequired(m_szUserPerm))
       dwRequiredProperties |= BIT_USERPERM;

    if (Query.IsPropertyRequired(m_szUseTempFolders))
       dwRequiredProperties |= BIT_PERSESSIONTEMPDIR;

    if (Query.IsPropertyRequired(m_szHelp))
        dwRequiredProperties |= BIT_HELP;

    if (Query.IsPropertyRequired(m_szAllowTSConnections))
       dwRequiredProperties |= BIT_ALLOWTSCONNECTIONS;

    if (Query.IsPropertyRequired(m_szSingleSession))
        dwRequiredProperties |= BIT_SINGLESESSION;

    if (Query.IsPropertyRequired(m_szProfilePath))
        dwRequiredProperties |= BIT_PROFILEPATH;

    if (Query.IsPropertyRequired(m_szHomeDirectory))
        dwRequiredProperties |= BIT_HOMEDIRECTORY;

    if (Query.IsPropertyRequired(m_szDirectConnectLicenseServers))
        dwRequiredProperties |= BIT_DIRECTCONNECTLICENSESERVERS;


    ISettingsComp *pSettings = NULL;
    
    hr = StackObj.m_pCfgComp->QueryInterface( IID_ISettingsComp , ( PVOID * )&pSettings ) ;

    do
    {
        if( SUCCEEDED( hr ) && pSettings != NULL )
        {

           // Method 2

            CInstance* pInstance = CreateNewInstance(pMethodContext);

            if( pInstance == NULL)
            {

               ERR((TB, "TerminalServiceSetting@ExecQuery: CreateNewInstance failed"));

               hr = WBEM_E_OUT_OF_MEMORY;

               break;            
            }            
      
            hr = LoadPropertyValues(pInstance, dwRequiredProperties);

            if( SUCCEEDED( hr ) )
            {
               hr = pInstance->Commit();
            }

            pInstance->Release();
        }
    
    }while (0);

    if ( pSettings != NULL )
    {
        pSettings->Release();
    }

    return hr;

}


//=--------------

BOOL CWin32_TerminalServiceSetting::IsInList(const CHStringArray &asArray, LPCWSTR pszString)
{
    DWORD dwSize = asArray.GetSize();

    for (DWORD x=0; x < dwSize; x++)
    {
        if( asArray[x].CompareNoCase(pszString) == 0 )
        {
            return TRUE;
        }
    }

    return FALSE;
}


//=---------
/*************************************************************************************
*
*  FUNCTION    : CWin32_TerminalServiceSetting::PutInstance
*
*  DESCRIPTION :    PutInstance is in provider classes that can 
*                   write instance information back to the registry.
*
*  INPUTS      :    A pointer to a CInstance object containing the key 
*                   property - TerminalServerMode.
* 
*                   A long that contains the flags described in 
*                   IWbemServices::PutInstanceAsync.  
*
*  RETURNS     :    WBEM_E_PROVIDER_NOT_CAPABLE if PutInstance is not available
*                   WBEM_E_FAILED if there is an error delivering the instance
*                   WBEM_E_INVALID_PARAMETER if any of the instance properties 
*                   are incorrect.
*                   WBEM_S_NO_ERROR if instance is properly delivered
*
*  COMMENTS    :    ActiveDesktop state, UserPerm and Logon are configurable through 
*                   this method as they are not Group Policy based nor server-overridable. 
*
***************************************************************************************/

HRESULT CWin32_TerminalServiceSetting::PutInstance ( const CInstance &Instance, long lFlags)
{   
    HRESULT hr = 0;               
    DWORD dwMode = 0;
    DWORD dwlicensing = 0;         // Licensing mode
    DWORD dwActiveDesktop = 0;     // Active Desktop Enabled or Disabled
    DWORD dwUserPerm = 0;          // Application Compatibility
    DWORD dwDeleteTempFolders = 0; // Delete Temporary Directories on Exit
    DWORD dwUseTempFolders = 0;
    DWORD dwData = 0;
    DWORD dwStatus = 0;
    CHString chData;
    CRegistry oRegObject;
    OSVERSIONINFOW OsVersionInfo;
    OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
    TCHAR tch[MAX_PATH] = {0};
	ICfgComp *pCfgComp = NULL;
        
    hr = WBEM_S_NO_ERROR;
    
	CStackClass StackObj;

	if(StackObj.m_pCfgComp == NULL)
	{
		return WBEM_E_ILLEGAL_NULL;
	}
    
    ISettingsComp *pSettings = NULL;

    hr = StackObj.m_pCfgComp->QueryInterface( IID_ISettingsComp , ( PVOID * )&pSettings ) ;
    
    do
    {
        if( SUCCEEDED (hr) && pSettings != NULL )
        {           
            if( Instance.GetDWORD(m_szActiveDesktop, dwActiveDesktop ) )
            {
                if( dwActiveDesktop != 0 && dwActiveDesktop != 1 )
                {
                    hr = WBEM_E_INVALID_PARAMETER;
                    
                    break;
                }

                pSettings->SetActiveDesktopState( dwActiveDesktop, &dwStatus );

                TRC2((TB, "TerminalServiceSetting@PutInstance: SetActiveDesktopState returned 0x%x\n" , dwStatus));
            }            
            
            if( Instance.GetDWORD( m_szUserPerm, dwUserPerm ) )
            {
                if( dwUserPerm != 0 && dwUserPerm != 1 )
                {
                    hr = WBEM_E_INVALID_PARAMETER;
                    
                    break;
                }

                pSettings->SetUserPerm(dwUserPerm, &dwStatus );

                TRC2((TB, "TerminalServiceSetting@PutInstance: SetUserPerm returned 0x%x\n" , dwStatus));               
            }            
            
          

            hr = oRegObject.OpenKey(HKEY_LOCAL_MACHINE, TS_LOGON_PATH);

            chData.Empty();

            if( SUCCEEDED( hr ) )
            {
                if( GetVersionEx( &OsVersionInfo) )
                {
                    if( OsVersionInfo.dwMajorVersion == 5 && OsVersionInfo.dwMinorVersion == 0 )
                    {
                        TRC2((TB, "TerminalServiceSetting@GetObject GetVersionInfo is Win2000"));

                        if( Instance.GetCHString(m_szLogons, chData ) )
                        {
                            if( chData.IsEmpty() || ((lstrcmp ((LPCTSTR)chData, L"0") != 0 ) && (lstrcmp ((LPCTSTR) chData, L"1") != 0)) )
                            {
                                hr = WBEM_E_INVALID_PARAMETER;
                
                                break;
                            }

                            // Todo: Add this for Beta2 to reverse logic

                            /*

                            if( lstrcmp ((LPCTSTR)chData, L"0") == 0 )
                            {
                                chData.Empty();
                                chData = L"1";
                            }
                            else
                            {
                                chData.Empty();
                                chData = L"0";
                            }
                            */
                                              
                            hr = oRegObject.WriteRegString(L"WinStationsDisabled", (LPTSTR) (LPCTSTR) chData);
                        
                            TRC2((TB, "TerminalServiceSetting@PutInstance WinStationsDisabled returned 0x%x\n" , hr));                                                   
                        }
                    }     
    
                    else
                    {
                        TRC2((TB, "TermServiceSetting@PutInstance GetVersionInfo is Whistler"));

                        if( Instance.GetCHString(m_szLogons, chData ) )
                        {
                            if( chData.IsEmpty() || ((lstrcmp ((LPCTSTR)chData, L"0") != 0 ) && (lstrcmp ((LPCTSTR) chData, L"1") != 0)) )
                            {
                                hr = WBEM_E_INVALID_PARAMETER;
                
                                break;
                            } 
                            
                            /*

                            if( lstrcmp ((LPCTSTR)chData, L"0") == 0 )
                            {
                                chData.Empty();
                                chData = L"1";
                            }
                            else
                            {
                                chData.Empty();
                                chData = L"0";
                            }
                            */
                            
                            hr = oRegObject.WriteRegString(L"WinStationsDisabled", (LPTSTR) (LPCTSTR) chData);
                        
                            TRC2((TB, "TermServiceSetting@PutInstance WinStationDisabled returned 0x%x\n" , hr));
                        }
                    }                                        
                }                                    
            }

            // ForceUpdate() is called explicitly to update WinstationsDisabled in the registry.

            if( SUCCEEDED( hr ) )
            {
                StackObj.m_pCfgComp->ForceUpdate();
            }
        }

    }while(0);
    
	
    if( pSettings != NULL )
    {
        pSettings->Release();
    }
    
    return hr;
    
}


//=---------
/*****************************************************************************
*
*  FUNCTION    :    CWin32_TerminalServiceSetting::DeleteInstance
*
*  DESCRIPTION :    DeleteInstance, like PutInstance, actually writes information
*                   to the software or hardware.  For most hardware devices, 
*                   DeleteInstance should not be implemented, but for software
*                   configuration, DeleteInstance implementation is plausible.
*
*  INPUTS      :    A pointer to a CInstance object containing the key properties. 
*                   A long that contains the flags described in 
*                   IWbemServices::DeleteInstanceAsync.  
*
*  RETURNS     :    WBEM_E_PROVIDER_NOT_CAPABLE if DeleteInstance is not available.
*                   WBEM_E_FAILED if there is an error deleting the instance.
*                   WBEM_E_INVALID_PARAMETER if any of the instance properties 
*                   are incorrect.
*                   WBEM_S_NO_ERROR if instance is properly deleted.
*
*  COMMENTS    : TO DO: If you don't intend to support deleting instances or are
*                       creating a 'method only' provider, remove this method.
*
*****************************************************************************/
HRESULT CWin32_TerminalServiceSetting::DeleteInstance ( const CInstance &Instance,  long lFlags )
{
    

    return (WBEM_E_PROVIDER_NOT_CAPABLE);

}


//=---------
/*****************************************************************************
*
*  FUNCTION    :    CWin32_TerminalServiceSetting::ExecMethod
*
*  DESCRIPTION :    Override this function to provide support for methods.  
*                   A method is an entry point for the user of your provider 
*                   to request your class perform some function above and 
*                   beyond a change of state.  (A change of state should be 
*                   handled by PutInstance() )
*
*  INPUTS      :    A pointer to a CInstance containing the instance the method was executed against.
*                   A string containing the method name
*                   A pointer to the CInstance which contains the IN parameters.
*                   A pointer to the CInstance to contain the OUT parameters.
*                   A set of specialized method flags
*
*  RETURNS     :    WBEM_E_PROVIDER_NOT_CAPABLE if not implemented for this class
*                   WBEM_S_NO_ERROR if method executes successfully
*                   WBEM_E_FAILED if error occurs executing method 
*
*  COMMENTS    :    Provides method to configure the License type base on
*                   the Terminal server mode, UseTempFolders, DeleteTempFolders
*                   and Help that are group policy based.
*
*****************************************************************************/
HRESULT CWin32_TerminalServiceSetting::ExecMethod ( const CInstance& Inst,
                        const BSTR bstrMethodName,
                        CInstance *pInParams,
                        CInstance *pOutParams,
                        long lFlags)

{
    
    
    DWORD dwMode = 0;
    DWORD dwLicensing = 0;
    DWORD dwStatus = 0;
    DWORD dwNewStatus = 0;
    DWORD dwData = 0;
    HANDLE hServer = NULL;
    BOOL fRet = FALSE;
    CHString chData;
    bool fData;
    bool bRet;
    CRegistry oRegObject;	
    HRESULT hr = WBEM_E_INVALID_PARAMETER;
    CStackClass StackObj;
    HKEY hKey = NULL;
    HKEY hOutKey = NULL;
    

	if(StackObj.m_pCfgComp == NULL)
	{
		return WBEM_E_ILLEGAL_NULL;
	}

    ISettingsComp *pSettings = NULL;

    if(pInParams == NULL)
    {
        return WBEM_E_INVALID_METHOD_PARAMETERS;
    }
    
    hr = StackObj.m_pCfgComp->QueryInterface( IID_ISettingsComp , ( PVOID * )&pSettings ) ;
        
    do
    {        
        if( SUCCEEDED (hr) && pSettings != NULL )
        {            
            if( _wcsicmp(bstrMethodName, m_szChangeMode) == 0 )
            {
                // Configures License type based on the Terminal Server Mode. {None, Remote Administration} for "Remote Admin", 
                // {Per Seat, Per CPU, ICL} for "Application Server" and {Personal Terminal Server} for "Personal Terminal Server".
                // uint32 ChangeMode([In] uint32 LicensingType);
                            
                hr = WBEM_S_NO_ERROR ;
                
                
                bRet = pInParams->GetDWORD(m_szLicensingType, dwLicensing);
                
                if ( !bRet )
                {
                    hr = WBEM_E_INVALID_PARAMETER;
                    
                    break;
                }                    
                                
                
                hServer = ServerLicensingOpen(NULL);

                if (NULL != hServer)
                {                
                    dwStatus = ServerLicensingSetPolicy(hServer, dwLicensing, &dwNewStatus);                               
                
                    TRC2( (TB, "TermServiceSetting@ExecMethod:ChangeMode ServerLicensingSetPolicy ret old: 0x%x new: 0x%x\n" , dwStatus, dwNewStatus) );  
                
                    if( ERROR_SUCCESS == dwStatus && ERROR_SUCCESS == dwNewStatus && pOutParams != NULL )
                    {
                        pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);
                    }
                    else if( ERROR_SUCCESS != dwStatus || ERROR_SUCCESS != dwNewStatus )
                    {                        
                        hr = WBEM_E_INVALID_OPERATION;                        

                        break;
                    }                    
                }
                
            }

            else if( _wcsicmp( bstrMethodName, m_szSetAllowTSConnections ) == 0 )
            {
                
                dwData = 0;
                dwStatus = 0; 
                bRet;
                
                RegGetMachinePolicy(&m_gpPolicy);

                if( m_gpPolicy.fPolicyDenyTSConnections == 0 )
                {  
                    TRC2((TB, "Condition to update fPolicyDenyTSConnections satisfied"));                        
                      
                    bRet = pInParams->GetDWORD(m_szAllowTSConnections, dwData);
                    

                    if ( !bRet || (dwData != 0 && dwData != 1 ))
                    {
                        hr = WBEM_E_INVALID_PARAMETER;
                        
                        break;
                    } 

                    // The bit is negated because it calls the function SetDenyTSConnections which is negative logic.
                    
                    if( dwData == 0 )
                    {
                        dwData = 1;                                            
                    }
                    else if( dwData == 1 )
                    {
                        dwData = 0;
                    }
                                        
                    hr = pSettings->SetDenyTSConnections( dwData , &dwStatus );
                    
                    if( SUCCEEDED( hr ) && pOutParams != NULL )
                    {
                        hr = StackObj.m_pCfgComp->ForceUpdate();

                        pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);
                        
                        TRC2((TB,"TSTerminalServiceSetting@ExecMethod:  SetAllowTSConnections ret 0x%x\n" , hr  ));
                    } 
                    
                }
                else
                {
                    
                    hr = WBEM_E_INVALID_OPERATION;
                    
                    break;
                    
                }
                
            }
            
            else if( _wcsicmp( bstrMethodName, m_szSetSingleSession ) == 0 )
            {
                
                dwData = 0;
                dwStatus = 0; 
                bRet;
                
                RegGetMachinePolicy(&m_gpPolicy);

                if( m_gpPolicy.fPolicySingleSessionPerUser == 0 )
                {  
                    TRC2((TB, "Condition to update fSingleSessionPerUser satisfied"));                        
                      
                    bRet = pInParams->GetDWORD(m_szSingleSession, dwData);
                    

                    if ( !bRet || (dwData != 0 && dwData != 1 ))
                    {
                        hr = WBEM_E_INVALID_PARAMETER;
                        
                        break;
                    }                                        
                    
                    hr = pSettings->SetSingleSessionState( dwData , &dwStatus );
                    
                    if( SUCCEEDED( hr ) && pOutParams != NULL )
                    {
                        hr = StackObj.m_pCfgComp->ForceUpdate();

                        pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);
                        
                        TRC2((TB,"TerminalServiceSetting@ExecMethod:  SetSingleSession ret 0x%x\n" , hr  ));
                    } 
                    
                }
                else
                {
                    
                    hr = WBEM_E_INVALID_OPERATION;
                    
                    break;
                    
                }
                
            }
            else if( _wcsicmp( bstrMethodName, m_szSetProfilePath ) == 0 )
            {
                
                BSTR bstrVal = NULL;
                dwStatus = 0; 
                bRet;
                
                RegGetMachinePolicy(&m_gpPolicy);

                if( m_gpPolicy.fPolicyWFProfilePath == 0 )
                {  
                    TRC2((TB, "Condition to update WFProfilePath satisfied"));                        
                      
                    bRet = pInParams->GetCHString(m_szProfilePath, chData);                    

                    if ( !bRet )
                    {
                        hr = WBEM_E_INVALID_PARAMETER;
                        
                        break;
                    }                                        

                    bstrVal = SysAllocString((LPTSTR) (LPCTSTR) (chData));

                    if(bstrVal != NULL)
                    {                                         
                        hr = pSettings->SetProfilePath( bstrVal , &dwStatus );
                    
                        if( SUCCEEDED( hr ) && pOutParams != NULL )
                        {
                            hr = StackObj.m_pCfgComp->ForceUpdate();

                            pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);
                        
                            TRC2((TB,"TerminalServiceSetting@ExecMethod:  SetProfilePath ret 0x%x\n" , hr  ));
                        }
                    }
                    
                }
                else
                {
                    
                    hr = WBEM_E_INVALID_OPERATION;
                    
                    break;
                    
                }
                
            }
            else if( _wcsicmp( bstrMethodName, m_szSetHomeDirectory ) == 0 )
            {
                
                BSTR bstrVal = NULL;
                dwStatus = 0; 
                bRet;
                
                RegGetMachinePolicy(&m_gpPolicy);

                if( m_gpPolicy.fPolicyWFHomeDir == 0 )
                {  
                    TRC2((TB, "Condition to update WFProfilePath satisfied"));                        
                      
                    bRet = pInParams->GetCHString(m_szHomeDirectory, chData);
                    

                    if ( !bRet )
                    {
                        hr = WBEM_E_INVALID_PARAMETER;
                        
                        break;
                    }                          

                    bstrVal = SysAllocString((LPTSTR) (LPCTSTR) (chData));

                    if(bstrVal != NULL)
                    {                   
                        hr = pSettings->SetHomeDir( bstrVal , &dwStatus );
                    
                        if( SUCCEEDED( hr ) && pOutParams != NULL )
                        {
                            hr = StackObj.m_pCfgComp->ForceUpdate();

                            pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);
                        
                            TRC2((TB,"TerminalServiceSetting@ExecMethod:  SetHomeDirectory ret 0x%x\n" , hr  ));
                        }
                    }
                    
                }
                else
                {
                    
                    hr = WBEM_E_INVALID_OPERATION;
                    
                    break;
                    
                }
                
            }        
            else if( _wcsicmp(bstrMethodName, m_szSetPolicyPropertyName) == 0 )
            {
                //  PropertyName is an enumeration of the properties: 
                //  DeleteTempFolders, UseTempFolders and Help which are flags that are either set
                //  to False or True according as whether Value is set to 0 or 1 respectively.
                //                                  
                //  uint32 SetPolicyPropertyName([In] string PropertyName, [In] boolean Value) ;
                
                RegGetMachinePolicy(&m_gpPolicy);
    
                pInParams->GetCHString(m_szPropertyName, chData);                
                
                if( chData.CompareNoCase(m_szDeleteTempFolders) == 0 )
                {
                    pInParams->Getbool(m_szValue, fData);
                    
                    TRC2((TB, "m_gpPolicy.fPolicyDeleteTempFoldersOnExit ret 0x%x\n", m_gpPolicy.fPolicyDeleteTempFoldersOnExit));                          
                    
                    if( m_gpPolicy.fPolicyDeleteTempFoldersOnExit == 0 )
                    {  
                        TRC2((TB, "Condition to update fPolicyDeleteTempFoldersOnExit satisfied"));
                        
                        if( fData != 0 && fData != 1 )
                        {
                            hr = WBEM_E_INVALID_PARAMETER;
                            
                            break;
                        }
                        
                        hr = pSettings->SetDelDirsOnExit(fData);
                        
                        TRC2((TB, "TerminalServiceSetting@PutInstance: SetDelDirsOnExit"));
                        
                        if( pOutParams != NULL )
                        {
                            pOutParams->SetDWORD(L"ReturnValue", hr);
                        }
                        
                    }
                    else
                    {
                        hr = WBEM_E_INVALID_OPERATION;
                        
                        break;
                    }
                }
                else if( chData.CompareNoCase(m_szUseTempFolders) == 0 )
                {
                    pInParams->Getbool(L"Value", fData);
                    
                    TRC2((TB, "m_gpPolicy.fPolicyTempFoldersPerSession ret 0x%x\n", m_gpPolicy.fPolicyTempFoldersPerSession));

                    
                    if( m_gpPolicy.fPolicyTempFoldersPerSession == 0 )
                    {
                        TRC2((TB, "Condition to update fPolicyTempFoldersPerSession satisfied"));
                        
                        if( fData != 0 && fData != 1 )
                        {
                            hr = WBEM_E_INVALID_PARAMETER;
                            
                            break;
                        }
                        
                        hr = pSettings->SetUseTempDirPerSession(fData );
                        
                        TRC2((TB, "TerminalServiceSetting@ExecMethod: SetUseTempDirPerSession"));
                        
                        if( pOutParams != NULL )
                        {
                            pOutParams->SetDWORD(L"ReturnValue", hr);
                        }
                        
                    }
                    else
                    {
                        hr = WBEM_E_INVALID_OPERATION;
                        
                        break;
                    }
                }
                else if( chData.CompareNoCase(m_szHelp) == 0 )
                {                      
                    hr = oRegObject.OpenKey(HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE);

                    if( SUCCEEDED (hr) )
                    {
                        if( ERROR_SUCCESS != oRegObject.ReadRegDWord(POLICY_TS_REMDSK_ALLOWTOGETHELP, &dwData) )
                        {
                            pInParams->Getbool(m_szValue, fData);                        
        
                            TRC2((TB, "Condition to update fAllowToGetHelp satisfied"));
            
                            if( fData != 0 && fData != 1 )
                            {
                                hr = WBEM_E_INVALID_PARAMETER;
                
                                break;
                            }
            
                            hr = pSettings->SetSalemHelpMode(fData, &dwStatus );
            
                            TRC2((TB, "TerminalServiceSetting@ExecMethod: Help"));
            
                            if( pOutParams != NULL && dwStatus == ERROR_SUCCESS )
                            {                               
                                pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);
                            }                                                
                            else
                            {
                                hr = WBEM_E_INVALID_OPERATION;
                
                                break;
                            }
                        }
                    }                            
                }
                else
                {
                    hr = WBEM_E_INVALID_METHOD_PARAMETERS;
                
                    break;
                }  
            }

                                
            else if(  _wcsicmp( bstrMethodName, m_szAddDirectConnectLicenseServer ) == 0 )
            {                      
                DWORD dwReturn = 0;
                 
                bRet = pInParams->GetCHString(m_szLicenseServerName, chData);

                if( chData.IsEmpty() )
                {
                    hr = WBEM_E_INVALID_PARAMETER;

                    break;
                }

              
                
                hr = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
                                    TERMINAL_SERVICE_PARAM_DISCOVERY ,
                                    0,
                                    KEY_READ ,
                                    &hKey );

                if( ERROR_SUCCESS == hr )
                { 


                    hr = RegCreateKeyEx( hKey ,
                                            L"LicenseServers",
                                            0,
                                            NULL,
                                            REG_OPTION_NON_VOLATILE,
                                            KEY_ALL_ACCESS,
                                            NULL,
                                            &hOutKey ,
                                            &dwReturn ); 
                    if( ERROR_SUCCESS == hr )
                    {                                    
                        hr = RegCreateKeyEx( hOutKey ,
                                                chData.LockBuffer(),
                                                0,
                                                NULL,
                                                REG_OPTION_NON_VOLATILE,
                                                KEY_ALL_ACCESS,
                                                NULL,
                                                &hOutKey ,
                                                &dwReturn );   
                        chData.UnlockBuffer();

                        TRC2((TB, "Win32_TerminalServiceSetting@ExecMethod: AddLicenseServer ret 0x%x" , hr));                 
                    }

                    if( hr == ERROR_SUCCESS )
                    {

                        pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);
                    }  
                                        
                    chData.Empty();
                }
            }

            else if(  _wcsicmp( bstrMethodName, m_szDeleteDirectConnectLicenseServer ) == 0 )
            {                      
                DWORD dwReturn = 0;
                 
                bRet = pInParams->GetCHString(m_szLicenseServerName, chData );

                
                if( chData.IsEmpty() )
                {
                    hr = WBEM_E_INVALID_PARAMETER;

                    break;
                }

                hr = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
                                    TERMINAL_SERVICE_PARAM_DISCOVERY_SERVERS,                                        
                                    0,
                                    KEY_ALL_ACCESS ,
                                    &hKey );

                if( ERROR_SUCCESS == hr )
                { 
            
                    hr = RegDeleteKey( hKey ,
                                         chData.LockBuffer() );      

                    TRC2((TB, "Win32_TerminalServiceSetting@ExecMethod: DeleteLicenseServer ret 0x%x" , hr));                       

                    if( hr == ERROR_SUCCESS )
                    {

                        pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);
                    }

                    chData.UnlockBuffer();

                    chData.Empty();                        
                
                }
                else
                {
                    hr = S_OK;
                }
            }                                                                                                            
        }

    }while (0);

    if( NULL != hKey )
    {
        RegCloseKey(hKey);
    }

    if(NULL != hOutKey)
    {
        RegCloseKey(hOutKey);
    }

    if( NULL != hServer )
    {
        ServerLicensingClose(hServer);
    }
    
    if( pSettings != NULL )
    {
        pSettings->Release();       
    }
    
    return hr;
}

//=---------

HRESULT CWin32_TerminalServiceSetting::LoadPropertyValues( CInstance *pInstance, DWORD dwRequiredProperties)
{         
    int Licensing;
    DWORD dwMode = 0;
    DWORD dwData = 0;
    ULONG ulMode = 0;
    CRegistry oRegObject;
    DWORD dwSize = 0;
    BOOL bData = 0;
    BOOL bActivate = 0;
    DWORD dwStatus = 0;
    DWORD dwType = 0;
    HANDLE      hServer = NULL;
    BYTE bbyte;
    OSVERSIONINFOW OsVersionInfo;
    OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
    LPTSTR lpLogon; 
    int iData;
    LPLCPOLICYINFO_V1W pPolicyInfo = NULL;
    ULONG  ulInfoStructVersion = LCPOLICYINFOTYPE_CURRENT;	
    CHString chLogon;
    CHString chData;
    HKEY hParamKey = NULL;
    HRESULT hr = WBEM_E_INVALID_PARAMETER;
    CHString chServerName;
    
    chServerName.Format(L"%s", (LPCTSTR)GetLocalComputerName());

    CStackClass StackObj;

	if(StackObj.m_pCfgComp == NULL)
	{
		return WBEM_E_ILLEGAL_NULL;
	}

    if( pInstance == NULL )
    {
        ERR((TB, "TermServiceSetting@LoadPropertyValues: invalid interface"));

        return E_FAIL;
    }
    ISettingsComp *pSettings = NULL;

    hr = StackObj.m_pCfgComp->QueryInterface( IID_ISettingsComp , ( PVOID * )&pSettings ) ;    

    if( SUCCEEDED (hr) && pSettings != NULL )
    {

        if( dwRequiredProperties & BIT_SERVERNAME )
        {
            pInstance->SetCHString(m_szServerName, chServerName);            
        }

        if( dwRequiredProperties & BIT_MODE )
        {
            pSettings->GetTermSrvMode(&dwMode , &dwStatus );
        
            TRC2((TB, "TermServiceSetting@LoadPropertyValues: GetTermSrvMode returned 0x%x\n" , dwStatus));

            if( ERROR_SUCCESS == dwStatus )
            {            
                pInstance->SetDWORD(m_szMode, dwMode);
            }            
        }

        if( dwRequiredProperties & BIT_LICENSING )
        {            
            hServer = ServerLicensingOpen(NULL);

            if (NULL != hServer)
            {
                if( ServerLicensingGetPolicy( hServer, &ulMode ) )
                {            
                    TRC2((TB, "TermServiceSetting@LoadPropertyValues: ServerLicensingGetPolicy ret 0x%x\n" , dwStatus));
                 
                    pInstance->SetDWORD(m_szLicensingType, (DWORD &)ulMode);   
                    
                    if( ServerLicensingGetPolicyInformation( hServer, ulMode, &ulInfoStructVersion, 
                        (LPLCPOLICYINFOGENERIC *) &pPolicyInfo ))
                    {
                        pInstance->SetCHString(m_szLicensingName, pPolicyInfo->lpPolicyName );
                        pInstance->SetCHString(m_szLicensingDescription, pPolicyInfo->lpPolicyDescription );

                        ServerLicensingFreePolicyInformation((LPLCPOLICYINFOGENERIC *)&pPolicyInfo);
                    }
                }      

                ServerLicensingClose(hServer);
            }
            
        }

        if( dwRequiredProperties & BIT_ACTIVEDESKTOP )
        {
            pSettings->GetActiveDesktopState(&bActivate , &dwStatus );

            TRC2((TB, "TermServiceSetting@LoadPropertyValues: GetActiveDesktopState returned 0x%x\n" , dwStatus));
            
            if( ERROR_SUCCESS == dwStatus )
            {
                pInstance->SetDWORD(m_szActiveDesktop, (DWORD &)bActivate);
            }

            if( 2 == dwStatus )
            {
                pInstance->SetDWORD(m_szActiveDesktop, 0);
            }
        }

        if( dwRequiredProperties & BIT_USERPERM )
        {
            pSettings->GetUserPerm(&bActivate , &dwStatus );

            TRC2((TB, "TermServiceSetting@LoadPropertyValues: GetUserPerm returned 0x%x\n" , dwStatus));

            if( ERROR_SUCCESS == dwStatus )
            {
                pInstance->SetDWORD(m_szUserPerm, bActivate);        
            }            
        }        
            

        if( dwRequiredProperties & BIT_DELETETEMPDIRS )
        {
            RegGetMachinePolicy(&m_gpPolicy);

            if( m_gpPolicy.fPolicyDeleteTempFoldersOnExit != 0 )
            {
                bActivate = m_gpPolicy.fDeleteTempFoldersOnExit;
            }
            else
            {
                pSettings->GetDelDirsOnExit( &bActivate );
            }

            TRC2((TB, "TermServiceSetting@LoadPropertyValues: GetDelDirsOnExit returned 0x%x\n" , hr));
            
            pInstance->SetDWORD(m_szDeleteTempFolders, bActivate);                        
        }

        if( dwRequiredProperties & BIT_PERSESSIONTEMPDIR )
        {
            RegGetMachinePolicy(&m_gpPolicy);

            if( m_gpPolicy.fPolicyTempFoldersPerSession != 0 )
            {
                bActivate = m_gpPolicy.fTempFoldersPerSession;
            }
            else
            {
                pSettings->GetUseTempDirPerSession(&bActivate );
            }

            TRC2((TB, "TermServiceSetting@LoadPropertyValues: GetUseTempDirsPerSession returned 0x%x\n" , hr));
              
            pInstance->SetDWORD(m_szUseTempFolders, bActivate);                        
        }
        

        if( dwRequiredProperties & BIT_LOGONS )
        {
            hr = oRegObject.OpenKey(HKEY_LOCAL_MACHINE, TS_LOGON_PATH);

            if( SUCCEEDED( hr ) )
            {   
                if( GetVersionEx( &OsVersionInfo) )
                {

                    if( OsVersionInfo.dwMajorVersion == 5 && OsVersionInfo.dwMinorVersion == 0 )
                    {
                        TRC2((TB, "TermServiceSetting@LoadPropertyValues: GetVersionInfo is Win2000"));

                        dwData = 0;
                                      
                        hr = oRegObject.ReadRegDWord(L"WinStationsDisabled", &dwData);
                        
                        TRC2((TB, "TermServiceSetting@LoadPropertyValues: GetWinStationsDisabled returned 0x%x\n" , hr));

                        if( SUCCEEDED (hr) )
                        {
                            if( dwData == 0 )
                            {
                                pInstance->SetCharSplat(m_szLogons, L"0");
                            }

                            else
                            {
                                pInstance->SetCharSplat(m_szLogons, L"1");
                            }
                        }                        
                    }     
    
                    else
                    {
                        TRC2((TB, "TermServiceSetting@LoadPropertyValues: GetVersionInfo is Whistler"));                    
          
                        hr = oRegObject.ReadRegString(L"WinStationsDisabled", &lpLogon, &dwData);
                        
                        TRC2((TB, "TermServiceSetting@LoadPropertyValues: GetWinStationsDisabled returned 0x%x\n" , hr));

                        if( SUCCEEDED( hr ) )
                        {        
                            pInstance->SetCharSplat(m_szLogons, lpLogon);
                        }                        
                    }
                }                                                      
            }
        }

        if( dwRequiredProperties & BIT_HELP )
        {
           
            hr = pSettings->GetSalemHelpMode(&iData, &dwStatus );            

            TRC2((TB, "TermServiceSetting@LoadPropertyValues: GetHelp returned 0x%x" , dwStatus));

            if( S_OK == dwStatus )
            {              
                pInstance->SetDWORD(m_szHelp, iData);            
            }
            else
            {
                pInstance->SetDWORD(m_szHelp, 0);
            }
        }

        if( dwRequiredProperties & BIT_ALLOWTSCONNECTIONS )
        {
           
            RegGetMachinePolicy(&m_gpPolicy);

            if( m_gpPolicy.fPolicyDenyTSConnections != 0 )
            {
                iData = m_gpPolicy.fDenyTSConnections;
            }
            else
            {                
                hr = pSettings->GetDenyTSConnections(&iData, &dwStatus );            

                TRC2((TB, "TermServiceSetting@LoadPropertyValues: GetAllowTSConnections returned 0x%x" , dwStatus));
            }

            // The bit is negated because it calls the function GetDenyTSConnections which is negative logic.

            if( iData == 0)
            {
                iData = 1;
            }
            else if( iData == 1)
            {
                iData = 0;
            }
             
            pInstance->SetDWORD(m_szAllowTSConnections, iData);                                                 
        
            TRC2((TB,"TSSessionSetting@LoadPropertyValues: AllowTSConnections" ));
        }

        if( dwRequiredProperties & BIT_SINGLESESSION)
        {  
            RegGetMachinePolicy(&m_gpPolicy);

            if( m_gpPolicy.fPolicySingleSessionPerUser != 0 )
            {
                bData = m_gpPolicy.fSingleSessionPerUser;
            }
            else
            {  
                hr = pSettings->GetSingleSessionState( &bData, &dwStatus);
            }
            dwData = bData;

            pInstance->SetDWORD(m_szSingleSession, dwData);                                               
        
            TRC2((TB,"TermServiceSetting@LoadPropertyValues: SingleSession" ));
        }
       
        if( dwRequiredProperties & BIT_PROFILEPATH)
        { 
            BSTR bstrData = NULL;

            chData.Empty();

            RegGetMachinePolicy(&m_gpPolicy);

            if( m_gpPolicy.fPolicyWFProfilePath != 0 )
            {               
                chData.Format(L"%s", m_gpPolicy.WFProfilePath);
            }
            else
            {                  
                hr = pSettings->GetProfilePath( &bstrData, &dwStatus);

                if( bstrData != NULL)
                {
                    chData.Format(L"%s", (LPCWSTR)(bstrData));

                    SysFreeString(bstrData);
                }
            }            

            pInstance->SetCHString(m_szProfilePath, chData);                          
        
            TRC2((TB,"TermServiceSetting@LoadPropertyValues: ProfilePath" ));
        }

        if( dwRequiredProperties & BIT_HOMEDIRECTORY)
        {  
            BSTR bstrData = NULL;

            chData.Empty();

            RegGetMachinePolicy(&m_gpPolicy);

            if( m_gpPolicy.fPolicyWFHomeDir != 0 )
            {                
                chData.Format(L"%s", m_gpPolicy.WFHomeDir);               
            }
            else
            {  
                hr = pSettings->GetHomeDir( &bstrData, &dwStatus);

                if(bstrData != NULL)
                {
                    chData.Format(L"%s", (LPCWSTR)(bstrData));

                    SysFreeString(bstrData);
                }
            }           

            pInstance->SetCHString(m_szHomeDirectory, chData);                                                         
        
            TRC2((TB,"TermServiceSetting@LoadPropertyValues: HomeDirectory" ));
        }

        if( dwRequiredProperties & BIT_DIRECTCONNECTLICENSESERVERS)
        {  
            
            DWORD dwValueType;
            DWORD cbValue = 0, dwDisp;
            LONG lReturn;
            DWORD cbServer;
            DWORD cServers;
            DWORD cchServerMax;
            LPWSTR szServer;
            DWORD i, j;
            CHString chServers;
            chServers.Empty();
            
            do
            {            

                lReturn = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                               TERMINAL_SERVICE_PARAM_DISCOVERY_SERVERS,
                               0,
                               KEY_READ,
                               &hParamKey );

                if (ERROR_SUCCESS != lReturn)
                {
                    break;
                }

                lReturn = RegQueryInfoKey(hParamKey,
                                          NULL,
                                          NULL,
                                          NULL,
                                          &cServers,
                                          &cchServerMax,
                                          NULL,
                                          NULL,
                                          NULL,
                                          NULL,
                                          NULL,
                                          NULL);

                if (ERROR_SUCCESS != lReturn)
                {
                    RegCloseKey( hParamKey );

                    break;
                }

                if (0 == cServers)
                {
                    RegCloseKey( hParamKey );

                    hParamKey = NULL;

                    break;
                }
                

                // Add one for null terminator
                cchServerMax++;

                szServer = (LPWSTR) LocalAlloc(LPTR,cchServerMax * sizeof(WCHAR));

                if(NULL == szServer)
                {
                    LocalFree(szServer);

                    RegCloseKey( hParamKey );

                    hParamKey = NULL;

                    break;
                } 
    
                for (i = 0; i < cServers; i++)
                {
                    if(!chServers.IsEmpty())
                    {
                        chServers+=L"; ";
                    }                                                       

                    cbServer = cchServerMax * sizeof(WCHAR);

                    lReturn = RegEnumKeyEx(hParamKey,
                                           i,
                                           szServer,
                                           &cbServer,
                                           NULL,
                                           NULL,
                                           NULL,
                                           NULL);

                    if (ERROR_SUCCESS != lReturn)
                    {
                        LocalFree(szServer);

                        RegCloseKey( hParamKey );

                        hParamKey = NULL;

                        break;
                    }

                    chServers+= szServer;                

                    
                }

                if(szServer)
                {
                    LocalFree(szServer);                      
                }

                pInstance->SetCHString(m_szDirectConnectLicenseServers, chServers);

            }while(0);
        }
    }
   

    if(hParamKey)
    {
        RegCloseKey(hParamKey);
    }

    if( pSettings != NULL )
    {
        pSettings->Release();
    }
    
    return S_OK;
}

//=---------
/*************************************************************************************
*
*  DESCRIPTION :    CWin32_TerminalService class is subclassed from the Win32_Service
*                   class in CIM schema. It provides live information such as Total
*                   sessions, Disconnected sessions, Resource constraint and 
*                   Raw session capacity.
*
***************************************************************************************/

CWin32_TerminalService::CWin32_TerminalService (LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) : Provider( lpwszName, lpwszNameSpace )
{
    if (g_hInstance != NULL)
    {
        TRC2((TB, "CWin32_TerminalService_ctor"));

        _tcscpy(m_szName, _T("Name"));

        _tcscpy(m_szCaption, _T("Caption"));

        _tcscpy(m_szTotalSessions, _T("TotalSessions"));

        _tcscpy(m_szDisconnectedSessions, _T("DisconnectedSessions"));

        _tcscpy(m_szResourceConstraint, _T("ResourceConstraint"));

        _tcscpy(m_szRawSessionCapacity, _T("RawSessionCapacity"));

        
    }    
}

//=-----------------

CWin32_TerminalService::~CWin32_TerminalService ()
{
}

//=--------------------
/************************************************************************************
*
*  DESCRIPTION :    Find a single instance based on the key property, "Name". 
*
*  INPUTS      :    A pointer to a CInstance object containing the key property, "Name". 
*                   A long that contains the flags described in 
*                   IWbemServices::GetObjectAsync.  
*
*  RETURNS     :    WBEM_S_NO_ERROR if the instance can be found
*                   WBEM_E_NOT_FOUND if the instance described by the key properties 
*                   could not be found
*                   WBEM_E_FAILED if the instance could be found but another error 
*                   occurred. 
*
**************************************************************************************/

HRESULT CWin32_TerminalService::GetObject ( CInstance* pInstance, long lFlags, CFrameworkQuery &Query )
{
    HRESULT hr = WBEM_E_NOT_FOUND;
    CHString chServerName;
    TCHAR tchServer[MAX_PATH] = {0};
    HANDLE hServerName = SERVERNAME_CURRENT;
    ULONG CurrentLogonId = (ULONG) -1;
    WINSTATIONLOADINDICATORDATA LIData;
    ULONG Length = 0;
    DWORD dwRequiredProperties = 0;
    CHString chName;

    pInstance->GetCHString(m_szName, chName);

    pInstance->SetCHString(m_szCaption, chName);

    if( chName.CompareNoCase(L"TermService") == 0 )
    {    
        chServerName.Format(L"%s", (LPCTSTR)GetLocalComputerName());
        wcscpy (tchServer, chServerName);
        bool bRet = 0;

        if (Query.IsPropertyRequired(m_szTotalSessions))
           dwRequiredProperties |= BIT_TOTALSESSIONS;

        if (Query.IsPropertyRequired(m_szDisconnectedSessions))
           dwRequiredProperties |= BIT_DISCONNECTEDSESSIONS;

        if (Query.IsPropertyRequired(m_szEstimatedSessionCapacity))
           dwRequiredProperties |= BIT_ESTIMATEDSESSIONCAPACITY;

        if (Query.IsPropertyRequired(m_szResourceConstraint))
           dwRequiredProperties |= BIT_RESOURCECONSTRAINT;

        if (Query.IsPropertyRequired(m_szRawSessionCapacity))
           dwRequiredProperties |= BIT_RAWSESSIONCAPACITY;

        hServerName = WinStationOpenServer (tchServer);

        CurrentLogonId = GetCurrentLogonId();

        if( hServerName != NULL )
        {
            bRet  = WinStationQueryInformation(hServerName, CurrentLogonId,
                                       WinStationLoadIndicator,
                                       &LIData,
                                       sizeof(LIData), &Length)  ;
            if( bRet )
            {
                hr = LoadPropertyValues(pInstance, dwRequiredProperties, LIData);
            }
        }
        else
        {        
            ERR((TB, "Win32_TerminalService@GetObject: WinStationQueryInformation GetLastError returned: 0x%x\n" ,GetLastError()));
        }
    }
          
    return hr;        
}

//=------------------

/*****************************************************************************
*
*  FUNCTION    :    CWin32_TerminalService::EnumerateInstances
*
*  DESCRIPTION :    Returns all the instances of this class.
*
*  INPUTS      :    A pointer to the MethodContext for communication with WinMgmt.
*                   A long that contains the flags described in 
*                   IWbemServices::CreateInstanceEnumAsync.  Note that the following
*                   flags are handled by (and filtered out by) WinMgmt:
*                   WBEM_FLAG_DEEP, WBEM_FLAG_SHALLOW, WBEM_FLAG_RETURN_IMMEDIATELY, 
*                   WBEM_FLAG_FORWARD_ONLY, WBEM_FLAG_BIDIRECTIONAL
*
*  RETURNS     :    WBEM_S_NO_ERROR if successful
*
*  COMMENTS    :    All instances on the machine are returned here and
*                   all properties that this class knows how to populate must 
*                   be filled in.  If there are no instances, return 
*                   WBEM_S_NO_ERROR.  
*
*****************************************************************************/

HRESULT CWin32_TerminalService::EnumerateInstances (MethodContext* pMethodContext, long lFlags )
{

    return WBEM_S_NO_ERROR;

    // Commented as implementation is protocol dependent
/*
    CHString chServerName;
    TCHAR tchServer[MAX_PATH] = {0};
    HANDLE hServer = SERVERNAME_CURRENT;
    WINSTATIONLOADINDICATORDATA LIData;
    ULONG CurrentLogonId = (ULONG) -1;
    ULONG Length;
    chServerName.Format(L"%s", (LPCTSTR)GetLocalComputerName());
    wcscpy (tchServer, chServerName);
    hServer = WinStationOpenServer (tchServer);
    bool bRet = 0;

    CurrentLogonId = GetCurrentLogonId();

    if (hServer != NULL)
    {        

        bRet  = WinStationQueryInformation(hServer, CurrentLogonId,
                                   WinStationLoadIndicator,
                                   &LIData,
                                   sizeof(LIData), &Length);

        TRC2((TB, "Win32_TerminalService@EnumerateInstances: WinStationQueryInformation bRet: 0x%x\n" , bRet));

        if (bRet)
        {
            CInstance* pInstance = CreateNewInstance(pMethodContext);        
    
            if( pInstance != NULL )
            {
               
                pInstance->SetCHString(m_szServerName, chServerName);                              

                hr = LoadPropertyValues(pInstance, BIT_ALL_PROPERTIES, LIData);

                if ( SUCCEEDED( hr ))
                {            
                    hr = pInstance->Commit();
                }        
                            
                pInstance->Release();             
            }
        }
    }
    else
    {
       
        TRC2((TB, "Win32_TerminalService@EnumerateInstances: WinStationQueryInformation GetLastError returned: 0x%x\n" , hr));
    }
           
    return hr; 
    */
    
}

//=-------------

HRESULT CWin32_TerminalService::ExecQuery (MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags)
{
    HRESULT hr = WBEM_S_NO_ERROR;
    DWORD dwRequiredProperties = 0;
    CHStringArray asNames;
    DWORD dwMode;
    DWORD dwStatus;
    CHString chServerName;
    TCHAR tchServer[MAX_PATH] = {0};
    bool bRet = 0;

    HANDLE hServerName = SERVERNAME_CURRENT;
    WINSTATIONLOADINDICATORDATA LIData;
    ULONG CurrentLogonId = (ULONG) -1;
    ULONG Length = 0;
    
    chServerName.Format(L"%s", (LPCTSTR)GetLocalComputerName());

    wcscpy (tchServer, chServerName);

    hServerName = WinStationOpenServer (tchServer);    

    CurrentLogonId = GetCurrentLogonId();

    if( hServerName != NULL )
    {
        bRet  = WinStationQueryInformation(hServerName, CurrentLogonId,
                                   WinStationLoadIndicator,
                                   &LIData,
                                  sizeof(LIData), &Length);       
        if( bRet )
        {
        
           // Method 2
           Query.GetValuesForProp(m_szName, asNames);

           BOOL bGetAllInstances = asNames.GetSize() == 0;

           // Method 1
           if (Query.IsPropertyRequired(m_szTotalSessions))
               dwRequiredProperties |= BIT_TOTALSESSIONS;

           if (Query.IsPropertyRequired(m_szDisconnectedSessions))
               dwRequiredProperties |= BIT_DISCONNECTEDSESSIONS;
    
           if (Query.IsPropertyRequired(m_szEstimatedSessionCapacity))
               dwRequiredProperties |= BIT_ESTIMATEDSESSIONCAPACITY;

           if (Query.IsPropertyRequired(m_szResourceConstraint))
               dwRequiredProperties |= BIT_RESOURCECONSTRAINT;

           if (Query.IsPropertyRequired(m_szRawSessionCapacity))
               dwRequiredProperties |= BIT_RAWSESSIONCAPACITY;


           CInstance* pInstance = CreateNewInstance(pMethodContext);

           if( pInstance != NULL)
           {                                                       
               
               pInstance->SetCHString(m_szName, chServerName);

               pInstance->SetCHString(m_szCaption, chServerName);

               hr = LoadPropertyValues( pInstance, dwRequiredProperties, LIData );

               if( SUCCEEDED( hr ) )
               {
                   hr = pInstance->Commit();
               }

               pInstance->Release();
           }
           else
           {
               ERR((TB, "Win32_TerminalService@GetObject@ExecQuery: CreateNewInstance failed"));
               hr = WBEM_E_OUT_OF_MEMORY;
           }
        }
    }
    else
    {
        
        TRC2((TB, "Win32_TerminalService@ExecQuery: WinStationQueryInformation GetLastError returned: 0x%x\n" , GetLastError()));
    }

   return hr;
   
}

//=---------------------


HRESULT CWin32_TerminalService::LoadPropertyValues( CInstance *pInstance, DWORD dwRequiredProperties, WINSTATIONLOADINDICATORDATA LIData)
{

    if( pInstance != NULL )
    {        
        
        if( dwRequiredProperties & BIT_TOTALSESSIONS )
        {
            pInstance->SetDWORD(m_szTotalSessions, LIData.TotalSessions);           
        }

        if( dwRequiredProperties & BIT_DISCONNECTEDSESSIONS )
        {
            pInstance->SetDWORD(m_szDisconnectedSessions, LIData.DisconnectedSessions);
        }

        if( dwRequiredProperties & BIT_ESTIMATEDSESSIONCAPACITY )
        {
            pInstance->SetDWORD(m_szEstimatedSessionCapacity, LIData.RemainingSessionCapacity);
        }
        
        if( dwRequiredProperties & BIT_RESOURCECONSTRAINT )
        { 
            switch( LIData.LoadFactor )
            {
            case 0:                
                pInstance->SetCharSplat(m_szResourceConstraint, L"Error");
                break;
            case 1:
                pInstance->SetCharSplat(m_szResourceConstraint, L"PagedPool");
                break;
            case 2:
                pInstance->SetCharSplat(m_szResourceConstraint, L"NonPagedPool");
                break;
            case 3:
                pInstance->SetCharSplat(m_szResourceConstraint, L"Available Memory");
                break;
            case 4:
                pInstance->SetCharSplat(m_szResourceConstraint, L"System PTEs");
                break;           
            case 5:
                pInstance->SetCharSplat(m_szResourceConstraint, L"CPU");
                break;        
   
            default:
                pInstance->SetCharSplat(m_szResourceConstraint, L"Error");
                break;
            }
        }
        if( dwRequiredProperties & BIT_RAWSESSIONCAPACITY )
        {
            pInstance->SetDWORD(m_szRawSessionCapacity, LIData.RawSessionCapacity); 
        }
    }

    return S_OK;
}


//=--------------

CWin32_TSSessionDirectory::CWin32_TSSessionDirectory (LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) : Provider( lpwszName, lpwszNameSpace )
{    
    if ( g_hInstance != NULL)
    {
        
        TRC2((TB, "CWin32_TSSessionDirectory_ctor"));

        _tcscpy(m_szMode, _T("TerminalServerMode"));

        _tcscpy(m_szSessionDirectoryActive, _T("SessionDirectoryActive"));

        _tcscpy(m_szSessionDirectoryLocation, _T("SessionDirectoryLocation"));

        _tcscpy(m_szSessionDirectoryClusterName, _T("SessionDirectoryClusterName"));

 //       _tcscpy(m_szSessionDirectoryAdditionalParams, _T("SessionDirectoryAdditionalParams"));

        _tcscpy(m_szSetSessionDirectoryProperty, _T("SetSessionDirectoryProperty"));

        _tcscpy(m_szSetSessionDirectoryActive, _T("SetSessionDirectoryActive"));

        _tcscpy(m_szPropertyName, _T("PropertyName"));

        _tcscpy(m_szValue, _T("Value"));

        _tcscpy(m_szSessionDirectoryExposeServerIP, _T("SessionDirectoryExposeServerIP"));

        _tcscpy(m_szSetSessionDirectoryExposeServerIP, _T("SetSessionDirectoryExposeServerIP"));
               
    }   
}

//=-------------

CWin32_TSSessionDirectory::~CWin32_TSSessionDirectory ()
{
 
}

//=------------

HRESULT CWin32_TSSessionDirectory::DeleteInstance ( const CInstance &Instance,  long lFlags )
{    
    return WBEM_E_PROVIDER_NOT_CAPABLE;
}

//=-------------------
/*****************************************************************************
*
*  FUNCTION    :    CWin32_TSSessionDirectory::EnumerateInstances
*
*  DESCRIPTION :    Returns all the instances of this class.
*
*  INPUTS      :    A pointer to the MethodContext for communication with WinMgmt.
*                   A long that contains the flags described in 
*                   IWbemServices::CreateInstanceEnumAsync.  Note that the following
*                   flags are handled by (and filtered out by) WinMgmt:
*                   WBEM_FLAG_DEEP, WBEM_FLAG_SHALLOW, WBEM_FLAG_RETURN_IMMEDIATELY, 
*                   WBEM_FLAG_FORWARD_ONLY, WBEM_FLAG_BIDIRECTIONAL
*
*  RETURNS     :    WBEM_S_NO_ERROR if successful
*
*  COMMENTS    :    All instances on the machine are returned here and
*                   all properties that this class knows how to populate must 
*                   be filled in.  If there are no instances, return 
*                   WBEM_S_NO_ERROR.  
*****************************************************************************/

HRESULT CWin32_TSSessionDirectory::EnumerateInstances (MethodContext* pMethodContext, long lFlags )
{    

    HRESULT hr = WBEM_E_INVALID_CLASS;
    OSVERSIONINFOW OsVersionInfo;
    OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
    ISettingsComp* pSettings = NULL;
    DWORD dwStatus = 0;
    DWORD dwMode = 0;

	CStackClass StackObj;

	if(StackObj.m_pCfgComp == NULL)
	{
		return WBEM_E_ILLEGAL_NULL;
	}
    
    if( GetVersionEx( &OsVersionInfo) )
    {
        if( ( OsVersionInfo.dwMajorVersion < 5 ) || ( OsVersionInfo.dwMajorVersion == 5 && OsVersionInfo.dwMinorVersion < 1 ))
        {
            return WBEM_E_INVALID_CLASS;
            
        }
    }

    hr = StackObj.m_pCfgComp->QueryInterface( IID_ISettingsComp , ( PVOID * )&pSettings ) ;

    if( SUCCEEDED( hr ) && pSettings != NULL )
    {
        pSettings->GetTermSrvMode(&dwMode , &dwStatus );
        
        TRC2((TB, "Win32_TSSessionDirectory@EnumInst: GetTermSrvMode: dwMode ret 0x%x\n" , dwMode));

        if( ERROR_SUCCESS == dwStatus && dwMode == 1)
        {             
            CInstance* pInstance = CreateNewInstance(pMethodContext);

            if( pInstance != NULL )
            {
                TRC2((TB, "Win32_TSSessionDirectory@EnumerateInstances: CreateNewInstance succeeded"));         

                hr = LoadPropertyValues(pInstance, BIT_ALL_PROPERTIES);

                if( SUCCEEDED( hr ))
                {
                    hr = pInstance->Commit();
                }

                pInstance->Release( );
            }
        }
    }

	
    if( pSettings != NULL)
    {
        pSettings->Release();
    }
    
    return hr ;
}

//=-------------


HRESULT CWin32_TSSessionDirectory::GetObject ( CInstance* pInstance, long lFlags, CFrameworkQuery &Query )
{    
    
    OSVERSIONINFOW OsVersionInfo;
    OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
    HRESULT hr = WBEM_E_INVALID_CLASS;

    ISettingsComp* pSettings = NULL;
    DWORD dwStatus = 0;
    DWORD dwMode = 0;
	ICfgComp *pCfgComp = NULL;

    if( GetVersionEx( &OsVersionInfo) )
    {
        if( ( OsVersionInfo.dwMajorVersion < 5 ) || ( OsVersionInfo.dwMajorVersion == 5 && OsVersionInfo.dwMinorVersion < 1 ) )
        {
            return WBEM_E_INVALID_CLASS;
            
        }
    } 

	CStackClass StackObj;

	if(StackObj.m_pCfgComp == NULL)
	{
		return WBEM_E_ILLEGAL_NULL;
	}

    hr = StackObj.m_pCfgComp->QueryInterface( IID_ISettingsComp , ( PVOID * )&pSettings ) ;

    if( SUCCEEDED( hr ) && pSettings != NULL )
    {
        pSettings->GetTermSrvMode(&dwMode , &dwStatus );   

        if( ERROR_SUCCESS == dwStatus && dwMode == 1)
        {

            ULONGLONG dwRequiredProperties = 0;

            if (Query.IsPropertyRequired(m_szMode))
               dwRequiredProperties |= BIT_MODE;

            if (Query.IsPropertyRequired(m_szSessionDirectoryActive))
                dwRequiredProperties |= BIT_SESSIONDIRECTORYACTIVE;

            if (Query.IsPropertyRequired(m_szSessionDirectoryLocation))
                dwRequiredProperties |= BIT_SESSIONDIRECTORY;

            if (Query.IsPropertyRequired(m_szSessionDirectoryClusterName))
                dwRequiredProperties |= BIT_CLUSTERNAME;

            if (Query.IsPropertyRequired(m_szSessionDirectoryExposeServerIP))
                dwRequiredProperties |= BIT_SESSIONDIRECTORYEXPOSESERVERIP;
           /* 
            if (Query.IsPropertyRequired(m_szSessionDirectoryAdditionalParams))
                dwRequiredProperties |= BIT_ADDITIONALPARAMS;    
        */
            if( pInstance != NULL )
            {        
                hr  = LoadPropertyValues(pInstance, dwRequiredProperties);

                TRC2((TB, "Win32_TSSessionDirectory@GetObject: LoadPropertyValues ret 0x%x\n" , hr));   
            }
        }
    }

    if( pSettings != NULL)
    {
        pSettings->Release();
    }
        
    return hr;
}

//=-----------------

HRESULT CWin32_TSSessionDirectory::ExecQuery (MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags)
{
    DWORD dwRequiredProperties = 0;
    CHStringArray asNames;
    CHString chSessionDirectory;
    HRESULT hr = WBEM_E_INVALID_CLASS;
    ISettingsComp* pSettings = NULL;
    DWORD dwStatus = 0;
    DWORD dwMode = 0;
	ICfgComp *pCfgComp = NULL;

    OSVERSIONINFOW OsVersionInfo;
    OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);

    if( GetVersionEx( &OsVersionInfo) )
    {
        if( ( OsVersionInfo.dwMajorVersion < 5 ) || ( OsVersionInfo.dwMajorVersion == 5 && OsVersionInfo.dwMinorVersion < 1 ))
        {
            return WBEM_E_INVALID_CLASS;
            
        }
    }    

    CStackClass StackObj;

	if(StackObj.m_pCfgComp == NULL)
	{
		return WBEM_E_ILLEGAL_NULL;
	}

    hr = StackObj.m_pCfgComp->QueryInterface( IID_ISettingsComp , ( PVOID * )&pSettings ) ;

    if( SUCCEEDED( hr ) && pSettings != NULL )
    {
        pSettings->GetTermSrvMode(&dwMode , &dwStatus );   

        if( ERROR_SUCCESS == dwStatus && dwMode == 1)
        {

           // Method 2
          //  Query.GetValuesForProp(m_szSessionDirectoryLocation, asNames);
            Query.GetValuesForProp(m_szMode, asNames);

            BOOL bGetAllInstances = asNames.GetSize() == 0;

           // Method 1

            if (Query.IsPropertyRequired(m_szMode))
               dwRequiredProperties |= BIT_MODE;

            if (Query.IsPropertyRequired(m_szSessionDirectoryActive))
                dwRequiredProperties |= BIT_SESSIONDIRECTORYACTIVE;

            if (Query.IsPropertyRequired(m_szSessionDirectoryLocation))
                dwRequiredProperties |= BIT_SESSIONDIRECTORY;

            if (Query.IsPropertyRequired(m_szSessionDirectoryClusterName))
                dwRequiredProperties |= BIT_CLUSTERNAME;

            if (Query.IsPropertyRequired(m_szSessionDirectoryExposeServerIP))
                dwRequiredProperties |= BIT_SESSIONDIRECTORYEXPOSESERVERIP;
           /* 
            if (Query.IsPropertyRequired(m_szSessionDirectoryAdditionalParams))
                dwRequiredProperties |= BIT_ADDITIONALPARAMS;                  
                  
        */
               // Method 2

            CInstance* pInstance = CreateNewInstance(pMethodContext);       

            if( pInstance != NULL)
            {
               
               pInstance->SetCHString(m_szSessionDirectoryLocation, chSessionDirectory );

               hr = LoadPropertyValues(pInstance, dwRequiredProperties);

               if( SUCCEEDED( hr ) )
               {
                   hr = pInstance->Commit();
               }

               pInstance->Release();
            }
            else
            {
                ERR((TB, "Win32_TSSessionDirectory@ExecQuery: CreateNewInstance failed"));                   

                hr = WBEM_E_OUT_OF_MEMORY;
            }
        }
    }

    if( pSettings != NULL )
    {
        pSettings->Release();
    }

    return hr;

}


//=--------------

BOOL CWin32_TSSessionDirectory::IsInList(const CHStringArray &asArray, LPCWSTR pszString)
{
    DWORD dwSize = asArray.GetSize();

    for( DWORD x=0; x < dwSize; x++ )
    {
        if( asArray[x].CompareNoCase(pszString) == 0 )
        {
            return TRUE;
        }
    }

    return FALSE;
}

//=-------------

HRESULT CWin32_TSSessionDirectory::ExecMethod ( const CInstance& Inst,
                                                          const BSTR bstrMethodName,
                                                          CInstance *pInParams,
                                                          CInstance *pOutParams,
                                                          long lFlags)
                                                          
{
                 
    DWORD dwData = 0;
    CHString chData;
    HKEY hKey = NULL;
    LONG lRet = 0;
    bool bRet;
    bool bUpdate = FALSE;
    DWORD dwSize = sizeof (DWORD);
    TCHAR szName[ SESSDIR_LENGTH ];
    ISettingsComp* pSettings = NULL;
    DWORD dwStatus = 0;
    DWORD dwMode = 0;
    HRESULT hr = WBEM_E_INVALID_CLASS;
    ICfgComp *pCfgComp = NULL;
    CHString chSessDirName;
    DWORD cbName;
    
    OSVERSIONINFOW OsVersionInfo;
    OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);

      

    CStackClass StackObj;

	if(StackObj.m_pCfgComp == NULL)
	{
		return WBEM_E_ILLEGAL_NULL;
	}

    if( pInParams == NULL )
    {
        ERR((TB, "TSSessionDirectory@ExecQuery: invalid interface"));

        return WBEM_E_INVALID_METHOD_PARAMETERS;
    }

    hr = StackObj.m_pCfgComp->QueryInterface( IID_ISettingsComp , ( PVOID * )&pSettings ) ;

    if( SUCCEEDED( hr ) && pSettings != NULL )
    {
        pSettings->GetTermSrvMode(&dwMode , &dwStatus );   

        if( ERROR_SUCCESS == dwStatus && dwMode == 0)
        {
            return WBEM_E_INVALID_CLASS;
        }
    }

    if( GetVersionEx( &OsVersionInfo) )
    {
        if( ( OsVersionInfo.dwMajorVersion < 5 ) || ( OsVersionInfo.dwMajorVersion == 5 && OsVersionInfo.dwMinorVersion < 1 ))
        {
            return WBEM_E_INVALID_CLASS;
            
        }
    }  
   
    /*
    
    Inst.GetCHString(m_szSessionDirectoryLocation, chSessDirName);
    
    if( chSessDirName.GetLength() > WINSTATIONNAME_LENGTH )
    {
        return WBEM_E_VALUE_OUT_OF_RANGE;
    }
    
    if( chSessDirName.IsEmpty() != 0 )
    {
        return WBEM_E_ILLEGAL_NULL;
    }
    */    
    
    do
    {
    
        // Sets one of the properties: SessionDirectoryLocation or SessionDirectoryClusterName 

        // uint32 SetSessionDirectoryProperty([In] string PropertyName, string Value);
    
        if( _wcsicmp(bstrMethodName, m_szSetSessionDirectoryProperty) == 0 )
        {
            lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
                                 REG_TS_CLUSTERSETTINGS ,
                                 0,
                                 KEY_READ | KEY_WRITE,
                                 &hKey );

            if( ERROR_SUCCESS != lRet )
            { 
                ERR((TB, "TSSessionDirectory@ExecQuery: RegOpenKeyEx failed"));

                hr = WBEM_E_INITIALIZATION_FAILURE;

                break;
            }
            
            pInParams->GetCHString (m_szPropertyName, chData);

            if( chData.CompareNoCase (m_szSessionDirectoryLocation) == 0 )
            {        
                RegGetMachinePolicy(&m_gpPolicy);

                chData.Empty();
                         
                bRet = pInParams->GetCHString(m_szValue, chData );

                if( ( m_gpPolicy.fPolicySessionDirectoryLocation == 0) && bRet )
                {     

                    if( chData.IsEmpty() )
                    {
                        hr = WBEM_E_INVALID_PARAMETER;
            
                        break;
                    }

                    if( chData.GetLength() > SESSDIR_LENGTH )
                    {
                        hr = WBEM_E_VALUE_OUT_OF_RANGE;
            
                        break;
                    }

                    lstrcpy(szName, chData);
                    cbName = (lstrlen(szName)+ 1) * sizeof(TCHAR);
                        
                    lRet = RegSetValueEx( hKey ,
                                            REG_TS_CLUSTER_STORESERVERNAME,
                                            NULL ,
                                            REG_SZ,
                                            ( CONST LPBYTE )szName ,
                                            cbName );      

                    TRC2((TB, "Win32_TSSessionDirectory@ExecMethod: SessionDirectory returned 0x%x" , lRet));   

                    
                    if( lRet == ERROR_SUCCESS )
                    {
                        bUpdate = TRUE;

                        pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);
                    }

                    chData.Empty();
                }
                else
                {
                    hr = WBEM_E_INVALID_OPERATION;

                    break;
                }
                
            }
            else if( chData.CompareNoCase(m_szSessionDirectoryClusterName) == 0 )
            {
                       
                RegGetMachinePolicy(&m_gpPolicy);

                chData.Empty();
                     
                bRet = pInParams->GetCHString(m_szValue, chData );

                if( ( m_gpPolicy.fPolicySessionDirectoryClusterName == 0) && bRet )
                {     

                    if( chData.IsEmpty() )
                    {
                        hr = WBEM_E_INVALID_PARAMETER;
        
                        break;
                    }

                    if( chData.GetLength() > SESSDIR_LENGTH )
                    {
                        hr = WBEM_E_VALUE_OUT_OF_RANGE;
        
                        break;
                    }

                    lstrcpy(szName, chData);
                    cbName = (lstrlen(szName)+ 1) * sizeof(TCHAR);
                    
                    lRet = RegSetValueEx( hKey ,
                                            REG_TS_CLUSTER_CLUSTERNAME,
                                            NULL ,
                                            REG_SZ,
                                            ( CONST LPBYTE )szName ,
                                            cbName );      

                    TRC2((TB, "Win32_TSSessionDirectory@ExecMethod: SessionDirectory returned 0x%x" , lRet));                       

                    if( lRet == ERROR_SUCCESS )
                    {
                        bUpdate = TRUE;

                        pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);
                    }

                    chData.Empty();                        
                }
                else
                {
                    hr = WBEM_E_INVALID_OPERATION;

                    break;
                }
            }

            else 
            {
                hr = WBEM_E_INVALID_METHOD;

                break;
            } 

            /*

            else if( chData.CompareNoCase(m_szSessionDirectoryAdditionalParams) == 0 )
            {
                       
                RegGetMachinePolicy(&m_gpPolicy);

                chData.Empty();
                     
                bRet = pInParams->GetCHString(m_szValue, chData );

                if( ( m_gpPolicy.fPolicySessionDirectoryAdditionalParams == 0) && bRet != 0 )
                {     

                    if( chData.IsEmpty() != 0 )
                    {
                        hr = WBEM_E_INVALID_PARAMETER;
        
                        break;
                    }

                    if( chData.GetLength() > SESSDIR_LENGTH )
                    {
                        hr = WBEM_E_VALUE_OUT_OF_RANGE;
        
                        break;
                    }

                    lstrcpy(szName, chData);

                    
                    lRet = RegSetValueEx( hKey ,
                                            REG_TS_CLUSTER_OPAQUESETTINGS,
                                            NULL ,
                                            REG_SZ,
                                            ( CONST LPBYTE )szName ,
                                            sizeof (szName) );      

                    ERR((TB, "Win32_TSSessionDirectory@ExecMethod: SessionDirectory returned 0x%x" , lRet));   

                    if( lRet == ERROR_SUCCESS )
                    {
                        pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);
                    }

                    chData.Empty();                        
                }
                else
                {
                    hr = WBEM_E_INVALID_OPERATION;

                    break;
                }
            }
            */
                                               
        }

        // Enables / Disables participation of a server in Session Directory

        // uint32 SetSessionDirectoryActive([In] uint32 Value);

        else if( _wcsicmp(bstrMethodName, m_szSetSessionDirectoryActive) == 0 )
        {
            lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
                         REG_CONTROL_TSERVER ,
                         0,
                         KEY_READ | KEY_WRITE,
                         &hKey );

            if( ERROR_SUCCESS == lRet )
            { 
                RegGetMachinePolicy(&m_gpPolicy);

                bRet = pInParams->GetDWORD( m_szSessionDirectoryActive, dwData );
                
                if( (m_gpPolicy.fPolicySessionDirectoryActive == 0) && bRet )
                {

                    if( dwData != 0 && dwData != 1 )
                    {
                        hr = WBEM_E_INVALID_PARAMETER;
                
                        break;
                    }
                     
                    lRet = RegSetValueEx( hKey ,
                                            REG_TS_SESSDIRACTIVE,
                                            0 ,
                                            REG_DWORD,
                                            ( LPBYTE )&dwData ,
                                            dwSize );                   

                    TRC2((TB, "Win32_TSSessionDirectory@ExecMethod: SessionDirectoryActive returned 0x%x" , lRet)); 
                
                    if( ERROR_SUCCESS == lRet )
                    {                      

                        bUpdate = TRUE;

                        pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);                        
                    }
                }
                else
                {
                    hr = WBEM_E_INVALID_METHOD;
                }
            }
        }

        // Enables / Disables exposing the IP Address of Session Directory Server

        // uint32 SetSessionDirectoryExposeServerIP([In] uint32 Value);

        else if( _wcsicmp(bstrMethodName, m_szSetSessionDirectoryExposeServerIP) == 0 )
        {
            lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
                         REG_CONTROL_TSERVER ,
                         0,
                         KEY_READ | KEY_WRITE,
                         &hKey );

            if( ERROR_SUCCESS == lRet )
            { 
                RegGetMachinePolicy(&m_gpPolicy);

                bRet = pInParams->GetDWORD( m_szSessionDirectoryExposeServerIP, dwData );
                
                //todo: change the policy to IP
                if( (m_gpPolicy.fPolicySessionDirectoryExposeServerIP == 0) && bRet )
                {

                    if( dwData != 0 && dwData != 1 )
                    {
                        hr = WBEM_E_INVALID_PARAMETER;
                
                        break;
                    }
                     
                    lRet = RegSetValueEx( hKey ,
                                            REG_TS_SESSDIR_EXPOSE_SERVER_ADDR,
                                            0 ,
                                            REG_DWORD,
                                            ( LPBYTE )&dwData ,
                                            dwSize );                   

                    TRC2((TB, "Win32_TSSessionDirectory@ExecMethod: SessionDirectoryExposeServerIP returned 0x%x" , lRet)); 
                
                    if( ERROR_SUCCESS == lRet )
                    {                      

                        bUpdate = TRUE;

                        pOutParams->SetDWORD(L"ReturnValue", WBEM_S_NO_ERROR);                        
                    }
                }
                else
                {
                    hr = WBEM_E_INVALID_METHOD;
                }
            }
        } 

    }while(0);

    if( bUpdate )
    {
        StackObj.m_pCfgComp->UpdateSessionDirectory(&dwStatus);
    }

    if( hKey != NULL )
    {
        RegCloseKey( hKey );
    }

        
    if( pSettings != NULL )
    {
        pSettings->Release();
    }

    return hr;
}


//=-------------

HRESULT CWin32_TSSessionDirectory::LoadPropertyValues( CInstance *pInstance, DWORD dwRequiredProperties)
{         
    LONG lRet = 0;    
    DWORD dwData = 0;
    DWORD dwSize = 0;
    HKEY hKey = NULL;
    static WCHAR tchData[ OPAQUESETTINGS_LENGTH +1] ;
    dwSize = sizeof( DWORD );
    
    
    lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
                         REG_CONTROL_TSERVER ,
                         0,
                         KEY_READ,
                         &hKey );

    if( ERROR_SUCCESS == lRet && hKey != NULL)
    {
        if( dwRequiredProperties & BIT_SESSIONDIRECTORYACTIVE )
        {  
            RegGetMachinePolicy(&m_gpPolicy);

            if( m_gpPolicy.fPolicySessionDirectoryActive != 0 )
            {
                dwData = m_gpPolicy.SessionDirectoryActive;
            }
            else
            {
                lRet = RegQueryValueEx( hKey ,
                                        REG_TS_SESSDIRACTIVE,
                                        NULL ,
                                        NULL ,
                                        (LPBYTE)&dwData ,
                                        &dwSize );
            }
   
            TRC2((TB, "Win32_TSSessionDirectory@LoadPropertyValues: SessionDirectoryActive returned 0x%x" , lRet));

            if( ERROR_SUCCESS == lRet )
            {            
                pInstance->SetDWORD(m_szSessionDirectoryActive, dwData);
            }
        }

        if( dwRequiredProperties & BIT_SESSIONDIRECTORYEXPOSESERVERIP )
        {  
            RegGetMachinePolicy(&m_gpPolicy);
            
            if( m_gpPolicy.fPolicySessionDirectoryExposeServerIP != 0 )
            {
                dwData = m_gpPolicy.SessionDirectoryExposeServerIP;
            }
            else
            {
                lRet = RegQueryValueEx( hKey ,
                                        REG_TS_SESSDIR_EXPOSE_SERVER_ADDR,
                                        NULL ,
                                        NULL ,
                                        (LPBYTE)&dwData ,
                                        &dwSize );
            }
   
            TRC2((TB, "Win32_TSSessionDirectory@LoadPropertyValues: SessionDirectoryExposeServerIP returned 0x%x" , lRet));

            if( ERROR_SUCCESS == lRet )
            {            
                pInstance->SetDWORD(m_szSessionDirectoryExposeServerIP, dwData);
            }
        }
        

        RegCloseKey (hKey);
    }

    
    lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
                                 REG_TS_CLUSTERSETTINGS ,
                                 0,
                                 KEY_READ,
                                 &hKey );
    

    if( ERROR_SUCCESS == lRet  && hKey != NULL)
    {

        if( dwRequiredProperties & BIT_SESSIONDIRECTORY )
        {
            RegGetMachinePolicy(&m_gpPolicy);

            if( m_gpPolicy.fPolicySessionDirectoryLocation != 0 )
            {
                lstrcpy(tchData, m_gpPolicy.SessionDirectoryLocation);
            }
            else
            {
         
                dwSize = sizeof( tchData );
            
                lRet = RegQueryValueEx( hKey ,
                                        REG_TS_CLUSTER_STORESERVERNAME,
                                        NULL ,
                                        NULL ,
                                        (LPBYTE)&tchData ,
                                        &dwSize );
            }
    
            TRC2((TB, "Win32_TSSessionDirectory@LoadPropertyValues: SessionDirectoryLocation returned 0x%x" , lRet));

            if( ERROR_SUCCESS == lRet )
            {            
                pInstance->SetCHString(m_szSessionDirectoryLocation, (LPTSTR)(LPCTSTR)&tchData);
            }
        }

        if( dwRequiredProperties & BIT_CLUSTERNAME )
        {
            RegGetMachinePolicy(&m_gpPolicy);

            if( m_gpPolicy.fPolicySessionDirectoryClusterName != 0 )
            {
                lstrcpy( tchData, m_gpPolicy.SessionDirectoryClusterName );
            }
            else
            {
                dwSize = sizeof( tchData );

                lRet = RegQueryValueEx( hKey ,
                                        REG_TS_CLUSTER_CLUSTERNAME,
                                        NULL ,
                                        NULL ,
                                        (LPBYTE)&tchData ,
                                        &dwSize );
            }

            TRC2((TB, "Win32_TSSessionDirectory@LoadPropertyValues: ClusterName returned 0x%x" , lRet));   

            if( ERROR_SUCCESS == lRet )
            {
                pInstance->SetCHString(m_szSessionDirectoryClusterName, (LPTSTR)(LPCTSTR)&tchData);            
            }
        }

/*
        if( dwRequiredProperties & BIT_ADDITIONALPARAMS )
        {

            dwSize = sizeof( tchData );
            
            lRet = RegQueryValueEx( hKey ,
                                    REG_TS_CLUSTER_OPAQUESETTINGS,
                                    NULL ,
                                    NULL ,
                                    (LPBYTE)&tchData ,
                                    &dwSize );
            

            TRC2((TB, "Win32_TSSessionDirectory@LoadPropertyValues: AdditionalParams returned 0x%x" , lRet));

            if( ERROR_SUCCESS == lRet )
            {            
                pInstance->SetCHString(m_szSessionDirectoryAdditionalParams, (LPTSTR)(LPCTSTR)&tchData);
            }            
        }
        */

        RegCloseKey( hKey );        
    }    
    
    return S_OK;
}

//=-------------------
/*

HRESULT CWin32_TSSessionDirectory::PutInstance ( const CInstance &Instance, long lFlags)
{   
    LONG hr = 0;               
    DWORD dwData;
    CHString chData;
    HKEY hKey;
    LONG lRet;
    DWORD dwSize = sizeof (DWORD);
    TCHAR szName[ SESSDIR_LENGTH ];
        
    hr = WBEM_S_NO_ERROR;
  
    do
    {
        lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
                         REG_CONTROL_TSERVER ,
                         0,
                         KEY_READ | KEY_WRITE,
                         &hKey );

        if ( ERROR_SUCCESS == lRet )
        {           
            if( Instance.GetDWORD( m_szSessionDirectoryActive, dwData ) )
            {
                if (dwData != 0 && dwData != 1)
                {
                    hr = WBEM_E_INVALID_PARAMETER;
                
                    break;
                }
                     
                lRet = RegSetValueEx( hKey ,
                                        REG_TS_SESSDIRACTIVE,
                                        0 ,
                                        REG_DWORD,
                                        ( LPBYTE )&dwData ,
                                        dwSize );                   

                ERR((TB, "Win32_TSSessionDirectory@PutInstance: SessionDirectoryActive returned 0x%x" , lRet)); 
                
                if (ERROR_SUCCESS == lRet && g_pCfgComp != NULL)
                {
                    g_pCfgComp->ForceUpdate();
                }
            }

            RegCloseKey (hKey);
        }
    
        lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
                         REG_TS_CLUSTERSETTINGS ,
                         0,
                         KEY_READ | KEY_WRITE,
                         &hKey );

        if ( ERROR_SUCCESS == lRet )
        { 
            chData.Empty();

            if( Instance.GetCHString(m_szSessionDirectoryLocation, chData ) )
            {
                if (chData.IsEmpty() != 0)
                {
                    hr = WBEM_E_INVALID_PARAMETER;
                
                    break;
                }

                if (chData.GetLength() > SESSDIR_LENGTH )
                {
                    hr = WBEM_E_VALUE_OUT_OF_RANGE;
                
                    break;
                }

                lstrcpy(szName, chData);

                            
                lRet = RegSetValueEx( hKey ,
                                        REG_TS_CLUSTER_STORESERVERNAME,
                                        NULL ,
                                        REG_SZ,
                                        ( CONST LPBYTE )szName ,
                                        sizeof (szName) );      

                ERR((TB, "Win32_TSSessionDirectory@PutInstance: SessionDirectory returned 0x%x" , lRet));   

                chData.Empty();
            }
             
    
            if( Instance.GetCHString( m_szSessionDirectoryClusterName, chData ) )
            {
                if (chData.IsEmpty() != 0)
                {
                    hr = WBEM_E_INVALID_PARAMETER;
            
                    break;
                }

                if (chData.GetLength() > SESSDIR_LENGTH )
                {
                    hr = WBEM_E_VALUE_OUT_OF_RANGE;
            
                    break;
                }

                lstrcpy(szName, chData);                   

                    
                lRet = RegSetValueEx( hKey ,
                                    REG_TS_CLUSTER_CLUSTERNAME,
                                    NULL ,
                                     REG_SZ,
                                    ( CONST LPBYTE )szName ,
                                    sizeof (szName) );

                ERR((TB, "Win32_TSSessionDirectory@PutInstance: ClusterName returned 0x%x" , lRet)); 

                chData.Empty();
            } 
                        

            if( Instance.GetCHString( m_szSessionDirectoryAdditionalParams, chData ) )
            {
                if (chData.IsEmpty() != 0)
                {
                    hr = WBEM_E_INVALID_PARAMETER;
            
                    break;
                }

                if (chData.GetLength() > OPAQUESETTINGS_LENGTH )
                {
                    hr = WBEM_E_VALUE_OUT_OF_RANGE;
            
                    break;
                }

                lstrcpy(szName, chData);

                lRet = RegSetValueEx( hKey ,
                                        REG_TS_CLUSTER_OPAQUESETTINGS,
                                        NULL ,
                                        REG_SZ,
                                        ( CONST LPBYTE )szName ,
                                        sizeof (szName) );
        
                ERR((TB, "Win32_TSSessionDirectory@PutInstance: AdditionalParams returned 0x%x" , lRet));
            }                                    

            RegCloseKey( hKey );            
        }
        
        if (g_pCfgComp != NULL)
        {
            g_pCfgComp->ForceUpdate();
        }

    }while (0);

    return hr;   
}
*/