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.
1345 lines
30 KiB
1345 lines
30 KiB
/*++
|
|
|
|
Copyright (c) 1999-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
HelpTab.h
|
|
|
|
Abstract:
|
|
|
|
Declaration __HelpEntry structure and CHelpSessionTable.
|
|
|
|
Author:
|
|
|
|
HueiWang 06/29/2000
|
|
|
|
--*/
|
|
#ifndef __CHELPSESSIONTABLE_H__
|
|
#define __CHELPSESSIONTABLE_H__
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
|
|
|
|
#define REGKEY_HELPSESSIONTABLE REG_CONTROL_HELPSESSIONENTRY
|
|
#define REGKEY_HELPENTRYBACKUP _TEXT("Backup")
|
|
|
|
#define REGVALUE_HELPSESSIONTABLE_DIRTY _TEXT("Dirty")
|
|
#define REGVALUE_HELPSESSION_DIRTY REGVALUE_HELPSESSIONTABLE_DIRTY
|
|
|
|
|
|
#define COLUMNNAME_SESSIONID _TEXT("SessionId")
|
|
#define COLUMNNAME_SESSIONNAME _TEXT("SessionName")
|
|
#define COLUMNNAME_SESSIONPWD _TEXT("SessionPwd")
|
|
#define COLUMNNAME_SESSIONDESC _TEXT("SessionDesc")
|
|
#define COLUMNNAME_SESSIONCREATEBLOB _TEXT("SessionCreateBlob")
|
|
#define COLUMNNAME_ENABLESESSIONRESOLVER _TEXT("EnableResolver")
|
|
#define COLUMNNAME_SESSIONRESOLVERBLOB _TEXT("Blob")
|
|
#define COLUMNNAME_SESSIONUSERID _TEXT("UserSID")
|
|
#define COLUMNNAME_CREATETIME _TEXT("CreationTime")
|
|
#define COLUMNNAME_RDSSETTING _TEXT("RDS Setting")
|
|
#define COLUMNNAME_KEYSTATUS _TEXT("Entry Status")
|
|
#define COLUMNNAME_EXPIRATIONTIME _TEXT("ExpirationTime")
|
|
|
|
#define COLUMNNAME_ICSPORT _TEXT("ICS Port")
|
|
#define COLUMNNAME_IPADDRESS _TEXT("IP Address")
|
|
|
|
#define ENTRY_VALID_PERIOD 30 // 30 days.
|
|
|
|
#define REGVALUE_HELPSESSION_ENTRY_NORMAL 1
|
|
#define REGVALUE_HELPSESSION_ENTRY_NEW 2
|
|
#define REGVALUE_HELPSESSION_ENTRY_DIRTY 3
|
|
#define REGVALUE_HELPSESSION_ENTRY_DELETED 4
|
|
#define REGVALUE_HELPSESSION_ENTRY_DELETEONSTARTUP 5
|
|
|
|
//
|
|
// Default value
|
|
static FILETIME defaultCreationTime = {0, 0};
|
|
|
|
struct __HelpEntry;
|
|
|
|
typedef __HelpEntry HELPENTRY;
|
|
typedef __HelpEntry* PHELPENTRY;
|
|
|
|
|
|
// similar to CComPtr
|
|
template <class T>
|
|
class BaseAccess : public T
|
|
{
|
|
};
|
|
|
|
//
|
|
// Template class for column value of registry DB,
|
|
// All column type must be derived from this template.
|
|
//
|
|
template <class T>
|
|
class HelpColumnValueBase {
|
|
|
|
//friend bool __cdecl
|
|
//operator==<>( const T& v1, const HelpColumnValueBase<T>& v2 );
|
|
|
|
//friend bool __cdecl
|
|
//operator==<>( const HelpColumnValueBase<T>& v2, const T& v1 );
|
|
|
|
private:
|
|
|
|
// copy of current value
|
|
T m_Value;
|
|
|
|
// Entry value has been modified and not yet
|
|
// written to registry/
|
|
BOOL m_bDirty;
|
|
|
|
// Registry value name
|
|
LPCTSTR m_pszColumnName;
|
|
|
|
// default value
|
|
T m_Default;
|
|
|
|
// HKEY to registry
|
|
HKEY m_hEntryKey;
|
|
|
|
// Reference to critical section, note
|
|
// we don't want to use one critical section for
|
|
// a value to conserve resource
|
|
CCriticalSection& m_Lock;
|
|
|
|
|
|
// TRUE if registry value will be updated immediately
|
|
// to reflect changes in m_Value
|
|
BOOL m_ImmediateUpdate;
|
|
|
|
//
|
|
// Encrypt data
|
|
//
|
|
const BOOL m_bEncrypt;
|
|
|
|
//
|
|
// Default implementation of GetValue(),
|
|
// GetValueSize(), GetValueType(), and
|
|
// SetValue(). These routine is used when
|
|
// writting to/reading from registry.
|
|
//
|
|
virtual const PBYTE
|
|
GetValue()
|
|
{
|
|
return (PBYTE)&m_Value;
|
|
}
|
|
|
|
virtual DWORD
|
|
GetValueSize()
|
|
{
|
|
return sizeof(m_Value);
|
|
}
|
|
|
|
virtual DWORD
|
|
GetValueType()
|
|
{
|
|
return REG_BINARY;
|
|
}
|
|
|
|
virtual BOOL
|
|
SetValue( PVOID pbData, DWORD cbData )
|
|
{
|
|
m_Value = *(T *)pbData;
|
|
return TRUE;
|
|
}
|
|
|
|
public:
|
|
|
|
//
|
|
// TRUE if registry value is updated right away, FALSE
|
|
// otherwise.
|
|
BOOL
|
|
IsImmediateUpdate()
|
|
{
|
|
return (NULL != m_hEntryKey && TRUE == m_ImmediateUpdate);
|
|
}
|
|
|
|
// similar to CComPtr
|
|
BaseAccess<T>* operator->() const
|
|
{
|
|
return (BaseAccess<T>*)&m_Value;
|
|
}
|
|
|
|
HelpColumnValueBase(
|
|
IN CCriticalSection& entryLock, // reference to critical section
|
|
IN HKEY hEntryKey, // HKEY to registry, can be NULL
|
|
IN LPCTSTR pszColumnName, // Name of registry value.
|
|
IN T DefaultValue, // Default value if value not in registry
|
|
IN BOOL bImmediateUpdate, // Update mode
|
|
IN BOOL bEncrypt = FALSE
|
|
) :
|
|
m_Lock(entryLock),
|
|
m_hEntryKey(hEntryKey),
|
|
m_bDirty(FALSE),
|
|
m_pszColumnName(pszColumnName),
|
|
m_Default(DefaultValue),
|
|
m_Value(DefaultValue),
|
|
m_ImmediateUpdate(bImmediateUpdate),
|
|
m_bEncrypt(bEncrypt)
|
|
{
|
|
}
|
|
|
|
//~HelpColumnValueBase()
|
|
//{
|
|
// m_Default.~T();
|
|
//}
|
|
|
|
HelpColumnValueBase&
|
|
operator=(const T& newVal)
|
|
{
|
|
DWORD dwStatus;
|
|
T orgValue;
|
|
|
|
CCriticalSectionLocker l(m_Lock);
|
|
|
|
m_bDirty = TRUE;
|
|
orgValue = m_Value;
|
|
m_Value = newVal;
|
|
|
|
if( TRUE == IsImmediateUpdate() )
|
|
{
|
|
dwStatus = DBUpdateValue(NULL);
|
|
|
|
MYASSERT(ERROR_SUCCESS == dwStatus);
|
|
|
|
if( ERROR_SUCCESS != dwStatus )
|
|
{
|
|
// restore value
|
|
m_Value = orgValue;
|
|
}
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
HelpColumnValueBase&
|
|
operator=(const HelpColumnValueBase& newVal)
|
|
{
|
|
if( this != &newVal )
|
|
{
|
|
CCriticalSectionLocker l(m_Lock);
|
|
m_Value = newVal.m_Value;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
bool
|
|
operator==(const T& v) const
|
|
{
|
|
return v == m_Value;
|
|
}
|
|
|
|
operator T()
|
|
{
|
|
return m_Value;
|
|
}
|
|
|
|
// Load value from registry
|
|
DWORD
|
|
DBLoadValue(
|
|
IN HKEY hKey
|
|
);
|
|
|
|
// update registry value
|
|
DWORD
|
|
DBUpdateValue(
|
|
IN HKEY hKey
|
|
);
|
|
|
|
// delete registry value
|
|
DWORD
|
|
DBDeleteValue(
|
|
IN HKEY hKey
|
|
);
|
|
|
|
// Change has been made but value has not
|
|
// been written to registry
|
|
BOOL
|
|
IsDirty()
|
|
{
|
|
return m_bDirty;
|
|
}
|
|
|
|
// Set immediate update mode.
|
|
void
|
|
EnableImmediateUpdate(
|
|
BOOL bImmediateUpdate
|
|
)
|
|
/*++
|
|
--*/
|
|
{
|
|
m_ImmediateUpdate = bImmediateUpdate;
|
|
}
|
|
|
|
// Change registry location for the value.
|
|
HKEY
|
|
SetRegStoreHandle(
|
|
IN HKEY hKey
|
|
)
|
|
/*++
|
|
|
|
--*/
|
|
{
|
|
HKEY oldKey = m_hEntryKey;
|
|
|
|
m_hEntryKey = hKey;
|
|
return oldKey;
|
|
}
|
|
};
|
|
|
|
//template <class T>
|
|
//bool __cdecl operator==( const T& v1, const HelpColumnValueBase<T>& v2 )
|
|
//{
|
|
// return v1 == v2.m_Value;
|
|
//}
|
|
|
|
//template <class T>
|
|
//bool __cdecl operator==( const HelpColumnValueBase<T>& v2, const T& v1 )
|
|
//{
|
|
// return v1 == v2.m_Value;
|
|
//}
|
|
|
|
template <class T>
|
|
DWORD
|
|
HelpColumnValueBase<T>::DBDeleteValue(
|
|
IN HKEY hKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete registry value for the column.
|
|
|
|
Parameter:
|
|
|
|
hKey : Handle to HKEY where the value is stored, NULL will use default
|
|
registry location passed in at object construction time or
|
|
SetRegStoreHandle()
|
|
|
|
Returns
|
|
|
|
ERROR_SUCCESS or error code.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
|
|
if( NULL == hKey )
|
|
{
|
|
hKey = m_hEntryKey;
|
|
}
|
|
|
|
//
|
|
// if no registry handle, no update is necessary,
|
|
// assume it is a memory only value.
|
|
//
|
|
|
|
if( NULL != hKey )
|
|
{
|
|
CCriticalSectionLocker l( m_Lock );
|
|
|
|
dwStatus = RegDeleteValue(
|
|
hKey,
|
|
m_pszColumnName
|
|
);
|
|
|
|
if( ERROR_SUCCESS == dwStatus )
|
|
{
|
|
m_bDirty = TRUE;
|
|
}
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
template <class T>
|
|
DWORD
|
|
HelpColumnValueBase<T>::DBUpdateValue(
|
|
IN HKEY hKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Update registry value.
|
|
|
|
Parameters:
|
|
|
|
hKey : Handle to registry key, NULL if use current location
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS or error code.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
|
|
if( NULL == hKey )
|
|
{
|
|
hKey = m_hEntryKey;
|
|
}
|
|
|
|
if( NULL != hKey )
|
|
{
|
|
// if value size is 0, no need to write anything to
|
|
// registry, instead delete it to save some
|
|
// space and let default value take care of reading.
|
|
if( 0 == GetValueSize() )
|
|
{
|
|
dwStatus = RegDeleteValue(
|
|
hKey,
|
|
m_pszColumnName
|
|
);
|
|
|
|
if( ERROR_FILE_NOT_FOUND == dwStatus || ERROR_SUCCESS == dwStatus )
|
|
{
|
|
// no value in registry
|
|
dwStatus = ERROR_SUCCESS;
|
|
m_bDirty = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PBYTE pbData = NULL;
|
|
DWORD cbData = 0;
|
|
|
|
cbData = GetValueSize();
|
|
|
|
if( m_bEncrypt )
|
|
{
|
|
pbData = (PBYTE)LocalAlloc( LPTR, cbData );
|
|
|
|
if( NULL == pbData )
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
memcpy( pbData, GetValue(), cbData );
|
|
dwStatus = TSHelpAssistantEncryptData(
|
|
NULL,
|
|
pbData,
|
|
&cbData
|
|
);
|
|
}
|
|
else
|
|
{
|
|
pbData = GetValue();
|
|
}
|
|
|
|
if( ERROR_SUCCESS == dwStatus )
|
|
{
|
|
dwStatus = RegSetValueEx(
|
|
hKey,
|
|
m_pszColumnName,
|
|
NULL,
|
|
GetValueType(),
|
|
pbData,
|
|
cbData
|
|
);
|
|
}
|
|
|
|
if( m_bEncrypt && NULL != pbData )
|
|
{
|
|
LocalFree( pbData );
|
|
}
|
|
}
|
|
|
|
if( ERROR_SUCCESS == dwStatus )
|
|
{
|
|
m_bDirty = FALSE;
|
|
}
|
|
}
|
|
|
|
CLEANUPANDEXIT:
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
template <class T>
|
|
DWORD
|
|
HelpColumnValueBase<T>::DBLoadValue(
|
|
IN HKEY hKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Load value from registry.
|
|
|
|
Parameters:
|
|
|
|
hKey : Registry handle to read the value from, NULL if uses
|
|
current location.
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS or error code.
|
|
|
|
--*/
|
|
{
|
|
PBYTE pbData = NULL;
|
|
DWORD cbData = 0;
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD dwType;
|
|
|
|
if( NULL == hKey )
|
|
{
|
|
hKey = m_hEntryKey;
|
|
}
|
|
|
|
if( NULL != hKey )
|
|
{
|
|
CCriticalSectionLocker l( m_Lock );
|
|
|
|
dwStatus = RegQueryValueEx(
|
|
hKey,
|
|
m_pszColumnName,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&cbData
|
|
);
|
|
|
|
if( ERROR_SUCCESS == dwStatus )
|
|
{
|
|
if( dwType == GetValueType() )
|
|
{
|
|
// we only read registry value that has expected data
|
|
// type
|
|
pbData = (PBYTE) LocalAlloc( LPTR, cbData );
|
|
if( NULL != pbData )
|
|
{
|
|
dwStatus = RegQueryValueEx(
|
|
hKey,
|
|
m_pszColumnName,
|
|
NULL,
|
|
&dwType,
|
|
pbData,
|
|
&cbData
|
|
);
|
|
|
|
if( ERROR_SUCCESS == dwStatus )
|
|
{
|
|
if( m_bEncrypt )
|
|
{
|
|
dwStatus = TSHelpAssistantDecryptData(
|
|
NULL,
|
|
pbData,
|
|
&cbData
|
|
);
|
|
|
|
}
|
|
|
|
if( ERROR_SUCCESS == dwStatus )
|
|
{
|
|
if( FALSE == SetValue(pbData, cbData) )
|
|
{
|
|
dwStatus = GetLastError();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwStatus = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// bad data type, delete it and use default value
|
|
(void)RegDeleteValue(
|
|
hKey,
|
|
m_pszColumnName
|
|
);
|
|
|
|
dwStatus = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
if( ERROR_FILE_NOT_FOUND == dwStatus )
|
|
{
|
|
// pick the default value if no value in registry
|
|
m_Value = m_Default;
|
|
dwStatus = ERROR_SUCCESS;
|
|
}
|
|
|
|
if( ERROR_SUCCESS == dwStatus )
|
|
{
|
|
m_bDirty = FALSE;
|
|
}
|
|
}
|
|
|
|
if( NULL != pbData )
|
|
{
|
|
LocalFree(pbData);
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
//
|
|
// GetValueType(), GetValueSize() for long registry value type.
|
|
//
|
|
inline DWORD
|
|
HelpColumnValueBase<long>::GetValueType()
|
|
{
|
|
return REG_DWORD;
|
|
}
|
|
|
|
inline DWORD
|
|
HelpColumnValueBase<long>::GetValueSize()
|
|
{
|
|
return sizeof(DWORD);
|
|
}
|
|
|
|
//
|
|
// GetValueType(), GetValueSize() for REMOTE_DESKTOP_SHARING_CLASS
|
|
// registry value type.
|
|
//
|
|
inline DWORD
|
|
HelpColumnValueBase<REMOTE_DESKTOP_SHARING_CLASS>::GetValueType()
|
|
{
|
|
return REG_DWORD;
|
|
}
|
|
|
|
inline DWORD
|
|
HelpColumnValueBase<REMOTE_DESKTOP_SHARING_CLASS>::GetValueSize()
|
|
{
|
|
return sizeof(DWORD);
|
|
}
|
|
|
|
//
|
|
// GetValue(), GetValueType(), GetValueSize(), SetValue() implmentation
|
|
// for CComBSTR
|
|
//
|
|
inline const PBYTE
|
|
HelpColumnValueBase<CComBSTR>::GetValue()
|
|
{
|
|
return (PBYTE)(LPTSTR)m_Value;
|
|
}
|
|
|
|
inline DWORD
|
|
HelpColumnValueBase<CComBSTR>::GetValueType()
|
|
{
|
|
return ( m_bEncrypt ) ? REG_BINARY : REG_SZ;
|
|
}
|
|
|
|
inline DWORD
|
|
HelpColumnValueBase<CComBSTR>::GetValueSize()
|
|
{
|
|
DWORD dwValueSize;
|
|
|
|
if( m_Value.Length() == 0 )
|
|
{
|
|
dwValueSize = 0;
|
|
}
|
|
else
|
|
{
|
|
dwValueSize = ( m_Value.Length() + 1 ) * sizeof(TCHAR);
|
|
}
|
|
|
|
return dwValueSize;
|
|
}
|
|
|
|
inline BOOL
|
|
HelpColumnValueBase<CComBSTR>::SetValue( PVOID pbData, DWORD cbData )
|
|
{
|
|
m_Value = (LPTSTR)pbData;
|
|
return TRUE;
|
|
}
|
|
|
|
typedef MAP< CComBSTR, PHELPENTRY > HelpEntryCache;
|
|
typedef HRESULT (WINAPI* EnumHelpEntryCallback)(
|
|
IN CComBSTR& bstrHelpId,
|
|
IN HANDLE userData
|
|
);
|
|
|
|
|
|
//
|
|
//
|
|
// CHelpSessionTable class
|
|
//
|
|
class CHelpSessionTable {
|
|
|
|
private:
|
|
|
|
typedef struct __EnumHelpEntryParm {
|
|
EnumHelpEntryCallback pCallback;
|
|
CHelpSessionTable* pTable;
|
|
HANDLE userData;
|
|
} EnumHelpEntryParm, *PEnumHelpEntryParm;
|
|
|
|
|
|
HKEY m_hHelpSessionTableKey;
|
|
/*static*/ HelpEntryCache m_HelpEntryCache;
|
|
DWORD m_NumHelp;
|
|
CComBSTR m_bstrFileName;
|
|
CCriticalSection m_TableLock;
|
|
|
|
DWORD m_dwEntryValidPeriod;
|
|
|
|
static HRESULT
|
|
RestoreHelpSessionTable(
|
|
HKEY hKey,
|
|
LPTSTR pszKeyName,
|
|
HANDLE userData
|
|
);
|
|
|
|
static HRESULT
|
|
EnumOpenHelpEntry(
|
|
HKEY hKey,
|
|
LPTSTR pszKeyName,
|
|
HANDLE userData
|
|
);
|
|
|
|
HRESULT
|
|
RestoreHelpSessionEntry(
|
|
HKEY hKey,
|
|
LPTSTR pszKeyName
|
|
);
|
|
|
|
HRESULT
|
|
LoadHelpEntry(
|
|
HKEY hKey,
|
|
LPTSTR pszKeyName,
|
|
PHELPENTRY* pHelpEntry
|
|
);
|
|
|
|
public:
|
|
|
|
void
|
|
LockHelpTable()
|
|
{
|
|
m_TableLock.Lock();
|
|
}
|
|
|
|
void
|
|
UnlockHelpTable()
|
|
{
|
|
m_TableLock.UnLock();
|
|
}
|
|
|
|
CHelpSessionTable();
|
|
~CHelpSessionTable();
|
|
|
|
static HRESULT
|
|
CreatePendingHelpTable();
|
|
|
|
// open help session table
|
|
HRESULT
|
|
OpenSessionTable(
|
|
IN LPCTSTR pszFileName
|
|
);
|
|
|
|
// close help session table
|
|
HRESULT
|
|
CloseSessionTable();
|
|
|
|
// Delete help session table
|
|
HRESULT
|
|
DeleteSessionTable();
|
|
|
|
// open a help session entry
|
|
HRESULT
|
|
OpenHelpEntry(
|
|
IN const CComBSTR& bstrHelpSession,
|
|
OUT PHELPENTRY* pHelpEntry
|
|
);
|
|
|
|
// create a help session entry
|
|
HRESULT
|
|
CreateInMemoryHelpEntry(
|
|
IN const CComBSTR& bstrHelpSession,
|
|
OUT PHELPENTRY* pHelpEntry
|
|
);
|
|
|
|
HRESULT
|
|
MemEntryToStorageEntry(
|
|
IN PHELPENTRY pHelpEntry
|
|
);
|
|
|
|
|
|
// delete a help session entry
|
|
HRESULT
|
|
DeleteHelpEntry(
|
|
IN const CComBSTR& bstrHelpSession
|
|
);
|
|
|
|
// remove help entry from cache
|
|
HRESULT
|
|
ReleaseHelpEntry(
|
|
IN CComBSTR& bstrHelpSession
|
|
);
|
|
|
|
HRESULT
|
|
EnumHelpEntry(
|
|
IN EnumHelpEntryCallback pFunc,
|
|
IN HANDLE userData
|
|
);
|
|
|
|
DWORD
|
|
NumEntries() { return m_NumHelp; }
|
|
|
|
BOOL
|
|
IsEntryExpired(
|
|
PHELPENTRY pHelpEntry
|
|
);
|
|
};
|
|
|
|
|
|
//
|
|
// __HelpEntry structure contains a single help entry.
|
|
//
|
|
struct __HelpEntry {
|
|
|
|
friend class CHelpSessionTable;
|
|
|
|
private:
|
|
|
|
CHelpSessionTable& m_pHelpSessionTable;
|
|
CCriticalSection m_Lock;
|
|
HKEY m_hEntryKey;
|
|
LONG m_RefCount;
|
|
//LONG m_Status;
|
|
|
|
HRESULT
|
|
BackupEntry();
|
|
|
|
HRESULT
|
|
RestoreEntryFromBackup();
|
|
|
|
HRESULT
|
|
DeleteEntryBackup();
|
|
|
|
|
|
LONG
|
|
AddRef()
|
|
{
|
|
DebugPrintf(
|
|
_TEXT("HelpEntry %p AddRef %d\n"),
|
|
this,
|
|
m_RefCount
|
|
);
|
|
|
|
return InterlockedIncrement( &m_RefCount );
|
|
}
|
|
|
|
LONG
|
|
Release()
|
|
{
|
|
DebugPrintf(
|
|
_TEXT("HelpEntry %p Release %d\n"),
|
|
this,
|
|
m_RefCount
|
|
);
|
|
|
|
if( 0 >= InterlockedDecrement( &m_RefCount ) )
|
|
{
|
|
MYASSERT( 0 == m_RefCount );
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return m_RefCount;
|
|
}
|
|
|
|
HRESULT
|
|
UpdateEntryValues(
|
|
HKEY hKey
|
|
);
|
|
|
|
HRESULT
|
|
LoadEntryValues(
|
|
HKEY hKey
|
|
);
|
|
|
|
void
|
|
EnableImmediateUpdate(
|
|
BOOL bImmediate
|
|
)
|
|
/*++
|
|
|
|
--*/
|
|
{
|
|
m_EnableResolver.EnableImmediateUpdate( bImmediate );
|
|
m_SessResolverBlob.EnableImmediateUpdate( bImmediate );
|
|
m_UserSID.EnableImmediateUpdate( bImmediate );
|
|
m_SessionRdsSetting.EnableImmediateUpdate( bImmediate );
|
|
m_SessionId.EnableImmediateUpdate( bImmediate );
|
|
m_CreationTime.EnableImmediateUpdate( bImmediate );
|
|
m_ExpirationTime.EnableImmediateUpdate( bImmediate );
|
|
m_ICSPort.EnableImmediateUpdate( bImmediate );
|
|
m_IpAddress.EnableImmediateUpdate( bImmediate );
|
|
m_SessionCreateBlob.EnableImmediateUpdate( bImmediate );
|
|
}
|
|
|
|
HKEY
|
|
ConvertHelpEntry(
|
|
HKEY hKey
|
|
)
|
|
/*++
|
|
|
|
--*/
|
|
{
|
|
HKEY oldKey = m_hEntryKey;
|
|
m_hEntryKey = hKey;
|
|
|
|
m_EnableResolver.SetRegStoreHandle(m_hEntryKey);
|
|
m_SessResolverBlob.SetRegStoreHandle(m_hEntryKey);
|
|
m_UserSID.SetRegStoreHandle(m_hEntryKey);
|
|
m_SessionRdsSetting.SetRegStoreHandle(m_hEntryKey);
|
|
m_SessionId.SetRegStoreHandle(m_hEntryKey);
|
|
m_CreationTime.SetRegStoreHandle(m_hEntryKey);
|
|
m_ExpirationTime.SetRegStoreHandle(m_hEntryKey);
|
|
|
|
m_ICSPort.SetRegStoreHandle(m_hEntryKey);
|
|
m_IpAddress.SetRegStoreHandle(m_hEntryKey);
|
|
|
|
m_SessionCreateBlob.SetRegStoreHandle(m_hEntryKey);
|
|
return oldKey;
|
|
}
|
|
|
|
HRESULT
|
|
DeleteEntry()
|
|
/*++
|
|
|
|
--*/
|
|
{
|
|
DWORD dwStatus;
|
|
|
|
CCriticalSectionLocker l(m_Lock);
|
|
|
|
m_EntryStatus = REGVALUE_HELPSESSION_ENTRY_DELETED;
|
|
dwStatus = m_EntryStatus.DBUpdateValue(m_hEntryKey);
|
|
|
|
if( NULL != m_hEntryKey )
|
|
{
|
|
RegCloseKey( m_hEntryKey );
|
|
m_hEntryKey = NULL;
|
|
}
|
|
|
|
MYASSERT( ERROR_SUCCESS == dwStatus );
|
|
|
|
return HRESULT_FROM_WIN32(dwStatus);
|
|
}
|
|
|
|
HelpColumnValueBase<long> m_EntryStatus;
|
|
HelpColumnValueBase<FILETIME> m_CreationTime;
|
|
|
|
DWORD
|
|
GetRefCount()
|
|
{
|
|
return m_RefCount;
|
|
}
|
|
|
|
|
|
public:
|
|
|
|
// Help Session ID
|
|
HelpColumnValueBase<CComBSTR> m_SessionId;
|
|
|
|
// Help Session create blob
|
|
HelpColumnValueBase<CComBSTR> m_SessionCreateBlob;
|
|
|
|
// Enable resolver callback
|
|
HelpColumnValueBase<long> m_EnableResolver;
|
|
|
|
// Blob to be passed to resolver
|
|
HelpColumnValueBase<CComBSTR> m_SessResolverBlob;
|
|
|
|
// SID of user that created this entry.
|
|
HelpColumnValueBase<CComBSTR> m_UserSID;
|
|
|
|
// Help session RDS setting.
|
|
HelpColumnValueBase<REMOTE_DESKTOP_SHARING_CLASS> m_SessionRdsSetting;
|
|
|
|
// Help Expiration date in absolute time
|
|
HelpColumnValueBase<FILETIME> m_ExpirationTime;
|
|
|
|
// ICS port
|
|
HelpColumnValueBase<long> m_ICSPort;
|
|
|
|
// IP Address when creating this ticket
|
|
HelpColumnValueBase<CComBSTR> m_IpAddress;
|
|
|
|
__HelpEntry(
|
|
IN CHelpSessionTable& Table,
|
|
IN HKEY hKey,
|
|
IN DWORD dwDefaultExpirationTime = ENTRY_VALID_PERIOD,
|
|
IN BOOL bImmediateUpdate = TRUE
|
|
) :
|
|
m_pHelpSessionTable(Table),
|
|
m_hEntryKey(hKey),
|
|
m_EntryStatus(m_Lock, hKey, COLUMNNAME_KEYSTATUS, REGVALUE_HELPSESSION_ENTRY_NEW, bImmediateUpdate),
|
|
m_CreationTime(m_Lock, hKey, COLUMNNAME_CREATETIME, defaultCreationTime, bImmediateUpdate),
|
|
m_SessionId(m_Lock, hKey, COLUMNNAME_SESSIONID, CComBSTR(), bImmediateUpdate),
|
|
m_SessionCreateBlob(m_Lock, hKey, COLUMNNAME_SESSIONCREATEBLOB, CComBSTR(), bImmediateUpdate),
|
|
m_EnableResolver(m_Lock, hKey, COLUMNNAME_ENABLESESSIONRESOLVER, FALSE, bImmediateUpdate),
|
|
m_SessResolverBlob(m_Lock, hKey, COLUMNNAME_SESSIONRESOLVERBLOB, CComBSTR(), bImmediateUpdate),
|
|
m_UserSID(m_Lock, hKey, COLUMNNAME_SESSIONUSERID, CComBSTR(), bImmediateUpdate),
|
|
m_SessionRdsSetting(m_Lock, hKey, COLUMNNAME_RDSSETTING, DESKTOPSHARING_DEFAULT, bImmediateUpdate),
|
|
m_ExpirationTime(m_Lock, hKey, COLUMNNAME_EXPIRATIONTIME, defaultCreationTime, bImmediateUpdate),
|
|
m_ICSPort(m_Lock, hKey, COLUMNNAME_ICSPORT, 0, bImmediateUpdate),
|
|
m_IpAddress(m_Lock, hKey, COLUMNNAME_IPADDRESS, CComBSTR(), bImmediateUpdate),
|
|
m_RefCount(1)
|
|
{
|
|
|
|
FILETIME ft;
|
|
|
|
// Sets up entry creation time.
|
|
GetSystemTimeAsFileTime( &ft );
|
|
|
|
//
|
|
// we are setting up default value for
|
|
// ticket creation and expiration time, enabling it update
|
|
// immediately will cause registry value to be overwritten.
|
|
//
|
|
m_CreationTime.EnableImmediateUpdate(FALSE);
|
|
m_ExpirationTime.EnableImmediateUpdate(FALSE);
|
|
|
|
m_CreationTime = ft;
|
|
|
|
// sets up default expiration time.
|
|
|
|
time_t curTime;
|
|
time(&curTime);
|
|
|
|
// 24 hour timeout period
|
|
curTime += (dwDefaultExpirationTime * 60 * 60 * 24);
|
|
|
|
UnixTimeToFileTime( curTime, &ft );
|
|
m_ExpirationTime = ft;
|
|
|
|
//
|
|
// enabling update mode for ticket creation and
|
|
// expiration time.
|
|
//
|
|
if( bImmediateUpdate )
|
|
{
|
|
// already setup the default, turn on the update mode,
|
|
// note, turning on update mode does not cause value to
|
|
// flush to registry.
|
|
m_CreationTime.EnableImmediateUpdate(bImmediateUpdate);
|
|
m_ExpirationTime.EnableImmediateUpdate(bImmediateUpdate);
|
|
}
|
|
}
|
|
|
|
|
|
~__HelpEntry()
|
|
{
|
|
//m_pHelpSessionTable.ReleaseHelpEntry( (CComBSTR)m_SessionId );
|
|
|
|
if( NULL != m_hEntryKey )
|
|
{
|
|
RegCloseKey( m_hEntryKey );
|
|
m_hEntryKey = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
__HelpEntry&
|
|
operator=(const __HelpEntry& newVal)
|
|
{
|
|
if( this != &newVal )
|
|
{
|
|
m_SessionId = newVal.m_SessionId;
|
|
m_EnableResolver = newVal.m_EnableResolver;
|
|
m_SessResolverBlob = newVal.m_SessResolverBlob;
|
|
m_UserSID = newVal.m_UserSID;
|
|
m_CreationTime = newVal.m_CreationTime;
|
|
m_SessionRdsSetting = newVal.m_SessionRdsSetting;
|
|
m_ExpirationTime = newVal.m_ExpirationTime;
|
|
m_ICSPort = newVal.m_ICSPort;
|
|
m_IpAddress = newVal.m_IpAddress;
|
|
m_SessionCreateBlob = newVal.m_SessionCreateBlob;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
HRESULT
|
|
BeginUpdate()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Begin update save a copied of entries and disable immediate
|
|
registry value update mode.
|
|
|
|
Parameters:
|
|
|
|
None.
|
|
|
|
Returns:
|
|
|
|
S_OK or error code.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hRes = S_OK;
|
|
|
|
m_Lock.Lock();
|
|
|
|
if( NULL != m_hEntryKey )
|
|
{
|
|
hRes = BackupEntry();
|
|
if( FAILED(hRes) )
|
|
{
|
|
// unlock entry if can't save
|
|
// a backup copy
|
|
m_Lock.UnLock();
|
|
}
|
|
else
|
|
{
|
|
// ignore individual value update mode and
|
|
// set to no immediate update
|
|
EnableImmediateUpdate(FALSE);
|
|
}
|
|
}
|
|
|
|
// note, we only commit changes to registry when caller
|
|
// invoke CommitUpdate() so we don't need to mark entry
|
|
// dirty in registry now.
|
|
return hRes;
|
|
}
|
|
|
|
HRESULT
|
|
CommitUpdate()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Commit all changes to registry.
|
|
|
|
Parameters:
|
|
|
|
None.
|
|
|
|
Returns:
|
|
|
|
S_OK or error code.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hRes = S_OK;
|
|
|
|
if( NULL != m_hEntryKey )
|
|
{
|
|
hRes = UpdateEntryValues( m_hEntryKey );
|
|
}
|
|
|
|
// ignore individual value update mode and
|
|
// set to immediate update
|
|
EnableImmediateUpdate(TRUE);
|
|
|
|
// let caller decide what to do when fail to update value.
|
|
UnlockEntry();
|
|
return hRes;
|
|
}
|
|
|
|
HRESULT
|
|
AbortUpdate()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Abort changes to value and restore back to
|
|
original value.
|
|
|
|
Parameters:
|
|
|
|
None.
|
|
|
|
Returns:
|
|
|
|
S_OK or error code.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hRes = HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR);
|
|
|
|
if( NULL != m_hEntryKey )
|
|
{
|
|
hRes = RestoreEntryFromBackup();
|
|
}
|
|
|
|
EnableImmediateUpdate(TRUE);
|
|
|
|
// let caller decide what to do when restore failed.
|
|
UnlockEntry();
|
|
return hRes;
|
|
}
|
|
|
|
HRESULT
|
|
Close()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Close a help entry and remove from cache, entry is undefined
|
|
after close.
|
|
|
|
Parameters:
|
|
|
|
None.
|
|
|
|
Returns:
|
|
|
|
S_OK or error code.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hRes;
|
|
|
|
hRes = m_pHelpSessionTable.ReleaseHelpEntry( (CComBSTR)m_SessionId );
|
|
|
|
if( FAILED(hRes) )
|
|
{
|
|
if( HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND) != hRes )
|
|
{
|
|
MYASSERT(FALSE);
|
|
}
|
|
|
|
Release();
|
|
}
|
|
|
|
// Always S_OK
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
Delete()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete a help entry from table, entry is undefined after delete.
|
|
|
|
Parameters:
|
|
|
|
None.
|
|
|
|
Returns:
|
|
|
|
S_OK or error code.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hRes;
|
|
|
|
// ignore error since restore will delete 'deleted' entry
|
|
hRes = m_pHelpSessionTable.DeleteHelpEntry( (CComBSTR)m_SessionId );
|
|
|
|
if( FAILED(hRes) )
|
|
{
|
|
//MYASSERT(FALSE);
|
|
Release();
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
HRESULT
|
|
Refresh()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reload entry from registry.
|
|
|
|
Parameters:
|
|
|
|
None.
|
|
|
|
Returns:
|
|
|
|
S_OK or error code.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hRes;
|
|
|
|
LockEntry();
|
|
hRes = LoadEntryValues(m_hEntryKey);
|
|
UnlockEntry();
|
|
|
|
return hRes;
|
|
}
|
|
|
|
void
|
|
LockEntry()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Lock entry for update.
|
|
|
|
Parameters:
|
|
|
|
None.
|
|
|
|
Returns:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
m_Lock.Lock();
|
|
}
|
|
|
|
void
|
|
UnlockEntry()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Unlock entry.
|
|
|
|
Parameters:
|
|
|
|
None.
|
|
|
|
Returns:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
m_Lock.UnLock();
|
|
}
|
|
|
|
//
|
|
// Check if entry is locked for update
|
|
BOOL
|
|
IsUpdateInProgress();
|
|
|
|
//
|
|
// Get CRITICAL_SECTION used in current entry, this
|
|
// routine is used by help session object to save resource
|
|
CCriticalSection&
|
|
GetLock()
|
|
{
|
|
return m_Lock;
|
|
}
|
|
|
|
// TRUE if entry is memory only, FALSE if entry
|
|
// is backup to registry
|
|
BOOL
|
|
IsInMemoryHelpEntry()
|
|
{
|
|
return (NULL == m_hEntryKey);
|
|
}
|
|
|
|
BOOL
|
|
IsEntryExpired();
|
|
};
|
|
|
|
|
|
#endif
|