Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

7232 lines
190 KiB

//Copyright (c) 1998 - 1999 Microsoft Corporation
/*********************************************************************************************
*
*
* Module Name:
*
* CfgComp.cpp
*
* Abstract:
* This Module contains the implemetation of functions for the CfgBkEnd Component
*
* Author: Arathi Kundapur. a-akunda
* Owner: alhen
*
*
* Revision:
*
*
************************************************************************************************/
#include "stdafx.h"
#define SECURITY_WIN32
#include "PtrArray.h"
#include "CfgBkEnd.h"
#include <winsta.h>
#include <regapi.h>
#include "defines.h"
#include "CfgComp.h"
#include "Security.h"
#include <utildll.h>
#define INITGUID
#include "objbase.h"
#include "initguid.h"
#include <netcfgx.h>
#include <cfg.h>
#include "devguid.h"
#include <aclapi.h>
#include <sddl.h>
#define REG_GUID_TABLE REG_CONTROL_TSERVER L"\\lanatable\\"
#define REG_GUID_TABLE_T REG_CONTROL_TSERVER L"\\lanatable"
#define LANA_ID L"LanaId"
#define ARRAYSIZE( rg ) sizeof( rg ) / sizeof( rg[0] )
#ifdef DBG
bool g_fDebug = false;
#endif
/***********************************************************************************************************/
#define RELEASEPTR(iPointer) if(iPointer) \
{ \
iPointer->Release();\
iPointer = NULL;\
}
/***************************************************************************************************************/
LPTSTR g_pszDefaultSecurity[] = {
L"DefaultSecurity",
L"ConsoleSecurity"
};
DWORD g_numDefaultSecurity = sizeof(g_pszDefaultSecurity)/sizeof(g_pszDefaultSecurity[0]);
BOOL TestUserForAdmin( );
DWORD RecursiveDeleteKey( HKEY hKeyParent , LPTSTR lpszKeyChild );
/***************************************************************************************************************
Name: GetSecurityDescriptor
Purpose: Gets the Security Descriptor for a Winstation
Returns: HRESULT.
Params:
in: pWSName - Name of the Winstation.
out: pSize - Size of the allocated buffer
ppSecurityDescriptor - Pointer to the buffer containing the security descriptor
****************************************************************************************************************/
STDMETHODIMP CCfgComp::GetSecurityDescriptor(PWINSTATIONNAMEW pWSName, long * pSize,PSECURITY_DESCRIPTOR * ppSecurityDescriptor)
{
HRESULT hResult = S_OK;
if(NULL == pSize || NULL == ppSecurityDescriptor || NULL == pWSName)
return E_INVALIDARG;
*pSize =0;
*ppSecurityDescriptor = NULL;
hResult = GetWinStationSecurity(FALSE, pWSName,(PSECURITY_DESCRIPTOR *)ppSecurityDescriptor);
if(FAILED(hResult))
{
//Try Getting Default Security Descriptor
hResult = GetWinStationSecurity(TRUE, NULL,(PSECURITY_DESCRIPTOR *)ppSecurityDescriptor);
}
if( SUCCEEDED( hResult ) && *ppSecurityDescriptor != NULL )
{
*pSize = GetSecurityDescriptorLength(*ppSecurityDescriptor);
}
return hResult;
}
/***************************************************************************************************************
Name: SetSecurityDescriptor
Purpose: Sets the Security Descriptor for a Winstation
Returns: HRESULT.
Params:
in: pWsName - Name of the Winstation.
Size - Size of the allocated buffer
pSecurityDescriptor - Pointer to the Security Descriptor
****************************************************************************************************************/
BOOL
CCfgComp::ValidDefaultSecurity(
const WCHAR* pwszName
)
/*++
--*/
{
for( DWORD i=0; i < g_numDefaultSecurity; i++ )
{
if( lstrcmpi( g_pszDefaultSecurity[i], pwszName ) == 0 )
{
break;
}
}
return ( i >= g_numDefaultSecurity ) ? FALSE : TRUE;
}
HRESULT
CCfgComp::SetSecurityDescriptor(
BOOL bDefaultSecurity,
PWINSTATIONNAMEW pWsName,
DWORD Size,
PSECURITY_DESCRIPTOR pSecurityDescriptor
)
/*++
--*/
{
HRESULT hResult = S_OK;
HKEY Handle1 = NULL, Handle2 = NULL;
//Check if the caller has write permissions.
if(!m_bAdmin)
{
ODS( L"SetSecurityDescriptor : User Is not Admin. \n" );
return E_ACCESSDENIED;
}
//Check the parametes for NULL
if(NULL == pWsName || NULL == pSecurityDescriptor || 0 == Size)
return E_INVALIDARG;
if( TRUE == bDefaultSecurity && FALSE == ValidDefaultSecurity( pWsName ) )
{
return E_INVALIDARG;
}
//Check for the validity of the Winstation name
/*if(NULL == GetWSObject(pWsName)) //Commented out to get Rename Work. This might not be needed .
return E_INVALIDARG;*/
//Check if the data passed is a valid security descriptor
if(ERROR_SUCCESS != ValidateSecurityDescriptor((PSECURITY_DESCRIPTOR)pSecurityDescriptor))
return E_INVALIDARG;
if(Size != GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)pSecurityDescriptor))
return E_INVALIDARG;
//Make the Resitry entries required.
if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,KEY_ALL_ACCESS, &Handle1 ) != ERROR_SUCCESS )
{
return E_FAIL;
}
if( TRUE == bDefaultSecurity )
{
if( RegSetValueEx( Handle1, pWsName, 0, REG_BINARY,(BYTE *)pSecurityDescriptor, Size ) != ERROR_SUCCESS )
{
hResult = E_FAIL;
}
}
else
{
if( RegOpenKeyEx(Handle1, pWsName, 0, KEY_ALL_ACCESS, &Handle2 ) != ERROR_SUCCESS )
{
RegCloseKey(Handle1);
return E_FAIL;
}
if( RegSetValueEx( Handle2, L"Security", 0, REG_BINARY,(BYTE *)pSecurityDescriptor, Size ) != ERROR_SUCCESS )
{
hResult = E_FAIL;
}
}
if( Handle1 != NULL )
{
RegCloseKey(Handle1);
}
if( Handle2 != NULL )
{
RegCloseKey(Handle2);
}
return hResult;
}
STDMETHODIMP CCfgComp::SetSecurityDescriptor(PWINSTATIONNAMEW pWsName, DWORD Size,PSECURITY_DESCRIPTOR pSecurityDescriptor)
{
return SetSecurityDescriptor( FALSE, pWsName, Size, pSecurityDescriptor );
}
/***************************************************************************************************************
Name: GetUserConfig
Purpose: Gets the UserConfig for a Winstation
Returns: HRESULT.
Params:
in: pWSName - Name of the Winstation.
out: pSize - Size of the allocated buffer
ppUser - Pointer to the buffer containing the UserConfig
****************************************************************************************************************/
STDMETHODIMP CCfgComp::GetUserConfig(PWINSTATIONNAMEW pWsName, long * pSize, PUSERCONFIG * ppUser, BOOLEAN bPerformMerger)
{
HRESULT hResult = S_OK;
WINSTATIONCONFIG2W WSConfig;
LONG Size = 0;
ULONG Length = 0;
*pSize = 0;
*ppUser = NULL;
//Read the information from the registry.
POLICY_TS_MACHINE p;
memset(&p, 0, sizeof(POLICY_TS_MACHINE));
if((ERROR_SUCCESS != RegWinStationQueryEx(NULL,&p,pWsName,&WSConfig,sizeof(WINSTATIONCONFIG2W),&Length,bPerformMerger)))
return E_FAIL;
Size = sizeof(WSConfig.Config.User);
*ppUser = (PUSERCONFIG)CoTaskMemAlloc(Size);
if(*ppUser == NULL)
return E_OUTOFMEMORY;
CopyMemory((PVOID)*ppUser,(CONST VOID *)&WSConfig.Config.User,Size);
*pSize = Size;
return hResult;
}
/***************************************************************************************************************
Name: GetEncryptionLevels
Purpose: Gets the Encyption Levels for a Winstation
Returns: HRESULT.
Params:
in: pName - Name of the Winstation or the Winstation Driver depending the value of Type
Type - Specifies whether the Name is a Winstation name or WD Name (WsName, WdName)
out: pNumEncryptionLevels - Number of Encryption Levels
ppEncryption - Pointer to the buffer containing the Encryption Levels
****************************************************************************************************************/
STDMETHODIMP CCfgComp::GetEncryptionLevels(WCHAR * pName, NameType Type,ULONG * pNumEncryptionLevels,Encryption ** ppEncryption)
{
HRESULT hResult = S_OK;
PWD pWD = NULL;
PWS pWS = NULL;
ULONG NumLevels = 0, Size =0 ,i = 0;
EncryptionLevel *pEncryptionLevels = NULL;
//Check the parameters
if(NULL == pNumEncryptionLevels || NULL == pName || NULL == ppEncryption)
return E_INVALIDARG;
*pNumEncryptionLevels = 0;
*ppEncryption = NULL;
//Get the pointer to the appropriate WD object.
if(Type == WsName)
{
pWS = GetWSObject(pName);
if(NULL == pWS)
return E_INVALIDARG;
pWD = GetWdObject(pWS->wdName);
if(NULL == pWD)
return E_FAIL;
}
else if(Type == WdName)
{
pWD = GetWdObject(pName);
if(NULL == pWD)
return E_INVALIDARG;
}
else
return E_INVALIDARG;
//Check if this object has the extension dll associated with it.
//Check if the function for encryption levels was exposed in the dll
if(!(pWD->hExtensionDLL && pWD->lpfnExtEncryptionLevels))
return E_FAIL;
//Get the EncryptionLevels. The Strings should be seperately extracted from the resource
NumLevels = (pWD->lpfnExtEncryptionLevels)(&pWS->wdName, &pEncryptionLevels);
if(NULL == pEncryptionLevels)
return E_FAIL;
Size = sizeof(Encryption);
Size = NumLevels * sizeof(Encryption);
*ppEncryption = (Encryption*)CoTaskMemAlloc(Size);
if(*ppEncryption == NULL)
return E_OUTOFMEMORY;
//copy the relevent data to the Encryption structure
for(i = 0; i < NumLevels; i++)
{
//Extract the string corresponding to the levels.
if(0 == LoadString(pWD->hExtensionDLL,pEncryptionLevels[i].StringID,
((*ppEncryption)[i]).szLevel, sizeof( ( ( *ppEncryption )[ i ] ).szLevel ) / sizeof( TCHAR ) ) )
{
hResult = E_FAIL;
break;
}
((*ppEncryption)[i]).RegistryValue = pEncryptionLevels[i].RegistryValue;
((*ppEncryption)[i]).szDescr[ 0 ] = 0;
if( pWD->lpfnExtGetEncryptionLevelDescr != NULL )
{
int nResID = 0;
if( ( pWD->lpfnExtGetEncryptionLevelDescr )( pEncryptionLevels[i].RegistryValue , &nResID ) != -1 )
{
LoadString( pWD->hExtensionDLL , nResID , ((*ppEncryption)[i]).szDescr , sizeof( ( (*ppEncryption )[ i ] ).szDescr ) / sizeof( TCHAR ) );
}
}
((*ppEncryption)[i]).Flags = pEncryptionLevels[i].Flags;
}
*pNumEncryptionLevels = NumLevels;
//pEncrptionLevels need not be cleaned up as it is global data in Rdpcfgex.dll
if(FAILED(hResult))
{
if(*ppEncryption)
{
CoTaskMemFree(*ppEncryption);
*ppEncryption = NULL;
*pNumEncryptionLevels = 0;
}
}
return hResult;
}
/***************************************************************************************************************
Name: FillWdArray
Purpose: Internal function to fill the m_WdArray
Returns: HRESULT.
Params:
****************************************************************************************************************/
STDMETHODIMP CCfgComp::FillWdArray()
{
//Use the functionalities already provided by the regapi,
//instead of reinventing the wheel
long Status;
ULONG Index, Index2, ByteCount, Entries, Entries2;
PDNAMEW PdKey;
WDNAMEW WdKey;
LONG QStatus;
WDCONFIG2W WdConfig;
PDCONFIG3W PdConfig;
TCHAR WdDll[MAX_PATH];
HRESULT hResult = S_OK;
/*
TCHAR * pPdName = NULL;
*/
PWD pWd = NULL;
//Delete if there are already entries in the list
DeleteWDArray();
//Enumerate the WD's from the Registry
for ( Index = 0, Entries = 1, ByteCount = sizeof(WDNAMEW);
(Status =
RegWdEnumerateW( NULL,
&Index,
&Entries,
WdKey,
&ByteCount )) == ERROR_SUCCESS;
ByteCount = sizeof(WDNAMEW) )
{
if ((QStatus = RegWdQueryW( NULL, WdKey, &WdConfig,
sizeof(WdConfig),
&ByteCount)) != ERROR_SUCCESS )
{
hResult = E_FAIL;
break;
}
/*
* Only place this Wd in the WdList if it's DLL is present
* on the system.
*/
GetSystemDirectory( WdDll, MAX_PATH );
lstrcat( WdDll, TEXT("\\Drivers\\") );
lstrcat( WdDll, WdConfig.Wd.WdDLL );
lstrcat( WdDll, TEXT(".sys" ) );
if ( lstr_access( WdDll, 0 ) != 0 )
continue;
/*
* Create a new WdList object and initialize from WdConfig
* structure, adding it to the end of the WdList.
*/
pWd = new WD;
if(NULL == pWd)
{
hResult = E_OUTOFMEMORY;
break;
}
lstrcpy(pWd->wdName,WdConfig.Wd.WdName);
lstrcpy(pWd->wdKey,WdKey);
pWd->wd2 = WdConfig;
// Load the extension DLL for this WD
pWd->hExtensionDLL = ::LoadLibrary(WdConfig.Wd.CfgDLL);
if(pWd->hExtensionDLL)
{
// ODS( L"Loaded extension dll\n" );
// Get the entry points
pWd->lpfnExtStart = (LPFNEXTSTARTPROC)::GetProcAddress(pWd->hExtensionDLL, szStart);
pWd->lpfnExtEnd = (LPFNEXTENDPROC)::GetProcAddress(pWd->hExtensionDLL, szEnd);
pWd->lpfnExtEncryptionLevels = (LPFNEXTENCRYPTIONLEVELSPROC)::GetProcAddress(pWd->hExtensionDLL, szEncryptionLevels);
pWd->lpfnExtDeleteObject = (LPFNEXTDELETEOBJECTPROC)::GetProcAddress(pWd->hExtensionDLL, szDeleteObject);
pWd->lpfnExtRegQuery = (LPFNEXTREGQUERYPROC)::GetProcAddress(pWd->hExtensionDLL, szRegQuery);
pWd->lpfnExtRegCreate = (LPFNEXTREGCREATEPROC)::GetProcAddress(pWd->hExtensionDLL, szRegCreate);
pWd->lpfnExtRegDelete = (LPFNEXTREGDELETEPROC)::GetProcAddress(pWd->hExtensionDLL, szRegDelete);
pWd->lpfnExtDupObject = (LPFNEXTDUPOBJECTPROC)::GetProcAddress(pWd->hExtensionDLL, szDupObject);
pWd->lpfnGetCaps = ( LPFNEXTGETCAPABILITIES )::GetProcAddress( pWd->hExtensionDLL , szGetCaps );
pWd->lpfnExtGetEncryptionLevelDescr =
( LPFNEXTGETENCRYPTIONLEVELDESCPROC )::GetProcAddress( pWd->hExtensionDLL , szGetEncryptionLevelDescr );
// Call the ExtStart() function in the extension DLL
if(pWd->lpfnExtStart)(*pWd->lpfnExtStart)(&WdConfig.Wd.WdName);
}
m_WDArray.Add( pWd);
//Get the names of the Transport drivers associated with this WD
for ( Index2 = 0, Entries2 = 1, ByteCount = sizeof(PDNAMEW);
(Status = RegPdEnumerateW(NULL,WdKey,TRUE,&Index2,&Entries2,PdKey,&ByteCount)) == ERROR_SUCCESS;
ByteCount = sizeof(PDNAMEW))
{
PDCONFIG3W *pPdConfig = NULL;
if ((QStatus = RegPdQueryW(NULL,WdKey,TRUE,PdKey,&PdConfig,sizeof(PdConfig),&ByteCount)) != ERROR_SUCCESS)
{
hResult = E_FAIL;
break;
}
/*
* Create a new PdName and initialize from PdConfig
* structure, then add to the TdName list.
*/
pPdConfig = new PDCONFIG3W;
if( pPdConfig == NULL )
{
hResult = E_OUTOFMEMORY;
break;
}
*pPdConfig = PdConfig;
pWd->PDConfigArray.Add( pPdConfig );
/*
pPdName = new PDNAMEW;
if(NULL == pPdName)
{
hResult = E_OUTOFMEMORY;
break;
}
lstrcpy((TCHAR *)pPdName,PdConfig.Data.PdName);
pWd->PDNameArray.Add(pPdName);
*/
}
}
if(FAILED(hResult))
{
//Error has occured, cleanup m_WDArray
DeleteWDArray();
}
return hResult;
}
/***************************************************************************************************************
Name: Initialize
Purpose: Initializes the object
Returns: HRESULT.
Params:
****************************************************************************************************************/
STDMETHODIMP CCfgComp::Initialize()
{
HRESULT hResult = S_OK;
#ifdef DBG
HKEY hKey;
LONG lStatus;
// To control debug spewage add/remove this regkey
lStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
L"Software\\Microsoft\\TSCC\\Debug",
0,
KEY_READ,
&hKey );
if( lStatus == ERROR_SUCCESS )
{
g_fDebug = true;
RegCloseKey( hKey );
}
#endif
//If already initialized, return
if(m_bInitialized)
return CFGBKEND_ALREADY_INITIALIZED;
//Is the user the admin?
/*
if(RegWinStationAccessCheck(NULL, KEY_ALL_ACCESS))
{
m_bAdmin = FALSE;
}
else
{
m_bAdmin = TRUE;
}
*/
m_bAdmin = TestUserForAdmin( );
// Fill up the WdArray with information regarding the Wd's installed on this machine.
hResult = FillWdArray();
if(SUCCEEDED(hResult))
{
//Fill up the WsArray with the info about the WS's on this machine.
hResult = FillWsArray();
}
if(SUCCEEDED(hResult))
m_bInitialized = TRUE;
else
{
//if Failed, Cleanup the memory used.
DeleteWSArray();
DeleteWDArray();
}
return hResult;
}
/***************************************************************************************************************
Name: FillWsArray
Purpose: Internal function to fill m_WsArray
Returns: HRESULT.
Params:
****************************************************************************************************************/
STDMETHODIMP CCfgComp::FillWsArray()
{
LONG Status;
ULONG Index, ByteCount, Entries;
WINSTATIONNAMEW WSName;
PWS pWsObject = NULL;
HRESULT hResult = S_OK;
WINSTATIONCONFIG2W* pWSConfig = NULL;
ULONG Size = 0;
//Ensure that the WS is empty.
DeleteWSArray();
Index = 0;
Size = sizeof(WINSTATIONCONFIG2W);
pWSConfig = (WINSTATIONCONFIG2W*)LocalAlloc(LMEM_FIXED, Size);
if(pWSConfig == NULL)
{
return E_FAIL;
}
//Enumerate Winstations
for ( Index = 0, Entries = 1, ByteCount = sizeof(WINSTATIONNAMEW);
(Status =
RegWinStationEnumerateW( NULL, &Index, &Entries,
WSName, &ByteCount )) == ERROR_SUCCESS;
ByteCount = sizeof(WINSTATIONNAMEW) )
{
ULONG Length;
Status = RegWinStationQueryW(NULL,
WSName,
pWSConfig,
sizeof(WINSTATIONCONFIG2W), &Length);
if(Status)
{
continue;
}
//Insert a WS object into the m_WSArray.
hResult = InsertInWSArray(WSName, pWSConfig,&pWsObject);
}
if(pWSConfig != NULL)
{
LocalFree(pWSConfig);
pWSConfig = NULL;
}
if(FAILED(hResult))
{
DeleteWSArray();
}
return hResult;
}
/***************************************************************************************************************
Name: InsertInWSArray
Purpose: Internal function to Insert a new WS in the m_WsArray
Returns: HRESULT.
Params:
in: pWSName - Name of the Winstation.
pWSConfig - PWINSTATIONCONFIG2W structure
out: ppObject - Pointer to the new object
****************************************************************************************************************/
STDMETHODIMP CCfgComp::InsertInWSArray( PWINSTATIONNAMEW pWSName,
PWINSTATIONCONFIG2W pWSConfig,
PWS * ppObject )
{
int Index = 0,Size = 0;
BOOL bAdded;
PWS pObject;
HRESULT hResult = S_OK;
//Create a new WS object and initialize.
pObject = new WS;
if ( NULL == pObject )
return E_OUTOFMEMORY;
lstrcpy(pObject->Name, pWSName);
pObject->fEnableWinstation = pWSConfig->Create.fEnableWinStation ? 1 : 0;
lstrcpy( pObject->pdName, pWSConfig->Pd[0].Create.PdName );
pObject->PdClass = (DWORD)pWSConfig->Pd[0].Create.SdClass;
// New addition
if( pObject->PdClass == SdAsync )
{
lstrcpy( pObject->DeviceName , pWSConfig->Pd[0].Params.Async.DeviceName );
}
//
lstrcpy( pObject->wdName, pWSConfig->Wd.WdName );
lstrcpy( pObject->Comment, pWSConfig->Config.Comment );
pObject->LanAdapter = (pObject->PdClass == SdNetwork) ? pWSConfig->Pd[0].Params.Network.LanAdapter : ( ULONG )-1;
pObject->uMaxInstanceCount = pWSConfig->Create.MaxInstanceCount;
//Traverse the WSArray and insert this new WS,
//keeping the list sorted by Name.
PWS pTempWs = NULL;
for ( Index = 0, bAdded = FALSE,Size = m_WSArray.GetSize();
Index < Size; Index++ )
{
pTempWs = (PWS)m_WSArray[Index];
if ( lstrcmpi( pTempWs->Name,pObject->Name ) > 0)
{
m_WSArray.InsertAt(Index, pObject );
bAdded = TRUE;
break;
}
}
//If we haven't yet added the WS, add it now to the tail
if ( !bAdded )
m_WSArray.Add(pObject);
//Set the ppObject referenced WS pointer to the new WS
//pointer and return the index of the new WS
*ppObject = pObject;
return hResult;
} // end CCfgComp::InsertInWSArray
/***************************************************************************************************************
Name: GetWdObject
Purpose: Internal function to get a WD object from m_WdArray
Returns: PWD - pointer to a WD object.
Params:
in: pWd - Name of the WD
****************************************************************************************************************/
PWD CCfgComp::GetWdObject(PWDNAMEW pWdName)
{
PWD pObject;
int Size = 0,Index = 0;
//Traverse the WD list
for (Index = 0, Size = m_WDArray.GetSize(); Index < Size; Index ++)
{
pObject = (PWD)m_WDArray[Index];
if ( !lstrcmpi( pObject->wdName, pWdName ) )
{
return(pObject);
}
/* when PWD includes WDCONFIG2
if( !lstrcmpi( pObject->wd2.Wd.WdName , pWdName ) )
{
return pObject;
}
*/
}
return(NULL);
} // end GetWdObject
//--------------------------------------------------------------------------------------------------------------
// expected return values WDF_ICA or WDF_TSHARE
//--------------------------------------------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetWdType( PWDNAMEW pWdName , PULONG pulType )
{
if( pWdName == NULL || pulType == NULL )
{
return E_INVALIDARG;
}
PWD pwdObject = GetWdObject( pWdName );
if( pwdObject != NULL )
{
*pulType = pwdObject->wd2.Wd.WdFlag;
return S_OK;
}
return E_FAIL;
}
/***************************************************************************************************************
Name: GetWSObject
Purpose: Internal function to get a WS Object from m_WsArray
Returns: PWS - Pointer to a WS Object.
Params:
in: pWSName - Name of the Winstation.
****************************************************************************************************************/
PWS CCfgComp::GetWSObject(WINSTATIONNAMEW WSName)
{
PWS pObject;
int Size = 0,Index = 0;
//Refresh( );
//Traverse the WD list
for (Index = 0, Size = m_WSArray.GetSize(); Index < Size; Index ++)
{
pObject = (PWS)m_WSArray[Index];
if ( !lstrcmpi( pObject->Name, WSName ) )
{
return(pObject);
}
}
return(NULL);
} // end GetWdObject
/***************************************************************************************************************
Name: GetWinStationSecurity
Purpose: Internal function used to Get Winstation Security
Returns: HRESULT.
Params:
in: pWSName - Name of the Winstation.
out: ppSecurityDescriptor - Pointer to the buffer containing the security descriptor
****************************************************************************************************************/
HRESULT CCfgComp::GetWinStationSecurity( BOOL bDefault, PWINSTATIONNAMEW pWSName,PSECURITY_DESCRIPTOR *ppSecurityDescriptor )
{
DWORD SDLength = 0;
DWORD ValueType =0;
HKEY Handle1 = NULL;
HKEY Handle2 = NULL;
HRESULT hResult = S_OK;
//BOOL bDefault = FALSE;
WCHAR ValueName[32]; // Just some number enough to hold string "Security" and DefaultSecurity"
if(NULL == ppSecurityDescriptor)
{
return E_INVALIDARG;
}
if( TRUE == bDefault )
{
if(NULL == pWSName )
{
//Default Security
lstrcpy( ValueName, L"DefaultSecurity" );
}
else if( lstrlen(pWSName) > sizeof(ValueName) / sizeof(ValueName[0]) - 1 )
{
ODS( L"CFGBKEND : GetWinStationSecurity -- default security key name is too long\n" );
return E_INVALIDARG;
}
else
{
ZeroMemory( ValueName, sizeof(ValueName) );
lstrcpy( ValueName, pWSName );
}
}
else
{
lstrcpy( ValueName, L"Security" );
}
*ppSecurityDescriptor = NULL;
if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,KEY_READ, &Handle1 ) != ERROR_SUCCESS)
{
ODS( L"CFGBKEND : GetWinStationSecurity -- RegOpenKey failed\n" );
return E_FAIL;
}
if(!bDefault)
{
if( RegOpenKeyEx( Handle1, pWSName , 0 , KEY_READ/*KEY_ALL_ACCESS*/, &Handle2 )!= ERROR_SUCCESS)
{
ODS( L"CFGBKEND : GetWinStationSecurity -- RegOpenKey( 2 ) failed\n" );
RegCloseKey(Handle1);
return E_FAIL;
}
RegCloseKey(Handle1);
Handle1 = Handle2;
Handle2 = NULL;
}
if( RegQueryValueEx( Handle1, ValueName, NULL, &ValueType,NULL, &SDLength ) != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetWinStationSecurity -- RegQueryValueEx failed for -- " );
ODS( ValueName );
ODS( L"\n" );
RegCloseKey(Handle1);
return E_FAIL;
}
//Return error if not correct data type
if (ValueType != REG_BINARY)
{
ODS( L"CFGBKEND : GetWinStationSecurity -- ValueType != REG_BINARY\n" );
RegCloseKey(Handle1);
return ERROR_FILE_NOT_FOUND;
}
//Allocate a buffer to read the Security info and read it
// ACLUI uses LocalFree
// *ppSecurityDescriptor = CoTaskMemAlloc(SDLength);
*ppSecurityDescriptor = ( PSECURITY_DESCRIPTOR )LocalAlloc( LMEM_FIXED , SDLength );
if ( *ppSecurityDescriptor == NULL )
{
RegCloseKey(Handle1);
return E_OUTOFMEMORY;
}
if( RegQueryValueEx( Handle1,ValueName, NULL, &ValueType,(BYTE *) *ppSecurityDescriptor, &SDLength ) == ERROR_SUCCESS )
{
//Check for a valid SD before returning.
if( ERROR_SUCCESS != ValidateSecurityDescriptor( *ppSecurityDescriptor ) )
{
hResult = E_FAIL;
}
}
else
{
hResult = E_FAIL;
}
if(Handle1)
{
RegCloseKey(Handle1);
Handle1 = NULL;
}
if(Handle2)
{
RegCloseKey(Handle2);
Handle2 = NULL;
}
if(FAILED(hResult))
{
if( *ppSecurityDescriptor != NULL )
{
// CoTaskMemFree(*ppSecurityDescriptor);
LocalFree( *ppSecurityDescriptor );
*ppSecurityDescriptor = NULL;
}
}
return hResult;
} // GetWinStationSecurity
//This function is borrowed from security.c in the tscfg project
/***************************************************************************************************************
Name: ValidateSecurityDescriptor
Purpose: Internal function to Validate a Security Descriptor
Returns: DWORD - Error Status.
Params:
in: pSecurityDescriptor - pointer to a security Descriptor.
****************************************************************************************************************/
DWORD CCfgComp::ValidateSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor)
{
// DWORD Error = ERROR_SUCCESS;
if( IsValidSecurityDescriptor( pSecurityDescriptor ) )
{
return ERROR_SUCCESS;
}
else
{
return GetLastError( );
}
} // end ValidateSecurityDescriptor
/***************************************************************************************************************
Name: GetWinstationList
Purpose: Gets the List of Winstations installed on a Machine
Returns: HRESULT.
Params:
out: NumWinstations - pointer to the Number of Winstations returned.
Size - pointer to the size of allocated buffer.
ppWS - Pointer to the allocated buffer containing the WS Structures
****************************************************************************************************************/
STDMETHODIMP CCfgComp::GetWinstationList(ULONG * NumWinstations, ULONG * Size, PWS * ppWS)
{
HRESULT hResult = S_OK;
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
WS * pWSTemp = NULL;
if(NULL == NumWinstations || NULL == Size || NULL == ppWS)
return E_INVALIDARG;
*NumWinstations = 0;
*Size = 0;
*ppWS = NULL;
ULONG Num = m_WSArray.GetSize();
*ppWS = (PWS)CoTaskMemAlloc(Num * sizeof(WS));
if(NULL == *ppWS)
return E_OUTOFMEMORY;
pWSTemp = (WS *)(*ppWS);
for(ULONG i = 0; i < Num ; i++)
{
lstrcpy(pWSTemp[i].Name,((WS *)m_WSArray[i])->Name);
lstrcpy(pWSTemp[i].pdName,((WS *)m_WSArray[i])->pdName);
lstrcpy(pWSTemp[i].wdName,((WS *)m_WSArray[i])->wdName);
lstrcpy(pWSTemp[i].Comment,((WS *)m_WSArray[i])->Comment);
pWSTemp[i].uMaxInstanceCount =((WS *)m_WSArray[i])->uMaxInstanceCount;
pWSTemp[i].fEnableWinstation =((WS *)m_WSArray[i])->fEnableWinstation;
pWSTemp[i].LanAdapter = ((WS *)m_WSArray[i])->LanAdapter;
pWSTemp[i].PdClass = ((WS *)m_WSArray[i])->PdClass;
}
*NumWinstations = Num;
*Size = Num * sizeof(WS);
return hResult;
}
/***************************************************************************************************************
Name: GetWdTypeList
Purpose: Gets the List of Winstation Drivers
Returns: HRESULT.
Params:
out: pNumWd - pointer to the number of entries returned.
pSize - pointer to the size of the allocated buffer
ppData - Pointer to an array of WDNAMEW
****************************************************************************************************************/
STDMETHODIMP CCfgComp::GetWdTypeList(ULONG * pNumWd, ULONG * pSize, WCHAR ** ppData)
{
HRESULT hResult = S_OK;
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
if(NULL == pNumWd || NULL == pSize || NULL == ppData)
return E_INVALIDARG;
WDNAMEW * pWdTemp = NULL;
*pNumWd = 0;
*pSize = 0;
*ppData = NULL;
ULONG Num = m_WDArray.GetSize();
*ppData = (WCHAR *)CoTaskMemAlloc(Num * sizeof(WDNAMEW));
if(NULL == *ppData)
return E_OUTOFMEMORY;
pWdTemp = (WDNAMEW *)(*ppData);
for(ULONG i = 0; i < Num ; i++)
{
lstrcpy(pWdTemp[i],((WD *)m_WDArray[i])->wdName);
}
*pNumWd = Num;
*pSize = Num * sizeof(WS);
return hResult;
}
/***************************************************************************************************************
Name: IsWSNameUnique
Purpose: Checks if the Name is already not an existing winstation
Returns: HRESULT.
Params:
in: pWSName - Name of the Winstation.
out: pUnique - pointer to whether the winstation name is unique
****************************************************************************************************************/
STDMETHODIMP CCfgComp::IsWSNameUnique(PWINSTATIONNAMEW pWSName,BOOL * pUnique)
{
if(NULL == pWSName || NULL == pUnique)
return E_INVALIDARG;
*pUnique = FALSE;
if((NULL == GetWSObject(pWSName)) && (lstrcmpi(pWSName,m_szConsole)))
*pUnique = TRUE;
return S_OK;
}
/***************************************************************************************************************
Name: GetTransportTypes
Purpose: Gets the Security Descriptor for a Winstation
Returns: HRESULT.
Params:
in: Name - Name of the Winstation or WD depending on the value of Type.
Type - Specifies whether the Name is a Winstation name or WD Name (WsName, WdName)
out: pNumPd - pointer to the number of Transport types returned
pSize - Size of the allocated buffer
ppSecurityDescriptor - Pointer to the buffer containing the Transport types supported
****************************************************************************************************************/
STDMETHODIMP CCfgComp::GetTransportTypes(WCHAR * Name, NameType Type,ULONG * pNumPd, ULONG * pSize, WCHAR * * ppData)
{
HRESULT hResult = S_OK;
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
if(NULL == pNumPd || NULL == pSize || NULL == ppData || NULL == Name)
return E_INVALIDARG;
WD * pWD = NULL;
WS * pWS = NULL;
*pNumPd = 0;
*pSize = 0;
*ppData = NULL;
PDNAMEW * pPdTemp = NULL;
if(Type == WsName)
{
pWS = GetWSObject(Name);
if(NULL == pWS)
return E_INVALIDARG;
pWD = GetWdObject(pWS->wdName);
if(NULL == pWD)
return E_FAIL;
}
else if(Type == WdName)
{
pWD = GetWdObject(Name);
if(NULL == pWD)
return E_INVALIDARG;
}
else
return E_INVALIDARG;
// ULONG Num = (pWD->PDNameArray).GetSize();
ULONG Num = ( pWD->PDConfigArray ).GetSize( );
*ppData = (WCHAR *)CoTaskMemAlloc(Num * sizeof(PDNAMEW));
if(NULL == *ppData)
return E_OUTOFMEMORY;
pPdTemp = (PDNAMEW *)(*ppData);
for(ULONG i = 0; i < Num ; i++)
{
// PDNAMEW * pPdName = (PDNAMEW *)pWD->PDNameArray[i];
PDNAMEW * pPdName = &( ( PDCONFIG3W * )pWD->PDConfigArray[i] )->Data.PdName;
lstrcpy(pPdTemp[i], *pPdName);
}
*pNumPd = Num;
*pSize = Num * sizeof(PDNAMEW);
return hResult;
}
/***************************************************************************************************************
Name: GetLanAdapterList
Purpose: Gets the List of Lan Adapters associated with a given protocol
Returns: HRESULT.
Params:
in: pdName - Name of the protocol.
out: pNumAdapters:pointer to the number of Lan adapters returned
pSize - Size of the allocated buffer
ppSecurityDescriptor - Pointer to An Array of DEVICENAME's
****************************************************************************************************************/
STDMETHODIMP CCfgComp::GetLanAdapterList(WCHAR * pdName, ULONG * pNumAdapters, ULONG * pSize, WCHAR ** ppData)
{
HRESULT hResult = S_OK, hr = S_OK;
//If not initialized return error
if(!m_bInitialized)
{
ODS( L"CCfgComp::GetLanAdapterList returned CFGBKEND_E_NOT_INITIALIZED\n" );
return CFGBKEND_E_NOT_INITIALIZED;
}
if(NULL == pdName || NULL == ppData || NULL == pNumAdapters || NULL == pSize)
{
ODS( L"CCfgComp::GetLanAdapterList returned INVALIDARG \n" );
return E_INVALIDARG;
}
*pNumAdapters = 0;
*pSize = 0;
*ppData = NULL;
int NumAdapters = 0;
TCHAR * pszDevice = NULL;
int length = 0;
DEVICENAMEW * pTempPointer = NULL;
CPtrArray DeviceArray;
//Interface pointer declarations
TCHAR szProtocol[256];
INetCfg * pnetCfg = NULL;
INetCfgClass * pNetCfgClass = NULL;
INetCfgClass * pNetCfgClassAdapter = NULL;
INetCfgComponent * pNetCfgComponent = NULL;
INetCfgComponent * pNetCfgComponentprot = NULL;
IEnumNetCfgComponent * pEnumComponent = NULL;
INetCfgComponentBindings * pBinding = NULL;
LPWSTR pDisplayName = NULL;
DWORD dwCharacteristics;
ULONG count = 0;
if( 0 == lstrcmpi( pdName , L"tcp" ) )
{
lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_TCPIP);
}
else if( 0 == lstrcmpi( pdName , L"netbios" ) )
{
lstrcpy(szProtocol,NETCFG_SERVICE_CID_MS_NETBIOS);
}
else if( 0 == lstrcmpi( pdName, L"ipx" ) )
{
lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_NWIPX);
}
else if( 0 == lstrcmpi( pdName , L"spx" ) )
{
lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_NWSPX);
}
else
{
return E_INVALIDARG;
}
/*
* Assumption: No NetBios Lana MAPPING
*/
//The First entry will be "All Lan Adapters"
pszDevice = new TCHAR[DEVICENAME_LENGTH];
if(NULL == pszDevice)
{
return E_OUTOFMEMORY;
}
length = LoadString(g_hInstance,IDS_ALL_LAN_ADAPTERS, pszDevice, DEVICENAME_LENGTH );
NumAdapters++;
DeviceArray.Add(pszDevice);
do
{
ODS( L"CFGBKEND : CoCreateInstance\n" );
hResult = CoCreateInstance(CLSID_CNetCfg,NULL,CLSCTX_SERVER,IID_INetCfg,(LPVOID *)&pnetCfg);
if( FAILED( hResult ) )
{
ODS( L"CFGBKEND : CoCreateInstance(CLSID_CNetCfg) failed\n" );
break;
}
if( pnetCfg != NULL )
{
ODS( L"pnetCfg->Initialize\n" );
// shaun cox changed the netcfgx.idl file
// alhen
hResult = pnetCfg->Initialize( NULL );
if( FAILED( hResult ) || pnetCfg == NULL )
{
ODS( L"CFGBKEND : netCfg::Init failed\n" );
break;
}
if( lstrcmpi( szProtocol , NETCFG_SERVICE_CID_MS_NETBIOS ) == 0 )
{
ODS( L"pnetCfg->QueryNetCfgClass for GUID_DEVCLASS_NETSERVICE\n" );
hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETSERVICE ,IID_INetCfgClass,(void **)&pNetCfgClass);
if( FAILED( hResult ) || pNetCfgClass == NULL)
{
ODS( L"CFGBKEND : pnetCfg->QueryNetCfgClass failed\n" );
break;
}
}
else
{
ODS( L"pnetCfg->QueryNetCfgClass for GUID_DEVCLASS_NETTRANS\n" );
hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETTRANS ,IID_INetCfgClass,(void **)&pNetCfgClass);
if( FAILED( hResult ) || pNetCfgClass == NULL)
{
ODS( L"CFGBKEND : pnetCfg->QueryNetCfgClass failed\n" );
break;
}
}
ODS( L"pnetCfg->QueryNetCfgClass\n" );
hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NET ,IID_INetCfgClass,(void **)&pNetCfgClassAdapter);
if( FAILED( hResult ) || pNetCfgClassAdapter == NULL )
{
ODS( L"CFGBKEND : pnetCfg->QueryNetCfgClass failed\n" );
break;
}
ODS( L"pNetCfgClass->FindComponent\n");
hResult = pNetCfgClass->FindComponent(szProtocol,&pNetCfgComponentprot);
if( FAILED( hResult ) || pNetCfgComponentprot == NULL)
{
ODS( L"CFGBKEND : pnetCfg->FindComponent\n" );
break;
}
ODS( L"pNetCfgComponentprot->QueryInterface\n" );
hResult = pNetCfgComponentprot->QueryInterface(IID_INetCfgComponentBindings,(void **)&pBinding);
if( FAILED( hResult ) || pBinding == NULL )
{
ODS( L"CFGBKEND : pNetCfgComponentprot->QueryInterface(IID_INetCfgComponentBindings ) failed \n " );
break;
}
ODS( L"pNetCfgClassAdapter->EnumComponents\n" );
hResult = pNetCfgClassAdapter->EnumComponents(&pEnumComponent);
RELEASEPTR(pNetCfgClassAdapter);
if( FAILED( hResult ) || pEnumComponent == NULL )
{
ODS( L"CFGBKEND : pNetCfgClassAdapter->EnumComponents failed \n" );
break;
}
// hResult = S_OK;
while(TRUE)
{
ODS( L"pEnumComponent->Next(1,&pNetCfgComponent,&count) \n" );
hr = pEnumComponent->Next(1,&pNetCfgComponent,&count);
if(count == 0 || NULL == pNetCfgComponent)
{
break;
}
ODS( L"pNetCfgComponent->GetCharacteristics(&dwCharacteristics) \n" );
hr = pNetCfgComponent->GetCharacteristics(&dwCharacteristics);
if( FAILED( hr ) )
{
RELEASEPTR(pNetCfgComponent);
ODS( L"CFGBKEND : pNetCfgComponent->GetCharacteristics failed\n" );
continue;
}
if(dwCharacteristics & NCF_PHYSICAL)
{
ODS( L"pBinding->IsBoundTo(pNetCfgComponent)\n" );
if(S_OK == pBinding->IsBoundTo(pNetCfgComponent))
{
ODS( L"pNetCfgComponent->GetDisplayName(&pDisplayName)\n" );
hResult = pNetCfgComponent->GetDisplayName(&pDisplayName);
if( FAILED( hResult ) )
{
ODS( L"CFGBKEND : pNetCfgComponent->GetDisplayName failed\n");
continue;
}
// this is not a leak Device array copies the ptr
// and we release towards the end
pszDevice = new TCHAR[DEVICENAME_LENGTH];
if(NULL == pszDevice)
{
hResult = E_OUTOFMEMORY;
break;
}
lstrcpy(pszDevice,pDisplayName);
DBGMSG( L"CFGBKEND: Adapter name %ws\n" , pszDevice );
DeviceArray.Add(pszDevice);
NumAdapters++;
CoTaskMemFree(pDisplayName);
}
}
}
RELEASEPTR(pNetCfgComponent);
}
}while( 0 );
ODS( L"RELEASEPTR(pBinding)\n" );
RELEASEPTR(pBinding);
ODS( L"RELEASEPTR(pEnumComponent)\n" );
RELEASEPTR(pEnumComponent);
ODS( L"RELEASEPTR(pNetCfgComponentprot)\n" );
RELEASEPTR(pNetCfgComponentprot);
ODS( L"RELEASEPTR(pNetCfgComponent)\n" );
RELEASEPTR(pNetCfgComponent);
ODS( L"RELEASEPTR(pNetCfgClass)\n" );
RELEASEPTR(pNetCfgClass);
if( pnetCfg != NULL )
{
pnetCfg->Uninitialize();
}
ODS( L"RELEASEPTR(pnetCfg)\n" );
RELEASEPTR(pnetCfg);
if( SUCCEEDED( hResult ) )
{
//Allocate Memory using CoTaskMemAlloc and copy data
*ppData = (WCHAR *)CoTaskMemAlloc(NumAdapters * sizeof(TCHAR) * DEVICENAME_LENGTH);
if(*ppData == NULL)
{
hResult = E_OUTOFMEMORY;
}
else
{
pTempPointer = (DEVICENAMEW *)(*ppData);
for(int i=0; i<NumAdapters; i++)
{
lstrcpy(pTempPointer[i],(TCHAR *)DeviceArray[i]);
}
}
}
for(int i=0;i < DeviceArray.GetSize();i++)
{
ODS( L"Deleteing DeviceArray\n" );
// I told u so.
delete [] DeviceArray[i];
}
*pNumAdapters = NumAdapters;
return hResult;
}
/***************************************************************************************************************
Name: GetLanAdapterList2
Purpose: Gets the List of Lan Adapters associated with a given protocol
Determine if lan ids are valid
Returns: HRESULT.
Params:
in: pdName - Name of the protocol.
out: pNumAdapters: pointer to the number of Lan adapters returned
ppGuidtbl:
GUIDTBL
-----------------------------
DispName display name [ 128 ]
guidNIC 32 byte buffer
dwLana value is set if regkey entry exist otherwise it will be created in the order obtained
dwStatus Any errors reported on a particular guid entry
-----------------------------
****************************************************************************************************************/
STDMETHODIMP CCfgComp::GetLanAdapterList2(WCHAR * pdName, ULONG * pNumAdapters , PGUIDTBL *ppGuidtbl )
{
HRESULT hResult = S_OK;
int nMaxLanAdapters = 4;
//If not initialized return error
if(!m_bInitialized)
{
ODS( L"CCfgComp::GetLanAdapterList2 returned CFGBKEND_E_NOT_INITIALIZED\n" );
return CFGBKEND_E_NOT_INITIALIZED;
}
if(NULL == pdName || NULL == pNumAdapters )
{
ODS( L"CCfgComp::GetLanAdapterList2 returned INVALIDARG \n" );
return E_INVALIDARG;
}
*pNumAdapters = 0;
int NumAdapters = 0;
//
*ppGuidtbl = ( PGUIDTBL )CoTaskMemAlloc( sizeof( GUIDTBL ) * nMaxLanAdapters );
if( *ppGuidtbl == NULL )
{
return E_OUTOFMEMORY;
}
ZeroMemory( *ppGuidtbl , sizeof( GUIDTBL ) * nMaxLanAdapters );
//Interface pointer declarations
TCHAR szProtocol[256];
INetCfg * pnetCfg = NULL;
INetCfgClass * pNetCfgClass = NULL;
INetCfgClass * pNetCfgClassAdapter = NULL;
INetCfgComponent * pNetCfgComponent = NULL;
INetCfgComponent * pNetCfgComponentprot = NULL;
IEnumNetCfgComponent * pEnumComponent = NULL;
INetCfgComponentBindings * pBinding = NULL;
LPWSTR pDisplayName = NULL;
DWORD dwCharacteristics;
ULONG count = 0;
if( 0 == lstrcmpi( pdName , L"tcp" ) )
{
lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_TCPIP);
}
else if( 0 == lstrcmpi( pdName , L"netbios" ) )
{
lstrcpy(szProtocol,NETCFG_SERVICE_CID_MS_NETBIOS);
}
else if( 0 == lstrcmpi( pdName, L"ipx" ) )
{
lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_NWIPX);
}
else if( 0 == lstrcmpi( pdName , L"spx" ) )
{
//lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_NWSPX);
lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_NWIPX);
}
else
{
return E_INVALIDARG;
}
/*
* Assumption: No NetBios Lana MAPPING
*/
//The First entry will be "All Lan Adapters"
if( lstrcmpi( pdName , L"netbios" ) != 0 )
{
LoadString( g_hInstance , IDS_ALL_LAN_ADAPTERS , (*ppGuidtbl )[0].DispName , DEVICENAME_LENGTH );
NumAdapters++;
}
do
{
ODS( L"CFGBKEND:GetLanAdapterList2 CoCreateInstance\n" );
hResult = CoCreateInstance(CLSID_CNetCfg,NULL,CLSCTX_SERVER,IID_INetCfg,(LPVOID *)&pnetCfg);
if( FAILED( hResult ) )
{
ODS( L"CFGBKEND:GetLanAdapterList2 CoCreateInstance(CLSID_CNetCfg) failed\n" );
break;
}
if( pnetCfg != NULL )
{
ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->Initialize\n" );
// shaun cox changed the netcfgx.idl file
// alhen
hResult = pnetCfg->Initialize( NULL );
if( FAILED( hResult ) )
{
ODS( L"CFGBKEND:GetLanAdapterList2 netCfg::Init failed\n" );
break;
}
if( lstrcmpi( szProtocol , NETCFG_SERVICE_CID_MS_NETBIOS ) == 0 )
{
ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass for GUID_DEVCLASS_NETSERVICE\n" );
hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETSERVICE ,IID_INetCfgClass,(void **)&pNetCfgClass);
if( FAILED( hResult ) || pNetCfgClass == NULL)
{
ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass failed\n" );
break;
}
}
else
{
ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass for GUID_DEVCLASS_NETTRANS\n" );
hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETTRANS ,IID_INetCfgClass,(void **)&pNetCfgClass);
if( FAILED( hResult ) || pNetCfgClass == NULL)
{
ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass failed\n" );
break;
}
}
ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass\n" );
hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NET ,IID_INetCfgClass,(void **)&pNetCfgClassAdapter);
if( FAILED( hResult ) || pNetCfgClassAdapter == NULL )
{
ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass failed\n" );
break;
}
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgClass->FindComponent\n");
hResult = pNetCfgClass->FindComponent(szProtocol,&pNetCfgComponentprot);
if( FAILED( hResult ) || pNetCfgComponentprot == NULL)
{
ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->FindComponent\n" );
break;
}
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponentprot->QueryInterface\n" );
hResult = pNetCfgComponentprot->QueryInterface(IID_INetCfgComponentBindings,(void **)&pBinding);
if( FAILED( hResult ) || pBinding == NULL )
{
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponentprot->QueryInterface(IID_INetCfgComponentBindings ) failed \n " );
break;
}
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgClassAdapter->EnumComponents\n" );
hResult = pNetCfgClassAdapter->EnumComponents(&pEnumComponent);
RELEASEPTR(pNetCfgClassAdapter);
if( FAILED( hResult ) || pEnumComponent == NULL )
{
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgClassAdapter->EnumComponents failed \n" );
break;
}
// hResult = S_OK;
while(TRUE)
{
ODS( L"CFGBKEND:GetLanAdapterList2 pEnumComponent->Next(1,&pNetCfgComponent,&count) \n" );
hResult = pEnumComponent->Next(1,&pNetCfgComponent,&count);
if(count == 0 || NULL == pNetCfgComponent)
{
break;
}
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetCharacteristics(&dwCharacteristics) \n" );
hResult = pNetCfgComponent->GetCharacteristics(&dwCharacteristics);
if( FAILED( hResult ) )
{
RELEASEPTR(pNetCfgComponent);
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetCharacteristics failed\n" );
continue;
}
DBGMSG( L"dwCharacteritics are 0x%x\n", dwCharacteristics );
if((dwCharacteristics & NCF_PHYSICAL) ||
((dwCharacteristics & NCF_VIRTUAL) && !(dwCharacteristics & NCF_HIDDEN)))
{
ODS( L"CFGBKEND:GetLanAdapterList2 pBinding->IsBoundTo(pNetCfgComponent)\n" );
if(S_OK == pBinding->IsBoundTo(pNetCfgComponent))
{
if( NumAdapters >= nMaxLanAdapters )
{
// add four more adapters
nMaxLanAdapters += 4;
*ppGuidtbl = ( PGUIDTBL )CoTaskMemRealloc( *ppGuidtbl , sizeof( GUIDTBL ) * nMaxLanAdapters );
if( *ppGuidtbl == NULL )
{
return E_OUTOFMEMORY;
}
}
ULONG ulDeviceStatus = 0;
hResult = pNetCfgComponent->GetDeviceStatus( &ulDeviceStatus );
if( FAILED( hResult ) )
{
DBGMSG( L"CFGBKEND:GetLanAdapterList2 GetDevice failed with 0x%x\n" , hResult );
continue;
}
DBGMSG( L"GetDevice status returned 0x%x\n" , ulDeviceStatus );
if( ulDeviceStatus == CM_PROB_DEVICE_NOT_THERE )
{
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetDeviceStatus PNP device not there\n");
continue;
}
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetDisplayName\n" );
hResult = pNetCfgComponent->GetDisplayName(&pDisplayName);
if( FAILED( hResult ) )
{
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetDisplayName failed\n");
continue;
}
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetInstanceGuid\n" );
hResult = pNetCfgComponent->GetInstanceGuid( & ( ( *ppGuidtbl )[ NumAdapters ].guidNIC ) );
if( FAILED( hResult ) )
{
ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetInstanceGuid failed\n");
continue;
}
lstrcpy( ( *ppGuidtbl )[ NumAdapters ].DispName , pDisplayName );
// the lana value will be adjusted if guid entry exist
// ( *ppGuidtbl )[ NumAdapters ].dwLana = ( DWORD )NumAdapters;
NumAdapters++;
CoTaskMemFree(pDisplayName);
}
}
}
RELEASEPTR(pNetCfgComponent);
}
}while( 0 );
ODS( L"RELEASEPTR(pBinding)\n" );
RELEASEPTR(pBinding);
ODS( L"RELEASEPTR(pEnumComponent)\n" );
RELEASEPTR(pEnumComponent);
ODS( L"RELEASEPTR(pNetCfgComponentprot)\n" );
RELEASEPTR(pNetCfgComponentprot);
ODS( L"RELEASEPTR(pNetCfgComponent)\n" );
RELEASEPTR(pNetCfgComponent);
ODS( L"RELEASEPTR(pNetCfgClass)\n" );
RELEASEPTR(pNetCfgClass);
if( pnetCfg != NULL )
{
pnetCfg->Uninitialize();
}
ODS( L"RELEASEPTR(pnetCfg)\n" );
RELEASEPTR(pnetCfg);
if( SUCCEEDED( hResult ) )
{
//
// Verify the existence of the guidtable and its entries
// also re-assign lana ids.
//
VerifyGuidsExistence( ppGuidtbl , ( int )NumAdapters , pdName );
}
*pNumAdapters = NumAdapters;
return hResult;
}
/***************************************************************************************************************
Name: VerifyGuidsExistence
Purpose: Determines the existence of the guid entries and reassigns lana ids
Note: ppGuidtbl passed in is valid
Returns: void
Params: [in] GUIDTBL **
[in] number of guid entries
***************************************************************************************************************/
void CCfgComp::VerifyGuidsExistence( PGUIDTBL *ppGuidtbl , int cItems , WCHAR *pdName )
{
HKEY hKey;
DWORD dwStatus;
TCHAR tchRootKey[ MAX_PATH ];
TCHAR tchGuid[ 40 ];
ODS( L"CFGBKEND:VerifyGuidsExistence\n" );
int nStart = 1;
if( lstrcmpi( pdName , L"netbios" ) == 0 )
{
nStart = 0;
}
for( int idx = nStart ; idx < cItems ; ++idx )
{
lstrcpy( tchRootKey , REG_GUID_TABLE );
StringFromGUID2( ( *ppGuidtbl )[ idx ].guidNIC , tchGuid , ARRAYSIZE( tchGuid ) );
lstrcat( tchRootKey , tchGuid );
dwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE , tchRootKey , 0 , KEY_READ , &hKey );
( *ppGuidtbl )[ idx ].dwStatus = dwStatus;
if( dwStatus == ERROR_SUCCESS )
{
DWORD dwSize = sizeof( DWORD );
RegQueryValueEx( hKey , LANA_ID , NULL , NULL , ( LPBYTE ) &( ( *ppGuidtbl )[ idx ].dwLana ) , &dwSize );
DBGMSG( L"CFGBKEND: VerifyGuidsExistence LanaId retrieved = %d\n" , ( *ppGuidtbl )[ idx ].dwLana );
}
else
{
ODS( L"CFGBKEND: VerifyGuidsExistence NIC must be new\n" );
( *ppGuidtbl )[ idx ].dwLana = 0 ;
}
RegCloseKey( hKey );
}
return;
}
/***************************************************************************************************************
Name: BuildGuidTable
Purpose: Given valid table entries reconstruct table
Note: ppGuidtbl passed in is valid and 1 base
Returns: HRESULT
Params: [in] GUIDTBL **
[in] number of guid entries
***************************************************************************************************************/
HRESULT CCfgComp::BuildGuidTable( PGUIDTBL *ppGuidtbl , int cItems , WCHAR *pdName )
{
HKEY hKey;
HKEY hSubKey;
DWORD dwStatus;
DWORD dwDisp;
DWORD dwSize = sizeof( DWORD );
TCHAR tchRootKey[ MAX_PATH ];
TCHAR tchGuid[ 40 ];
DWORD rgdwOldLanaIds[ 256 ] = { 0 }; // man what machine will hold 256 nics?
// get last lanaIndex
dwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE , REG_GUID_TABLE , 0 , KEY_READ , &hKey );
DWORD dwMaxIdVal = 0;
DWORD dwVal = 0;
int nOldAdapters = 0;
if( dwStatus == ERROR_SUCCESS )
{
do
{
dwStatus = RegEnumKey( hKey , nOldAdapters , tchGuid , sizeof( tchGuid ) / sizeof( TCHAR ) );
if( dwStatus != ERROR_SUCCESS )
{
break;
}
if( RegOpenKeyEx( hKey , tchGuid , 0 , KEY_READ , &hSubKey ) == ERROR_SUCCESS )
{
RegQueryValueEx( hSubKey , LANA_ID , NULL , NULL , ( LPBYTE ) &dwVal , &dwSize );
rgdwOldLanaIds[ nOldAdapters ] = dwVal;
// calculate max value
if( dwMaxIdVal < dwVal )
{
dwMaxIdVal = dwVal;
}
RegCloseKey( hSubKey );
}
nOldAdapters++;
_ASSERTE( nOldAdapters < 256 );
} while( 1 );
RegCloseKey( hKey );
}
// remove old table
RecursiveDeleteKey( HKEY_LOCAL_MACHINE , REG_GUID_TABLE_T );
// create new table
int nStart = 1;
if( lstrcmpi( pdName , L"netbios" ) == 0 )
{
nStart = 0;
}
for( int idx = nStart ; idx < cItems ; ++idx )
{
lstrcpy( tchRootKey , REG_GUID_TABLE );
StringFromGUID2( ( *ppGuidtbl )[ idx ].guidNIC , tchGuid , ARRAYSIZE( tchGuid ) );
lstrcat( tchRootKey , tchGuid );
// modify lana id
if( ( *ppGuidtbl )[ idx ].dwStatus != ERROR_SUCCESS )
{
( *ppGuidtbl )[ idx ].dwLana = 0;
AdjustLanaId( ppGuidtbl , cItems , idx , &dwMaxIdVal , rgdwOldLanaIds , &nOldAdapters , nStart );
}
dwStatus = RegCreateKeyEx( HKEY_LOCAL_MACHINE , tchRootKey , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_READ|KEY_WRITE , NULL , &hKey , &dwDisp );
( *ppGuidtbl )[ idx ].dwStatus = dwStatus;
if( dwStatus == ERROR_SUCCESS )
{
RegSetValueEx( hKey , LANA_ID , 0 , REG_DWORD , ( LPBYTE )& ( ( *ppGuidtbl )[ idx ].dwLana ) , sizeof( DWORD ) );
RegCloseKey( hKey );
}
}
return S_OK;
}
/*-----------------------------------------------------------------------------------------------
AdjustLanaId
PARAMETERS: pGuidtbl : Table of queried entries
cItems : Number of items in list
idx : Entry to modify lana
pdwMaxIndex : New max value of lana index
NOTES: Since Lana is a dword; after 2^32-1 iterations lana ids will recycle to
the first available entry
-----------------------------------------------------------------------------------------------*/
HRESULT CCfgComp::AdjustLanaId( PGUIDTBL *ppGuidtbl , int cItems , int idx , PDWORD pdwMaxId , PDWORD pdwOldLanaIds , int* pnOldItems , int nStart )
{
// find the maxium value for the lana_id
for( int i = nStart ; i < cItems ; ++i )
{
if( *pdwMaxId < ( *ppGuidtbl )[ i ].dwLana )
{
*pdwMaxId = ( *ppGuidtbl )[ i ].dwLana ;
}
}
*pdwMaxId = *pdwMaxId + 1;
// check for overflow max id will be 0xfffffffe
if( *pdwMaxId == ( DWORD )-1 )
{
*pdwMaxId = 1;
do
{
for( i = 0 ; i < *pnOldItems; ++i )
{
if( *pdwMaxId == pdwOldLanaIds[ i ] )
{
*pdwMaxId = *pdwMaxId + 1;
break;
}
}
if( i >= *pnOldItems )
{
// no duplicate found use the current maxid
break;
}
} while( 1 );
}
( *ppGuidtbl )[ idx ].dwLana = *pdwMaxId;
// add new entry to the old table
if( *pnOldItems < 256 )
{
pdwOldLanaIds[ *pnOldItems ] = *pdwMaxId;
*pnOldItems = *pnOldItems + 1;
}
return S_OK;
}
//----------------------------------------------------------------------------------------------
// Delete a key and all of its descendents.
//----------------------------------------------------------------------------------------------
DWORD RecursiveDeleteKey( HKEY hKeyParent , LPTSTR lpszKeyChild )
{
// Open the child.
HKEY hKeyChild;
DWORD dwRes = RegOpenKeyEx(hKeyParent, lpszKeyChild , 0 , KEY_WRITE | KEY_READ, &hKeyChild);
if (dwRes != ERROR_SUCCESS)
{
return dwRes;
}
// Enumerate all of the decendents of this child.
FILETIME time;
TCHAR szBuffer[256];
DWORD dwSize = sizeof( szBuffer ) / sizeof( TCHAR );
while( RegEnumKeyEx( hKeyChild , 0 , szBuffer , &dwSize , NULL , NULL , NULL , &time ) == S_OK )
{
// Delete the decendents of this child.
dwRes = RecursiveDeleteKey(hKeyChild, szBuffer);
if (dwRes != ERROR_SUCCESS)
{
RegCloseKey(hKeyChild);
return dwRes;
}
dwSize = sizeof( szBuffer ) / sizeof( TCHAR );
}
// Close the child.
RegCloseKey( hKeyChild );
// Delete this child.
return RegDeleteKey( hKeyParent , lpszKeyChild );
}
/***************************************************************************************************************
Name: SetUserConfig
Purpose: Sets the UserConfig for a Winstation
Returns: HRESULT.
Params:
in: pWSName - Name of the Winstation.
size - Size of the input buffer in bytes
pUserConfig - Pointer to the UserConfig to be set
****************************************************************************************************************/
STDMETHODIMP CCfgComp::SetUserConfig(PWINSTATIONNAMEW pWsName, ULONG size, PUSERCONFIG pUserConfig , PDWORD pdwStatus )
{
WINSTATIONCONFIG2W WsConfig;
ULONG Length;
*pdwStatus = ERROR_INVALID_PARAMETER;
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
//Check if the caller has write permissions.
if( !m_bAdmin)
{
*pdwStatus = ERROR_ACCESS_DENIED;
ODS( L"CFGBKEND: ERROR_ACCESS_DENIED\n" );
return E_ACCESSDENIED;
}
//Check the parametes for NULL
if(NULL == pWsName || NULL == pUserConfig || 0 == size)
{
return E_INVALIDARG;
}
//Check for the validity of the Winstation name
if(NULL == GetWSObject(pWsName))
{
*pdwStatus = ERROR_INVALID_NAME;
return E_INVALIDARG;
}
//Atleast check if the size of the buffer passed is correct.
if(size != sizeof(USERCONFIGW))
return E_INVALIDARG;
// Query the registry for WinStation data
*pdwStatus = RegWinStationQueryW( NULL,pWsName,&WsConfig,sizeof(WINSTATIONCONFIG2W), &Length);
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND: SetUserConfig failed at RegWinstationQueryW\n" );
return E_FAIL;
}
//Copy the UserConfig structure to the pWsConfig.
CopyMemory((PVOID)&(WsConfig.Config.User),(CONST VOID *)pUserConfig,size);
*pdwStatus = RegWinStationCreateW(NULL,pWsName,FALSE,&WsConfig,sizeof(WsConfig));
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND: SetUserConfig failed at RegWinStationCreateW\n" );
return E_FAIL;
}
return S_OK;
}
/***************************************************************************************************************
Name: EnableWinstation
Purpose: Enables/Disables a given Winstation
Returns: HRESULT.
Params:
in: pWSName - Name of the Winstation.
fEnable - TRUE: Enable, FALSE:Disable
****************************************************************************************************************/
STDMETHODIMP CCfgComp::EnableWinstation(PWINSTATIONNAMEW pWSName, BOOL fEnable)
{
WINSTATIONCONFIG2W WsConfig;
LONG Status;
ULONG Length;
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
//Check if the caller has write permissions.
if(!m_bAdmin)
return E_ACCESSDENIED;
//Check the parametes for NULL
if(NULL == pWSName)
return E_INVALIDARG;
//Check for the validity of the Winstation name, this would eliminate the system console
if(NULL == GetWSObject(pWSName))
return E_INVALIDARG;
// Query the registry for WinStation data
Status = RegWinStationQueryW( NULL,pWSName,&WsConfig,sizeof(WINSTATIONCONFIG2W), &Length);
if(Status)
return E_FAIL;
WsConfig.Create.fEnableWinStation = fEnable;
Status = RegWinStationCreateW(NULL,pWSName,FALSE,&WsConfig,sizeof(WsConfig));
if ( Status)
return E_FAIL;
return S_OK;
}
/***************************************************************************************************************
Name: RenameWinstation
Purpose: Renames a given Winstation
Returns: HRESULT.
Params:
in: pOldWinstation - Name of the Winstation to be renamed.
pNewWinstation - New Name for the Winstation
****************************************************************************************************************/
STDMETHODIMP CCfgComp::RenameWinstation(PWINSTATIONNAMEW pOldWinstation, PWINSTATIONNAMEW pNewWinstation)
{
WINSTATIONCONFIG2W WsConfig;
LONG Status, size = 0;
ULONG Length; BOOL Unique;
void * pExtObject = NULL;
void * pExtDupObject = NULL;
HRESULT hResult = S_OK;
PWD pWD = NULL;
PWS pWS = NULL;
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
//Check if the caller has write permissions.
if(!m_bAdmin)
return E_ACCESSDENIED;
//Check the parametes for NULL
if(NULL == pOldWinstation || NULL == pNewWinstation)
return E_INVALIDARG;
IsWSNameUnique(pNewWinstation,&Unique);
if(!Unique)
return E_INVALIDARG;
//The new Winstation Name cannot be Console
if(0 ==(lstrcmpi(pNewWinstation,m_szConsole)))
return E_INVALIDARG;
//Check the length of the new winstation name
if(lstrlen(pNewWinstation) > WINSTATIONNAME_LENGTH)
return E_INVALIDARG;
//Check for the validity of the Winstation name, this would eliminate the system console
pWS = GetWSObject(pOldWinstation);
if(NULL == pWS)
return E_INVALIDARG;
//Get the WD object associated with this Winstation.
pWD = GetWdObject(pWS->wdName);
if(NULL == pWD)
return E_FAIL;
//Query the registry for WinStation data
Status = RegWinStationQueryW(NULL,pOldWinstation,&WsConfig,sizeof(WINSTATIONCONFIG2W), &Length);
if(Status)
return E_FAIL;
//Get the ExtensionObject data(third party) this will be used for Creating and Deleting the registry keys.
if(pWD->lpfnExtRegQuery && pWD->hExtensionDLL)
{
pExtObject = (pWD->lpfnExtRegQuery)(pOldWinstation, &(WsConfig.Pd[0]));
}
// Get the Security descriptor for the old Winstation
// Must free pSecurityDescriptor via LocalFree]
// check to see if previous winstation had a security key defined --
// we do this so that if the default security was used we don't
// create a "security" keyvalue in the new winstation
HKEY hKeyWinstation;
HKEY hKeyWinstationName;
if( RegOpenKeyEx(
HKEY_LOCAL_MACHINE ,
WINSTATION_REG_NAME,
0,
KEY_READ,
&hKeyWinstation ) == ERROR_SUCCESS)
{
if( RegOpenKeyEx(
hKeyWinstation ,
pOldWinstation ,
0 ,
KEY_READ,
&hKeyWinstationName ) == ERROR_SUCCESS)
{
if( RegQueryValueEx(
hKeyWinstationName ,
L"Security" ,
NULL ,
NULL ,
NULL ,
NULL ) == ERROR_SUCCESS )
{
hResult = GetSecurityDescriptor(
pOldWinstation ,
&size ,
&pSecurityDescriptor );
}
RegCloseKey( hKeyWinstationName );
}
RegCloseKey( hKeyWinstation );
}
if( FAILED( hResult ) )
{
DBGMSG( L"CFGBKEND!RenameWinstation GetSecurityDescriptor failed 0x%x\n " , hResult );
return E_FAIL;
}
do
{
//Create a new registry key with the data.
Status = RegWinStationCreateW(NULL,pNewWinstation,TRUE,&WsConfig,sizeof(WsConfig));
if( Status != ERROR_SUCCESS )
{
hResult = E_FAIL;
break;
}
//Create new extension data.
if(pWD->lpfnExtDupObject && pWD->hExtensionDLL && pExtObject)
{
pExtDupObject = (pWD->lpfnExtDupObject)(pExtObject);
if(pWD->lpfnExtRegCreate && pWD->hExtensionDLL && pExtDupObject)
{
(pWD->lpfnExtRegCreate)(pNewWinstation,pExtDupObject,TRUE);
}
}
//Set the Security information from the previous Winstation
if( pSecurityDescriptor != NULL )
{
hResult = SetSecurityDescriptor(pNewWinstation,size,pSecurityDescriptor);
if( FAILED( hResult ) )
{
break;
}
}
//delete old extension data
if(pWD->lpfnExtRegDelete && pWD->hExtensionDLL && pExtObject)
{
if( ERROR_SUCCESS != ( ( pWD->lpfnExtRegDelete )( pOldWinstation , pExtObject ) ) )
{
hResult = CFGBKEND_EXTDELETE_FAILED;
}
}
//Delete old registy key
Status = RegWinStationDeleteW(NULL,pOldWinstation);
if( Status != ERROR_SUCCESS )
{
//delete the new winstation that was created
if(pWD->lpfnExtRegDelete && pWD->hExtensionDLL && pExtDupObject)
{
(pWD->lpfnExtRegDelete)(pNewWinstation,pExtDupObject);
}
RegWinStationDeleteW(NULL,pNewWinstation);
hResult = E_FAIL;
break;
}
//update the object created in the list of winstation objects.
lstrcpy(pWS->Name,pNewWinstation);
} while( 0 );
//Release pSecurityDescriptor Memory
if( pSecurityDescriptor != NULL )
{
LocalFree( pSecurityDescriptor );
}
//Delete the Extension Objects.
if(pWD->lpfnExtDeleteObject && pWD->hExtensionDLL)
{
if( pExtObject )
(pWD->lpfnExtDeleteObject)(pExtObject);
if(pExtDupObject)
(pWD->lpfnExtDeleteObject)(pExtDupObject);
}
if(hResult == CFGBKEND_EXTDELETE_FAILED)
{
if(pWD->lpfnExtRegDelete && pWD->hExtensionDLL && pExtObject)
(pWD->lpfnExtRegDelete)(pOldWinstation,pExtObject);
}
// force termsrv to re-read settings!!!
hResult = ForceUpdate( );
return hResult;
}
/***************************************************************************************************************
Name: IsSessionReadOnly
Purpose: Checks if the Current session readonly.
Returns: HRESULT.
Params:
out: pReadOnly - pointer to whether the current session is readonly.
****************************************************************************************************************/
STDMETHODIMP CCfgComp::IsSessionReadOnly(BOOL * pReadOnly)
{
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
if(NULL == pReadOnly)
return E_INVALIDARG;
*pReadOnly = !m_bAdmin;
return S_OK;
}
/***************************************************************************************************************
Name: UnInitialize
Purpose: Uninitializes the Object
Returns: HRESULT.
Params:
****************************************************************************************************************/
STDMETHODIMP CCfgComp::UnInitialize()
{
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
DeleteWDArray();
DeleteWSArray();
m_bInitialized = FALSE;
return S_OK;
}
/***************************************************************************************************************
Name: DeleteWDArray
Purpose: Internal function to delete m_WdArray
Returns: void.
Params:
****************************************************************************************************************/
void CCfgComp::DeleteWDArray()
{
for(int i = 0; i < m_WDArray.GetSize();i++)
{
PWD pWd = ( PWD )m_WDArray[ i ];
if( pWd != NULL )
{
if( pWd->hExtensionDLL != NULL )
{
// ODS( L"Freeing extension dll\n" );
FreeLibrary( pWd->hExtensionDLL );
}
for( int j = 0 ; j < pWd->PDConfigArray.GetSize( ); j++ )
{
if( pWd->PDConfigArray[ j ] != NULL )
{
delete[] pWd->PDConfigArray[ j ];
}
}
delete[] m_WDArray[i];
}
}
m_WDArray.RemoveAll( );
return;
}
/***************************************************************************************************************
Name: DeleteWSArray
Purpose: Internal function to delete m_WSArray
Returns: void.
Params:
****************************************************************************************************************/
void CCfgComp::DeleteWSArray()
{
for(int i = 0; i <m_WSArray.GetSize();i++)
{
if(m_WSArray[i])
delete [] m_WSArray[i];
}
m_WSArray.RemoveAll( );
return;
}
/***************************************************************************************************************
Name: GetDefaultSecurityDescriptor
Purpose: Gets the Default Security Descriptor for a Winstation
Returns: HRESULT.
Params:
out: pSize - Size of the allocated buffer
ppSecurityDescriptor - Pointer to the buffer containing the security descriptor
****************************************************************************************************************/
STDMETHODIMP CCfgComp::GetDefaultSecurityDescriptor(long * pSize, PSECURITY_DESCRIPTOR * ppSecurityDescriptor)
{
HRESULT hResult = S_OK;
//If not initialized return error
if( !m_bInitialized )
{
return CFGBKEND_E_NOT_INITIALIZED;
}
if(NULL == pSize || NULL == ppSecurityDescriptor)
{
return E_INVALIDARG;
}
*pSize = 0;
*ppSecurityDescriptor = NULL;
//Try Getting Default Security Descriptor
hResult = GetWinStationSecurity(TRUE, NULL,(PSECURITY_DESCRIPTOR *)ppSecurityDescriptor);
if(SUCCEEDED(hResult) && *ppSecurityDescriptor != NULL )
{
*pSize = GetSecurityDescriptorLength( *ppSecurityDescriptor );
}
return hResult;
}
/***************************************************************************************************************
Name: UpDateWS
Purpose: UpDates the Winstation Information
Returns: HRESULT.
Params:
in: winstationInfo - WS
Data - Data fields to be updated
****************************************************************************************************************/
STDMETHODIMP CCfgComp::UpDateWS( PWS pWinstationInfo, DWORD Data , PDWORD pdwStatus, BOOLEAN bPerformMerger )
{
WINSTATIONCONFIG2W WSConfig;
ULONG Length;
_ASSERTE( pWinstationInfo != NULL );
*pdwStatus = 0;
if( pWinstationInfo == NULL || !( Data & UPDATE_ALL ) )
{
return E_INVALIDARG;
}
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
//Check if the caller has write permissions.
if( !m_bAdmin)
{
*pdwStatus = ERROR_ACCESS_DENIED;
return E_ACCESSDENIED;
}
//Check for the validity of the Winstation name, this would eliminate the system console
if(NULL == GetWSObject( pWinstationInfo->Name ) )
{
*pdwStatus = ERROR_INVALID_NAME;
return E_INVALIDARG;
}
// Query the registry for WinStation data
POLICY_TS_MACHINE p;
memset(&p, 0, sizeof(POLICY_TS_MACHINE));
*pdwStatus = RegWinStationQueryEx( NULL, &p, pWinstationInfo->Name,&WSConfig,sizeof(WINSTATIONCONFIG2W), &Length, bPerformMerger);
if( *pdwStatus != ERROR_SUCCESS )
{
return E_FAIL;
}
if( Data & UPDATE_LANADAPTER )
{
WSConfig.Pd[0].Params.Network.LanAdapter = pWinstationInfo->LanAdapter;
}
if( Data & UPDATE_ENABLEWINSTATION )
{
WSConfig.Create.fEnableWinStation = pWinstationInfo->fEnableWinstation;
}
if( Data & UPDATE_MAXINSTANCECOUNT )
{
WSConfig.Create.MaxInstanceCount = pWinstationInfo->uMaxInstanceCount;
}
if( Data & UPDATE_COMMENT )
{
lstrcpy( WSConfig.Config.Comment , pWinstationInfo->Comment );
}
/*
switch(Data)
{
case LANADAPTER:
WSConfig.Pd[0].Params.Network.LanAdapter = winstationInfo.LanAdapter;
break;
case ENABLEWINSTATION:
WSConfig.Create.fEnableWinStation = winstationInfo.fEnableWinstation;
break;
case MAXINSTANCECOUNT:
WSConfig.Create.MaxInstanceCount = winstationInfo.uMaxInstanceCount;
break;
case COMMENT:
lstrcpy(WSConfig.Config.Comment,winstationInfo.Comment);
break;
// case ASYNC:
// break;
case ALL:
WSConfig.Pd[0].Params.Network.LanAdapter = winstationInfo.LanAdapter;
WSConfig.Create.fEnableWinStation = winstationInfo.fEnableWinstation;
WSConfig.Create.MaxInstanceCount = winstationInfo.uMaxInstanceCount;
lstrcpy(WSConfig.Config.Comment,winstationInfo.Comment);
break;
default:
return E_INVALIDARG;
break;
}
*/
*pdwStatus = RegWinStationCreateW( NULL , pWinstationInfo->Name , FALSE , &WSConfig , sizeof( WSConfig ) );
if( *pdwStatus != ERROR_SUCCESS )
{
return E_FAIL;
}
// force termsrv to re-read settings!!!
return ForceUpdate( );
}
/***************************************************************************************************************
Name: GetWSInfo
Purpose: Gets Information about a Winstation
Returns: HRESULT.
Params:
in: pWSName - Name of the Winstation.
out: pSize - Size of the allocated buffer
ppWS - Pointer to the buffer containing the WS
****************************************************************************************************************/
STDMETHODIMP CCfgComp::GetWSInfo(PWINSTATIONNAME pWSName, long * pSize, WS ** ppWS)
{
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
PWS pWS1 = NULL;
if(NULL == pWSName || NULL == pSize || NULL == ppWS)
return E_INVALIDARG;
*ppWS = NULL;
*pSize = 0;
pWS1 = GetWSObject(pWSName);
if(NULL == pWS1)
return E_INVALIDARG;
*ppWS = (WS *)CoTaskMemAlloc(sizeof(WS));
if(NULL == *ppWS)
return E_OUTOFMEMORY;
CopyMemory((PVOID)*ppWS,(CONST VOID *)pWS1,sizeof(WS));
*pSize = sizeof(WS);
return S_OK;
}
/***************************************************************************************************************
Name: CreateNewWS
Purpose: Creates a new WS
Returns: HRESULT.
Params:
in: WinstationInfo - Info about new UI.
UserCnfgSize - Size of the Userconfig Buffer
pserConfig - Pointer to USERCONFIG.
pAsyncConfig - Can be NULL if async is not used
****************************************************************************************************************/
STDMETHODIMP CCfgComp::CreateNewWS(WS WinstationInfo, long UserCnfgSize, PUSERCONFIG pUserConfig,PASYNCCONFIGW pAsyncConfig)
{
WINSTATIONCONFIG2W WSConfig;
WDCONFIG2W WdConfig;
PDCONFIG3W PdConfig;
BOOL Unique;
ULONG ByteCount;
HRESULT hResult = S_OK;
PWD pWd = NULL;
DWORD dwStatus = ERROR_SUCCESS;
//If not initialized return error
if(!m_bInitialized)
{
ODS( L"CFGBKEND : CreateNewWS not initialized\n" );
return CFGBKEND_E_NOT_INITIALIZED;
}
do
{
//Check if the caller has write permissions.
if(!m_bAdmin)
{
ODS( L"CFGBKEND : CreateNewWS not Admin\n" );
hResult = E_ACCESSDENIED;
break;
}
pWd = GetWdObject(WinstationInfo.wdName);
if(NULL == pWd)
{
ODS( L"CFGBKEND : CreateNewWS no WD Object found\n" );
hResult = E_INVALIDARG;
break;
}
if(UserCnfgSize != sizeof(USERCONFIGW) && pUserConfig == NULL)
{
ODS( L"CFGBKEND : CreateNewWS UserConfig invalid\n" );
hResult = E_INVALIDARG;
break;
}
//See if the Name of the Winstation is Unique
hResult = IsWSNameUnique(WinstationInfo.Name,&Unique);
if( FAILED( hResult ) )
{
break;
}
if(0 == Unique)
{
ODS( L"CFGBKEND : CreateNewWS WINSTA name not unique\n" );
hResult = E_INVALIDARG;
break;
}
//Check the length of the new winstation name
if(lstrlen(WinstationInfo.Name) > WINSTATIONNAME_LENGTH)
{
hResult = E_INVALIDARG;
break;
}
//Now begins the actual work.
ZeroMemory(&WSConfig, sizeof(WINSTATIONCONFIG2W));
//WINSTATIONCONFIG2W.Create
WSConfig.Create.fEnableWinStation = WinstationInfo.fEnableWinstation;
WSConfig.Create.MaxInstanceCount = WinstationInfo.uMaxInstanceCount;
//WINSTATIONCONFIG2W.Wd
dwStatus = RegWdQueryW(NULL,pWd->wdKey, &WdConfig,sizeof(WdConfig),&ByteCount);
if(ERROR_SUCCESS != dwStatus )
{
DBGMSG( L"CFGBKEND : CreateNewWS@RegWdQuery failed with 0x%x\n" , dwStatus );
hResult = E_FAIL;
break;
}
WSConfig.Wd = WdConfig.Wd;
//WINSTATIONCONFIG2W.Config
lstrcpy(WSConfig.Config.Comment,WinstationInfo.Comment);
CopyMemory( ( PVOID )&WSConfig.Config.User , ( CONST VOID * )pUserConfig , UserCnfgSize );
//WINSTATIONCONFIG2W.Pd
dwStatus = RegPdQueryW( NULL , pWd->wdKey , TRUE , WinstationInfo.pdName , &PdConfig , sizeof(PdConfig) , &ByteCount );
if( ERROR_SUCCESS != dwStatus )
{
DBGMSG( L"CFGBKEND : CreateNewWS RegPdQuery failed with 0x%x\n" , dwStatus );
hResult = E_FAIL;
break;
}
WSConfig.Pd[0].Create = PdConfig.Data;
WSConfig.Pd[0].Params.SdClass = (SDCLASS)WinstationInfo.PdClass;
if(SdNetwork == (SDCLASS)WinstationInfo.PdClass)
{
WSConfig.Pd[0].Params.Network.LanAdapter = WinstationInfo.LanAdapter;
}
else if(SdAsync == (SDCLASS)WinstationInfo.PdClass)
{
if(NULL != pAsyncConfig)
{
pAsyncConfig->fConnectionDriver = *( pAsyncConfig->ModemName ) ? TRUE : FALSE;
WSConfig.Pd[0].Params.Async = *pAsyncConfig;
CDCONFIG cdConfig;
SetupAsyncCdConfig( pAsyncConfig , &cdConfig );
if( cdConfig.CdName[ 0 ] != 0 )
{
dwStatus = RegCdCreateW( NULL , pWd->wdKey , cdConfig.CdName , TRUE , &cdConfig , sizeof( CDCONFIG ) );
if( dwStatus != ERROR_SUCCESS )
{
DBGMSG( L"CFGBKEND: RegCdCreateW returned 0x%x\n", dwStatus );
if( dwStatus == ERROR_ALREADY_EXISTS )
{
hResult = S_FALSE;
}
else if( dwStatus == ERROR_CANTOPEN )
{
hResult = E_ACCESSDENIED;
break;
}
else
{
hResult = E_FAIL;
break;
}
}
WSConfig.Cd = cdConfig;
}
}
}
//Get the additional Pd's. Currently only ICA has this.
GetPdConfig(pWd->wdKey,WSConfig);
//Try Creating
dwStatus = ( DWORD )RegWinStationCreate( NULL , WinstationInfo.Name , TRUE , &WSConfig , sizeof(WINSTATIONCONFIG2) );
if( dwStatus != ERROR_SUCCESS )
{
DBGMSG( L"CFGBKEND : CreateNewWS@RegWinStationCreate failed 0x%x\n" , dwStatus );
hResult = E_FAIL;
break;
}
//Create the extension Data, Currently only ICA has this
void * pExtObject = NULL;
if(pWd->lpfnExtRegQuery && pWd->hExtensionDLL)
{
pExtObject = (pWd->lpfnExtRegQuery)(L"", &(WSConfig.Pd[0]));
}
if(pExtObject)
{
if(pWd->lpfnExtRegCreate)
{
(pWd->lpfnExtRegCreate)(WinstationInfo.Name,pExtObject,TRUE);
}
}
//Delete the extension object
if(pWd->lpfnExtDeleteObject && pExtObject)
{
(pWd->lpfnExtDeleteObject )(pExtObject );
}
//Add the Winstation to our local list.
PWS pObject = NULL;
hResult = InsertInWSArray(WinstationInfo.Name,&WSConfig,&pObject);
if( SUCCEEDED( hResult ) )
{
hResult = ForceUpdate( );
}
}while( 0 );
return hResult;
}
/***************************************************************************************************************
Name: GetDefaultUserConfig
Purpose: Gets the Default User Configuration for a given Winstation Driver
Returns: HRESULT.
Params:
in: WdName - Name of the Winstation Driver.
out: pSize - Size of the allocated buffer
ppUser - Pointer to the buffer containing the UserConfig
****************************************************************************************************************/
STDMETHODIMP CCfgComp::GetDefaultUserConfig(WCHAR * WdName,long * pSize, PUSERCONFIG * ppUser)
{
LONG QStatus;
WDCONFIG2W WdConfig;
ULONG ByteCount;
PWD pWd = NULL;
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
if(NULL == pSize || NULL == ppUser || NULL == WdName)
return E_INVALIDARG;
pWd = GetWdObject(WdName);
if(NULL == pWd)
return E_INVALIDARG;
if (( QStatus = RegWdQueryW( NULL, pWd->wdKey, &WdConfig,
sizeof(WdConfig),
&ByteCount )) != ERROR_SUCCESS )
return E_FAIL;
*ppUser = (PUSERCONFIG)CoTaskMemAlloc(sizeof(WdConfig.User));
if(*ppUser == NULL)
return E_OUTOFMEMORY;
CopyMemory((PVOID)*ppUser,(CONST VOID *)&WdConfig.User,sizeof(WdConfig.User));
*pSize = sizeof(WdConfig.User);
return S_OK;
}
/***************************************************************************************************************
Name: IsNetWorkConnectionUnique
Purpose: Checks if the combination of Winstation driver name, LanAdapter and the transport is Unique.
Returns: HRESULT.
Params:
in: WdName - Name of the Winstation Driver.
PdName - Name of the Transport
LanAdapter - LanAdapter Index
out: pUnique - pointer to whether the information is unique or not.
****************************************************************************************************************/
STDMETHODIMP CCfgComp::IsNetWorkConnectionUnique(WCHAR * WdName, WCHAR * PdName, ULONG LanAdapter, BOOL * pUnique)
{
//If not initialized return error
if( !m_bInitialized )
{
return CFGBKEND_E_NOT_INITIALIZED;
}
//Check for uniqueness of this combination,
//Transport, Type , LanAdapter
if( NULL == WdName || NULL == PdName || NULL == pUnique )
{
return E_INVALIDARG;
}
*pUnique = TRUE;
int nSize = m_WSArray.GetSize();
for(int i = 0; i < nSize; i++ )
{
if(lstrcmpi(WdName,((WS *)(m_WSArray[i]))->wdName) == 0 )
{
if(lstrcmpi(PdName,((WS *)(m_WSArray[i]))->pdName) == 0)
{
// Make sure there's not a lanadapter configured for all settings
if( ( LanAdapter == 0 ) ||
( LanAdapter == ( ( WS * )( m_WSArray[ i ] ) )->LanAdapter ) ||
( ( ( WS * )( m_WSArray[ i ] ) )->LanAdapter == 0 ) )
//( oldLanAdapter != ( ( WS * )( m_WSArray[ i ] ) )->LanAdapter && ( ( WS * )( m_WSArray[ i ] ) )->LanAdapter == 0 ) )
{
*pUnique = FALSE;
break;
}
}
}
}
return S_OK;
}
/***************************************************************************************************************
Name: DeleteWS
Purpose: Deletes a given Winstation
Returns: HRESULT.
Params:
in: pWSName - Name of the Winstation.
out: pSize - Size of the allocated buffer
ppSecurityDescriptor - Pointer to the buffer containing the security descriptor
****************************************************************************************************************/
STDMETHODIMP CCfgComp::DeleteWS(PWINSTATIONNAME pWs)
{
HRESULT hResult = S_OK;
PWS pWinsta = NULL;
PWD pWD = NULL;
void * pExtObject = NULL;
WINSTATIONCONFIG2W WsConfig;
ULONG Length = 0;
long Status;
//If not initialized return error
if(!m_bInitialized)
return CFGBKEND_E_NOT_INITIALIZED;
//Check if the caller has write permissions.
if(!m_bAdmin)
return E_ACCESSDENIED;
//Check if Valid Winstation Name
if(NULL == pWs)
return E_INVALIDARG;
//Check for the validity of the Winstation name,
pWinsta = GetWSObject(pWs);
if(NULL == pWinsta)
return E_INVALIDARG;
//Get the WD object associated with this Winstation.
pWD = GetWdObject(pWinsta->wdName);
if(NULL == pWD)
return E_FAIL;
//Query the registry for WinStation data
Status = RegWinStationQueryW(NULL,pWs,&WsConfig,sizeof(WINSTATIONCONFIG2W), &Length);
if(Status)
return E_FAIL;
#if 0 // tscc now uses aclui
// Remove name entry keys
TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server\\winstations\\" );
HKEY hKey;
lstrcat( tchRegPath , pWs );
lstrcat( tchRegPath , L"\\NamedEntries" );
OutputDebugString( tchRegPath );
if( RegOpenKey( HKEY_LOCAL_MACHINE , tchRegPath , &hKey ) == ERROR_SUCCESS )
{
RegDeleteValue( hKey , L"cbSize" );
RegDeleteValue( hKey , L"NE" );
RegCloseKey( hKey );
RegDeleteKey( HKEY_LOCAL_MACHINE , tchRegPath );
}
#endif
//Get the ExtensionObject data(third party) this will be used for Creating and Deleting the registry keys.
if(pWD->lpfnExtRegQuery && pWD->hExtensionDLL)
{
pExtObject = (pWD->lpfnExtRegQuery)(pWs, &(WsConfig.Pd[0]));
if(pWD->lpfnExtRegDelete && pExtObject)
{
//Try Deleting the Extension entries in the registy
if(ERROR_SUCCESS != (pWD->lpfnExtRegDelete)(pWs,pExtObject))
hResult = CFGBKEND_EXTDELETE_FAILED;
//Delete the extension object. It will not be used further.
if(pWD->lpfnExtDeleteObject)
(pWD->lpfnExtDeleteObject)(pExtObject);
}
}
//Delete registy key
Status = RegWinStationDeleteW(NULL,pWs);
if (Status)
return Status;
//update our list of winstation objects.
PWS pObject;
int Size = 0,Index = 0;
/*
* Traverse the WD list
*/
for (Index = 0, Size = m_WSArray.GetSize(); Index < Size; Index ++)
{
pObject = (PWS)m_WSArray[Index];
if ( !lstrcmpi( pObject->Name, pWs ) )
{
m_WSArray.RemoveAt(Index,1);
delete pObject;
break;
}
}
return hResult;
}
//----------------------------------------------------------------------
// good to call when you've updated the winstation security descriptor
//----------------------------------------------------------------------
STDMETHODIMP CCfgComp::ForceUpdate( void )
{
if( !m_bInitialized )
{
ODS( L"CFGBKEND : CCfgComp::ForceUpdate return NOT_INIT\n" );
return CFGBKEND_E_NOT_INITIALIZED;
}
//Check if the caller has write permissions.
if(!m_bAdmin)
{
ODS( L"CFGBKEND : CCfgComp::ForceUpdate -- not admin\n" );
return E_ACCESSDENIED;
}
if( _WinStationReadRegistry( SERVERNAME_CURRENT ) )
{
return S_OK;
}
ODS( L"CFGBKEND : ForceUpdate failed Winstation not updated\n" );
return E_FAIL;
}
//----------------------------------------------------------------------
// Must delete the array completely first.
//----------------------------------------------------------------------
STDMETHODIMP CCfgComp::Refresh( void )
{
//Check if the caller has write permissions.
/* bugid 364103
if(!m_bAdmin)
{
return E_ACCESSDENIED;
}
*/
HRESULT hr = FillWdArray();
if( SUCCEEDED( hr) )
{
hr = FillWsArray();
}
return hr;
}
//----------------------------------------------------------------------
// Obtain Winstation SDCLASS type
// m_WDArray must already be initialized
//----------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetTransportType( WCHAR *wszDriverName , WCHAR *wszTransportType , DWORD *sdtype )
{
_ASSERTE( wszDriverName != NULL || wszTransportType != NULL || sdtype != NULL );
if( wszDriverName == NULL || wszTransportType == NULL || sdtype == NULL )
{
return E_INVALIDARG;
}
*sdtype = SdNone;
PWD pWd = GetWdObject( wszDriverName );
if( pWd != NULL )
{
BOOL bFound = FALSE;
for( int i = 0; i < pWd->PDConfigArray.GetSize( ) ; ++i )
{
if( lstrcmpi( wszTransportType , ( ( PDCONFIG3W *)pWd->PDConfigArray[ i ] )->Data.PdName ) == 0 )
{
bFound = TRUE;
break;
}
}
if( bFound )
{
*sdtype = ( ( PDCONFIG3W * )pWd->PDConfigArray[ i ] )->Data.SdClass;
return S_OK;
}
}
return E_FAIL;
}
//----------------------------------------------------------------------
// Async's are unique if device name protocol type vary from other
// winstations.
//----------------------------------------------------------------------
STDMETHODIMP CCfgComp::IsAsyncUnique( WCHAR *wszDeviceName , WCHAR *wszProtocolType , BOOL *pbUnique )
{
_ASSERTE( wszDecoratedName != NULL || wszProtocolType != NULL || pbUnique != NULL );
if( wszDeviceName == NULL || wszProtocolType == NULL || pbUnique == NULL )
{
return E_INVALIDARG;
}
*pbUnique = TRUE;
// Traverse the WinStationList.
for( int i = 0; i < m_WSArray.GetSize(); i++ )
{
if( lstrcmpi( wszProtocolType , ( ( WS * )( m_WSArray[ i ] ) )->wdName ) == 0 )
{
if( SdAsync == ( ( WS *)( m_WSArray[i] ) )->PdClass )
{
if( !lstrcmpi( wszDeviceName , ( ( WS * )( m_WSArray[ i ] ) )->DeviceName ) == 0 )
{
*pbUnique = FALSE;
break;
}
}
}
}
return S_OK;
}
//----------------------------------------------------------------------
// Pull async configuration from the registry
//----------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetAsyncConfig( WCHAR *wszName , NameType nt , PASYNCCONFIGW pAsync )
{
if( wszName == NULL || pAsync == NULL )
{
ODS( L"CFGBKEND: Invalid arg @ GetAsyncConfig\n" );
return E_INVALIDARG;
}
WINSTATIONCONFIG2W WSConfig2;
ULONG ulLength = 0;
if( nt == WsName )
{
//Read the information from the registry.
if( RegWinStationQueryW( NULL , wszName , &WSConfig2 , sizeof( WINSTATIONCONFIG2W) , &ulLength ) != ERROR_SUCCESS )
{
ODS( L"CFGBKEND: RegWinStationQueryW failed @ GetAsyncConfig\n " );
return E_FAIL;
}
*pAsync = WSConfig2.Pd[0].Params.Async;
}
else if( nt == WdName )
{
PWD pObject = GetWdObject( wszName );
if( pObject == NULL )
{
return E_UNEXPECTED;
}
*pAsync = pObject->wd2.Async;
}
else
{
return E_INVALIDARG;
}
return S_OK;
}
//----------------------------------------------------------------------
// Push async config back in to the registry
//----------------------------------------------------------------------
STDMETHODIMP CCfgComp::SetAsyncConfig( WCHAR *wszName , NameType nt , PASYNCCONFIGW pAsync , PDWORD pdwStatus )
{
*pdwStatus = 0;
if( wszName == NULL || pAsync == NULL )
{
ODS( L"CFGBKEND: Invalid arg @ SetAsyncConfig\n" );
*pdwStatus = ERROR_INVALID_PARAMETER;
return E_INVALIDARG;
}
WINSTATIONCONFIG2W WSConfig2;
// WDCONFIG2W wdConfig2;
ULONG ulLength = 0;
if( nt == WsName )
{
//Read the information from the registry.
CDCONFIG cdConfig;
ZeroMemory( ( PVOID )&cdConfig , sizeof( CDCONFIG ) );
if( ( *pdwStatus = RegWinStationQueryW( NULL , wszName , &WSConfig2 , sizeof( WINSTATIONCONFIG2W) , &ulLength ) ) != ERROR_SUCCESS )
{
ODS( L"CFGBKEND: RegWinStationQueryW failed @ SetAsyncConfig\n" );
return E_FAIL;
}
pAsync->fConnectionDriver = *( pAsync->ModemName ) ? TRUE : FALSE;
SetupAsyncCdConfig( pAsync , &cdConfig );
WSConfig2.Pd[0].Params.Async = *pAsync;
WSConfig2.Cd = cdConfig;
if( ( *pdwStatus = RegWinStationCreateW( NULL , wszName , FALSE , &WSConfig2 , sizeof( WINSTATIONCONFIG2W ) ) ) != ERROR_SUCCESS )
{
ODS( L"CFGBKEND: RegWinStationCreateW failed @ SetAsyncConfig\n" );
return E_FAIL;
}
}
/*else if( nt == WdName )
{
PWD pObject = GetWdObject( wszName );
if( pObject == NULL )
{
ODS( L"CFGBKEND: Failed to obtain WD @ SetAsyncConfig\n" );
*pdwStatus = ERROR_INVALID_NAME;
return E_FAIL;
}
if( ( *pdwStatus = RegWdQueryW( NULL , pObject->wdKey , &wdConfig2 , sizeof( WDCONFIG2W ) , &ulLength ) ) != ERROR_SUCCESS )
{
ODS( L"CFGBKEND: RegWdQueryW failed @ SetAsyncConfig driver name is " );
ODS( pObject->wdKey );
ODS( L"\n" );
return E_FAIL;
}
wdConfig2.Async = *pAsync;
if( ( *pdwStatus = RegWdCreateW( NULL , pObject->wdKey , FALSE , &wdConfig2 , sizeof( WDCONFIG2W ) ) ) != ERROR_SUCCESS )
{
ODS( L"CFGBKEND: RegWdCreateW failed @ SetAsyncConfig\n" );
return E_FAIL;
}
}*/
else
{
*pdwStatus = ERROR_INVALID_PARAMETER;
return E_INVALIDARG;
}
return S_OK;
}
//----------------------------------------------------------------------
// GetDeviceList expects the name of the WD
// the return is a BLOB PDPARAMs containing ASYNCCONFG's
//----------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetDeviceList( WCHAR *wszName , NameType Type , ULONG *pulItems , LPBYTE *ppBuffer )
{
PWD pObject = NULL;
if( wszName == NULL || pulItems == NULL )
{
ODS( L"CFGBKEND : @GetDeviceList - Driver or WinSta Name invalid\n" );
return E_INVALIDARG;
}
if( Type == WsName )
{
PWS pWS = GetWSObject( wszName );
if( NULL == pWS )
{
ODS( L"CFGBKEND : @GetDeviceList - No winsta object found\n" );
return E_INVALIDARG;
}
pObject = GetWdObject( pWS->wdName );
if( NULL == pObject )
{
ODS( L"CFGBKEND : @GetDeviceList - No WD object found\n" );
return E_FAIL;
}
}
else
{
pObject = GetWdObject( wszName );
}
if( pObject == NULL )
{
ODS( wszName ); ODS( L" - @GetDeviceList - driver object not found\n" );
return E_UNEXPECTED;
}
PDCONFIG3W *pPdConfig3 = NULL;
int nItems = ( pObject->PDConfigArray ).GetSize( );
for( int i = 0; i < nItems ; i++)
{
if( SdAsync == ( ( PDCONFIG3W * )pObject->PDConfigArray[i] )->Data.SdClass )
{
pPdConfig3 = ( PDCONFIG3W * )pObject->PDConfigArray[i];
break;
}
}
if( pPdConfig3 == NULL )
{
ODS( L"@GetDeviceList - PDCONFIG3 not found for ASYNC\n" );
return E_UNEXPECTED;
}
// Get the list of PDPARAMS -- last param if true queries registry for com devices
// if false uses DosDevices to obtain list
ODS( L"CFGBKEND : Calling WinEnumerateDevices\n" );
LPBYTE lpBuffer = ( LPBYTE )WinEnumerateDevices( NULL , pPdConfig3 , pulItems , FALSE );
if( lpBuffer == NULL )
{
ODS( L"CFGBKEND : WinEnumerateDevices failed @ CCfgComp::GetDeviceList\n" );
return E_OUTOFMEMORY;
}
// don't forget to free with LocalFree
*ppBuffer = lpBuffer;
return S_OK;
}
//----------------------------------------------------------------------
// GetConnType retreives the name of the connection type for an Async
// device. The list of resource ids is match the order of the
// CONNECTCONFIG enum data type.
//----------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetConnTypeName( int idxItem , WCHAR *rgwszConnectName )
{
int rgIds[] = { IDS_CONNECT_CTS , IDS_CONNECT_DSR , IDS_CONNECT_RI ,
IDS_CONNECT_DCD , IDS_CONNECT_FIRST_CHARACTER ,
IDS_CONNECT_ALWAYS , -1 };
_ASSERTE( rgwszConnectName != NULL );
_ASSERTE( idxItem >= 0 && idxItem < ARRAYSIZE( rgIds ) );
if( rgIds[ idxItem ] == -1 )
{
return S_FALSE;
}
if( !GetResourceStrings( rgIds , idxItem , rgwszConnectName ) )
{
ODS( L"Error happen in CCfgComp::GetConnTypeName\n" );
return E_FAIL;
}
return S_OK;
}
//----------------------------------------------------------------------
// GetModemCallbackString
//----------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetModemCallbackString( int idxItem , WCHAR *rgwszModemCallBackString )
{
int rgIds[] = { IDS_MODEM_CALLBACK_DISABLED , IDS_MODEM_CALLBACK_ROVING , IDS_MODEM_CALLBACK_FIXED , -1 };
_ASSERTE( rgwszModemCallBackString != NULL );
_ASSERTE( idxItem >= 0 && idxItem < ARRAYSIZE( rgIds ) );
if( rgIds[ idxItem ] == -1 )
{
return S_FALSE;
}
if( !GetResourceStrings( rgIds , idxItem , rgwszModemCallBackString ) )
{
ODS( L"Error happen in CCfgComp::GetConnTypeName\n" );
return E_FAIL;
}
return S_OK;
}
//----------------------------------------------------------------------
// Returns the name of hardware flow control receive string
//----------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetHWReceiveName( int idxItem , WCHAR *rgwszHWRName )
{
int rgIds[] = { IDS_ASYNC_ADVANCED_HWRX_NOTHING ,
IDS_ASYNC_ADVANCED_HWRX_TURN_OFF_RTS ,
IDS_ASYNC_ADVANCED_HWRX_TURN_OFF_DTR , -1
};
_ASSERTE( rgwszHWRName != NULL );
_ASSERTE( idxItem >= 0 && idxItem < ARRAYSIZE( rgIds ) );
if( rgIds[ idxItem ] == -1 )
{
return S_FALSE;
}
if( !GetResourceStrings( rgIds , idxItem , rgwszHWRName ) )
{
ODS( L"Error happen in CCfgComp::GetHWReceiveName\n" );
return E_FAIL;
}
return S_OK;
}
//----------------------------------------------------------------------
// returns the name of hardware flow control transmit string
//----------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetHWTransmitName( int idxItem , WCHAR *rgwzHWTName )
{
int rgIds[] = { IDS_ASYNC_ADVANCED_HWTX_ALWAYS ,
IDS_ASYNC_ADVANCED_HWTX_WHEN_CTS_IS_ON,
IDS_ASYNC_ADVANCED_HWTX_WHEN_DSR_IS_ON,
-1
};
_ASSERTE( rgwszHWRName != NULL );
_ASSERTE( idxItem >= 0 && idxItem < ARRAYSIZE( rgIds ) );
if( rgIds[ idxItem ] == -1 )
{
return S_FALSE;
}
if( !GetResourceStrings( rgIds , idxItem , rgwzHWTName ) )
{
ODS( L"Error happen in CCfgComp::GetHWReceiveName\n" );
return E_FAIL;
}
return S_OK;
}
//----------------------------------------------------------------------
// Internal method call -- helper function.
//----------------------------------------------------------------------
BOOL CCfgComp::GetResourceStrings( int *prgIds , int iItem , WCHAR *rgwszList )
{
_ASSERTE( rgwszList != NULL );
if( rgwszList == NULL )
{
ODS( L"rgwszList is NULL @ CCfgComp::GetResourceStrings\n" );
return FALSE;
}
TCHAR tchConType[ 80 ];
if( LoadString( _Module.GetResourceInstance( ) , prgIds[ iItem ] , tchConType , sizeof( tchConType ) / sizeof( TCHAR ) ) == 0 )
{
ODS( L"String resource not found @ CCfgComp::GetResourceStrings\n" );
return FALSE;
}
// copy enough characters
lstrcpyn( rgwszList , tchConType , sizeof( tchConType ) );
return TRUE;
}
//----------------------------------------------------------------------
HRESULT CCfgComp::GetCaps( WCHAR *szWdName , ULONG *pMask )
{
if( szWdName == NULL || pMask == NULL )
{
ODS( L"CCfgComp::GetCaps returned INVALIDARG\n" );
return E_INVALIDARG;
}
PWD pObject = GetWdObject( szWdName );
if( pObject == NULL )
{
return E_UNEXPECTED;
}
if( pObject->lpfnGetCaps != NULL )
{
*pMask = ( pObject->lpfnGetCaps )( );
}
return S_OK;
}
//----------------------------------------------------------------------
HRESULT CCfgComp::QueryLoggedOnCount( WCHAR *pWSName , PLONG pCount )
{
ODS( L"CFGBKEND : CCfgComp::QueryLoggedOnCount\n" );
*pCount = 0;
ULONG Entries = 0;
TCHAR *p;
PLOGONID pLogonId;
if(FALSE == WinStationEnumerate( NULL , &pLogonId, &Entries))
{
return E_FAIL;
}
if( pLogonId )
{
for( ULONG i = 0; i < Entries; i++ )
{
/*
* Check active, connected, and shadowing WinStations, and increment
* the logged on count if the specified name matches the 'root'
* name of current winstation.
*/
if( ( pLogonId[i].State == State_Active ) || ( pLogonId[i].State == State_Connected ) || ( pLogonId[i].State == State_Shadow ) )
{
// remove appended connection number
p = _tcschr( pLogonId[i].WinStationName , TEXT('#') );
if( p != NULL )
{
*p = TEXT('\0');
}
if( !lstrcmpi( pWSName, pLogonId[i].WinStationName ) )
{
*pCount += 1 ;
}
}
}
WinStationFreeMemory(pLogonId);
}
return S_OK;
} // end QueryLoggedOnCount
/*
//-----------------------------------------------------------------------------
// returns the number of configured winstations
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetNumofWinStations( PULONG nWinsta )
{
if( nWinsta == NULL )
{
ODS( L"CFGBKEND : GetNumofWinStations - INVALID ARG\n" );
return E_INVALIDARG;
}
*nWinsta = ( ULONG )m_WSArray.GetSize();
return S_OK;
}
*/
//-----------------------------------------------------------------------------
// returns the number of configured winstations
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetNumofWinStations(WCHAR * WdName,WCHAR * PdName, PULONG nWinsta )
{
if( nWinsta == NULL || NULL == WdName || NULL == PdName )
{
ODS( L"CFGBKEND : GetNumofWinStations - INVALID ARG\n" );
return E_INVALIDARG;
}
ULONG lCount = 0;
for( int i = 0; i < m_WSArray.GetSize(); i++ )
{
if(lstrcmpi(WdName,( ( WS *)( m_WSArray[i] ) )->wdName) == 0 )
{
if(lstrcmpi( PdName , ( ( WS * )( m_WSArray[ i ] ) )->pdName ) == 0 )
{
lCount++;
}
}
}
*nWinsta = lCount;
return S_OK;
}
//-----------------------------------------------------------------------------
STDMETHODIMP_(BOOL) CCfgComp::IsAsyncDeviceAvailable(LPCTSTR pDeviceName)
{
/*
* If this is an async WinStation, the device is the same as the
* one we're checking, but this is not the current WinStation being
* edited, return FALSE.
* THIS NEEDS TO BE REVIEWED - alhen
*/
//return TRUE;
if( pDeviceName != NULL )
{
for( int i = 0; i < m_WSArray.GetSize(); i++ )
{
if( SdAsync == ( ( WS *)( m_WSArray[i] ) )->PdClass )
{
if( lstrcmpi( pDeviceName , ( ( WS * )( m_WSArray[ i ] ) )->DeviceName ) == 0 )
{
return FALSE;
}
}
}
}
return TRUE;
}
#if 0 // removed for final
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetCachedSessions(DWORD * pCachedSessions)
{
HKEY Handle = NULL;
DWORD ValueBuffer = 0;
DWORD ValueType = 0;
LONG Status = 0;
DWORD ValueSize = sizeof(ValueBuffer);
if(NULL == pCachedSessions)
{
return E_INVALIDARG;
}
*pCachedSessions = 0;
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
KEY_READ, &Handle );
if ( Status == ERROR_SUCCESS )
{
Status = RegQueryValueEx( Handle,
REG_CITRIX_IDLEWINSTATIONPOOLCOUNT,
NULL,
&ValueType,
(LPBYTE) &ValueBuffer,
&ValueSize );
if ( Status == ERROR_SUCCESS )
{
if(ValueType == REG_DWORD)
{
*pCachedSessions = ValueBuffer;
}
else
{
Status = E_FAIL;
}
}
}
if(Handle)
{
RegCloseKey(Handle);
}
return Status;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::SetCachedSessions(DWORD dCachedSessions)
{
// TODO: Add your implementation code here
LONG Status = 0;
HKEY Handle = NULL;
if(RegServerAccessCheck(KEY_ALL_ACCESS))
{
return E_ACCESSDENIED;
}
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
KEY_READ | KEY_SET_VALUE, &Handle );
if ( Status == ERROR_SUCCESS )
{
Status = RegSetValueEx(Handle,REG_CITRIX_IDLEWINSTATIONPOOLCOUNT,
0,REG_DWORD,(const BYTE *)&dCachedSessions,
sizeof(dCachedSessions));
}
if(Handle)
{
RegCloseKey(Handle);
}
return Status;
}
#endif // removed
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetDelDirsOnExit(BOOL * pDelDirsOnExit)
{
HKEY Handle = NULL;
DWORD ValueBuffer = 0;
DWORD ValueType = 0;
LONG Status = 0;
DWORD ValueSize = sizeof(ValueBuffer);
if(NULL == pDelDirsOnExit)
{
return E_INVALIDARG;
}
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
KEY_READ, &Handle );
if ( Status == ERROR_SUCCESS )
{
Status = RegQueryValueEx( Handle,
REG_CITRIX_DELETETEMPDIRSONEXIT,
NULL,
&ValueType,
(LPBYTE) &ValueBuffer,
&ValueSize );
if ( Status == ERROR_SUCCESS )
{
if(ValueType == REG_DWORD)
{
if(ValueBuffer)
{
*pDelDirsOnExit = TRUE;
}
else
{
*pDelDirsOnExit = FALSE;
}
}
else
{
Status = E_FAIL;
}
}
}
if(Handle)
{
RegCloseKey(Handle);
}
return Status;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::SetDelDirsOnExit(BOOL bDelDirsOnExit)
{
LONG Status = 0;
HKEY Handle = NULL;
/* admin only
if(RegServerAccessCheck(KEY_ALL_ACCESS))
{
return E_ACCESSDENIED;
}
*/
if( !m_bAdmin )
{
ODS( L"CCfgComp::SetDelDirsOnExit not admin\n" );
return E_ACCESSDENIED;
}
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
KEY_READ | KEY_SET_VALUE, &Handle );
if ( Status == ERROR_SUCCESS )
{
Status = RegSetValueEx(Handle,REG_CITRIX_DELETETEMPDIRSONEXIT,
0,REG_DWORD,(const BYTE *)&bDelDirsOnExit,
sizeof(bDelDirsOnExit));
}
if(Handle)
{
RegCloseKey(Handle);
}
return Status;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetUseTempDirPerSession(BOOL * pbTempDir)
{
HKEY Handle = NULL;
DWORD ValueBuffer = 0;
DWORD ValueType = 0;
LONG Status = 0;
DWORD ValueSize = sizeof(ValueBuffer);
if(NULL == pbTempDir)
{
return E_INVALIDARG;
}
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
KEY_READ, &Handle );
if ( Status == ERROR_SUCCESS )
{
Status = RegQueryValueEx( Handle,
REG_TERMSRV_PERSESSIONTEMPDIR,
NULL,
&ValueType,
(LPBYTE) &ValueBuffer,
&ValueSize );
if ( Status == ERROR_SUCCESS )
{
if(ValueType == REG_DWORD)
{
if(ValueBuffer)
{
*pbTempDir = TRUE;
}
else
{
*pbTempDir = FALSE;
}
}
else
{
Status = E_FAIL;
}
}
}
if(Handle)
{
RegCloseKey(Handle);
}
return Status;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::SetUseTempDirPerSession(BOOL bTempDirPerSession)
{
LONG Status = 0;
HKEY Handle = NULL;
/* admin only bugid294645
if(RegServerAccessCheck(KEY_ALL_ACCESS))
{
return E_ACCESSDENIED;
}
*/
if( !m_bAdmin )
{
ODS( L"CCfgComp::SetUseTempDirPerSession not admin\n" );
return E_ACCESSDENIED;
}
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
KEY_READ | KEY_SET_VALUE, &Handle );
if ( Status == ERROR_SUCCESS )
{
Status = RegSetValueEx(Handle,REG_TERMSRV_PERSESSIONTEMPDIR,
0,REG_DWORD,(const BYTE *)&bTempDirPerSession,
sizeof(bTempDirPerSession));
}
if(Handle)
{
RegCloseKey(Handle);
}
return Status;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetInternetConLic( BOOL *pbInternetConLic , PDWORD pdwStatus )
{
// shouldn't be called on post-Win2000 machines
_ASSERTE( FALSE );
UNREFERENCED_PARAMETER(pbInternetConLic);
if( pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = ERROR_NOT_SUPPORTED;
return E_FAIL;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::SetInternetConLic( BOOL bInternetConLic , PDWORD pdwStatus )
{
// shouldn't be called on post-Win2000 machines
_ASSERTE( FALSE );
UNREFERENCED_PARAMETER(bInternetConLic);
if( pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = ERROR_NOT_SUPPORTED;
return E_FAIL;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetLicensingMode( ULONG * pulMode , PDWORD pdwStatus )
{
BOOL fRet;
HRESULT hr = S_OK;
if( NULL == pulMode || pdwStatus == NULL )
{
return E_INVALIDARG;
}
HANDLE hServer = ServerLicensingOpen(NULL);
if (NULL == hServer)
{
*pdwStatus = GetLastError();
return E_FAIL;
}
fRet = ServerLicensingGetPolicy(
hServer,
pulMode
);
if (fRet)
{
*pdwStatus = ERROR_SUCCESS;
}
else
{
*pdwStatus = GetLastError();
hr = E_FAIL;
}
ServerLicensingClose(hServer);
return hr;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetLicensingModeInfo( ULONG ulMode , WCHAR **pwszName, WCHAR **pwszDescription, PDWORD pdwStatus )
{
#define MAX_LICENSING_STRING_LEN 1024
UINT nNameResource, nDescResource;
int nRet;
if( NULL == pwszName || NULL == pwszDescription || pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = ERROR_SUCCESS;
*pwszName = NULL;
*pwszDescription = NULL;
switch (ulMode)
{
case 1:
nNameResource = IDS_LICENSING_RA_NAME;
nDescResource = IDS_LICENSING_RA_DESC;
break;
case 2:
nNameResource = IDS_LICENSING_PERSEAT_NAME;
nDescResource = IDS_LICENSING_PERSEAT_DESC;
break;
case 4:
nNameResource = IDS_LICENSING_PERSESSION_NAME;
nDescResource = IDS_LICENSING_PERSESSION_DESC;
break;
default:
return E_INVALIDARG;
break;
}
*pwszName = (WCHAR *) CoTaskMemAlloc((MAX_LICENSING_STRING_LEN+1)*sizeof(WCHAR));
if (NULL == *pwszName)
{
*pdwStatus = ERROR_NOT_ENOUGH_MEMORY;
goto return_failure;
}
*pwszDescription = (WCHAR *) CoTaskMemAlloc((MAX_LICENSING_STRING_LEN+1)*sizeof(WCHAR));
if (NULL == *pwszDescription)
{
*pdwStatus = ERROR_NOT_ENOUGH_MEMORY;
goto return_failure;
}
nRet = LoadString(g_hInstance,
nNameResource,
*pwszName,
MAX_LICENSING_STRING_LEN+1);
if (0 == nRet)
{
*pdwStatus = GetLastError();
goto return_failure;
}
nRet = LoadString(g_hInstance,
nDescResource,
*pwszDescription,
MAX_LICENSING_STRING_LEN+1);
if (0 == nRet)
{
*pdwStatus = GetLastError();
goto return_failure;
}
return S_OK;
return_failure:
if (NULL != *pwszName)
{
CoTaskMemFree(*pwszName);
*pwszName = NULL;
}
if (NULL != *pwszDescription)
{
CoTaskMemFree(*pwszDescription);
*pwszDescription = NULL;
}
return E_FAIL;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetLicensingModeList( ULONG *pcModes , ULONG **prgulModes, PDWORD pdwStatus )
{
ULONG *rgulModes = NULL;
BOOL fRet;
HRESULT hr = S_OK;
if( NULL == pcModes || NULL == prgulModes || pdwStatus == NULL )
{
return E_INVALIDARG;
}
HANDLE hServer = ServerLicensingOpen(NULL);
if (NULL == hServer)
{
*pdwStatus = GetLastError();
return E_FAIL;
}
fRet = ServerLicensingGetAvailablePolicyIds(
hServer,
&rgulModes,
pcModes
);
if (fRet)
{
*pdwStatus = ERROR_SUCCESS;
*prgulModes = (ULONG *) CoTaskMemAlloc((*pcModes)*sizeof(ULONG));
if (NULL != *prgulModes)
{
memcpy(*prgulModes,rgulModes,(*pcModes)*sizeof(ULONG));
}
else
{
*pdwStatus = ERROR_NOT_ENOUGH_MEMORY;
hr = E_FAIL;
}
LocalFree(rgulModes);
}
else
{
*pdwStatus = GetLastError();
hr = E_FAIL;
}
return hr;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::SetLicensingMode( ULONG ulMode , PDWORD pdwStatus, PDWORD pdwNewStatus )
{
if( pdwStatus == NULL || pdwNewStatus == NULL )
{
return E_INVALIDARG;
}
HANDLE hServer = ServerLicensingOpen(NULL);
if (NULL == hServer)
{
*pdwStatus = GetLastError();
return E_FAIL;
}
*pdwStatus = ServerLicensingSetPolicy(hServer,
ulMode,
pdwNewStatus);
ServerLicensingClose(hServer);
return ((*pdwStatus == ERROR_SUCCESS) && (*pdwNewStatus == ERROR_SUCCESS)) ? S_OK : E_FAIL;
}
//-----------------------------------------------------------------------------
// pUserPerm == TRUE if security is relaxed
// FALSE for tight security
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::SetUserPerm( BOOL bUserPerm , PDWORD pdwStatus )
{
if( !m_bAdmin )
{
ODS( L"CFGBKEND:SetUserPerm not admin\n" );
return E_ACCESSDENIED;
}
if( pdwStatus == NULL )
{
ODS( L"CFGBKEND-SetUserPerm invalid arg\n" );
return E_INVALIDARG;
}
HKEY hKey;
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
REG_CONTROL_TSERVER,
0 ,
KEY_READ | KEY_SET_VALUE,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
DBGMSG( L"CFGBKEND-SetUserPerm RegOpenKeyEx failed 0x%x\n", *pdwStatus );
return E_FAIL;
}
*pdwStatus = RegSetValueEx( hKey ,
L"TSUserEnabled" ,
0 ,
REG_DWORD ,
( const PBYTE )&bUserPerm ,
sizeof( BOOL ) );
if( *pdwStatus != ERROR_SUCCESS )
{
DBGMSG( L"CFGBKEND-SetUserPerm RegSetValueEx failed 0x%x\n" , *pdwStatus );
return E_FAIL;
}
RegCloseKey( hKey );
return S_OK;
}
//-----------------------------------------------------------------------------
// pUserPerm == TRUE if security is relaxed
// FALSE for tight security
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetUserPerm( BOOL *pbUserPerm , PDWORD pdwStatus )
{
HKEY hKey;
DWORD dwSize = sizeof( DWORD );
DWORD dwValue;
if( pbUserPerm == NULL || pdwStatus == NULL )
{
ODS( L"CFGBKEND-GetUserPerm invalid arg\n" );
return E_INVALIDARG;
}
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
REG_CONTROL_TSERVER,
0 ,
KEY_READ ,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
DBGMSG( L"CFGBKEND-GetUserPerm RegOpenKeyEx failed 0x%x\n", *pdwStatus );
return E_FAIL;
}
*pdwStatus = RegQueryValueEx( hKey,
L"TSUserEnabled",
NULL,
NULL,
( LPBYTE )&dwValue,
&dwSize );
if( *pdwStatus != ERROR_SUCCESS )
{
DBGMSG( L"CFGBKEND-GetUserPerm RegQueryValueEx failed 0x%x\n", *pdwStatus );
// not a true failure this means the key does not exist
// set to one for relaxed security
dwValue = 1;
*pdwStatus = S_OK;
}
RegCloseKey( hKey );
*pbUserPerm = !( ( BOOL )( dwValue == 0 ) );
return S_OK;
}
#if 1
//-----------------------------------------------------------------------------
//Private function
//-----------------------------------------------------------------------------
void CCfgComp::GetPdConfig( WDNAME WdKey,WINSTATIONCONFIG2W& WsConfig)
{
LONG Status;
PDCONFIG3 PdConfig;PDCONFIG3 PdSelected;PDCONFIG3 PdConfig2;
ULONG Index = 0, Entries, ByteCount = sizeof(PDNAME);
PDNAME PdKey;
// BOOL bFound = FALSE;
ULONG ByteCount2 = sizeof(PDNAME);
ULONG Index1 = 1; // start off with one since WsConfig.Pd[0] is already populated
do
{
Entries = 1;
// outer loop searches for keys in /Wds / ( wdname ) /Tds
Status = RegPdEnumerate(NULL,WdKey,TRUE,&Index,&Entries,PdKey,&ByteCount);
if(Status != ERROR_SUCCESS)
{
break;
}
Status = RegPdQuery( NULL,WdKey,TRUE,PdKey,&PdConfig,sizeof(PdConfig),&ByteCount );
if(Status != ERROR_SUCCESS)
{
break;
}
if(0 == lstrcmpi(WsConfig.Pd[0].Create.PdName, PdConfig.Data.PdName))
{
PdSelected = PdConfig;
// bFound = TRUE;
//
ULONG Index2 = 0;
do
{
// innerloop forces the search in Wds/ (wdname )/ Pds
// Index must now be set to zero so that we get the first item
Status = RegPdEnumerate(NULL,WdKey,FALSE,&Index2,&Entries,PdKey,&ByteCount2);
if(Status != ERROR_SUCCESS)
{
break;
}
Status = RegPdQuery( NULL,WdKey,FALSE,PdKey,&PdConfig2,sizeof(PdConfig),&ByteCount2);
if(Status != ERROR_SUCCESS)
{
break;
}
for( UINT i = 0; i < PdSelected.RequiredPdCount ; i++)
{
if(0 == lstrcmpi(PdSelected.RequiredPds[i],PdConfig2.Data.PdName))
{
WsConfig.Pd[Index1].Create = PdConfig2.Data;
WsConfig.Pd[Index1].Params.SdClass = PdConfig2.Data.SdClass;
Index1++;
if(Index1 > MAX_PDCONFIG)
{
break;
}
}
}
}while(1);
}
/*
if(bFound)
{
break;
}
*/
}while(1);
return;
}
#endif
#if 0
//-----------------------------------------------------------------------------
//Private function
//-----------------------------------------------------------------------------
void CCfgComp::GetPdConfig( WDNAME WdKey,WINSTATIONCONFIG2W& WsConfig)
{
LONG Status;
PDCONFIG3 PdConfig;
PDCONFIG3 PdSelected;
PDCONFIG3 PdConfig2;
ULONG Index = 0, Entries = 1, ByteCount = sizeof(PDNAME);
PDNAME PdKey;
BOOL bFound = FALSE;
ULONG ByteCount2 = sizeof(PDNAME);
ULONG Index1 = 1;
do
{
Status = RegPdEnumerate(NULL,WdKey,TRUE,&Index,&Entries,PdKey,&ByteCount);
if(Status != ERROR_SUCCESS)
{
break;
}
// we could speed this up by enumerating only for the protocol type
/*
Status = RegPdQuery( NULL,WdKey,TRUE,PdKey,&PdConfig,sizeof(PdConfig),&ByteCount );
if(Status != ERROR_SUCCESS)
{
break;
}
*/
DBGMSG( L"CFGBKEND: PdKey is at first %ws\n", PdKey );
DBGMSG( L"CFGBKEND: WsConfig.Pd[0].Create.PdName is %ws\n", WsConfig.Pd[0].Create.PdName );
if( 0 == lstrcmpi(WsConfig.Pd[0].Create.PdName, PdKey ) ) //PdConfig.Data.PdName))
{
Status = RegPdQuery( NULL,WdKey,TRUE,PdKey,&PdConfig,sizeof(PdConfig),&ByteCount );
if(Status != ERROR_SUCCESS)
{
break;
}
PdSelected = PdConfig;
bFound = TRUE;
// why didn't we reset Index to zero?
Index = 0;
// why didn't we reset Entries back to one?
Entries = 1;
do
{
DBGMSG( L"CFGBKEND: WdKey is %ws\n" , WdKey );
DBGMSG( L"CFGBKEND: PdKey before Enum is %ws\n", PdKey );
Status = RegPdEnumerate(NULL,WdKey,FALSE,&Index,&Entries,PdKey,&ByteCount2);
if(Status != ERROR_SUCCESS)
{
break;
}
DBGMSG( L"CFGBKEND: PdKey is %ws\n", PdKey );
Status = RegPdQuery( NULL,WdKey,FALSE,PdKey,&PdConfig2,sizeof(PdConfig),&ByteCount2);
if(Status != ERROR_SUCCESS)
{
ODS(L"RegPdQuery failed\n" );
break;
}
ODS(L"RegPdQuery ok\n" );
for( UINT i = 0; i < PdSelected.RequiredPdCount ; i++)
{
DBGMSG( L"CFGBKEND: Required pd name %s\n", PdConfig2.Data.PdName );
DBGMSG( L"CFGBKEND: ReqName is list is %s\n", PdSelected.RequiredPds[i] );
if( 0 == lstrcmpi( PdSelected.RequiredPds[i] , PdConfig2.Data.PdName ) )
{
DBGMSG( L"CFGBKEND: Copying pdconfig2 for pd name %s\n" , PdConfig2.Data.PdName );
WsConfig.Pd[Index1].Create = PdConfig2.Data;
WsConfig.Pd[Index1].Params.SdClass = PdConfig2.Data.SdClass;
Index1++;
if(Index1 > MAX_PDCONFIG)
{
break;
}
}
}
}while(1);
}
if(bFound)
{
break;
}
}while(1);
return;
}
#endif
#if 0 // removed for final
//-----------------------------------------------------------------------------
//Private function
//-----------------------------------------------------------------------------
BOOL CCfgComp::CompareSD(PSECURITY_DESCRIPTOR pSd1,PSECURITY_DESCRIPTOR pSd2)
{
DWORD dwErr;
ULONG index1 = 0;
//int index2 = 0;
ULONG cAce1 = 0;
EXPLICIT_ACCESS *pAce1 = NULL;
ULONG cAce2 = 0;
EXPLICIT_ACCESS *pAce2 = NULL;
BOOL bMatch = TRUE;
if (!IsValidSecurityDescriptor(pSd1) || !IsValidSecurityDescriptor(pSd2))
{
return FALSE;
}
dwErr = LookupSecurityDescriptorParts(
NULL,
NULL,
&cAce1,
&pAce1,
NULL,
NULL,
pSd1);
if (ERROR_SUCCESS != dwErr)
{
return FALSE;
}
dwErr = LookupSecurityDescriptorParts(
NULL,
NULL,
&cAce2,
&pAce2,
NULL,
NULL,
pSd2);
if (ERROR_SUCCESS != dwErr)
{
bMatch = FALSE;
goto cleanup;
}
if(cAce1 != cAce2)
{
bMatch = FALSE;
goto cleanup;
}
for(index1 = 0; index1 < cAce1; index1++)
{
//for(index2 = 0; index2 < cAce1; index2++)
{
if ( _tcscmp(GetTrusteeName(&pAce1[index1].Trustee),GetTrusteeName(&pAce2[index1].Trustee)) ||
(pAce1[index1].grfAccessPermissions != pAce2[index1].grfAccessPermissions)||
(pAce1[index1].grfAccessMode != pAce2[index1].grfAccessMode ))
{
bMatch = FALSE;
break;
}
}
}
cleanup:
if(pAce1)
{
LocalFree(pAce1);
}
if(pAce2)
{
LocalFree(pAce2);
}
return bMatch;
}
#endif
//-----------------------------------------------------------------------------
BOOL CCfgComp::RegServerAccessCheck(REGSAM samDesired)
{
LONG Status = 0;
HKEY Handle = NULL;
/*
* Attempt to open the registry
* at the requested access level.
*/
if ( (Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
samDesired, &Handle )) == ERROR_SUCCESS )
{
RegCloseKey( Handle );
}
return( Status );
}
#if 0 // removed for final release
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetDefaultSecurity(ULONG * pDefaultSecurity)
{
HRESULT hResult = S_OK;
//Check the parameters
if(NULL == pDefaultSecurity)
{
return E_INVALIDARG;
}
*pDefaultSecurity = 0;
PSECURITY_DESCRIPTOR pDefaultDescriptor = NULL;
PSECURITY_DESCRIPTOR pTempDescriptor = NULL;
pDefaultDescriptor = ReadSecurityDescriptor(0);
if(NULL == pDefaultDescriptor)
{
*pDefaultSecurity = 0;
return hResult;
}
for(int i = 0; i < NUM_DEFAULT_SECURITY; i++)
{
pTempDescriptor = ReadSecurityDescriptor(i+1);
if(NULL == pTempDescriptor)
{
continue;
}
if(TRUE == CompareSD(pDefaultDescriptor,pTempDescriptor))
{
*pDefaultSecurity = i+1;
break;
}
else
{
LocalFree(pTempDescriptor);
pTempDescriptor = NULL;
}
}
if(pDefaultDescriptor)
{
LocalFree(pDefaultDescriptor);
}
if(pTempDescriptor)
{
LocalFree(pTempDescriptor);
}
return hResult;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::SetDefaultSecurity(ULONG Offset)
{
HRESULT hResult;
if( !m_bAdmin )
{
return E_ACCESSDENIED;
}
if(0 == Offset)
{
return E_INVALIDARG;
}
PSECURITY_DESCRIPTOR pTempDescriptor = NULL;
pTempDescriptor = ReadSecurityDescriptor(Offset);
if(NULL == pTempDescriptor)
{
return E_FAIL;
}
hResult = SetDefaultSecurityDescriptor( pTempDescriptor );
if( pTempDescriptor != NULL )
{
LocalFree(pTempDescriptor);
}
return hResult;
}
//-----------------------------------------------------------------------------
PSECURITY_DESCRIPTOR CCfgComp::ReadSecurityDescriptor(ULONG index)
{
PBYTE pData = NULL;
TCHAR * pValue = NULL;
HLOCAL hLocal;
HKEY Handle = NULL;
DWORD ValueType = 0;
DWORD ValueSize=0;
LONG Status = 0;
switch(index)
{
case 0:
pValue = REG_DEF_SECURITY;
break;
case 1:
pValue = REG_REMOTE_SECURITY;
break;
case 2:
pValue = REG_APPL_SECURITY;
break;
case 3:
pValue = REG_ANON_SECURITY;
break;
default:
return NULL;
}
if(NULL == pValue)
{
return NULL;
}
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,
KEY_READ, &Handle );
if ( Status == ERROR_SUCCESS )
{
Status = RegQueryValueEx( Handle,
pValue,
NULL,
&ValueType,
NULL,
&ValueSize );
if(Status != ERROR_SUCCESS)
{
return NULL;
}
hLocal = LocalAlloc(LMEM_FIXED, ValueSize);
if(NULL == hLocal)
{
return pData;
}
pData = (LPBYTE)LocalLock(hLocal);
if(NULL == pData)
{
return NULL;
}
Status = RegQueryValueEx( Handle,
pValue,
NULL,
&ValueType,
pData,
&ValueSize );
if(Status != ERROR_SUCCESS)
{
RegCloseKey(Handle);
LocalFree(pData);
return NULL;
}
}
if(Handle)
{
RegCloseKey(Handle);
}
return (PSECURITY_DESCRIPTOR)pData;
}
//-----------------------------------------------------------------------------
HRESULT CCfgComp::SetDefaultSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurity)
{
if(NULL == pSecurity)
{
return E_INVALIDARG;
}
if(ValidateSecurityDescriptor(pSecurity)!=ERROR_SUCCESS)
{
return E_INVALIDARG;
}
HKEY Handle = NULL;
LONG Status = 0;
ULONG Size = 0;
Size = GetSecurityDescriptorLength(pSecurity);
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,
KEY_READ |KEY_SET_VALUE , &Handle );
if ( Status == ERROR_SUCCESS )
{
Status = RegSetValueEx(Handle,
REG_DEF_SECURITY,
0,
REG_BINARY,
(BYTE *)pSecurity,
Size);
if(Status != ERROR_SUCCESS)
{
return E_FAIL;
}
}
if( Handle )
{
RegCloseKey(Handle);
}
if( !_WinStationReInitializeSecurity( SERVERNAME_CURRENT ) )
{
ODS( L"CFGBKEND: _WinStationReInitializeSecurity failed\n" );
return E_FAIL;
}
return S_OK;
}
#endif //
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::SetActiveDesktopState( /* in */ BOOL bActivate , /* out */ PDWORD pdwStatus )
{
// HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoActiveDesktop
if( !m_bAdmin )
{
ODS( L"CFGBKEND : SetActiveDesktopState caller does not have admin rights\n" );
*pdwStatus = ERROR_ACCESS_DENIED;
return E_ACCESSDENIED;
}
// try to open key
HKEY hKey;
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer" ) ,
0,
KEY_READ | KEY_WRITE ,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
if( bActivate )
{
ODS( L"CFGBKEND : SetActiveDesktopState -- RegOpenEx unable to open key\n" );
return E_FAIL;
}
else
{
// the key doesn't exist but we were trying to disable anyway donot pro
// we should assert( 0 ) here because we should not be disabling what
// could not have been enabled
return S_FALSE;
}
}
if( !bActivate )
{
DWORD dwValue = 1;
*pdwStatus = RegSetValueEx( hKey ,
TEXT( "NoActiveDesktop" ),
NULL,
REG_DWORD,
( LPBYTE )&dwValue ,
sizeof( DWORD ) );
}
else
{
*pdwStatus = RegDeleteValue( hKey , TEXT( "NoActiveDesktop" ) );
}
RegCloseKey( hKey );
if( *pdwStatus != NO_ERROR )
{
ODS( L"CFGBKEND : SetActiveDesktopState returned error\n" );
return E_FAIL;
}
return S_OK;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetActiveDesktopState( /* out */ PBOOL pbActive , /* out */PDWORD pdwStatus)
{
if( pbActive == NULL )
{
ODS( L"CFGBKEND : GetActiveDesktop -- invaild arg\n" );
return E_INVALIDARG;
}
// try to open key
HKEY hKey;
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer" ) ,
0,
KEY_READ ,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetActiveDesktopState -- RegOpenEx unable to open key\n" );
return E_FAIL;
}
DWORD dwData = 0;
DWORD dwSize = sizeof( DWORD );
*pdwStatus = RegQueryValueEx( hKey ,
TEXT( "NoActiveDesktop" ) ,
NULL ,
NULL ,
( LPBYTE )&dwData ,
&dwSize );
// Status of this key is enabled if the key does not exist
if( *pdwStatus == ERROR_SUCCESS )
{
*pbActive = !( BOOL )dwData;
}
RegCloseKey( hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
DBGMSG( L"CFGBKEND : GetActiveDesktopState -- error ret 0x%x\n" , *pdwStatus );
if( *pdwStatus == ERROR_FILE_NOT_FOUND )
{
*pbActive = TRUE;
return S_FALSE;
}
return E_FAIL;
}
return S_OK;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetTermSrvMode( /* out */ PDWORD pdwMode , PDWORD pdwStatus )
{
ODS( L"CFGBKEND : GetTermSrvMode\n" );
if( pdwMode == NULL || pdwStatus == NULL )
{
return E_INVALIDARG;
}
HKEY hKey;
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
REG_CONTROL_TSERVER,
0,
KEY_READ ,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetTermSrvMode -- RegOpenEx unable to open key\n" );
return E_FAIL;
}
DWORD dwData = 0;
DWORD dwSize = sizeof( DWORD );
*pdwStatus = RegQueryValueEx( hKey ,
TEXT( "TSAppCompat" ) ,
NULL ,
NULL ,
( LPBYTE )&dwData ,
&dwSize );
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetTermSrvMode -- RegQueryValueEx failed\n" );
*pdwMode = 1; // for application server
}
else
{
*pdwMode = dwData;
}
RegCloseKey( hKey );
return S_OK;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetSalemHelpMode( BOOL *pVal, PDWORD pdwStatus)
{
HKEY hKey;
ODS( L"CFGBKEND : GetSalemHelpMode\n" );
if( pVal == NULL || pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
REG_CONTROL_GETHELP,
0,
KEY_READ ,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetSalemHelpMode -- RegOpenEx unable to open key\n" );
*pVal = 1; // default to help is available
// don't want to fail caller so return S_OK
return S_OK;
}
DWORD dwData = 0;
DWORD dwSize = sizeof( DWORD );
*pdwStatus = RegQueryValueEx( hKey ,
POLICY_TS_REMDSK_ALLOWTOGETHELP,
NULL ,
NULL ,
( LPBYTE )&dwData ,
&dwSize );
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetSalemHelpMode -- RegQueryValueEx failed\n" );
*pVal = 1; // assume help is available
}
else
{
*pVal = dwData;
}
RegCloseKey( hKey );
return S_OK;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::SetSalemHelpMode( BOOL val, PDWORD pdwStatus )
{
HKEY hKey;
ODS( L"CFGBKEND : SetSalemHelpMode\n" );
if( pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
REG_CONTROL_GETHELP,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
);
if( ERROR_SUCCESS != *pdwStatus )
{
ODS( L"CFGBKEND : SetSalemHelpMode -- RegCreateKeyEx failed\n" );
return E_FAIL;
}
DWORD dwValue;
dwValue = (val) ? 1 : 0;
*pdwStatus = RegSetValueEx(
hKey,
POLICY_TS_REMDSK_ALLOWTOGETHELP,
0,
REG_DWORD,
(LPBYTE) &dwValue,
sizeof(DWORD)
);
RegCloseKey(hKey);
return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
}
//-----------------------------------------------------------------------------
HRESULT CCfgComp::GetSingleSessionState( BOOL *pVal, PDWORD pdwStatus )
{
HKEY hKey;
TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server" );
ODS( L"CFGBKEND : GetSingleSessionState\n" );
if( pVal == NULL || pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
tchRegPath ,
0,
KEY_READ ,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetSingleSessionState -- RegOpenKeyEx unable to open key\n" );
return S_OK;
}
DWORD dwData = 0;
DWORD dwSize = sizeof( DWORD );
*pdwStatus = RegQueryValueEx( hKey ,
L"fSingleSessionPerUser",
NULL ,
NULL ,
( LPBYTE )&dwData ,
&dwSize );
if( *pdwStatus == ERROR_SUCCESS )
{
*pVal = dwData;
}
else
{
ODS( L"CFGBKEND : GetSingleSessionState -- RegQueryValueEx failed\n" );
}
RegCloseKey( hKey );
return S_OK;
}
//----------------------------------------------------------------------------
HRESULT CCfgComp::SetSingleSessionState( BOOL val, PDWORD pdwStatus )
{
HKEY hKey;
TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server" );
ODS( L"CFGBKEND : SetSingleSessionState\n" );
if( pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
tchRegPath,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
);
if( ERROR_SUCCESS != *pdwStatus )
{
ODS( L"CFGBKEND : SetSingleSessionState -- RegCreateKeyEx failed\n" );
if (ERROR_ACCESS_DENIED == *pdwStatus)
return E_ACCESSDENIED;
else
return E_FAIL;
}
DWORD dwValue;
dwValue = (val) ? 1 : 0;
*pdwStatus = RegSetValueEx(
hKey,
L"fSingleSessionPerUser",
0,
REG_DWORD,
(LPBYTE) &dwValue,
sizeof(DWORD)
);
RegCloseKey(hKey);
return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
}
//-----------------------------------------------------------------------------
HRESULT CCfgComp::GetColorDepth ( PWINSTATIONNAME pWs, BOOL *pVal, PDWORD pdwStatus )
{
HKEY hKey;
TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server\\winstations\\" );
if(pWs != NULL)
{
lstrcat( tchRegPath , pWs );
}
ODS( L"CFGBKEND : GetColorDepth\n" );
if( pVal == NULL || pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
tchRegPath ,
0,
KEY_READ ,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetColorDepth -- RegOpenKeyEx unable to open key\n" );
return E_FAIL;
}
DWORD dwData = 0;
DWORD dwSize = sizeof( DWORD );
*pdwStatus = RegQueryValueEx( hKey ,
L"fInheritColorDepth",
NULL ,
NULL ,
( LPBYTE )&dwData ,
&dwSize );
if( *pdwStatus == ERROR_SUCCESS )
{
*pVal = dwData;
}
else
{
ODS( L"CFGBKEND : GetColorDepth -- RegQueryValueEx failed\n" );
}
RegCloseKey( hKey );
return S_OK;
}
//----------------------------------------------------------------------------
HRESULT CCfgComp::SetColorDepth( PWINSTATIONNAME pWs, BOOL val, PDWORD pdwStatus )
{
HKEY hKey;
TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server\\winstations\\" );
if(pWs != NULL)
{
lstrcat( tchRegPath , pWs );
}
ODS( L"CFGBKEND : SetColorDepth\n" );
if( pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
tchRegPath ,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
);
if( ERROR_SUCCESS != *pdwStatus )
{
ODS( L"CFGBKEND : SetColorDepth -- RegCreateKeyEx failed\n" );
return E_FAIL;
}
DWORD dwValue;
dwValue = (val) ? 1 : 0;
*pdwStatus = RegSetValueEx(
hKey,
L"fInheritColorDepth",
0,
REG_DWORD,
(LPBYTE) &dwValue,
sizeof(DWORD)
);
RegCloseKey(hKey);
return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
}
//-----------------------------------------------------------------------------
HRESULT CCfgComp::GetKeepAliveTimeout ( PWINSTATIONNAME pWs, BOOL *pVal, PDWORD pdwStatus )
{
HKEY hKey;
TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server\\winstations\\" );
if(pWs != NULL)
{
lstrcat( tchRegPath , pWs );
}
ODS( L"CFGBKEND : GetKeepAliveTimeout\n" );
if( pVal == NULL || pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
tchRegPath ,
0,
KEY_READ ,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetKeepAliveTimeout -- RegOpenKeyEx unable to open key\n" );
return E_FAIL;
}
DWORD dwData = 0;
DWORD dwSize = sizeof( DWORD );
*pdwStatus = RegQueryValueEx( hKey ,
L"KeepAliveTimeout",
NULL ,
NULL ,
( LPBYTE )&dwData ,
&dwSize );
if( *pdwStatus == ERROR_SUCCESS )
{
*pVal = dwData;
}
else
{
ODS( L"CFGBKEND : GetKeepAliveTimeout -- RegQueryValueEx failed\n" );
}
RegCloseKey( hKey );
return S_OK;
}
//----------------------------------------------------------------------------
HRESULT CCfgComp::SetKeepAliveTimeout( PWINSTATIONNAME pWs, BOOL val, PDWORD pdwStatus )
{
HKEY hKey;
TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server\\winstations\\" );
if(pWs != NULL)
{
lstrcat( tchRegPath , pWs );
}
ODS( L"CFGBKEND : SetKeepAliveTimeout\n" );
if( pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
tchRegPath ,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
);
if( ERROR_SUCCESS != *pdwStatus )
{
ODS( L"CFGBKEND : SetKeepAliveTimeout -- RegCreateKeyEx failed\n" );
return E_FAIL;
}
DWORD dwValue;
dwValue = (val) ? 1 : 0;
*pdwStatus = RegSetValueEx(
hKey,
L"KeepAliveTimeout",
0,
REG_DWORD,
(LPBYTE) &dwValue,
sizeof(DWORD)
);
RegCloseKey(hKey);
return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
}
//-----------------------------------------------------------------------------
HRESULT CCfgComp::GetDenyTSConnections ( BOOL *pVal, PDWORD pdwStatus )
{
HKEY hKey;
ODS( L"CFGBKEND : GetDenyTSConnections\n" );
if( pVal == NULL || pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
REG_CONTROL_TSERVER ,
0,
KEY_READ ,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetDenyTSConnections -- RegOpenKeyEx unable to open key\n" );
return S_OK;
}
DWORD dwData = 0;
DWORD dwSize = sizeof( DWORD );
*pdwStatus = RegQueryValueEx( hKey ,
L"fDenyTSConnections",
NULL ,
NULL ,
( LPBYTE )&dwData ,
&dwSize );
if( *pdwStatus == ERROR_SUCCESS )
{
*pVal = dwData;
}
else
{
ODS( L"CFGBKEND : GetDenyTSConnections -- RegQueryValueEx failed\n" );
}
RegCloseKey( hKey );
return S_OK;
}
//----------------------------------------------------------------------------
HRESULT CCfgComp::SetDenyTSConnections( BOOL val, PDWORD pdwStatus )
{
HKEY hKey;
ODS( L"CFGBKEND : SetDenyTSConnections\n" );
if( pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
REG_CONTROL_TSERVER ,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
);
if( ERROR_SUCCESS != *pdwStatus )
{
ODS( L"CFGBKEND : SetDenyTSConnections -- RegCreateKeyEx failed\n" );
return E_FAIL;
}
DWORD dwValue;
dwValue = (val) ? 1 : 0;
*pdwStatus = RegSetValueEx(
hKey,
L"fDenyTSConnections",
0,
REG_DWORD,
(LPBYTE) &dwValue,
sizeof(DWORD)
);
RegCloseKey(hKey);
return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
}
//-----------------------------------------------------------------------------
HRESULT CCfgComp::GetProfilePath ( BSTR *pbstrVal, PDWORD pdwStatus )
{
HKEY hKey;
DWORD dwSize = 0;
static TCHAR tchData[ MAX_PATH ] ;
dwSize = sizeof( tchData);
ODS( L"CFGBKEND : GetProfilePath\n" );
if( pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
REG_CONTROL_TSERVER ,
0,
KEY_READ ,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetProfilePath -- RegOpenKeyEx unable to open key\n" );
return E_FAIL;
}
dwSize = sizeof( tchData );
*pdwStatus = RegQueryValueEx( hKey ,
L"WFProfilePath",
NULL ,
NULL ,
(LPBYTE)&tchData ,
&dwSize );
if( *pdwStatus == ERROR_SUCCESS )
{
*pbstrVal = SysAllocString (tchData);
}
else
{
ODS( L"CFGBKEND : GetProfilePath -- RegQueryValueEx failed\n" );
}
RegCloseKey( hKey );
return S_OK;
}
//----------------------------------------------------------------------------
HRESULT CCfgComp::SetProfilePath( BSTR bstrVal, PDWORD pdwStatus )
{
HKEY hKey;
TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server" );
ODS( L"CFGBKEND : SetProfilePath\n" );
if( pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
tchRegPath,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
);
if( ERROR_SUCCESS != *pdwStatus )
{
ODS( L"CFGBKEND : SetProfilePath -- RegCreateKeyEx failed\n" );
return E_FAIL;
}
*pdwStatus = RegSetValueEx(
hKey,
L"WFProfilePath",
0,
REG_SZ,
( LPBYTE const )(bstrVal) ,
(lstrlen(bstrVal)+1)*sizeof(WCHAR)
);
ODS( L"CFGBKEND : SetProfilePath -- RegCreateKeyEx failed\n" );
if(bstrVal != NULL)
{
SysFreeString(bstrVal);
}
RegCloseKey(hKey);
return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
}
//-----------------------------------------------------------------------------
HRESULT CCfgComp::GetHomeDir ( BSTR *pbstrVal, PDWORD pdwStatus )
{
HKEY hKey;
DWORD dwSize = 0;
static TCHAR tchData[ MAX_PATH ] ;
dwSize = sizeof( tchData);
ODS( L"CFGBKEND : GetHomeDir\n" );
if( pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
REG_CONTROL_TSERVER ,
0,
KEY_READ ,
&hKey );
if( *pdwStatus != ERROR_SUCCESS )
{
ODS( L"CFGBKEND : GetProfilePath -- RegOpenKeyEx unable to open key\n" );
return E_FAIL;
}
*pdwStatus = RegQueryValueEx( hKey ,
L"WFHomeDir",
NULL ,
NULL ,
(LPBYTE)&tchData ,
&dwSize );
if( *pdwStatus == ERROR_SUCCESS )
{
*pbstrVal = SysAllocString (tchData);
}
else
{
ODS( L"CFGBKEND : GetHomeDir -- RegQueryValueEx failed\n" );
}
RegCloseKey( hKey );
return S_OK;
}
//----------------------------------------------------------------------------
HRESULT CCfgComp::SetHomeDir( BSTR bstrVal, PDWORD pdwStatus )
{
HKEY hKey = NULL;
ODS( L"CFGBKEND : SetHomeDir\n" );
if( pdwStatus == NULL )
{
return E_INVALIDARG;
}
*pdwStatus = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
REG_CONTROL_TSERVER ,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
);
if( ERROR_SUCCESS != *pdwStatus )
{
ODS( L"CFGBKEND : SetHomeDir -- RegCreateKeyEx failed\n" );
return E_FAIL;
}
*pdwStatus = RegSetValueEx(
hKey,
L"WFHomeDir",
0,
REG_SZ,
( LPBYTE const )(bstrVal) ,
(lstrlen(bstrVal)+1)*sizeof(WCHAR)
);
if(bstrVal != NULL)
{
SysFreeString(bstrVal);
}
RegCloseKey(hKey);
return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::GetWdKey( WCHAR *wdname , WCHAR *wdkey )
{
if( wdname == NULL || wdkey == NULL )
{
return E_INVALIDARG;
}
PWD pWD = GetWdObject( wdname );
if(NULL == pWD)
{
return E_FAIL;
}
lstrcpy( wdkey , pWD->wdKey );
return S_OK;
}
/*=-----------------------------------------------------------------------------
pwszWinstaName -- name of winstation to modify.
pwszAccountName -- is the netbios name of the user we want to modify.
dwMask -- winstation specific access.
fDel -- TRUE to delete all DACL or SACL for the specifed
account if it exist, FALSE to add entry.
fAllow -- TRUE to allow, FALSE to deny, parameter ignored if
fDel is set to TRUE
fNew -- TRUE removes all existing entries for this account
FALSE no action taken, parameter ignored if fDel
is set to TRUE.
fAuditing -- TRUE, modify SACL, FALSE modify DACL.
pdwStatus -- status of operation
Remark:
fDel fNew Operation
------- ------- ------------------------------------------
TRUE ignored Delete all entries for the specified user.
FALSE TRUE Delete all entries then add allow or deny
entry for the specified user.
FALSE FALSE Add allow or deny entry for the specified user,
no modify to existing entries.
=----------------------------------------------------------------------------*/
STDMETHODIMP CCfgComp::ModifyUserAccess( WCHAR *pwszWinstaName ,
WCHAR *pwszAccountName ,
DWORD dwMask ,
BOOL fDel ,
BOOL fAllow ,
BOOL fNew ,
BOOL fAuditing ,
PDWORD pdwStatus )
{
return ModifyWinstationSecurity( FALSE,
pwszWinstaName,
pwszAccountName,
dwMask,
fDel,
fAllow,
fNew,
fAuditing,
pdwStatus
);
}
//-----------------------------------------------------------------------------
STDMETHODIMP CCfgComp::ModifyDefaultSecurity( WCHAR *pwszWinstaName ,
WCHAR *pwszAccountName ,
DWORD dwMask ,
BOOL fDel ,
BOOL fAllow ,
BOOL fAuditing ,
PDWORD pdwStatus )
{
HRESULT hr = S_OK;
if( NULL == pwszWinstaName || 0 == lstrlen(pwszWinstaName) )
{
for( DWORD i = 0; i < g_numDefaultSecurity && SUCCEEDED(hr) ; i++ )
{
hr = ModifyWinstationSecurity(
TRUE,
g_pszDefaultSecurity[i],
pwszAccountName,
dwMask,
fDel,
fAllow,
FALSE, // never recreate default security
fAuditing,
pdwStatus
);
}
}
else
{
hr = ModifyWinstationSecurity(
TRUE,
pwszWinstaName,
pwszAccountName,
dwMask,
fDel,
fAllow,
FALSE, // never recreate default security
fAuditing,
pdwStatus
);
}
return hr;
}
DWORD
CCfgComp::GetUserSid(
LPCTSTR pwszAccountName,
PSID* ppUserSid
)
/*++
Abstract:
Retrieve User SID for user account.
Parameter:
pwszAccountName : Name of the account to retrieve SID.
ppUserSid : Pointer to PSID to receive SID for the account.
Returns:
ERROR_SUCCESS or Error Code
Note :
Retrieve only local account or domain account.
--*/
{
DWORD cbSid = 0;
DWORD cbDomain = 0;
PSID pSID = NULL;
LPTSTR pszDomain = NULL;
BOOL bStatus;
DWORD dwStatus = ERROR_SUCCESS;
SID_NAME_USE seUse;
bStatus = LookupAccountName(
NULL ,
pwszAccountName ,
NULL ,
&cbSid,
NULL ,
&cbDomain,
&seUse);
if( FALSE == bStatus )
{
dwStatus = GetLastError();
if( ERROR_INSUFFICIENT_BUFFER != dwStatus )
{
goto CLEANUPANDEXIT;
}
}
dwStatus = ERROR_SUCCESS;
pSID = ( PSID )LocalAlloc( LMEM_FIXED , cbSid );
pszDomain = ( LPTSTR )LocalAlloc( LMEM_FIXED , sizeof(WCHAR) * (cbDomain + 1) );
if( pSID == NULL || pszDomain == NULL )
{
dwStatus = GetLastError();
goto CLEANUPANDEXIT;
}
if( !LookupAccountName( NULL ,
pwszAccountName ,
pSID ,
&cbSid,
pszDomain ,
&cbDomain,
&seUse ) )
{
dwStatus = GetLastError();
}
else
{
*ppUserSid = pSID;
pSID = NULL;
}
CLEANUPANDEXIT:
if( NULL != pszDomain )
{
LocalFree( pszDomain );
}
if( NULL != pSID )
{
LocalFree( pSID );
}
return dwStatus;
}
DWORD
CCfgComp::RemoveUserEntriesInACL(
LPCTSTR pszUserName,
PACL pAcl,
PACL* ppNewAcl
)
/*++
Abstract :
Remote all DACL or SACL from ACL for the account.
Parameters:
pszUserName : Name of the user account to be removed from ACL list.
pAcl : Pointer to ACL.
ppNewAcl : Pointer to PACL to receive resulting ACL.
Returns:
ERROR_SUCCESS
ERROR_FILE_NOT_FOUND All ACL are flagged as INHERITED_ACE.
other error code
--*/
{
DWORD dwStatus;
DWORD dwNumNewEntries = 0;
PSID pUserSid = NULL;
ULONG cbExplicitEntries = 0;
PEXPLICIT_ACCESS prgExplicitEntries = NULL;
PEXPLICIT_ACCESS prgExplicitEntriesNew = NULL;
//
// We can use this funtion since we don't use INHERITED_ACE
//
dwStatus = GetExplicitEntriesFromAcl(
pAcl ,
&cbExplicitEntries,
&prgExplicitEntries
);
if( ERROR_SUCCESS != dwStatus )
{
goto CLEANUPANDEXIT;
}
if( 0 == cbExplicitEntries )
{
dwStatus = ERROR_FILE_NOT_FOUND;
goto CLEANUPANDEXIT;
}
dwStatus = GetUserSid( pszUserName, &pUserSid );
if( ERROR_SUCCESS != dwStatus )
{
goto CLEANUPANDEXIT;
}
// create a big enough buffer
prgExplicitEntriesNew = ( PEXPLICIT_ACCESS )LocalAlloc( LMEM_FIXED , sizeof( EXPLICIT_ACCESS ) * cbExplicitEntries );
if( prgExplicitEntriesNew == NULL )
{
dwStatus = GetLastError();
goto CLEANUPANDEXIT;
}
for( ULONG idx = 0 ; idx < cbExplicitEntries; idx++ )
{
if( prgExplicitEntries[ idx ].Trustee.TrusteeForm == TRUSTEE_IS_SID )
{
if( !EqualSid( pUserSid, prgExplicitEntries[ idx ].Trustee.ptstrName ) )
{
// this one we can keep
// copy over EXPLICIT_ACCESS
prgExplicitEntriesNew[ dwNumNewEntries ].grfAccessPermissions = prgExplicitEntries[ idx ].grfAccessPermissions;
prgExplicitEntriesNew[ dwNumNewEntries ].grfAccessMode = prgExplicitEntries[ idx ].grfAccessMode;
prgExplicitEntriesNew[ dwNumNewEntries ].grfInheritance = prgExplicitEntries[ idx ].grfInheritance;
BuildTrusteeWithSid( &prgExplicitEntriesNew[ dwNumNewEntries ].Trustee , prgExplicitEntries[ idx ].Trustee.ptstrName );
dwNumNewEntries++;
}
}
}
dwStatus = SetEntriesInAcl(
dwNumNewEntries,
prgExplicitEntriesNew,
NULL,
ppNewAcl
);
CLEANUPANDEXIT:
if( pUserSid != NULL )
{
LocalFree( pUserSid );
}
if( prgExplicitEntriesNew != NULL )
{
LocalFree( prgExplicitEntriesNew );
}
if( NULL != prgExplicitEntries )
{
LocalFree( prgExplicitEntries );
}
return dwStatus;
}
HRESULT
CCfgComp::ModifyWinstationSecurity(
BOOL bDefaultSecurity,
WCHAR *pwszWinstaName ,
WCHAR *pwszAccountName ,
DWORD dwMask ,
BOOL fDel , // delete existing ACL entries for user passed in
BOOL fAllow , // Grant/Deny ACL
BOOL fNew , // New entries
BOOL fAuditing ,
PDWORD pdwStatus
)
/*++
Abstract :
Modify specific winstation security.
Parameters:
bDefaultSecurity : TRUE to modify default security, FALSE otherwise. Current
default security are ConsoleSecurity and DefaultSecurity.
pwszWinstaName : Name of the winstation or default security to be modified, if
bDefaultSecurity is TRUE, valid winstation name are ConsoleSecurity
and DefaultSecurity.
pwszAccountName : is the netbios name of the user we want to modify.
dwMask : winstation specific access.
fDel : TRUE to delete all DACL or SACL for the specifed
account if it exist, FALSE to add entry.
fAllow : TRUE to allow, FALSE to deny, parameter ignored if
fDel is set to TRUE
fNew : TRUE removes all existing entries for this account
FALSE no action taken, parameter ignored if fDel
is set to TRUE.
fAuditing : TRUE, modify SACL, FALSE modify DACL.
pdwStatus : Return status of operation
Returns:
S_OK, E_FAIL, E_INVALIDARG, win32 status code is returned via *pdwStatus.
Remark:
fDel fNew Operation
------- ------- ------------------------------------------
TRUE ignored Delete all entries for the specified user.
FALSE TRUE Delete all entries then add allow or deny
entry for the specified user.
FALSE FALSE Add allow or deny entry for the specified user,
no modify to existing entries.
--*/
{
EXPLICIT_ACCESS ea;
HRESULT hr;
PACL pNewAcl = NULL;
PACL pAcl = NULL;
BOOL bOwnerDefaulted = FALSE;
BOOL bDaclDefaulted = FALSE;
BOOL bDaclPresent = FALSE;
BOOL bSaclPresent = FALSE;
BOOL bSaclDefaulted = FALSE;
PSECURITY_DESCRIPTOR pSD;
LONG lSize = 0;
DWORD dwSDLen = 0;
PACL pSacl = NULL;
PACL pDacl = NULL;
PSECURITY_DESCRIPTOR pNewSD = NULL;
if( pwszAccountName == NULL || pdwStatus == NULL )
{
ODS( L"CCfgComp::ModifyUserAccess -- invalid arg\n" );
return E_INVALIDARG;
}
*pdwStatus = 0;
if( TRUE == bDefaultSecurity )
{
if( FALSE == ValidDefaultSecurity( pwszWinstaName ) )
{
*pdwStatus = ERROR_INVALID_PARAMETER;
return E_INVALIDARG;
}
}
else if( pwszWinstaName == NULL )
{
*pdwStatus = ERROR_INVALID_PARAMETER;
return E_INVALIDARG;
}
hr = GetWinStationSecurity( bDefaultSecurity, pwszWinstaName , &pSD );
if( FAILED( hr ) )
{
//Try Getting Default Security Descriptor
hr = GetWinStationSecurity(TRUE, NULL, &pSD);
}
if( SUCCEEDED( hr ) )
{
if( pSD != NULL )
{
lSize = GetSecurityDescriptorLength(pSD);
}
else
{
hr = E_FAIL;
*pdwStatus = ERROR_INTERNAL_ERROR;
}
}
else
{
*pdwStatus = ERROR_INTERNAL_ERROR;
return hr;
}
if( fAuditing )
{
if( pSD != NULL && !GetSecurityDescriptorSacl( pSD ,
&bSaclPresent,
&pAcl,
&bSaclDefaulted ) )
{
*pdwStatus = GetLastError( ) ;
hr = E_FAIL;
}
}
else
{
if( pSD != NULL && !GetSecurityDescriptorDacl( pSD ,
&bDaclPresent,
&pAcl,
&bDaclDefaulted ) )
{
*pdwStatus = GetLastError( ) ;
hr = E_FAIL;
}
}
// remove all entries for this user
if( SUCCEEDED( hr ) )
{
if( fNew || fDel )
{
// SetEntriesInAcl() does not remove DENY_ACCESS ACL,
// pAcl will point to DACL or SACL depends on fAuditing
// flag.
*pdwStatus = RemoveUserEntriesInACL(
pwszAccountName,
pAcl,
&pNewAcl
);
if( *pdwStatus == ERROR_SUCCESS)
{
// DO NOTHING.
}
else if( *pdwStatus == ERROR_FILE_NOT_FOUND )
{
pNewAcl = pAcl;
*pdwStatus = ERROR_SUCCESS;
}
else
{
hr = E_FAIL;
}
}
}
if( SUCCEEDED(hr) && !fDel )
{
// auditing is requested build SACL
if( fAuditing )
{
BuildExplicitAccessWithName( &ea ,
pwszAccountName ,
dwMask ,
fAllow ? SET_AUDIT_SUCCESS : SET_AUDIT_FAILURE ,
NO_INHERITANCE );
*pdwStatus = SetEntriesInAcl( 1 , &ea , pAcl , &pNewAcl );
if( *pdwStatus != ERROR_SUCCESS )
{
hr = E_FAIL;
}
}
else
{
BuildExplicitAccessWithName( &ea ,
pwszAccountName ,
dwMask ,
fAllow ? GRANT_ACCESS : DENY_ACCESS ,
NO_INHERITANCE );
*pdwStatus = SetEntriesInAcl( 1 , &ea , pAcl , &pNewAcl );
if( *pdwStatus != ERROR_SUCCESS )
{
hr = E_FAIL;
}
}
}
// re-build SD.
ULONG cbExplicitEntriesDACL = 0;
PEXPLICIT_ACCESS prgExplicitEntriesDACL = NULL;
ULONG cbExplicitEntriesSACL = 0;
PEXPLICIT_ACCESS prgExplicitEntriesSACL = NULL;
if( SUCCEEDED( hr ) )
{
if( fAuditing )
{
if( GetExplicitEntriesFromAcl( pNewAcl ,
&cbExplicitEntriesSACL ,
&prgExplicitEntriesSACL ) != ERROR_SUCCESS )
{
ODS( L"CFGBKEND! GetExplicitEntriesFromAcl failed\n" );
*pdwStatus = GetLastError();
hr = E_FAIL;
}
if( !GetSecurityDescriptorDacl( pSD , &bDaclPresent , &pDacl , &bDaclDefaulted ) )
{
ODS( L"CFGBKEND! GetSecurityDescriptorDacl failed\n" );
*pdwStatus = GetLastError();
hr = E_FAIL;
}
else
{
if( GetExplicitEntriesFromAcl( pDacl ,
&cbExplicitEntriesDACL ,
&prgExplicitEntriesDACL ) != ERROR_SUCCESS )
{
ODS( L"CFGBKEND! GetExplicitEntriesFromAcl failed\n" );
*pdwStatus = GetLastError();
hr = E_FAIL;
}
}
}
else
{
if( GetExplicitEntriesFromAcl( pNewAcl ,
&cbExplicitEntriesDACL ,
&prgExplicitEntriesDACL ) != ERROR_SUCCESS )
{
ODS( L"CFGBKEND! GetExplicitEntriesFromAcl failed\n" );
*pdwStatus = GetLastError();
hr = E_FAIL;
}
if( !GetSecurityDescriptorSacl( pSD , &bSaclPresent , &pSacl , &bSaclDefaulted ) )
{
ODS( L"CFGBKEND! GetSecurityDescriptorSacl failed\n" );
*pdwStatus = GetLastError();
hr = E_FAIL;
}
else
{
if( GetExplicitEntriesFromAcl( pSacl ,
&cbExplicitEntriesSACL ,
&prgExplicitEntriesSACL ) != ERROR_SUCCESS )
{
ODS( L"CFGBKEND! GetExplicitEntriesFromAcl failed\n" );
*pdwStatus = GetLastError();
hr = E_FAIL;
}
}
}
if( SUCCEEDED(hr) )
{
TRUSTEE trustmeOwner;
PSID pOwner;
if( !GetSecurityDescriptorOwner( pSD , &pOwner , &bOwnerDefaulted ) )
{
ODS( L"CFGBKEND! GetSecurityDescriptorOwner failed\n" );
*pdwStatus = GetLastError();
hr = E_FAIL;
}
if( SUCCEEDED( hr ) )
{
BuildTrusteeWithSid( &trustmeOwner , pOwner );
*pdwStatus = BuildSecurityDescriptor( &trustmeOwner ,
&trustmeOwner ,
cbExplicitEntriesDACL ,
prgExplicitEntriesDACL,
cbExplicitEntriesSACL,
prgExplicitEntriesSACL,
NULL,
&dwSDLen ,
&pNewSD );
hr = HRESULT_FROM_WIN32( *pdwStatus );
}
if( SUCCEEDED( hr ) )
{
hr = SetSecurityDescriptor( bDefaultSecurity, pwszWinstaName , dwSDLen , pNewSD );
if( pNewSD != NULL )
{
LocalFree( pNewSD );
}
}
}
}
if( NULL != prgExplicitEntriesDACL )
{
LocalFree( prgExplicitEntriesDACL );
}
if( NULL != prgExplicitEntriesSACL )
{
LocalFree( prgExplicitEntriesSACL );
}
if( pSD != NULL )
{
LocalFree( pSD );
}
//
// pNewAcl might point to pAcl, check RemoteUserEntriesInAcl() on above.
//
if( pNewAcl != NULL && pNewAcl != pAcl )
{
LocalFree( pNewAcl );
}
return hr;
}
/*=----------------------------------------------------------------------------------------------------------------
GetUserPermList
[ in ] pwszWinstaName Name of winstation
[ out] pcbItems The number of items in the user permission list
[ out] ppUserPermList structure defined in idldefs.h
=----------------------------------------------------------------------------------------------------------------*/
STDMETHODIMP CCfgComp::GetUserPermList( WCHAR *pwszWinstaName , PDWORD pcbItems , PUSERPERMLIST *ppUserPermList , BOOL fAudit )
{
HRESULT hr;
PSECURITY_DESCRIPTOR pSD = NULL;
BOOL bAclDefaulted;
BOOL bAclPresent;
PACL pAcl = NULL;
LONG lSize;
ULONG cbExplicitEntries = 0;
PEXPLICIT_ACCESS prgExplicitEntries = NULL;
hr = GetSecurityDescriptor( pwszWinstaName , &lSize , &pSD );
if( SUCCEEDED( hr ) )
{
if( fAudit )
{
if( !GetSecurityDescriptorSacl( pSD ,
&bAclPresent,
&pAcl,
&bAclDefaulted ) )
{
ODS( L"CFGBKEND!GetUserPermList GetSecurityDescriptorSacl failed\n" );
hr = E_FAIL;
}
}
else if( !GetSecurityDescriptorDacl( pSD ,
&bAclPresent,
&pAcl,
&bAclDefaulted ) )
{
ODS( L"CFGBKEND!GetUserPermList GetSecurityDescriptorDacl failed\n" );
hr = E_FAIL;
}
}
if( SUCCEEDED( hr ) )
{
if( GetExplicitEntriesFromAcl( pAcl ,
&cbExplicitEntries ,
&prgExplicitEntries ) != ERROR_SUCCESS )
{
ODS( L"CFGBKEND!GetUserPermList GetExplicitEntriesFromAcl failed\n" );
hr = E_FAIL;
}
*pcbItems = cbExplicitEntries;
}
if( SUCCEEDED( hr ) )
{
*ppUserPermList = ( PUSERPERMLIST )CoTaskMemAlloc( sizeof( USERPERMLIST ) * cbExplicitEntries );
if( *ppUserPermList != NULL )
{
for( ULONG i = 0; i < cbExplicitEntries; ++i )
{
( *ppUserPermList )[ i ].Name[ 0 ] = 0;
( *ppUserPermList )[ i ].Sid[ 0 ] = 0;
if( prgExplicitEntries[ i ].Trustee.TrusteeForm == TRUSTEE_IS_SID )
{
WCHAR szDomain[ 120 ];
WCHAR szUser[ 128 ];
DWORD dwSizeofName = sizeof( szUser ) / sizeof( WCHAR );
DWORD dwSizeofDomain = sizeof( szDomain ) / sizeof( WCHAR );
SID_NAME_USE snu;
if( LookupAccountSid( NULL ,
prgExplicitEntries[ i ].Trustee.ptstrName ,
szUser ,
&dwSizeofName ,
szDomain ,
&dwSizeofDomain ,
&snu ) )
{
if( dwSizeofDomain > 0 )
{
lstrcpy( ( *ppUserPermList )[ i ].Name , szDomain );
lstrcat( ( *ppUserPermList )[ i ].Name , L"\\" );
}
lstrcat( ( *ppUserPermList )[ i ].Name , szUser );
LPTSTR pszSid = NULL;
if( ConvertSidToStringSid( prgExplicitEntries[ i ].Trustee.ptstrName , &pszSid ) )
{
if( pszSid != NULL )
{
lstrcpyn( ( *ppUserPermList )[ i ].Sid , pszSid , 256 );
LocalFree( pszSid );
}
}
}
}
else if( prgExplicitEntries[ i ].Trustee.TrusteeForm == TRUSTEE_IS_NAME )
{
lstrcpy( ( *ppUserPermList )[ i ].Name , GetTrusteeName( &prgExplicitEntries[ i ].Trustee ) );
// todo reverse lookup for sid
// not sure if we'll ever need this
}
( *ppUserPermList )[ i ].Mask = prgExplicitEntries[ i ].grfAccessPermissions;
( *ppUserPermList )[ i ].Type = prgExplicitEntries[ i ].grfAccessMode;
}
}
else
{
ODS( L"CFGBKEND!GetUserPermList no mem for UserPermList\n" );
hr = E_OUTOFMEMORY;
}
}
if( prgExplicitEntries != NULL )
{
LocalFree( prgExplicitEntries );
}
if( pSD != NULL )
{
LocalFree( pSD );
}
return hr;
}
//-----------------------------------------------------------------------------
HRESULT CCfgComp::UpdateSessionDirectory( PDWORD pdwStatus )
{
HRESULT hr = S_OK;
if( !_WinStationUpdateSettings( SERVERNAME_CURRENT,
WINSTACFG_SESSDIR ,
0 ) )
{
hr = E_FAIL;
}
*pdwStatus = GetLastError( );
return hr;
}
//-----------------------------------------------------------------------------
/*****************************************************************************
*
* TestUserForAdmin
*
* Returns whether the current thread is running under admin
* security.
*
* ENTRY:
* Param1 (input/output)
* Comments
*
* EXIT:
* STATUS_SUCCESS - no error
*
* alhen
*
* Code is from
* HOWTO: Determine if Running In User Context of Local Admin Acct
* Last reviewed: March 4, 1998
* Article ID: Q118626
*
* corrected by alhen "common coding errors"
*
*
****************************************************************************/
BOOL TestUserForAdmin( )
{
PSID psidAdministrators = NULL;
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
BOOL bSuccess;
BOOL bIsMember = FALSE;
bSuccess = AllocateAndInitializeSid( &siaNtAuthority , 2 ,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&psidAdministrators );
if( bSuccess )
{
CheckTokenMembership( NULL , psidAdministrators , &bIsMember );
FreeSid( psidAdministrators );
}
return bIsMember;
}