//----------------------------------------------------------------------------
// ObjectWindows
// Copyright (c) 1994, 1996 by Borland International, All Rights Reserved
//
/// \file
/// General Registry access & registration implementation
/// TRegKey, TRegValue, TRegKeyIterator, TRegValueIterator
/// TXRegistry
/// TRegItem, TRegList, TRegLink - associative array of localizable string parameters
/// OC registry functions
//----------------------------------------------------------------------------
#if !defined(OWL_REGISTRY_H)
#define OWL_REGISTRY_H
#include <owl/private/defs.h>
#if defined(BI_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <owl/private/checks.h>
#include <owl/except.h>
#include <owl/wsysinc.h>
#include <owl/lclstrng.h>
#include <owl/private/memory.h>
#include <owl/private/strmdefs.h>
#include <vector>
#include <optional>
#include <type_traits>
#include <cstddef>
namespace owl {
/// \cond NoSuppressDoxygenWarning
#include <owl/preclass.h>
/// \endcond
/// \addtogroup winsys_group
/// @{
//----------------------------------------------------------------------------
// Direct registry access classes. Can read & iterate as well as create and
// write keys and value-data pairs
//
class _OWLCLASS TRegKey;
class _OWLCLASS TRegValueIterator;
//
/// Encapsulates a value-data entry within one registration key.
//
class _OWLCLASS TRegValue
{
public:
TRegValue(const TRegKey& key, LPCTSTR name);
TRegValue(const TRegKey& key, const tstring& name);
explicit TRegValue(const TRegValueIterator& iter);
#if defined(BI_COMP_BORLANDC)
// Circumvent bug in std::optional (requires default constructor for the contained object type).
// TODO: Remove this when the library is standard compliant.
//
TRegValue();
#endif
/// \name Accessors
/// @{
LPCTSTR GetName() const;
const uint32 GetDataType() const;
const uint32 GetDataSize() const;
const uint8* GetData() const;
operator uint32() const;
operator uint64() const;
operator LPCTSTR() const;
/// @}
/// \name Mutators
/// @{
long Set(uint32 type, const uint8* data, uint32 dataSize);
long Set(uint32 value);
long Set(uint64 value);
long Set(LPCTSTR value);
long Set(const tstring& value);
TRegValue& operator =(uint32 value);
TRegValue& operator =(uint64 value);
TRegValue& operator =(LPCTSTR value);
TRegValue& operator =(const tstring& value);
long Delete();
/// @}
private:
const TRegKey& Key; ///< Key that this value lives in
tstring Name; ///< Value name; if empty, this object represents the default value for the associated key.
uint32 DataType; ///< Type code for value data
mutable std::vector<uint8> Data; ///< Value data; mutable to support lazy retrieval (see RetrieveOnDemand).
uint32 DataSize; ///< Size in bytes of Data
long QueryTypeAndSize();
void RetrieveOnDemand() const;
};
class _OWLCLASS TRegKeyIterator;
//
/// Encapsulates a registration key in the Windows Registry.
//
class _OWLCLASS TRegKey
{
public:
typedef HKEY THandle;
//
/// Enumeration used to specify whether a key should be created (or simply opened).
//
enum TCreateOK
{
CreateOK, ///< Create key if it does not exist.
NoCreate ///< Don't create, simply open.
};
/// \name Accessors to system predefined registry keys
/// @{
static auto GetClassesRoot() -> TRegKey&;
static auto GetClassesRootClsid() -> TRegKey&;
static auto GetCurrentConfig() -> TRegKey&;
static auto GetCurrentUser() -> TRegKey&;
static auto GetLocalMachine() -> TRegKey&;
static auto GetPerformanceData() -> TRegKey&;
static auto GetUsers() -> TRegKey&;
/// @}
#if defined(OWL5_COMPAT)
/// \name Deprecated alternative accessors to system predefined registry keys
/// @{
static auto ClassesRoot() -> TRegKey& { return GetClassesRoot(); }
static auto ClassesRootClsid() -> TRegKey& { return GetClassesRootClsid(); }
static auto CurrentConfig() -> TRegKey& { return GetCurrentConfig(); }
static auto CurrentUser() -> TRegKey& { return GetCurrentUser(); }
static auto LocalMachine() -> TRegKey& { return GetLocalMachine(); }
static auto PerformanceData() -> TRegKey& { return GetPerformanceData(); }
static auto Users() -> TRegKey& { return GetUsers(); }
/// @}
#endif
TRegKey(THandle baseKey, tstring keyName, REGSAM samDesired = KEY_ALL_ACCESS, TCreateOK createOK = CreateOK);
TRegKey(THandle baseKey, LPCTSTR keyName, REGSAM samDesired = KEY_ALL_ACCESS, TCreateOK createOK = CreateOK);
explicit TRegKey(const TRegKeyIterator& iter, REGSAM samDesired = KEY_ALL_ACCESS);
TRegKey(THandle aliasKey, bool shouldClose, tstring keyName);
explicit TRegKey(THandle aliasKey, bool shouldClose = false, LPCTSTR keyName = nullptr);
TRegKey(TRegKey&&) noexcept;
TRegKey(const TRegKey&) = delete;
TRegKey& operator =(const TRegKey&) = delete;
#if defined(BI_COMP_BORLANDC)
// Circumvent bug in std::optional (requires default constructor for the contained object type).
// TODO: Remove this when the library is standard compliant.
//
TRegKey() = default;
#endif
~TRegKey();
operator THandle() const;
auto GetHandle() const -> THandle { return Key; }
long DeleteKey(LPCTSTR subKeyName);
long DeleteKey(const tstring& subKeyName)
{ return DeleteKey(subKeyName.c_str()); }
long NukeKey(LPCTSTR subKeyName);
long NukeKey(const tstring& subKeyName)
{ return NukeKey(subKeyName.c_str()); }
long Flush() const;
/// \name Security attributes
/// @{
//
/// Encapsulates a SECURITY_DESCRIPTOR.
///
/// This class is used by TRegKey::GetSecurity(SECURITY_INFORMATION) const and
/// TRegKey::SetSecurity(SECURITY_INFORMATION, const TSecurityDescriptor&) const.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-security_descriptor">
/// SECURITY_DESCRIPTOR</a> in the Windows API.
///
class TSecurityDescriptor
{
public:
TSecurityDescriptor(const TRegKey& key, SECURITY_INFORMATION infoRequested);
auto IsValid() const noexcept -> bool;
auto GetControl() const -> SECURITY_DESCRIPTOR_CONTROL;
auto GetLength() const -> DWORD;
auto GetDacl() const -> std::optional<PACL>;
auto GetGroup() const -> PSID;
auto GetOwner() const -> PSID;
auto GetRevision() const -> DWORD;
auto GetRmControl() const -> std::optional<UCHAR>;
auto GetSacl() const -> std::optional<PACL>;
void Initialize(DWORD revision = SECURITY_DESCRIPTOR_REVISION);
void RemoveDacl();
void RemoveGroup();
void RemoveOwner();
void RemoveRmControl();
void RemoveSacl();
void SetDacl(PACL dacl, bool daclDefaulted = false);
void SetGroup(PSID group, bool groupDefaulted = false);
void SetOwner(PSID owner, bool ownerDefaulted = false);
void SetRmControl(UCHAR rmControl);
void SetSacl(PACL sacl, bool saclDefaulted = false);
/// \name Security descriptor buffer access
/// @{
auto GetData() noexcept -> SECURITY_DESCRIPTOR* { return reinterpret_cast<SECURITY_DESCRIPTOR*>(Data.data()); }
auto GetData() const noexcept -> const SECURITY_DESCRIPTOR* { return reinterpret_cast<const SECURITY_DESCRIPTOR*>(Data.data()); }
auto GetDataSize() const noexcept -> int { return static_cast<int>(Data.size()); }
/// @}
/// \name SECURITY_DESCRIPTOR_CONTROL queries
/// @{
auto IsFlagSet(SECURITY_DESCRIPTOR_CONTROL mask) const { return (GetControl() & mask) == mask; } ///< Returns true if all the set bits in the given mask are set in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsAbsolute() const { return !IsFlagSet(SE_SELF_RELATIVE); } ///< Returns the inverse of the SE_SELF_RELATIVE flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsDaclAutoInheritRequired() const { return IsFlagSet(SE_DACL_AUTO_INHERIT_REQ); } ///< Returns the SE_DACL_AUTO_INHERIT_REQ flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsDaclAutoInherited() const { return IsFlagSet(SE_DACL_AUTO_INHERITED); } ///< Returns the SE_DACL_AUTO_INHERITED flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsDaclDefaulted() const { return IsFlagSet(SE_DACL_DEFAULTED); } ///< Returns the SE_DACL_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsDaclPresent() const { return IsFlagSet(SE_DACL_PRESENT); } ///< Returns the SE_DACL_PRESENT flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsDaclProtected() const { return IsFlagSet(SE_DACL_PROTECTED); } ///< Returns the SE_DACL_PROTECTED flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsGroupDefaulted() const { return IsFlagSet(SE_GROUP_DEFAULTED); } ///< Returns the SE_GROUP_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsOwnerDefaulted() const { return IsFlagSet(SE_OWNER_DEFAULTED); } ///< Returns the SE_OWNER_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsRmControlValid() const { return IsFlagSet(SE_RM_CONTROL_VALID); } ///< Returns the SE_RM_CONTROL_VALID flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsSaclAutoInheritRequired() const { return IsFlagSet(SE_SACL_AUTO_INHERIT_REQ); } ///< Returns the SE_SACL_AUTO_INHERIT_REQ flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsSaclAutoInherited() const { return IsFlagSet(SE_SACL_AUTO_INHERITED); } ///< Returns the SE_SACL_AUTO_INHERITED flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsSaclDefaulted() const { return IsFlagSet(SE_SACL_DEFAULTED); } ///< Returns the SE_SACL_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsSaclPresent() const { return IsFlagSet(SE_SACL_PRESENT); } ///< Returns the SE_SACL_PRESENT flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsSaclProtected() const { return IsFlagSet(SE_SACL_PROTECTED); } ///< Returns the SE_SACL_PROTECTED flag in the SECURITY_DESCRIPTOR_CONTROL structure.
auto IsSelfRelative() const { return IsFlagSet(SE_SELF_RELATIVE); } ///< Returns the SE_SELF_RELATIVE flag in the SECURITY_DESCRIPTOR_CONTROL structure.
/// @}
private:
std::vector<std::byte> Data;
};
auto GetSecurity(SECURITY_INFORMATION infoRequested, PSECURITY_DESCRIPTOR secDesc, DWORD* secDescSize) const -> long;
auto GetSecurity(SECURITY_INFORMATION infoRequested) const -> TSecurityDescriptor;
auto SetSecurity(SECURITY_INFORMATION infoToSet, PSECURITY_DESCRIPTOR secDesc) const -> long;
void SetSecurity(SECURITY_INFORMATION infoToSet, const TSecurityDescriptor& s) const;
/// @}
// Saving & loading of this key & subKeys
//
long Save(LPCTSTR fileName);
long Save(const tstring& fileName)
{ return Save(fileName.c_str()); }
long LoadKey(LPCTSTR subKeyName, LPCTSTR fileName);
long LoadKey(const tstring& subKeyName, const tstring& fileName)
{ return LoadKey(subKeyName.c_str(), fileName.c_str()); }
long ReplaceKey(LPCTSTR subKeyName, LPCTSTR newFileName, LPCTSTR oldFileName);
long ReplaceKey(const tstring& subKeyName, const tstring& newFileName, const tstring& oldFileName)
{ return ReplaceKey(subKeyName.c_str(), newFileName.c_str(), oldFileName.c_str()); }
long Restore(LPCTSTR fileName, uint32 options = 0);
long Restore(const tstring& fileName, uint32 options = 0)
{ return Restore(fileName.c_str(), options); }
long UnLoadKey(LPCTSTR subKeyName);
long UnLoadKey(const tstring& subKeyName)
{ return UnLoadKey(subKeyName.c_str()); }
long QueryInfo(LPTSTR class_, DWORD* classSize,
DWORD* subkeyCount, DWORD* maxSubkeyNameSize, DWORD* maxSubkeyClassSize,
DWORD* valueCount, DWORD* maxValueNameSize, DWORD* maxValueDataSize,
DWORD* securityDescriptorSize, PFILETIME lastWriteTime) const;
//
/// Data structure returned by QueryInfo.
//
struct TInfo
{
tstring Class;
DWORD SubkeyCount;
DWORD MaxSubkeyNameSize;
DWORD MaxSubkeyClassSize;
DWORD ValueCount;
DWORD MaxValueNameSize;
DWORD MaxValueDataSize; ///< In bytes.
DWORD SecurityDescriptorSize;
FILETIME LastWriteTime;
};
auto QueryInfo() const -> TInfo;
LPCTSTR GetName() const;
auto HasSubkey(const tstring& keyName) const -> bool;
auto GetSubkey(const tstring& keyName, REGSAM samDesired = KEY_READ) const->std::optional<TRegKey>;
uint32 GetSubkeyCount() const;
auto HasValue(const tstring& valueName) const -> bool;
auto GetValue(const tstring& valueName) const->std::optional<TRegValue>;
uint32 GetValueCount() const;
//
/// Returns the value of the given name, if it exists, or the given default value, otherwise.
/// A conversion of the TRegValue to type T is attempted. The provided default value must be
/// convertible to T. The types supported for T are owl::uint32, owl::uint64 and owl::tstring.
///
/// \note T can not be LPCTSTR, because that would return a pointer to a dead object (the
/// TRegValue object looked up is local to the function). Use owl::tstring instead.
//
template <typename T>
auto GetValueOrDefault(const tstring& valueName, T defaultValue) const
{
static_assert(!std::is_pointer_v<T>, "Return type can not be pointer.");
const auto v = GetValue(valueName);
return v ? static_cast<T>(*v) : defaultValue;
}
// Friend iterators only...?
// TODO: Provide string-returning overload.
//
long EnumKey(int index, LPTSTR subKeyName, int subKeyNameSize) const;
#if defined(OWL5_COMPAT)
// Older, nameless subkey+(Default) value access
//
long SetDefValue(LPCTSTR subkeyName, uint32 type,
LPCTSTR data, uint32 dataSize);
long SetDefValue(const tstring& subkeyName, uint32 type, const tstring& data, uint32 dataSize)
{ return SetDefValue(subkeyName.c_str(), type, data.c_str(), dataSize); }
long QueryDefValue(LPCTSTR subkeyName, LPTSTR data,
uint32* dataSize) const;
long QueryDefValue(const tstring& subkeyName, LPTSTR data, uint32* dataSize) const
{ return QueryDefValue(subkeyName.c_str(), data, dataSize); }
#endif
// Newer, named value set & get functions. Subkeys must be opened
//
long SetValue(LPCTSTR valName, uint32 type, const uint8* data, uint32 dataSize) const;
long SetValue(const tstring& valName, uint32 type, const uint8* data, uint32 dataSize) const
{ return SetValue(valName.c_str(), type, data, dataSize); }
long SetValue(LPCTSTR valName, uint32 data) const;
long SetValue(const tstring& valName, uint32 data) const
{ return SetValue(valName.c_str(), data); }
long SetValue(LPCTSTR valName, const tstring& value) const;
long SetValue(const tstring& valName, const tstring& value) const
{ return SetValue(valName.c_str(), value); }
long QueryValue(LPCTSTR valName, uint32* type, uint8* data, uint32* dataSize) const;
long QueryValue(const tstring& valName, uint32* type, uint8* data, uint32* dataSize) const
{ return QueryValue(valName.c_str(), type, data, dataSize); }
long DeleteValue(LPCTSTR valName) const;
long DeleteValue(const tstring& valName) const
{ return DeleteValue(valName.c_str()); }
// Friend iterators only...?
// TODO: Provide value-returning overload.
//
long EnumValue(int index, LPTSTR valueName, uint32& valueNameSize, uint32* type = 0, uint8* data = 0, uint32* dataSize = 0) const;
protected:
THandle Key; ///< This Key's Handle.
tstring Name; ///< This Key's Name.
DWORD SubkeyCount; ///< Number of subkeys.
DWORD ValueCount; ///< Number of value entries.
bool ShouldClose; ///< Should this key be closed on destruction.
};
//
/// Iterator for walking thru the subkeys of a key.
//
class _OWLCLASS TRegKeyIterator
{
public:
TRegKeyIterator(const TRegKey& key);
operator bool();
uint32 operator ++();
uint32 operator ++(int);
uint32 operator --();
uint32 operator --(int);
uint32 operator [](int index);
int Current() const;
const TRegKey& BaseKey() const;
void Reset();
private:
const TRegKey& Key;
int Index;
};
//
/// Iterator for walking through the values of a key.
//
class _OWLCLASS TRegValueIterator
{
public:
TRegValueIterator(const TRegKey& regKey);
operator bool();
uint32 operator ++();
uint32 operator ++(int);
uint32 operator --();
uint32 operator --(int);
uint32 operator [](int index);
int Current() const;
const TRegKey& BaseKey() const;
void Reset();
private:
const TRegKey& Key;
int Index;
};
//----------------------------------------------------------------------------
//
/// Thrown for errors within the Registry classes.
//
class _OWLCLASS TXRegistry : public TXOwl
{
public:
TXRegistry(const tstring& context, const TRegKey& key, long errorCode = 0)
: TXOwl{context}, KeyName{key.GetName()}, ErrorCode{errorCode}
{}
TXRegistry(const tstring& context, tstring keyName, long errorCode = 0)
: TXOwl{context}, KeyName{std::move(keyName)}, ErrorCode{errorCode}
{}
auto GetKeyName() const -> const tstring& { return KeyName; }
auto GetErrorCode() const -> long { return ErrorCode; }
private:
tstring KeyName;
long ErrorCode;
};
//----------------------------------------------------------------------------
// Registration parameter structures and formatting functions
//
//
/// Used internally to provide buffers for formating registration strings.
//
class _OWLCLASS TRegFormatHeap
{
public:
TRegFormatHeap();
~TRegFormatHeap();
tchar* Alloc(int spaceNeeded);
private:
struct TBlock
{
TBlock* Next; ///< Next heap in chain.
tchar Data[1]; ///< Allocated memory starts here.
};
TBlock* Head;
};
//
/// A single registration list entry.
///
/// TRegItem defines localizable values for parameters or subkeys. These values can
/// be passed to TLocaleString, which defines a localizable substitute for char*.
/// TRegItem contains several undocumented functions that are used privately by the
/// registration macros REGFORMAT and REGSTATUS.
//
struct _OWLCLASS TRegItem
{
const char* Key; ///< Non-localized parameter or registry subkey
TLocaleString Value; ///< Localizable value for parameter or subkey
// Used privately by REGFORMAT, REGSTATUS macros.
//
static tchar* RegFormat(int f, int a, int t, int d, TRegFormatHeap& heap);
static tchar* RegFormat(LPCTSTR f, int a, int t, int d, TRegFormatHeap& heap);
static tchar* RegFormat(const tstring& f, int a, int t, int d, TRegFormatHeap& heap) { return RegFormat(f.c_str(), a, t, d, heap); }
static tchar* RegFlags(long flags, TRegFormatHeap& heap);
static tchar* RegVerbOpt(int mf, int sf, TRegFormatHeap& heap);
static void OverflowCheck();
};
//
/// A registration parameter table, composed of a list of TRegItems.
//
/// Holds an array of items of type TRegItem. Provides functionality that lets you
/// access each item in the array and return the name of the item. Instead of
/// creating a TRegList directly, you can use ObjectWindows' registration macros to
/// build a TRegList for you.
//
class _OWLCLASS TRegList
{
public:
TRegList(TRegItem* _list);
LPCTSTR Lookup(LPCSTR key, TLangId lang = TLocaleString::UserDefaultLangId);
LPCTSTR Lookup(const std::string& key, TLangId lang = TLocaleString::UserDefaultLangId)
{ return Lookup(key.c_str(), lang); }
TLocaleString& LookupRef(LPCSTR key);
TLocaleString& LookupRef(const std::string& key)
{ return LookupRef(key.c_str()); }
LPCTSTR operator[](LPCSTR key);
LPCTSTR operator[](const std::string& key)
{ return operator[](key.c_str()); }
TRegItem* Items;
};
//
/// A linked structure in which each node points to a list of TRegList
/// objects (or TRegList-derived objects) or TDocTemplate objects.
///
/// Each object has an item name and a string value associated with the item name. The structure
/// forms a typical linked list as the following diagram illustrates:
/// \image html bm251.BMP
///
/// A TDocTemplate object uses the following variation of the TRegLink structure:
/// \image html bm252.BMP
//
class _OWLCLASS TRegLink
{
public:
TRegLink(TRegList& regList, TRegLink*& head);
virtual ~TRegLink();
TRegLink* GetNext() const;
void SetNext(TRegLink* link);
TRegList& GetRegList() const;
static void AddLink(TRegLink** head, TRegLink* newLink);
static bool RemoveLink(TRegLink** head, TRegLink* remLink);
protected:
TRegLink(); ///< Derived class must fill in ptrs
TRegLink* Next; ///< Next RegLink
TRegList* RegList; ///< Pointer to registration parameter table
};
//
// Registration parameter table macro definitions
//
#define BEGIN_REGISTRATION(regname) \
extern TRegItem regname##_list[];\
extern TRegFormatHeap __regHeap;\
TRegList regname(regname##_list);\
TRegItem regname##_list[] = {
#define END_REGISTRATION {0,{0}} };
#define REGDATA(var,val) {#var, {val}},
#define REGXLAT(var,val) {#var, {AUTOLANG_XLAT val}},
#define REGITEM(key,val) {" " key, {val}},
#define REGFORMAT(i,f,a,t,d) {"format" #i,{TRegItem::RegFormat(f,a,t,d,__regHeap)}},
#define REGSTATUS(a,f) {"aspect" #a, {TRegItem::RegFlags(f,__regHeap)}},
#define REGVERBOPT(v,mf,sf) {#v "opt",{TRegItem::RegVerbOpt(mf,sf,__regHeap)}},
#define REGICON(i) {"iconindex",{TRegItem::RegFlags(i,__regHeap)}},
#define REGDOCFLAGS(i) {"docflags",{TRegItem::RegFlags(i,__regHeap)}},
//
// Buffer size is no longer needed, use the macro below
//
#define REGISTRATION_FORMAT_BUFFER(n) \
TRegFormatHeap __regHeap;
#define REGISTRATION_FORMAT_HEAP \
TRegFormatHeap __regHeap;
//----------------------------------------------------------------------------
// Clipboard and registry data transfer format definitions
//
const int ocrVerbLimit = 8; ///< Maximum number of verbs registered per class.
const int ocrFormatLimit = 8; ///< Maximum number of data formats per class.
//
/// Format: standard clipboard numeric format, or name of custom format.
//
enum ocrClipFormat
{
ocrText = 1, ///< CF_TEXT
ocrBitmap = 2, ///< CF_BITMAP
ocrMetafilePict = 3, ///< CF_METAFILEPICT
ocrSylk = 4, ///< CF_SYLK
ocrDif = 5, ///< CF_DIF
ocrTiff = 6, ///< CF_TIFF
ocrOemText = 7, ///< CF_OEMTEXT
ocrDib = 8, ///< CF_DIB
ocrPalette = 9, ///< CF_PALETTE
ocrPenData = 10, ///< CF_PENDATA
ocrRiff = 11, ///< CF_RIFF
ocrWave = 12, ///< CF_WAVE
ocrUnicodeText = 13, ///< CF_UNICODETEXT Win32 only
ocrEnhMetafile = 14, ///< CF_ENHMETAFILE Win32 only
};
#define ocrRichText _T("Rich Text Format")
#define ocrEmbedSource _T("Embed Source")
#define ocrEmbeddedObject _T("Embedded Object")
#define ocrLinkSource _T("Link Source")
#define ocrObjectDescriptor _T("Object Descriptor")
#define ocrLinkSrcDescriptor _T("Link Source Descriptor")
//
/// Aspect: view types supported by transfer.
//
enum ocrAspect
{
ocrContent = 1, ///< DVASPECT_CONTENT - normal display representation.
ocrThumbnail = 2, ///< DVASPECT_THUMBNAIL - picture appropriate for browser.
ocrIcon = 4, ///< DVASPECT_ICON - iconized representation of object.
ocrDocPrint = 8, ///< DVASPECT_DOCPRINT - print preview representation.
};
//
/// Medium: means of data transfer.
//
enum ocrMedium
{
ocrNull = 0,
ocrHGlobal = 1, ///< TYMED_HGLOBAL - global memory handle.
ocrFile = 2, ///< TYMED_FILE - data as contents of file.
ocrIStream = 4, ///< TYMED_ISTREAM - instance of an IStream object.
ocrIStorage = 8, ///< TYMED_ISTORAGE - streams within an instance of IStorage.
ocrGDI = 16, ///< TYMED_GDI - GDI object in global handle.
ocrMfPict = 32, ///< TYMED_MFPICT - CF_METAFILEPICT containing global handle.
ocrStaticMed = 1024 ///< OLE 2 static object.
};
//
/// Direction: transfer directions supported.
//
enum ocrDirection
{
ocrGet = 1,
ocrSet = 2,
ocrGetSet = 3,
};
//----------------------------------------------------------------------------
// Miscellaneous registry definitions
//
//
/// IOleObject miscellaneous status flags, defined for each or all aspects.
//
enum ocrObjectStatus
{
ocrRecomposeOnResize = 1, ///< Request redraw on container resize.
ocrOnlyIconic = 2, ///< Only useful context view is Icon.
ocrInsertNotReplace = 4, ///< Should not replace current select.
ocrStatic = 8, ///< Object is an OLE static object.
ocrCantLinkInside = 16, ///< Should not be the link source.
ocrCanLinkByOle1 = 32, ///< Only used in OBJECTDESCRIPTOR.
ocrIsLinkObject = 64, ///< Set by OLE2 link for OLE1 compat.
ocrInsideOut = 128, ///< Can be activated concurrently.
ocrActivateWhenVisible = 256, ///< Hint to cntnr when ocrInsideOut set.
ocrRenderingIsDeviceIndependent = 512, ///< No decisions made based on target.
ocrNoSpecialRendering = 512, ///< Older enum for previous entry.
};
//
/// IOleObject verb menu flags.
//
enum ocrVerbMenuFlags
{
ocrGrayed = 1, ///< MF_GRAYED
ocrDisabled = 2, ///< MF_DISABLED
ocrChecked = 8, ///< MF_CHECKED
ocrMenuBarBreak = 32, ///< MF_MENUBARBREAK
ocrMenuBreak = 64, ///< MF_MENUBAR
};
//
/// IOleObject verb attribute flags.
//
enum ocrVerbAttributes
{
ocrNeverDirties = 1, ///< Verb can never cause object to become dirty.
ocrOnContainerMenu = 2, ///< Only useful context view is Icon.
};
//
// Entries for <usage> registration parameter, class factory registration mode
//
#define ocrSingleUse _T("1") ///< Single client per instance.
#define ocrMultipleUse _T("2") ///< Multiple clients per instance.
#define ocrMultipleLocal _T("3") ///< Multiple clients, separate inproc server.
//----------------------------------------------------------------------------
// High-level table based registration support
//
//
/// List of parameterized template strings that represent the actual entries to be registered.
///
/// List is indexed from 1 for used with param-list template activation strings. See TRegParamList below.
//
// TODO: Add string-class support in constructor.
//
class _OWLCLASS TRegTemplateList
{
public:
TRegTemplateList(TRegKey& basekey, LPCTSTR _list[]);
~TRegTemplateList();
int GetCount() const;
TRegKey& GetBaseKey();
LPCTSTR operator [](int i);
// Enable/Disable and activate templates
//
void DisableAll();
void EnableAll();
void Enable(int i);
void Enable(LPCTSTR set);
void Enable(const tstring& set) { Enable(set.c_str()); }
void Activate(int i);
void Activate(LPCTSTR set);
void Activate(const tstring& set) { Activate(set.c_str()); }
bool IsActive(int i) const;
private:
TRegKey& BaseKey; ///< Registry key on which these templates are based.
const tchar** List; ///< List of templates.
int Count; ///< Number of templates in list.
int8* EnabledFlags; // Which templates are currently enabled/active.
};
//
/// A list of param entries for use as an intermediate between a TRegList and
/// the actual template list used to generate the registration.
///
/// Provides default values in 'Default', and tags required templates using octal char entries in
/// 'TemplatesNeeded'.
//
class _OWLCLASS TRegParamList
{
public:
struct TEntry
{
LPCTSTR Param; ///< Substituted parameter name.
LPCTSTR Default; ///< Default value, 0 if no default & param is required.
LPCTSTR TemplatesNeeded; ///< Octal string list of template indices to activate.
};
TRegParamList(const TEntry*);
~TRegParamList();
int Find(LPCTSTR param);
int Find(const tstring& param) { return Find(param.c_str()); }
int GetCount() const;
const tchar*& Value(int i);
void ResetDefaultValues();
const TEntry& operator [](int i) const;
private:
const TEntry* List;
int Count;
const tchar** Values;
};
//
/// High level symbol-based registry entry manipulation.
///
//
// TODO: Add string-class support in constructor.
//
class _OWLCLASS TRegSymbolTable
{
public:
TRegSymbolTable(TRegKey& basekey, LPCTSTR tplList[], const TRegParamList::TEntry* paramList);
void Init(LPCTSTR filter);
void UpdateParams(TLangId lang, TRegItem* item);
void StreamOut(TRegItem* item, tostream& out);
TRegTemplateList Templates;
TRegParamList Params;
int UserKeyCount;
};
//
/// TRegistry provides high level stream and list access to the registry.
//
class _OWLCLASS TRegistry
{
public:
static int Validate(TRegKey& baseKey, tistream& in); ///< Returns number of mismatched entries
static void Update(TRegKey& baseKey, tistream& in); ///< Writes lines to registry
#pragma pack(push,4)
struct TUnregParams
{
tchar Prepend; ///< Optional tchar to prepend to key before removing.
LPCTSTR Name; ///< Name of param.
TRegKey* BaseKey; ///< Key that that the param is based upon.
};
#pragma pack(pop)
static int Unregister(TRegList& regInfo, const TUnregParams* params, const TRegItem* overrides = 0);
};
/// @}
/// \cond NoSuppressDoxygenWarning
#include <owl/posclass.h>
/// \endcond
//----------------------------------------------------------------------------
// TRegKey inlines
//
//
/// Returns the HANDLE identifying this registry key.
//
inline TRegKey::operator THandle() const
{
return Key;
}
//
/// Enumerates the subkeys of this registry key.
//
inline long TRegKey::EnumKey(int index, LPTSTR subKeyName, int subKeyNameSize) const
{
return ::RegEnumKey(Key, index, subKeyName, subKeyNameSize);
//::RegEnumKeyEx(); ??
}
//
/// Deletes the specified subkey of this registry key.
//
inline long TRegKey::DeleteKey(LPCTSTR subKeyName)
{
return ::RegDeleteKey(Key, subKeyName);
}
//
/// Writes the attribute of this key in the registry
//
inline long TRegKey::Flush() const
{
return ::RegFlushKey(Key);
}
//
/// Retrieves a copy of the security descriptor protecting this registry key.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-reggetkeysecurity">
/// RegGetKeySecurity</a> in the Windows API.
//
inline auto TRegKey::GetSecurity(SECURITY_INFORMATION infoRequested, PSECURITY_DESCRIPTOR secDesc, DWORD* secDescSize) const -> long
{
return ::RegGetKeySecurity(Key, infoRequested, secDesc, secDescSize);
}
//
/// Retrieves a copy of the security descriptor protecting this registry key.
/// \param infoRequested indicates the requested security information.
/// \returns If successful, a TRegKey::TSecurityDescriptor is returned.
/// \exception TXRegistry is thrown on failure.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-reggetkeysecurity">
/// RegGetKeySecurity</a> in the Windows API.
//
inline auto TRegKey::GetSecurity(SECURITY_INFORMATION infoRequested) const -> TSecurityDescriptor
{
return TSecurityDescriptor{*this, infoRequested};
}
//
/// Sets the security descriptor of this key.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetkeysecurity">
/// RegSetKeySecurity</a> in the Windows API.
//
inline auto TRegKey::SetSecurity(SECURITY_INFORMATION infoToSet, PSECURITY_DESCRIPTOR secDesc) const -> long
{
return ::RegSetKeySecurity(Key, infoToSet, secDesc);
}
//
/// Sets the security descriptor of this key.
///
/// \param infoToSet indicates the security information to set.
/// \param s is the new security descriptor.
///
/// \exception TXRegistry is thrown on failure.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetkeysecurity">
/// RegSetKeySecurity</a> in the Windows API.
//
inline void TRegKey::SetSecurity(SECURITY_INFORMATION infoToSet, const TSecurityDescriptor& s) const
{
const auto r = SetSecurity(infoToSet, const_cast<SECURITY_DESCRIPTOR*>(s.GetData()));
if (r != ERROR_SUCCESS) throw TXRegistry{_T("TRegKey::SetSecurity failed"), *this, r};
}
//
/// Saves this key and all of its subkeys and values to the specified file.
//
inline long TRegKey::Save(LPCTSTR fileName)
{
return ::RegSaveKey(Key, fileName, 0/*Security*/);
}
//
/// Creates a subkey under HKEY_USER or HKEY_LOCAL_MACHINE and stores registration
/// information from a specified file into that subkey. This registration
/// information is in the form of a hive. A hive is a discrete body of keys,
/// subkeys, and values that is rooted at the top of the registry hierarchy. A hive
/// is backed by a single file and a .LOG file.
//
inline long TRegKey::LoadKey(LPCTSTR subKeyName, LPCTSTR fileName)
{
return ::RegLoadKey(Key, subKeyName, fileName);
}
//
/// Replaces the file backing this key and all of its subkeys with another file, so
/// that when the system is next started, the key and subkeys will have the values
/// stored in the new file.
//
inline long TRegKey::ReplaceKey(LPCTSTR subKeyName, LPCTSTR newFileName, LPCTSTR oldFileName)
{
return ::RegReplaceKey(Key, subKeyName, newFileName, oldFileName);
}
//
/// Reads the registry information in a specified file and copies it over this key.
/// This registry information may be in the form of a key and multiple levels of
/// subkeys.
//
inline long TRegKey::Restore(LPCTSTR fileName, uint32 options)
{
return ::RegRestoreKey(Key, fileName, options);
}
//
/// Unloads this key and its subkeys from the registry.
//
inline long TRegKey::UnLoadKey(LPCTSTR subKeyName)
{
return ::RegUnLoadKey(Key, subKeyName);
}
//
/// Returns the number of subkeys attached to this key.
//
inline uint32 TRegKey::GetSubkeyCount() const
{
return SubkeyCount;
}
//
/// Returns the number of values attached to this key.
//
inline uint32 TRegKey::GetValueCount() const
{
return ValueCount;
}
//
/// Returns a string identifying this key.
//
inline LPCTSTR TRegKey::GetName() const
{
return Name.c_str();
}
//
/// Associates a value with this key.
//
inline long TRegKey::SetValue(LPCTSTR valName, uint32 type, const uint8* data, uint32 dataSize) const
{
return ::RegSetValueEx(Key, valName, 0, type, data, dataSize);
}
//
/// Associates a 4-byte value with this key.
//
inline long TRegKey::SetValue(LPCTSTR valName, uint32 data) const
{
return SetValue(valName, REG_DWORD, (uint8*) &data, sizeof data);
}
//
/// Associates a string value with this key.
//
inline long TRegKey::SetValue(LPCTSTR valName, const tstring& value) const
{
const auto data = reinterpret_cast<const uint8*>(value.data());
const auto dataSize = static_cast<uint32>((value.size() + 1) * sizeof(tchar));
return SetValue(valName, REG_SZ, data, dataSize);
}
//
/// Retrieves the value associated with the unnamed value for this key in the registry.
//
inline long TRegKey::QueryValue(LPCTSTR valName, uint32* type, uint8* data, uint32* dataSize) const
{
#if defined WINELIB //it seems that Winlib SDK declares a 'unsigned int*' instead of DWORD* and GCC it's tooo strict
return ::RegQueryValueEx(Key, valName, 0, (unsigned int*) type, data, (unsigned int*) dataSize);
#else
return ::RegQueryValueEx(Key, valName, 0, type, data, dataSize);
#endif//WINELIB
}
//
/// Removes a named value from this registry key.
//
inline long TRegKey::DeleteValue(LPCTSTR valName) const
{
return ::RegDeleteValue(Key, valName);
}
#if defined(OWL5_COMPAT)
//
/// Sets the default [unnamed] value associated with this key.
//
inline long TRegKey::SetDefValue(LPCTSTR subkeyName, uint32 type, LPCTSTR data, uint32 dataSize)
{
return ::RegSetValue(Key, subkeyName, type, data, dataSize);
}
//
/// Retrieves the default [unnamed] value associated with this key.
//
inline long TRegKey::QueryDefValue(LPCTSTR subkeyName, LPTSTR data, uint32* dataSize) const
{
#if defined WINELIB // It seems that Winlib SDK declares a 'int*' instead of DWORD*, and GCC is too strict.
return ::RegQueryValue(Key, subkeyName, data, (int*) dataSize);
#else
return ::RegQueryValue(Key, subkeyName, data, (long*) dataSize);
#endif
}
#endif
//
/// Enumerates the values associated with this key.
/// Copy the value name and data block associated with the passed index.
//
inline long TRegKey::EnumValue(int index, LPTSTR valueName, uint32& valueNameSize, uint32* type, uint8* data, uint32* dataSize) const
{
#if defined WINELIB // It seems that Winlib SDK declares a 'int*' instead of DWORD*, and GCC is too strict.
return ::RegEnumValue(Key, index, valueName, (unsigned int*) &valueNameSize, 0, (unsigned int*) type, data, (unsigned int*) dataSize);
#else
return ::RegEnumValue(Key, index, valueName, &valueNameSize, 0, type, data, dataSize);
#endif
}
//----------------------------------------------------------------------------
// TRegValue inlines
//
//
/// Returns a string identifying this value.
//
inline LPCTSTR TRegValue::GetName() const
{
return Name.c_str();
}
//
/// Returns the type code for the data associated with this value
//
inline const uint32 TRegValue::GetDataType() const
{
return DataType;
}
//
/// Returns the size in bytes of the data associated with this value.
//
inline const uint32 TRegValue::GetDataSize() const
{
return DataSize;
}
//----------------------------------------------------------------------------
// TRegKeyIterator inlines
//
//
/// Creates a subkey iterator for a registration key.
//
inline TRegKeyIterator::TRegKeyIterator(const TRegKey& key)
:
Key(key),
Index(0)
{
}
//
/// Tests the validity of this iterator.
/// \return True if the iterator's index is greater than or equal to 0 and less than the number of subkeys.
//
inline TRegKeyIterator::operator bool()
{
return Index >= 0 && Index < int(Key.GetSubkeyCount());
}
//
/// Preincrements to the next subkey.
//
inline uint32 TRegKeyIterator::operator ++()
{
return ++Index;
}
//
/// Postincrements to the next subkey.
//
inline uint32 TRegKeyIterator::operator ++(int)
{
return Index++;
}
//
/// Predecrements to the previous subkey.
//
inline uint32 TRegKeyIterator::operator --()
{
return --Index;
}
//
/// Postdecrements to the previous subkey.
//
inline uint32 TRegKeyIterator::operator --(int)
{
return Index--;
}
//
/// Sets the index of the iterator to the passed value.
/// \return The new index.
//
inline uint32 TRegKeyIterator::operator [](int index)
{
PRECONDITION((index >= 0) && (index < int(Key.GetSubkeyCount())));
return Index = index;
}
//
/// Returns the index to the current subkey.
//
inline int TRegKeyIterator::Current() const
{
return Index;
}
//
/// Returns the registration key this iterator is bound to.
//
inline const TRegKey& TRegKeyIterator::BaseKey() const
{
return Key;
}
//
/// Resets the subkey index to zero.
//
inline void TRegKeyIterator::Reset()
{
Index = 0;
}
//----------------------------------------------------------------------------
// TRegValueIterator inlines
//
//
/// Creates a value iterator for a registration key.
//
inline TRegValueIterator::TRegValueIterator(const TRegKey& regKey)
: Key(regKey), Index(0)
{}
//
/// Tests the validity of this iterator.
/// \return True if the iterator's index is greater than or equal to 0 and less than the number of values.
//
inline TRegValueIterator::operator bool()
{
return Index >= 0 && Index < int(Key.GetValueCount());
}
//
/// Preincrements to the next value.
//
inline uint32 TRegValueIterator::operator ++()
{
return ++Index;
}
//
/// Postincrements to the next value.
//
inline uint32 TRegValueIterator::operator ++(int)
{
return Index++;
}
//
/// Predecrements to the previous value.
//
inline uint32 TRegValueIterator::operator --()
{
return --Index;
}
//
/// Postdecrements to the previous value.
//
inline uint32 TRegValueIterator::operator --(int)
{
return Index--;
}
//
/// Sets the index of the iterator to the passed value.
/// \return The new index.
//
inline uint32 TRegValueIterator::operator [](int index)
{
PRECONDITION((index >= 0) && (index < int(Key.GetValueCount())));
return Index = index;
}
//
/// Returns the index to the current value.
//
inline int TRegValueIterator::Current() const
{
return Index;
}
//
/// Returns the registration key that this iterator is bound to.
//
inline const TRegKey& TRegValueIterator::BaseKey() const
{
return Key;
}
//
/// Resets the value index to zero
//
inline void TRegValueIterator::Reset()
{
Index = 0;
}
//----------------------------------------------------------------------------
// TRegList inlines
//
//
/// Constructs a TRegList object from an array of TRegItems terminated by a NULL item name.
//
inline TRegList::TRegList(TRegItem* _list)
: Items(_list)
{
PRECONDITION(_list);
}
//
/// The array operator uses an item name (key) to locate an item in the array.
/// Returns the value of the passed key as a const tchar*.
//
inline LPCTSTR TRegList::operator[](LPCSTR key)
{
PRECONDITION(key);
return Lookup(key);
}
//----------------------------------------------------------------------------
// TRegLink inlines
//
//
/// Registration link node destructor.
//
inline TRegLink::~TRegLink()
{}
//
/// Returns a pointer to the next link.
//
inline TRegLink* TRegLink::GetNext() const
{
return Next;
}
inline void TRegLink::SetNext(TRegLink* link)
{
Next = link;
}
//
/// Returns a pointer to the registration parameter table (reglist).
//
inline TRegList& TRegLink::GetRegList() const
{
return *RegList;
}
//
/// Protected constructor where the derived class must initialize all pointers.
//
inline TRegLink::TRegLink()
: Next(0), RegList(0)
{}
//----------------------------------------------------------------------------
// TRegTemplateList
//
//
/// Returns the number of templates in this list.
//
inline int TRegTemplateList::GetCount() const
{
return Count;
}
//
/// Returns the registry key upon which these templates are based.
//
inline TRegKey& TRegTemplateList::GetBaseKey()
{
return BaseKey;
}
//
/// Returns the template string at the passed index.
/// \note The list is indexed beginning with 1 not 0.
//
inline LPCTSTR TRegTemplateList::operator [](int i)
{
PRECONDITION(i > 0 && i <= Count);
if (i <= 0 || i > Count)
return 0;
else
return List[i - 1];
}
//
/// Disables all templates in this list.
//
inline void TRegTemplateList::DisableAll()
{
memset(EnabledFlags, 0x80, Count);
}
//
/// Enables all templates in this list.
//
inline void TRegTemplateList::EnableAll()
{
memset(EnabledFlags, 0x00, Count);
}
//
/// Enables the template at the passed index.
/// \note The list is indexed beginning with 1 not 0.
//
inline void TRegTemplateList::Enable(int i)
{
PRECONDITION(i > 0 && i <= Count);
if (i > 0 && i <= Count)
EnabledFlags[i - 1] = 0;
}
//
/// Activates the template at the passed index.
/// \note The list is indexed beginning with 1 not 0.
//
inline void TRegTemplateList::Activate(int i)
{
PRECONDITION(i > 0 && i <= Count);
if (i > 0 && i <= Count)
EnabledFlags[i - 1]++;
}
//
/// Returns true if the template at the passed index is active, false otherwise.
/// \note The list is indexed beginning with 1 not 0.
//
inline bool TRegTemplateList::IsActive(int i) const
{
PRECONDITION(i > 0 && i <= Count);
if (i > 0 && i <= Count)
return EnabledFlags[i - 1] > 0;
else
return false;
}
//----------------------------------------------------------------------------
// TRegParamList
//
//
/// Return the number of param entries in this list.
//
inline int TRegParamList::GetCount() const
{
return Count;
}
//
/// Return the template string at the passed index.
//
inline const TRegParamList::TEntry& TRegParamList::operator [](int i) const
{
PRECONDITION(i >= 0 && i < Count);
return List[i];
}
//
/// Return the value of the param entry at the passed index.
//
inline const tchar*& TRegParamList::Value(int i)
{
PRECONDITION(i >= 0 && i < Count);
return Values[i];
}
} // OWL namespace
#endif // OWL_REGISTRY_H
↑ V302 Member operator[] of 'TRegKeyIterator' class has a 32-bit type argument. Use memsize-type here.
↑ V302 Member operator[] of 'TRegValueIterator' class has a 32-bit type argument. Use memsize-type here.
↑ V302 Member operator[] of 'TRegTemplateList' class has a 32-bit type argument. Use memsize-type here.
↑ V302 Member operator[] of 'TRegParamList' class has a 32-bit type argument. Use memsize-type here.
↑ V690 The 'TRegKey' class implements a move constructor, but lacks the move assignment operator. It is dangerous to use such a class.