Leaked source code of windows server 2003
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

/*++
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