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.
1955 lines
52 KiB
1955 lines
52 KiB
/*++
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ads.cpp
|
|
|
|
Abstract:
|
|
|
|
This module implements ADSI extension for Terminal Server User Properties.
|
|
|
|
Author:
|
|
|
|
Rashmi Patankar (RashmiP) 10-Aug-2001
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "stdafx.h"
|
|
#include "ADsTSProps.h"
|
|
#include <ntsam.h>
|
|
#include <shlwapi.h>
|
|
|
|
#define MAX_STRING_SIZE 256
|
|
#define CTX_USER_PARAM_MAX_SIZE (3 * sizeof(USERCONFIG))
|
|
#define PARMS_SIZE 15520
|
|
|
|
|
|
#ifndef RETURN_ON_FAILURE
|
|
#define RETURN_ON_FAILURE(expr) { \
|
|
HRESULT HiddenHr = expr; if ( !SUCCEEDED(HiddenHr) ) { return HiddenHr; }\
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifndef BREAK_ON_FAILURE
|
|
#define BREAK_ON_FAILURE(x) hr = x; if (!SUCCEEDED(hr)) break
|
|
#endif
|
|
|
|
|
|
#define RETURN_ON_INVALID_PARAMETER(x) if(x!=FALSE && x!=TRUE) {return E_ADS_BAD_PARAMETER;}
|
|
|
|
|
|
// Static variables
|
|
CComTypeInfoHolder ADsTSUserEx::m_StaticHolder =
|
|
{ &__uuidof(IADsTSUserEx), &LIBID_TSUSEREXLib, 1, 0, NULL, 0 };
|
|
|
|
SERVER_TO_MODE ADsTSUserEx::m_StaticServerMap;
|
|
CComPtr<IADsPathname> ADsTSUserEx::m_StaticpPath(NULL);
|
|
CComAutoCriticalSection ADsTSUserEx::m_StaticCritSec;
|
|
|
|
|
|
#define INMINUTES 60000
|
|
#define MAX_TIME_LIMIT 71580
|
|
#define ARRAYSIZE(A) ((sizeof(A))/sizeof(A[0]))
|
|
#define NCP_SET 0x02 /* Series of Object ID numbers, each 4
|
|
bytes long */
|
|
#define WIN_CFGPRESENT L"CfgPresent"
|
|
#define CFGPRESENT_VALUE 0xB00B1E55
|
|
|
|
#define F1MSK_INHERITAUTOLOGON 0x80000000
|
|
#define F1MSK_INHERITRESETBROKEN 0x40000000
|
|
#define F1MSK_INHERITRECONNECTSAME 0x20000000
|
|
#define F1MSK_INHERITINITIALPROGRAM 0x10000000
|
|
#define F1MSK_INHERITCALLBACK 0x08000000
|
|
#define F1MSK_INHERITCALLBACKNUMBER 0x04000000
|
|
#define F1MSK_INHERITSHADOW 0x02000000
|
|
#define F1MSK_INHERITMAXSESSIONTIME 0x01000000
|
|
#define F1MSK_INHERITMAXDISCONNECTIONTIME 0x00800000
|
|
#define F1MSK_INHERITMAXIDLETIME 0x00400000
|
|
#define F1MSK_INHERITAUTOCLIENT 0x00200000
|
|
#define F1MSK_INHERITSECURITY 0x00100000
|
|
#define F1MSK_PROMPTFORPASSWORD 0x00080000
|
|
#define F1MSK_RESETBROKEN 0x00040000
|
|
#define F1MSK_RECONNECTSAME 0x00020000
|
|
#define F1MSK_LOGONDISABLED 0x00010000
|
|
#define F1MSK_AUTOCLIENTDRIVES 0x00008000
|
|
#define F1MSK_AUTOCLIENTLPTS 0x00004000
|
|
#define F1MSK_FORCECLIENTLPTDEF 0x00002000
|
|
#define F1MSK_DISABLEENCRYPTION 0x00001000
|
|
#define F1MSK_HOMEDIRECTORYMAPROOT 0x00000800
|
|
#define F1MSK_USEDEFAULTGINA 0x00000400
|
|
#define F1MSK_DISABLECPM 0x00000200
|
|
#define F1MSK_DISABLECDM 0x00000100
|
|
#define F1MSK_DISABLECCM 0x00000080
|
|
#define F1MSK_DISABLELPT 0x00000040
|
|
#define F1MSK_DISABLECLIP 0x00000020
|
|
#define F1MSK_DISABLEEXE 0x00000010
|
|
#define F1MSK_WALLPAPERDISABLED 0x00000008
|
|
#define F1MSK_DISABLECAM 0x00000004
|
|
#define DEFAULTFLAGS (F1MSK_INHERITAUTOLOGON|F1MSK_INHERITINITIALPROGRAM|F1MSK_INHERITAUTOCLIENT|F1MSK_AUTOCLIENTDRIVES|F1MSK_AUTOCLIENTLPTS|F1MSK_FORCECLIENTLPTDEF|F1MSK_DISABLEENCRYPTION)
|
|
|
|
|
|
#define BAIL_IF_ERROR(hr) if (FAILED(hr)) { goto cleanup; }
|
|
|
|
|
|
namespace
|
|
{
|
|
const WCHAR OS_VERSION_4[] = L"4.0";
|
|
const WCHAR OS_VERSION_5[] = L"5.0";
|
|
const WCHAR OS_VERSION_51[] = L"5.1";
|
|
const WCHAR LDAP_PREFIX[] = L"LDAP://";
|
|
|
|
WCHAR LDAP_PARAMETERS_NAME[] = L"UserParameters";
|
|
WCHAR WINNT_PARAMETERS_NAME[] = L"Parameters";
|
|
|
|
WCHAR WIN_WFPROFILEPATH[] = L"WFProfilePath";
|
|
WCHAR WIN_WFHOMEDIR[] = L"WFHomeDir";
|
|
WCHAR WIN_WFHOMEDIRDRIVE[] = L"WFHomeDirDrive";
|
|
WCHAR WIN_NWLOGONSERVER[] = L"NWLogonServer";
|
|
WCHAR WIN_SHADOW[] = L"Shadow";
|
|
WCHAR WIN_MAXCONNECTIONTIME[] = L"MaxConnectionTime";
|
|
WCHAR WIN_MAXDISCONNECTIONTIME[] = L"MaxDisconnectionTime";
|
|
WCHAR WIN_MAXIDLETIME[] = L"MaxIdleTime";
|
|
WCHAR WIN_FLAGS1[] = L"CfgFlags1";
|
|
WCHAR WIN_INITIALPROGRAM[] = L"InitialProgram";
|
|
WCHAR WIN_WORKDIRECTORY[] = L"WorkDirectory";
|
|
}
|
|
|
|
typedef struct _USER_PROPERTY {
|
|
WCHAR PropertyLength; // length of property name
|
|
WCHAR ValueLength; // length of property value
|
|
WCHAR PropertyFlag; // type of property (1 = set, 2 = item)
|
|
WCHAR Property[1]; // start of property name, followed by value
|
|
} USER_PROPERTY, *PUSER_PROPERTY;
|
|
|
|
//
|
|
// This is the structure that maps the beginning of the user's Parameters
|
|
// field. It is only separate so that we can do a sizeof() without including
|
|
// the first property, which may or may not be there.
|
|
//
|
|
|
|
typedef struct _USER_PROPERTIES_HDR {
|
|
WCHAR BacklevelParms[48]; // RAS & Mac data stored here.
|
|
WCHAR PropertySignature; // signature that we can look for.
|
|
WCHAR PropertyCount; // number of properties present.
|
|
} USER_PROPERTIES_HDR, *PUSER_PROPERTIES_HDR;
|
|
|
|
//
|
|
// This structure maps out the whole of the user's Parameters field when
|
|
// the user properties structure is present and at least one property is
|
|
// defined.
|
|
//
|
|
|
|
typedef struct _USER_PROPERTIES {
|
|
USER_PROPERTIES_HDR Header;
|
|
USER_PROPERTY FirstProperty;
|
|
} USER_PROPERTIES, *PUSER_PROPERTIES;
|
|
|
|
|
|
|
|
ADsTSUserEx::ADsTSUserEx()
|
|
{
|
|
HRESULT hr = NULL;
|
|
ITypeLib *pITypeLib = NULL;
|
|
m_pTypeInfo = NULL;
|
|
m_vbIsLDAP = FALSE;
|
|
m_vbUpLevelAllowed = FALSE;
|
|
m_pOuterDispatch = NULL;
|
|
m_pADs = NULL;
|
|
|
|
hr = LoadRegTypeLib(LIBID_TSUSEREXLib,
|
|
1,
|
|
0,
|
|
PRIMARYLANGID(GetSystemDefaultLCID()),
|
|
&pITypeLib );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = pITypeLib->GetTypeInfoOfGuid( IID_IADsTSUserEx, &m_pTypeInfo);
|
|
}
|
|
|
|
pITypeLib->Release();
|
|
}
|
|
|
|
|
|
ADsTSUserEx::~ADsTSUserEx()
|
|
{
|
|
if ( m_pTypeInfo )
|
|
{
|
|
m_pTypeInfo->Release();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
|
|
STDMETHODIMP ADsTSUserEx::InterfaceSupportsErrorInfo(REFIID riid) throw()
|
|
{
|
|
|
|
static const IID* arr[] =
|
|
{
|
|
&__uuidof(IADsTSUserEx),
|
|
};
|
|
|
|
for ( int i=0; i < sizeof(arr)/sizeof(arr[0]); ++i )
|
|
{
|
|
if (InlineIsEqualGUID(*arr[i],riid))
|
|
{
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return S_FALSE;
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// ADsTSUserEx::InternalGetLong
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT ADsTSUserEx::InternalGetLong(/*in*/ BSTR bstrProperty,
|
|
/*out*/ LONG *lpVal) throw()
|
|
{
|
|
_ASSERT(lpVal);
|
|
|
|
HRESULT hr = S_OK;
|
|
LONG lVal = 0;
|
|
LONG UPLength = 0;
|
|
TCHAR * pTemp = NULL;
|
|
VARIANT Parms;
|
|
|
|
*lpVal = 0;
|
|
|
|
VariantInit(&Parms);
|
|
|
|
if( m_vbIsLDAP )
|
|
{
|
|
hr = m_pADs->Get(LDAP_PARAMETERS_NAME, &Parms);
|
|
}
|
|
else
|
|
{
|
|
hr = m_pADs->Get(WINNT_PARAMETERS_NAME, &Parms);
|
|
}
|
|
|
|
if(ERROR_SUCCESS != hr)
|
|
{
|
|
hr = S_OK;
|
|
goto cleanup;
|
|
}
|
|
|
|
UPLength = (SysStringLen(Parms.bstrVal ) +
|
|
CTX_USER_PARAM_MAX_SIZE+1) * sizeof(WCHAR);
|
|
|
|
pTemp = (TCHAR*)LocalAlloc(LPTR, UPLength);
|
|
|
|
if(NULL == pTemp)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
memcpy(pTemp, V_BSTR(&Parms), SysStringLen(Parms.bstrVal)*sizeof(WCHAR));
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
if(m_vbUpLevelAllowed)
|
|
{
|
|
NTSTATUS ntstatus = UsrPropGetValue(bstrProperty, &lVal, sizeof(lVal), pTemp);
|
|
|
|
if( ntstatus == STATUS_SUCCESS )
|
|
{
|
|
*lpVal = lVal;
|
|
}
|
|
else if(ntstatus == STATUS_OBJECT_NAME_NOT_FOUND)
|
|
{
|
|
if(_wcsicmp(bstrProperty, L"Shadow") == 0)
|
|
{
|
|
*lpVal = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if(NULL != pTemp)
|
|
{
|
|
LocalFree(pTemp);
|
|
}
|
|
|
|
VariantClear(&Parms);
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// InternalSetValue
|
|
//
|
|
// Most of the complexity of this dll is here.
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT ADsTSUserEx::InternalSetValue(/*[in]*/ WCHAR *wszProperty,
|
|
/*[in]*/ LONG lNewVal) throw()
|
|
{
|
|
|
|
|
|
HRESULT hr = S_OK;
|
|
ULONG UPLength = 0;
|
|
TCHAR* pTemp = NULL;
|
|
VARIANT Parms;
|
|
VARIANT var;
|
|
ULONG ulFlags = DEFAULTFLAGS;
|
|
ULONG CfgPresent = CFGPRESENT_VALUE;
|
|
|
|
VariantInit(&var);
|
|
|
|
///////////////////////////
|
|
// If the provider is LDAP
|
|
///////////////////////////
|
|
|
|
if(m_vbUpLevelAllowed)
|
|
{
|
|
if ( m_vbIsLDAP )
|
|
{
|
|
hr = m_pADs->Get(LDAP_PARAMETERS_NAME, &Parms);
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
Parms.bstrVal = SysAllocString(L"CtxCfgPresent");
|
|
UPLength = PARMS_SIZE;
|
|
}
|
|
|
|
UPLength = (SysStringLen(Parms.bstrVal) +
|
|
CTX_USER_PARAM_MAX_SIZE+1) *
|
|
sizeof(WCHAR);
|
|
|
|
pTemp = (TCHAR*)LocalAlloc(LPTR, UPLength);
|
|
|
|
if(NULL == pTemp)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
memcpy(pTemp, V_BSTR(&Parms), SysStringLen(Parms.bstrVal)*sizeof(WCHAR));
|
|
|
|
hr = UsrPropGetValue( WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
pTemp ) ;
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
ulFlags = DEFAULTFLAGS;
|
|
|
|
UsrPropSetValue( WIN_CFGPRESENT,
|
|
&CfgPresent,
|
|
sizeof(CfgPresent),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength );
|
|
|
|
UsrPropSetValue(WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength
|
|
);
|
|
}
|
|
|
|
hr = UsrPropSetValue(wszProperty,
|
|
&lNewVal,
|
|
sizeof(lNewVal),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength
|
|
);
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
V_BSTR(&var) = SysAllocString(pTemp);
|
|
V_VT(&var) = VT_BSTR;
|
|
// Now set the info
|
|
hr = m_pADs->Put(LDAP_PARAMETERS_NAME, var);
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = m_pADs->Get(WINNT_PARAMETERS_NAME, &Parms);
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
UPLength = (SysStringLen(Parms.bstrVal) +
|
|
CTX_USER_PARAM_MAX_SIZE+1) *
|
|
sizeof(WCHAR);
|
|
|
|
pTemp = (TCHAR*)LocalAlloc(LPTR, UPLength);
|
|
|
|
if(NULL == pTemp)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
memcpy(pTemp, V_BSTR(&Parms), SysStringLen(Parms.bstrVal)*sizeof(WCHAR));
|
|
|
|
|
|
hr = UsrPropGetValue( WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
pTemp ) ;
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
ulFlags = DEFAULTFLAGS;
|
|
|
|
UsrPropSetValue( WIN_CFGPRESENT,
|
|
&CfgPresent,
|
|
sizeof(CfgPresent),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength );
|
|
|
|
UsrPropSetValue(WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength
|
|
);
|
|
}
|
|
|
|
|
|
hr = UsrPropSetValue(wszProperty,
|
|
&lNewVal,
|
|
sizeof(lNewVal),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength
|
|
);
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
V_BSTR(&var) = SysAllocString(pTemp);
|
|
V_VT(&var) = VT_BSTR;
|
|
|
|
hr = m_pADs->Put(WINNT_PARAMETERS_NAME, var);
|
|
}
|
|
}
|
|
cleanup:
|
|
|
|
if(NULL != pTemp)
|
|
{
|
|
LocalFree(pTemp);
|
|
}
|
|
|
|
VariantClear(&Parms);
|
|
VariantClear(&var);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// InternalSetString
|
|
//
|
|
// Most of the complexity of this dll is here.
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT ADsTSUserEx::InternalSetString(/*[in]*/ WCHAR* wszProperty,
|
|
/*[in]*/ BSTR bstrNewVal) throw()
|
|
{
|
|
if ( !bstrNewVal )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
BOOL fDefaultValue = 0;
|
|
BOOL Update = FALSE;
|
|
ULONG UPLength = 0;
|
|
TCHAR* pTemp = NULL;
|
|
VARIANT Parms;
|
|
VARIANT var;
|
|
ULONG ulFlags = 0;
|
|
ULONG CfgPresent = CFGPRESENT_VALUE;
|
|
|
|
VariantInit(&var);
|
|
|
|
///////////////////////////
|
|
// If the provider is LDAP
|
|
///////////////////////////
|
|
|
|
if(wszProperty == NULL || (bstrNewVal && SysStringLen(bstrNewVal)> MAX_STRING_SIZE))
|
|
{
|
|
return E_ADS_BAD_PARAMETER;
|
|
}
|
|
|
|
if ((_wcsicmp(wszProperty, L"InitialProgram") == 0) || (_wcsicmp(wszProperty, L"WorkDirectory") == 0))
|
|
{
|
|
InternalSetLong(F1MSK_INHERITINITIALPROGRAM, FALSE);
|
|
}
|
|
|
|
if(m_vbUpLevelAllowed)
|
|
{
|
|
if ( m_vbIsLDAP )
|
|
{
|
|
hr = m_pADs->Get(LDAP_PARAMETERS_NAME, &Parms);
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
Parms.bstrVal = SysAllocString(L"CtxCfgPresent");
|
|
UPLength = PARMS_SIZE;
|
|
fDefaultValue = 0;
|
|
}
|
|
else
|
|
{
|
|
UPLength = (SysStringLen(Parms.bstrVal) +
|
|
CTX_USER_PARAM_MAX_SIZE+1) *
|
|
sizeof(WCHAR);
|
|
|
|
fDefaultValue = (V_BSTR(&Parms)==0) ? 1: 0 ;
|
|
}
|
|
|
|
pTemp = (TCHAR*)LocalAlloc(LPTR, UPLength);
|
|
|
|
if(NULL == pTemp)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
memcpy(pTemp, V_BSTR(&Parms), SysStringLen(Parms.bstrVal)*sizeof(WCHAR));
|
|
|
|
hr = UsrPropGetValue( WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
pTemp ) ;
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
ulFlags = DEFAULTFLAGS;
|
|
|
|
UsrPropSetValue( WIN_CFGPRESENT,
|
|
&CfgPresent,
|
|
sizeof(CfgPresent),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength );
|
|
|
|
UsrPropSetValue(WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength
|
|
);
|
|
}
|
|
|
|
hr = UsrPropSetString(wszProperty,
|
|
bstrNewVal,
|
|
pTemp,
|
|
UPLength,
|
|
fDefaultValue
|
|
);
|
|
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
V_BSTR(&var) = SysAllocString(pTemp);
|
|
V_VT(&var) = VT_BSTR;
|
|
|
|
hr = m_pADs->Put(LDAP_PARAMETERS_NAME, var);
|
|
}
|
|
else
|
|
{
|
|
hr = m_pADs->Get(WINNT_PARAMETERS_NAME, &Parms);
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
|
|
UPLength = (SysStringLen(Parms.bstrVal) +
|
|
CTX_USER_PARAM_MAX_SIZE+1) *
|
|
sizeof(WCHAR);
|
|
|
|
fDefaultValue = (V_BSTR(&Parms)==0) ? 1: 0 ;
|
|
|
|
pTemp = (TCHAR*)LocalAlloc(LPTR, UPLength);
|
|
|
|
if(NULL == pTemp)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
memcpy(pTemp, V_BSTR(&Parms), SysStringLen(Parms.bstrVal)*sizeof(WCHAR));
|
|
|
|
hr = UsrPropGetValue( WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
pTemp ) ;
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
ulFlags = DEFAULTFLAGS;
|
|
|
|
UsrPropSetValue( WIN_CFGPRESENT,
|
|
&CfgPresent,
|
|
sizeof(CfgPresent),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength );
|
|
|
|
UsrPropSetValue(WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength
|
|
);
|
|
}
|
|
|
|
hr = UsrPropSetString(wszProperty,
|
|
bstrNewVal,
|
|
pTemp,
|
|
UPLength,
|
|
fDefaultValue
|
|
);
|
|
}
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
V_BSTR(&var) = SysAllocString(pTemp);
|
|
V_VT(&var) = VT_BSTR;
|
|
|
|
hr = m_pADs->Put(WINNT_PARAMETERS_NAME, var);
|
|
}
|
|
}
|
|
cleanup:
|
|
|
|
if(NULL != pTemp)
|
|
{
|
|
LocalFree(pTemp);
|
|
}
|
|
|
|
VariantClear(&Parms);
|
|
VariantClear(&var);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// InternalSetLong
|
|
//
|
|
// Most of the complexity of this dll is here.
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT ADsTSUserEx::InternalSetLong(/*[in]*/ LONG lProperty,
|
|
/*[in]*/ LONG lNewVal) throw()
|
|
{
|
|
|
|
|
|
HRESULT hr = S_OK;
|
|
ULONG ulFlags = 0;
|
|
ULONG UPLength = 0;
|
|
TCHAR* pTemp = NULL;
|
|
VARIANT Parms;
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
ULONG CfgPresent = CFGPRESENT_VALUE;
|
|
|
|
|
|
///////////////////////////
|
|
// If the provider is LDAP
|
|
///////////////////////////
|
|
|
|
if(m_vbUpLevelAllowed)
|
|
{
|
|
if ( m_vbIsLDAP )
|
|
{
|
|
hr = m_pADs->Get(LDAP_PARAMETERS_NAME, &Parms);
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
Parms.bstrVal = SysAllocString(L"CtxCfgPresent");
|
|
UPLength = PARMS_SIZE;
|
|
}
|
|
|
|
UPLength = (sizeof(V_BSTR(&Parms)) +
|
|
CTX_USER_PARAM_MAX_SIZE) *
|
|
sizeof(WCHAR);
|
|
|
|
pTemp = (TCHAR*)LocalAlloc(LPTR, UPLength);
|
|
|
|
if(NULL == pTemp)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
memcpy(pTemp, V_BSTR(&Parms), SysStringLen(Parms.bstrVal)*sizeof(WCHAR));
|
|
|
|
|
|
hr = UsrPropGetValue( WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
pTemp ) ;
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
ulFlags = DEFAULTFLAGS;
|
|
|
|
UsrPropSetValue( WIN_CFGPRESENT,
|
|
&CfgPresent,
|
|
sizeof(CfgPresent),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength );
|
|
|
|
}
|
|
|
|
if(lNewVal == 0)
|
|
{
|
|
ulFlags &= (~(lProperty));
|
|
}
|
|
else
|
|
{
|
|
ulFlags |= lProperty;
|
|
}
|
|
|
|
hr = UsrPropSetValue(WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength
|
|
);
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
V_BSTR(&var) = SysAllocString(pTemp);
|
|
V_VT(&var) = VT_BSTR;
|
|
|
|
hr = m_pADs->Put(LDAP_PARAMETERS_NAME, var);
|
|
}
|
|
else
|
|
{
|
|
hr = m_pADs->Get(WINNT_PARAMETERS_NAME, &Parms);
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
UPLength = (sizeof(V_BSTR(&Parms)) +
|
|
CTX_USER_PARAM_MAX_SIZE) *
|
|
sizeof(WCHAR);
|
|
|
|
pTemp = (TCHAR*)LocalAlloc(LPTR, UPLength);
|
|
|
|
if(NULL == pTemp)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
memcpy(pTemp, V_BSTR(&Parms), SysStringLen(Parms.bstrVal)*sizeof(WCHAR));
|
|
|
|
hr = UsrPropGetValue( WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
pTemp ) ;
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
ulFlags = DEFAULTFLAGS;
|
|
|
|
UsrPropSetValue( WIN_CFGPRESENT,
|
|
&CfgPresent,
|
|
sizeof(CfgPresent),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength );
|
|
}
|
|
|
|
if(lNewVal == 0)
|
|
{
|
|
ulFlags &= (~(lProperty));
|
|
}
|
|
else
|
|
{
|
|
ulFlags |= lProperty;
|
|
}
|
|
|
|
hr = UsrPropSetValue(WIN_FLAGS1,
|
|
&ulFlags,
|
|
sizeof(ulFlags),
|
|
FALSE,
|
|
pTemp,
|
|
UPLength
|
|
);
|
|
|
|
if( ERROR_SUCCESS != hr )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
V_BSTR(&var) = SysAllocString(pTemp);
|
|
V_VT(&var) = VT_BSTR;
|
|
|
|
hr = m_pADs->Put(WINNT_PARAMETERS_NAME, var);
|
|
}
|
|
}
|
|
cleanup:
|
|
|
|
if(NULL != pTemp)
|
|
{
|
|
LocalFree(pTemp);
|
|
}
|
|
|
|
VariantClear(&Parms);
|
|
VariantClear(&var);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// ADsTSUserEx::InternalGetString
|
|
//
|
|
// Works with
|
|
// ProfilePath
|
|
// HomeDirectory
|
|
// HomeDrive
|
|
// WorkDirectory
|
|
// InitialProgram
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT ADsTSUserEx::InternalGetString(/*in*/ BSTR bstrProperty,
|
|
/*out*/ BSTR *pbstrVal
|
|
) throw()
|
|
{
|
|
_ASSERT(pbstrVal);
|
|
|
|
HRESULT hr = S_OK;
|
|
TCHAR tchbuf[MAX_STRING_SIZE+1] = L"";
|
|
TCHAR* pTemp = NULL;
|
|
LONG UPLength = 0;
|
|
VARIANT Parms;
|
|
*pbstrVal = NULL;
|
|
|
|
if( m_vbIsLDAP )
|
|
{
|
|
hr = m_pADs->Get(LDAP_PARAMETERS_NAME, &Parms);
|
|
}
|
|
else
|
|
{
|
|
hr = m_pADs->Get(WINNT_PARAMETERS_NAME, &Parms);
|
|
}
|
|
|
|
if( ERROR_SUCCESS == hr )
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
UPLength = (SysStringLen(Parms.bstrVal) +
|
|
CTX_USER_PARAM_MAX_SIZE+1) *
|
|
sizeof(WCHAR);
|
|
|
|
pTemp = (TCHAR*)LocalAlloc(LPTR, UPLength);
|
|
|
|
if(NULL == pTemp)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
memcpy(pTemp, V_BSTR(&Parms), SysStringLen(Parms.bstrVal)*sizeof(WCHAR));
|
|
|
|
NTSTATUS ntstatus = UsrPropGetString(bstrProperty,
|
|
tchbuf,
|
|
sizeof(tchbuf),
|
|
pTemp
|
|
);
|
|
|
|
if( ntstatus == STATUS_SUCCESS )
|
|
{
|
|
*pbstrVal = SysAllocString(tchbuf);
|
|
}
|
|
else if ( ntstatus != STATUS_OBJECT_NAME_NOT_FOUND )
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
} // else return the error.
|
|
|
|
|
|
if( (hr == E_ADS_PROPERTY_NOT_FOUND) || (hr == DISP_E_MEMBERNOTFOUND) )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if(NULL != pTemp)
|
|
{
|
|
LocalFree(pTemp);
|
|
}
|
|
|
|
VariantClear(&Parms);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// ADsTSUserEx::GetInfoWinNTComputer
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT ADsTSUserEx::GetInfoWinNTComputer(LPWSTR ServerName) throw()
|
|
{
|
|
// This is a Computer, not a Domain that was used as a string
|
|
|
|
// now detect if that's a w2k standalone or a NT4
|
|
// Get the computer object to see what version of the
|
|
// OS is used
|
|
|
|
CComPtr<IADsComputer> pComputer;
|
|
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pszUserName = NULL;
|
|
LPWSTR pszPassword = NULL;
|
|
DWORD dwAuthFlags = 0;
|
|
|
|
CComPtr<IADs> pDomain;
|
|
CComBSTR Version;
|
|
|
|
hr = ADsOpenObject(ServerName,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
__uuidof(IADsComputer),
|
|
reinterpret_cast<VOID**> (&pComputer));
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
|
|
//Get the OperatingSystemVersion attribute
|
|
hr = pComputer->get_OperatingSystemVersion(&Version);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
LONG lVer = 0;
|
|
|
|
lVer = _wtol(Version);
|
|
|
|
if(lVer >= 4)
|
|
{
|
|
|
|
// Not a domain account and NT 5.1: standalone through WinNT
|
|
m_vbUpLevelAllowed = VARIANT_TRUE;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
cleanup:
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// ADsTSUserEx::GetInfoWinNT
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT ADsTSUserEx::GetInfoWinNT(IADsPathname* pPath) throw()
|
|
{
|
|
if (NULL == pPath)
|
|
return E_FAIL;
|
|
|
|
//////////////////////////////////////////////
|
|
// WinNT Provider: retrieve the server's name
|
|
//////////////////////////////////////////////
|
|
|
|
HRESULT hr = S_OK;
|
|
LONG NbElements;
|
|
CComBSTR Bstr;
|
|
|
|
|
|
RETURN_ON_FAILURE(pPath->GetNumElements( &NbElements ));
|
|
RETURN_ON_FAILURE(pPath->GetElement( 1, &Bstr ));
|
|
|
|
SERVER_TO_MODE::iterator MapIterator;
|
|
wstring TempString(Bstr);
|
|
|
|
MapIterator = m_StaticServerMap.find(TempString);
|
|
if ( MapIterator != m_StaticServerMap.end() )
|
|
{
|
|
// found in the map
|
|
m_vbUpLevelAllowed = MapIterator->second;
|
|
return hr;
|
|
}
|
|
|
|
CComBSTR ServerName = L"WinNT://";
|
|
ServerName.AppendBSTR(Bstr);
|
|
|
|
/////////////////////////
|
|
// Computer (not domain)
|
|
/////////////////////////
|
|
|
|
if ( NbElements == 3 ) // Computer (not domain)
|
|
{
|
|
hr = GetInfoWinNTComputer(ServerName.m_str);
|
|
}
|
|
else if ( NbElements == 2 ) // Domain
|
|
{
|
|
// WinNT Provider
|
|
// AND Domain Controller
|
|
// => No Upper-Level allowed stop there
|
|
|
|
hr = GetInfoWinNTComputer(ServerName.m_str);
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
m_StaticServerMap.insert(SERVER_TO_MODE::value_type(
|
|
TempString,
|
|
m_vbUpLevelAllowed
|
|
));
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// ExtractDCFromLDAP
|
|
//
|
|
// String assumed to be like
|
|
// "LDAP://DC=ntdev,DC=microsoft,DC=com" string (example)
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT ExtractDCFromLDAP(IADsPathname* pPath, CComBSTR& NewName) throw()
|
|
{
|
|
if (NULL == pPath)
|
|
return E_FAIL;
|
|
|
|
LONG Count;
|
|
RETURN_ON_FAILURE(pPath->GetNumElements(&Count));
|
|
NewName = LDAP_PREFIX;
|
|
|
|
CComBSTR Bstr;
|
|
for ( int i = 0; i<Count; ++i )
|
|
{
|
|
RETURN_ON_FAILURE(pPath->GetElement(i,&Bstr));
|
|
|
|
WCHAR Header[4];
|
|
lstrcpynW(Header,Bstr, 4); // 3 plus \0
|
|
if ( lstrcmpiW(Header, L"DC=") == 0 )
|
|
{
|
|
NewName.AppendBSTR(Bstr);
|
|
NewName.Append(L",");
|
|
}
|
|
Bstr.Empty();
|
|
}
|
|
NewName[NewName.Length()-1] = L'\0';
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// ADsTSUserEx::GetInfoLDAP
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT ADsTSUserEx::GetInfoLDAP(IADsPathname* pPath) throw()
|
|
{
|
|
if (NULL == pPath)
|
|
return E_FAIL;
|
|
|
|
// LDAP provider
|
|
CComBSTR ServerName;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwAuthFlags = 0;
|
|
|
|
RETURN_ON_FAILURE(ExtractDCFromLDAP(pPath, ServerName));
|
|
|
|
SERVER_TO_MODE::iterator MapIterator;
|
|
wstring TempString(ServerName);
|
|
|
|
MapIterator = m_StaticServerMap.find(TempString);
|
|
if ( MapIterator != m_StaticServerMap.end() )
|
|
{
|
|
// found in the map
|
|
m_vbUpLevelAllowed = MapIterator->second;
|
|
return S_OK;
|
|
}
|
|
|
|
m_vbUpLevelAllowed = VARIANT_TRUE;
|
|
|
|
m_StaticServerMap.insert(SERVER_TO_MODE::value_type( TempString,
|
|
m_vbUpLevelAllowed
|
|
));
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// ADsTSUserEx::Operate
|
|
//
|
|
// Parameters should be varUserName, varPassword, varAuthFlags. ignored here
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP ADsTSUserEx::Operate(ULONG Code,
|
|
VARIANT varData1,
|
|
VARIANT varData2,
|
|
VARIANT varData3) throw()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
switch (Code)
|
|
{
|
|
case ADS_EXT_INITCREDENTIALS:
|
|
{
|
|
|
|
// Initialize the IADs smart pointer
|
|
// (member)
|
|
RETURN_ON_FAILURE(OuterQueryInterface(
|
|
__uuidof(IADs),
|
|
reinterpret_cast<void**>(&m_pADs)
|
|
));
|
|
///////////////////////////////////////////////////////
|
|
// Figure out the domain or server name using Pathname
|
|
///////////////////////////////////////////////////////
|
|
CComBSTR BstrPath;
|
|
hr = m_pADs->get_ADsPath(&BstrPath);
|
|
m_pADs.p->Release();
|
|
|
|
if (!SUCCEEDED(hr))
|
|
return hr;
|
|
|
|
CComBSTR BstrProvider;
|
|
m_StaticCritSec.Lock();
|
|
do
|
|
{
|
|
if ( !m_StaticpPath )
|
|
{
|
|
BREAK_ON_FAILURE(CoCreateInstance(
|
|
__uuidof(Pathname),
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
__uuidof(IADsPathname),
|
|
reinterpret_cast<void**>(&m_StaticpPath )
|
|
));
|
|
}
|
|
|
|
/////////////////////////////////////////
|
|
// Get the provider used (WinNT or LDAP)
|
|
/////////////////////////////////////////
|
|
BREAK_ON_FAILURE(m_StaticpPath->Set(
|
|
BstrPath,
|
|
ADS_SETTYPE_FULL
|
|
));
|
|
|
|
BREAK_ON_FAILURE(m_StaticpPath->Retrieve(
|
|
ADS_FORMAT_PROVIDER,
|
|
&BstrProvider
|
|
));
|
|
|
|
// Check for "WinNT" and "LDAP"
|
|
// return E_FAIL for other providers
|
|
if ( lstrcmpW(BstrProvider,L"WinNT") == 0 )
|
|
{
|
|
m_vbIsLDAP = VARIANT_FALSE;
|
|
hr = GetInfoWinNT(m_StaticpPath );
|
|
}
|
|
else if ( lstrcmpW(BstrProvider,L"LDAP") == 0 )
|
|
{
|
|
m_vbIsLDAP = VARIANT_TRUE;
|
|
hr = GetInfoLDAP(m_StaticpPath );
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
while (FALSE);
|
|
|
|
|
|
m_StaticCritSec.Unlock();
|
|
|
|
break;
|
|
}
|
|
case ADS_EXT_INITIALIZE_COMPLETE:
|
|
default:
|
|
{
|
|
// Default case should not fail
|
|
break;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// ADsTSUserEx::PrivateGetIDsOfNames
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP ADsTSUserEx::PrivateGetIDsOfNames(const struct _GUID &riid,
|
|
USHORT** rgszNames,
|
|
UINT cNames,
|
|
ULONG lcid,
|
|
LONG* rgdispid)
|
|
{
|
|
if ( !rgdispid )
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
return m_StaticHolder.GetIDsOfNames(riid, rgszNames, cNames, lcid,
|
|
rgdispid);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// ADsTSUserEx::PrivateInvoke
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP ADsTSUserEx::PrivateInvoke(LONG dispidMember,
|
|
const struct _GUID &riid,
|
|
ULONG lcid,
|
|
USHORT wFlags,
|
|
DISPPARAMS* pdispparams,
|
|
VARIANT* pvarResult,
|
|
EXCEPINFO* pexcepinfo,
|
|
UINT* puArgErr)
|
|
{
|
|
return m_StaticHolder.Invoke(this, dispidMember, riid, lcid, wFlags,
|
|
pdispparams, pvarResult, pexcepinfo,
|
|
puArgErr);
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////
|
|
// Delegating IDispatch Methods to the aggregator
|
|
//////////////////////////////////////////////////////
|
|
STDMETHODIMP ADsTSUserEx::GetTypeInfoCount(UINT* pctinfo)
|
|
{
|
|
|
|
if ( !m_pOuterDispatch )
|
|
{
|
|
RETURN_ON_FAILURE(OuterQueryInterface(
|
|
__uuidof(IDispatch),
|
|
reinterpret_cast<void**>(&m_pOuterDispatch)
|
|
));
|
|
}
|
|
|
|
return m_pOuterDispatch->GetTypeInfoCount( pctinfo );
|
|
|
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
|
|
{
|
|
|
|
if ( !m_pOuterDispatch )
|
|
{
|
|
RETURN_ON_FAILURE(OuterQueryInterface(
|
|
__uuidof(IDispatch),
|
|
reinterpret_cast<void**>(&m_pOuterDispatch)
|
|
));
|
|
}
|
|
|
|
return m_pOuterDispatch->GetTypeInfo( itinfo, lcid, pptinfo );
|
|
|
|
}
|
|
|
|
STDMETHODIMP ADsTSUserEx::GetIDsOfNames(REFIID riid,
|
|
LPOLESTR* rgszNames,
|
|
UINT cNames,
|
|
LCID lcid,
|
|
DISPID* rgdispid)
|
|
{
|
|
|
|
if ( !m_pOuterDispatch )
|
|
{
|
|
RETURN_ON_FAILURE(OuterQueryInterface(
|
|
__uuidof(IDispatch),
|
|
reinterpret_cast<void**>(&m_pOuterDispatch)
|
|
));
|
|
}
|
|
|
|
return m_pOuterDispatch->GetIDsOfNames(riid, rgszNames, cNames, lcid,
|
|
rgdispid);
|
|
|
|
|
|
|
|
}
|
|
|
|
STDMETHODIMP ADsTSUserEx::Invoke(DISPID dispidMember, REFIID riid,
|
|
LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT*
|
|
pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
|
|
{
|
|
IDispatch *pDisp;
|
|
HRESULT hr = S_OK;
|
|
hr = OuterQueryInterface( IID_IDispatch, (void**) &pDisp );
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = pDisp->Invoke( dispidMember, riid, lcid, wFlags,
|
|
pdispparams, pvarResult, pexcepinfo, puArgErr);
|
|
pDisp->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// End delegating IDispatch Methods
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_TerminalServicesProfilePath(BSTR *pVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalGetString(WIN_WFPROFILEPATH, pVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_TerminalServicesProfilePath(BSTR pNewVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalSetString(WIN_WFPROFILEPATH, pNewVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_TerminalServicesHomeDirectory(BSTR *pVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalGetString(WIN_WFHOMEDIR, pVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_TerminalServicesHomeDirectory(BSTR pNewVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
BSTR bstrVal = NULL;
|
|
|
|
if(pNewVal && PathIsUNC(pNewVal))
|
|
{
|
|
//There sould be some value for HomeDrive
|
|
|
|
InternalGetString(WIN_WFHOMEDIRDRIVE, &bstrVal);
|
|
|
|
if(!bstrVal || !SysStringLen(bstrVal))
|
|
{
|
|
if(bstrVal)
|
|
{
|
|
SysFreeString(bstrVal);
|
|
}
|
|
|
|
bstrVal = SysAllocString(L"Z:");
|
|
|
|
if(bstrVal)
|
|
{
|
|
InternalSetString(WIN_WFHOMEDIRDRIVE, bstrVal);
|
|
SysFreeString(bstrVal);
|
|
bstrVal = NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Local path or empty path
|
|
//Reset HomeDrive.
|
|
bstrVal = SysAllocString(L"");
|
|
|
|
if(bstrVal)
|
|
{
|
|
InternalSetString(WIN_WFHOMEDIRDRIVE, bstrVal);
|
|
SysFreeString(bstrVal);
|
|
bstrVal = NULL;
|
|
}
|
|
}
|
|
|
|
return InternalSetString(WIN_WFHOMEDIR, pNewVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_TerminalServicesHomeDrive(BSTR *pVal) throw()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
hr = InternalGetString(WIN_WFHOMEDIRDRIVE, pVal);
|
|
|
|
if(pVal && !SysStringLen(*pVal))
|
|
{
|
|
BSTR bstrVal = NULL;
|
|
|
|
InternalGetString(WIN_WFHOMEDIR, &bstrVal);
|
|
|
|
if(bstrVal && PathIsUNC(bstrVal))
|
|
{
|
|
*pVal = SysAllocString(L"Z:");
|
|
}
|
|
|
|
if(bstrVal)
|
|
{
|
|
SysFreeString(bstrVal);
|
|
bstrVal = NULL;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_TerminalServicesHomeDrive(BSTR pNewVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
if(!pNewVal || !SysStringLen(pNewVal))
|
|
{
|
|
return InternalSetString(WIN_WFHOMEDIRDRIVE, pNewVal);
|
|
}
|
|
|
|
if(SysStringLen(pNewVal) > 2)
|
|
{
|
|
return E_ADS_BAD_PARAMETER;
|
|
}
|
|
CharUpper( pNewVal );
|
|
|
|
if( *pNewVal >= 'C' && *pNewVal <= 'Z' && (_tcschr(pNewVal, _T(':'))!=NULL ))
|
|
{
|
|
return InternalSetString(WIN_WFHOMEDIRDRIVE, pNewVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_BAD_PARAMETER;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_AllowLogon(LONG *pVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LONG lLogon = 0;
|
|
|
|
hr = InternalGetLong(WIN_FLAGS1, &lLogon);
|
|
RETURN_ON_FAILURE(hr);
|
|
|
|
*pVal = (lLogon & F1MSK_LOGONDISABLED) ? 0 : 1;
|
|
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_AllowLogon(LONG NewVal) throw()
|
|
{
|
|
RETURN_ON_INVALID_PARAMETER(NewVal);
|
|
NewVal = NewVal? 0 : 1;
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalSetLong(F1MSK_LOGONDISABLED, NewVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_EnableRemoteControl(LONG *pVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LONG lShadow = 0;
|
|
|
|
hr = InternalGetLong(WIN_SHADOW, &lShadow);
|
|
|
|
RETURN_ON_FAILURE(hr);
|
|
|
|
*pVal = lShadow;
|
|
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_EnableRemoteControl(LONG NewVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
if(NewVal < 0 || NewVal > 4)
|
|
{
|
|
return E_ADS_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
return InternalSetValue(WIN_SHADOW, NewVal);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_MaxDisconnectionTime(LONG *pVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
hr = InternalGetLong(WIN_MAXDISCONNECTIONTIME, pVal);
|
|
|
|
RETURN_ON_FAILURE(hr);
|
|
|
|
*pVal /= INMINUTES;
|
|
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_MaxDisconnectionTime(LONG NewVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
if(NewVal < 0 || NewVal > MAX_TIME_LIMIT )
|
|
{
|
|
return E_ADS_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
return InternalSetValue(WIN_MAXDISCONNECTIONTIME, NewVal*INMINUTES);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_MaxConnectionTime(LONG *pVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
hr = InternalGetLong(WIN_MAXCONNECTIONTIME, pVal);
|
|
|
|
RETURN_ON_FAILURE(hr);
|
|
|
|
*pVal /= INMINUTES;
|
|
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_MaxConnectionTime(LONG NewVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
if(NewVal < 0 || NewVal > MAX_TIME_LIMIT )
|
|
{
|
|
return E_ADS_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
return InternalSetValue(WIN_MAXCONNECTIONTIME, NewVal*INMINUTES);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_MaxIdleTime(LONG *pVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
hr = InternalGetLong(WIN_MAXIDLETIME, pVal);
|
|
|
|
RETURN_ON_FAILURE(hr);
|
|
|
|
*pVal /= INMINUTES;
|
|
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_MaxIdleTime(LONG NewVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
if(NewVal < 0 || NewVal > MAX_TIME_LIMIT )
|
|
{
|
|
return E_ADS_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
return InternalSetValue(WIN_MAXIDLETIME, NewVal*INMINUTES);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_ReconnectionAction(LONG *pVal) throw()
|
|
{
|
|
LONG lDisconnect;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
hr = InternalGetLong(WIN_FLAGS1, &lDisconnect);
|
|
|
|
RETURN_ON_FAILURE(hr);
|
|
|
|
*pVal = (lDisconnect & F1MSK_RECONNECTSAME) ? 1 : 0;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_ReconnectionAction(LONG NewVal) throw()
|
|
{
|
|
RETURN_ON_INVALID_PARAMETER(NewVal);
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalSetLong(F1MSK_RECONNECTSAME, NewVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_BrokenConnectionAction(LONG *pVal) throw()
|
|
{
|
|
LONG lReconnect;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
hr = InternalGetLong(WIN_FLAGS1, &lReconnect);
|
|
|
|
RETURN_ON_FAILURE(hr);
|
|
|
|
*pVal = (lReconnect & F1MSK_RESETBROKEN) ? 1 : 0;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_BrokenConnectionAction(LONG NewVal) throw()
|
|
{
|
|
RETURN_ON_INVALID_PARAMETER(NewVal);
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalSetLong(F1MSK_RESETBROKEN, NewVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_ConnectClientDrivesAtLogon(LONG *pVal) throw()
|
|
{
|
|
|
|
LONG lAutoClientDrives;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
hr = InternalGetLong(WIN_FLAGS1, &lAutoClientDrives);
|
|
|
|
RETURN_ON_FAILURE(hr);
|
|
|
|
if (lAutoClientDrives & F1MSK_AUTOCLIENTDRIVES)
|
|
{
|
|
*pVal = 1;
|
|
}
|
|
else
|
|
{
|
|
*pVal = 0;
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_ConnectClientDrivesAtLogon(LONG NewVal) throw()
|
|
{
|
|
RETURN_ON_INVALID_PARAMETER(NewVal);
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalSetLong(F1MSK_AUTOCLIENTDRIVES, NewVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_ConnectClientPrintersAtLogon(LONG *pVal) throw()
|
|
{
|
|
|
|
LONG lAutoClientPrinters;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
hr = InternalGetLong(WIN_FLAGS1, &lAutoClientPrinters);
|
|
|
|
RETURN_ON_FAILURE(hr);
|
|
|
|
if (lAutoClientPrinters & F1MSK_AUTOCLIENTLPTS)
|
|
{
|
|
*pVal = 1;
|
|
}
|
|
else
|
|
{
|
|
*pVal = 0;
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_ConnectClientPrintersAtLogon(LONG NewVal) throw()
|
|
{
|
|
RETURN_ON_INVALID_PARAMETER(NewVal);
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalSetLong(F1MSK_AUTOCLIENTLPTS, NewVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_DefaultToMainPrinter(LONG *pVal) throw()
|
|
{
|
|
|
|
LONG lDefaultPrinter;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
hr = InternalGetLong(WIN_FLAGS1, &lDefaultPrinter);
|
|
|
|
RETURN_ON_FAILURE(hr);
|
|
|
|
if (lDefaultPrinter & F1MSK_FORCECLIENTLPTDEF)
|
|
{
|
|
*pVal = 1;
|
|
}
|
|
else
|
|
{
|
|
*pVal = 0;
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_DefaultToMainPrinter(LONG NewVal) throw()
|
|
{
|
|
RETURN_ON_INVALID_PARAMETER(NewVal);
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalSetLong(F1MSK_FORCECLIENTLPTDEF, NewVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_TerminalServicesWorkDirectory(BSTR *pVal) throw()
|
|
{
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalGetString(WIN_WORKDIRECTORY, pVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_TerminalServicesWorkDirectory(BSTR pNewVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalSetString(WIN_WORKDIRECTORY, pNewVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::get_TerminalServicesInitialProgram(BSTR *pVal) throw()
|
|
{
|
|
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalGetString(WIN_INITIALPROGRAM, pVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP ADsTSUserEx::put_TerminalServicesInitialProgram(BSTR pNewVal) throw()
|
|
{
|
|
if (m_vbUpLevelAllowed)
|
|
{
|
|
return InternalSetString(WIN_INITIALPROGRAM, pNewVal);
|
|
}
|
|
else
|
|
{
|
|
return E_ADS_PROPERTY_NOT_FOUND;
|
|
}
|
|
}
|