windows-nt/Source/XPSP1/NT/ds/security/services/scerpc/escprov/persistmgr.h
2020-09-26 16:20:57 +08:00

653 lines
20 KiB
C++

// persistmgr.h: interface for the SCE persistence related classes.
// Copyright (c)1997-2001 Microsoft Corporation
//
//////////////////////////////////////////////////////////////////////
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include <ntsecapi.h>
#include <secedit.h>
#include "compkey.h"
//
// macro to save the similar code
//
#define SCE_PROV_IfErrorGotoCleanup(x) {if (FAILED(hr = (x))) goto CleanUp;}
//
// some helper functions
//
LPCWSTR EscSeekToChar(LPCWSTR pszSource, WCHAR wchChar, bool* pbEscaped, bool bEndIfNotFound);
void TrimCopy(LPWSTR pDest, LPCWSTR pSource, int iLen);
//
// make them visible to all those who include this header
//
extern const WCHAR wchCookieSep;
extern const WCHAR wchTypeValSep;
extern const WCHAR wchTypeValLeft;
extern const WCHAR wchTypeValRight;
extern const WCHAR wchMethodLeft;
extern const WCHAR wchMethodRight;
extern const WCHAR wchMethodSep;
extern const WCHAR wchParamSep;
extern LPCWSTR pszListPrefix;
extern LPCWSTR pszKeyPrefix;
extern LPCWSTR pszNullKey;
extern LPCWSTR pszAttachSectionValue;
//
// some constants
//
const int iFormatIntegral = 1;
const int iFormatInt8 = 2;
const int iFormatFloat = 3;
const int iFormatCurrenty = 4;
const int iFormatArray = 5;
const int MAX_INT_LENGTH = 32;
const int MAX_DOUBLE_LENGTH = 64;
const int MAX_COOKIE_COUNT_PER_LINE = 10;
const DWORD INVALID_COOKIE = 0;
/*
Class description
Naming:
CScePropertyMgr stands SCE wbem Property Manager.
Base class:
None.
Purpose of class:
(1) This class is used to access properties (both Put and Get). The main
reason for having this function is that we can override many versions,
one for each major data type the caller is expecting. Otherwise, it will
be all variants.
Design:
(1) Trivial. Just some overrides of both Get and Put.
(2) The class is attaching (Attach) to a particular wbem object. It can
be freely re-attached by calling Attach multiple times. This is good
inside a loop.
Use:
(1) Create an instance of this class.
(2) Attach the wbem object to the manager.
(3) Access (put or get) the properties as you wish.
*/
class CScePropertyMgr
{
public:
CScePropertyMgr();
~CScePropertyMgr();
void Attach(IWbemClassObject *pObj);
//
//property Put methods:
//
HRESULT PutProperty(LPCWSTR pszProperty, VARIANT* pVar);
HRESULT PutProperty(LPCWSTR pszProperty, LPCWSTR szValue);
HRESULT PutProperty(LPCWSTR pszProperty, DWORD iValue);
HRESULT PutProperty(LPCWSTR pszProperty, float fValue);
HRESULT PutProperty(LPCWSTR pszProperty, double dValue);
HRESULT PutProperty(LPCWSTR pszProperty, bool bValue);
HRESULT PutProperty(LPCWSTR pszProperty, PSCE_NAME_LIST strList);
//
// property Get methods:
//
HRESULT GetProperty(LPCWSTR pszProperty, VARIANT* pVar);
HRESULT GetProperty(LPCWSTR pszProperty, BSTR *pbstrValue);
HRESULT GetProperty(LPCWSTR pszProperty, DWORD *piValue);
HRESULT GetProperty(LPCWSTR pszProperty, bool *pbValue);
HRESULT GetProperty(LPCWSTR szProperty, PSCE_NAME_LIST *strList);
//
// we can expand the the path as well.
//
HRESULT GetExpandedPath(LPCWSTR pszPathName, BSTR *pbstrValue, BOOL* pbIsDB);
private:
CComPtr<IWbemClassObject> m_srpClassObj;
};
/*
Class description
Naming:
CSceStore stands SCE Store.
Base class:
None.
Purpose of class:
(1) This class is to encapulate the notation of persistence store for SCE. Almost
everything we do with SCE provider (other than execute a function like Configure)
is to put instances into a template store. That store can currently be a .INF file,
or a database (.sdb). Our goal is to isolate this store from the rest of the
code so that when we expand our store types (like XML), the code affected will
be greatly reduced and thus improve code maintainability drastically.
Design:
(1) Move all SCE engine backend specific functionality here. This is a little bit
confusing because there are so many. See the comments to locate these functions.
(2) To support current property saving, we have SavePropertyToStore (several overrides)
function.
(3) To support current property saving, we have GetPropertyFromStore (several overrides)
function. Both (2) and (3) maintain a high fidelity to the current .inf and .sdb APIs.
(4) To ease the confusion that saving in a particular way means to delete, we also have
DeletePropertyFromStore, DeleteSectionFromStore functions.
(5) Ideally, we only need GetPropertyFromStore and SavePropertyToStore functions.
(6) To allow future growth of maximum extensibility, we planned (not yet) to support IPersistStream.
Use:
(1) Create an instance of this class.
(2) Specify the persistence properties (SetPersistPath and SetPersistProperties).
(3) Call appropriate functions.
*/
class CSceStore
{
public:
CSceStore();
~CSceStore(){}
HRESULT SetPersistProperties(IWbemClassObject* pClassObj, LPCWSTR lpszPathPropertyName);
HRESULT SetPersistPath(LPCWSTR pszPath);
HRESULT SetPersistStream(IPersistStream* pSceStream)
{
return WBEM_E_NOT_SUPPORTED; // not yet
}
HRESULT SavePropertyToStore(LPCWSTR pszSection, LPCWSTR pszKey, LPCWSTR pszValue)const;
HRESULT SavePropertyToStore(LPCWSTR pszSection, LPCWSTR pszKey, DWORD Data)const;
HRESULT SavePropertyToStore(LPCWSTR pszSection, LPCWSTR pszKey, DWORD Data, WCHAR delim, LPCWSTR pszValue)const;
HRESULT GetPropertyFromStore(LPCWSTR pszSection, LPCWSTR pszKey, LPWSTR *ppszBuffer, DWORD* pdwRead)const;
//
// the following two methods are to stop our current semantics to let
// deleting and saving share the same function. Callers be aware:
// WritePrivateProfileString (which we ultimately use in inf file store) can't report
// error when deleting a non existent key. So, don't rely on this return code to catch
// the "deleting non-existent property" error.
//
HRESULT
DeletePropertyFromStore (
IN LPCWSTR pszSection,
IN LPCWSTR pszKey
)const
{
return SavePropertyToStore(pszSection, pszKey, (LPCWSTR)NULL);
}
HRESULT DeleteSectionFromStore (
IN LPCWSTR pszSection
)const;
//
// the following functions are designed for the maximum compability of the current INF file API and its
// SCE backend support on reading/writing
//
HRESULT GetSecurityProfileInfo (
AREA_INFORMATION Area,
PSCE_PROFILE_INFO *ppInfoBuffer,
PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
)const;
HRESULT WriteSecurityProfileInfo (
AREA_INFORMATION Area,
PSCE_PROFILE_INFO ppInfoBuffer,
PSCE_ERROR_LOG_INFO *Errlog,
bool bAppend
)const;
void
FreeSecurityProfileInfo (
IN OUT PSCE_PROFILE_INFO pInfo
)const
{
if (pInfo != NULL)
{
SceFreeProfileMemory(pInfo);
}
}
HRESULT GetObjectSecurity (
AREA_INFORMATION Area,
LPCWSTR pszObjectName,
PSCE_OBJECT_SECURITY *ppObjSecurity
)const;
void
FreeObjectSecurity (
IN OUT PSCE_OBJECT_SECURITY pObjSecurity
)const
{
if (pObjSecurity)
SceFreeMemory(pObjSecurity, SCE_STRUCT_OBJECT_SECURITY);
}
LPCWSTR
GetExpandedPath ()const
{
return m_bstrExpandedPath;
}
SCE_STORE_TYPE
GetStoreType ()const
{
return m_SceStoreType;
}
HRESULT WriteAttachmentSection (
LPCWSTR pszKey,
LPCWSTR pszData
)const;
private:
HRESULT SavePropertyToDB (
LPCWSTR pszSection,
LPCWSTR pszKey,
LPCWSTR pszData
)const;
HRESULT GetPropertyFromDB (
LPCWSTR pszSection,
LPCWSTR pszKey,
LPWSTR *ppszBuffer,
DWORD* pdwRead
)const;
CComBSTR m_bstrExpandedPath;
CComPtr<IWbemClassObject> m_srpWbemClassObj;
SCE_STORE_TYPE m_SceStoreType;
};
//==========================================================================
//
// some global parsing related functions:
//
HRESULT VariantFromFormattedString (
LPCWSTR pszString, // [in]
VARIANT* pVar // [out]
);
HRESULT FormatVariant (
VARIANT* pVar,
BSTR* pbstrData
);
HRESULT GetObjectPath (
IWbemClassObject* pSpawn, // [in]
LPCWSTR pszStorePath, // [in]
LPCWSTR pszCompoundKey, // [in]
BSTR* pbstrPath // [out]
);
HRESULT ParseCompoundKeyString (
LPCWSTR pszCur,
LPWSTR* ppszName,
VARIANT* pVar,
LPCWSTR* ppNext
);
HRESULT PopulateKeyProperties (
LPCWSTR pszCompoundKey, // [in]
CScePropertyMgr* pPropMgr // [in]
);
HRESULT CurrencyFromFormatString (
LPCWSTR lpszFmtStr,
VARIANT* pVar
);
HRESULT ArrayFromFormatString (
LPCWSTR lpszFmtStr,
VARTYPE vt,
VARIANT* pVar
);
HRESULT FormatArray (
VARIANT* pVar,
BSTR* pbstrData
);
HRESULT GetStringPresentation (
VARIANT* pVar,
BSTR* pbstrValue
);
void* GetVoidPtrOfVariant (
VARTYPE vt, // can't be VT_ARRAY, which is done separately
VARIANT* pVar
);
HRESULT VariantFromStringValue (
LPCWSTR szValue, // [in]
VARTYPE vt, // [in]
VARIANT* pVar // [out]
);
//==========================================================================
/*
Class description
Naming:
CScePersistMgr stands SCE Persistence Manager.
Base class:
(1) CComObjectRootEx<CComMultiThreadModel> for threading model and IUnknown
(2) CComCoClass<CScePersistMgr, &CLSID_ScePersistMgr> for class factory support
(3) IScePersistMgr, our custom interface
Purpose of class:
(1) This class is to encapulate the ultimate goal of persistence. This manager
can persist any cooperating class (ISceClassObject). ISceClassObject is designed
to supply a wbem object's (name, value) pairs together with its easy access to
the information whether a property is a key property or not. All these are rather
straight forward for any wbem object.
(2) Make the persistence model extremely simple: Save, Load, Delete.
(3) Current use of this persistence manager is intended for embedding classes. To adapt it
for use of native classes, we need a lot more work. The reason is that native object's
persistence is an intimate knowledge of SCE backend. It knows precisely how the instances
are persisted. That kind of dependency ties both sides up. Unless the SCE backend modifies
for a more object-oriented approach, any attempt for persisting native objects will fail.
Design:
(1) This is an IScePersistMgr.
(2) This is not a directly instantiatable class. See the constructor and destructor, they are
both protected. See Use section for creation steps.
(3) maintain two vectors, one for key property values and one for non-key property values.
We very often need to access key properties differently because they form the key to
identify the object.
(4) To quickly identify an instance and keep redundant data away from the store, an instance is
identified by its cookie (just a unique DWORD number). For each cookie, the key properties
should be conveniently available. For that purpose, we developed the notation of string
format Compound Key. It is pretty much just an encoding of key property names and its
values using a string. For example, if the key of the class has two properties CompanyName (string)
and RegNumber (DWORD), then an instance of this class identified by:
CompanyName = "ABCDEFG Inc.", RegNumber = 123456789
will have its compound key in string format as follows:
CompanyName<VT_BSTR : "ABCDEFG Inc.">RegNumber<VT_I4 : 123456789>
Use:
(1) Create an instance of this class. Since it's not a directly instantiatable class, you need
to use CComObject<CScePersistMgr> for creation:
CComObject<CScePersistMgr> *pPersistMgr = NULL;
hr = CComObject<CScePersistMgr>::CreateInstance(&pPersistMgr);
(2) Attach an ISceClassObject object to this instance by calling Attach.
(3) Call appropriate functions.
Notes:
This class is not intended for derivation. It's a final class. The destructor is thus not virtual.
*/
class ATL_NO_VTABLE CScePersistMgr
: public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CScePersistMgr, &CLSID_ScePersistMgr>,
public IScePersistMgr
{
public:
BEGIN_COM_MAP(CScePersistMgr)
COM_INTERFACE_ENTRY(IScePersistMgr)
END_COM_MAP()
DECLARE_NOT_AGGREGATABLE( CScePersistMgr )
DECLARE_REGISTRY_RESOURCEID(IDR_SceProv)
protected:
CScePersistMgr();
~CScePersistMgr();
public:
//
// IScePersistMgr
//
STDMETHOD(Attach) (
REFIID guid, // [in]
IUnknown *pObj // [iid_is][in]
);
STDMETHOD(Save) ();
STDMETHOD(Load) (
BSTR bstrStorePath, // [in]
IWbemObjectSink *pHandler //[in]
);
STDMETHOD(Delete) (
BSTR bstrStorePath, // [in]
IWbemObjectSink *pHandler //[in]
);
private:
HRESULT GetCompoundKey (
BSTR* pbstrKey // [out]
);
//
// inline
//
HRESULT
GetSectionName (
OUT BSTR* pbstrSection
)
{
return m_srpObject->GetClassName(pbstrSection);
}
//
// inline
//
HRESULT
GetClassName (
OUT BSTR* pbstrClassName
)
{
return m_srpObject->GetClassName(pbstrClassName);
}
HRESULT FormatNonKeyPropertyName (
DWORD dwCookie, // [in]
DWORD dwIndex, // [in]
BSTR* pbstrStorePropName, // [out]
BSTR* pbstrTrueName // [out]
);
HRESULT FormatPropertyValue (
SceObjectPropertyType type, // [in]
DWORD dwIndex, // [in]
BSTR* pbstrProp // [out]
);
HRESULT LoadInstance (
CSceStore* pSceStore,
LPCWSTR pszSectionName,
LPCWSTR pszCompoundKey,
DWORD dwCookie,
IWbemClassObject** ppNewObj
);
HRESULT SaveProperties (
CSceStore* pSceStore,
DWORD dwCookie,
LPCWSTR pszSection
);
HRESULT DeleteAllNonKeyProperties (
CSceStore* pSceStore,
DWORD dwCookie,
LPCWSTR pszSection
);
std::vector<LPWSTR>* GetKeyPropertyNames (
IWbemServices* pNamespace,
IWbemContext* pCtx
);
std::vector<CPropValuePair*> m_vecKeyValueList;
std::vector<CPropValuePair*> m_vecPropValueList;
CComPtr<ISceClassObject> m_srpObject;
};
//==========================================================================
typedef struct tagVtTypeStruct
{
LPCWSTR pszVtTypeString;
VARTYPE vt;
} VtTypeStruct;
//==========================================================================
/*
Class description
Naming:
CMapStringToVt stands for String to VT (VARTYPE) Map.
Base class:
None.
Purpose of class:
CMapStringToVt is a straight forward class wrapping up a map.
Design:
(1) GetType very efficiently returns the VARTYPE for the given string version of the vt.
Use:
(1) Create an instance of this class.
(2) Call GetType to get the VARTYPE value for the given string version of the vt. For
example, GetType(L"VT_BSTR") will return VT_BSTR;
*/
class CMapStringToVt
{
public:
CMapStringToVt (
DWORD dwCount,
VtTypeStruct* pInfoArray
);
VARTYPE GetType (
LPCWSTR,
VARTYPE* pSubType
);
private:
typedef std::map<LPCWSTR, VARTYPE, strLessThan<LPCWSTR> > MapStringToVt;
MapStringToVt m_Map;
};
//==========================================================================
/*
Class description
Naming:
CMapVtToString stands for VT (VARTYPE) to String Map.
Base class:
None.
Purpose of class:
CMapVtToString is a straight forward class wrapping up a map. It is the exact inverse
version of CMapStringToVt
Design:
(1) GetTypeString very efficiently returns the string version of the given VARTYPE.
(2) GetTypeString can also efficiently return the string version of the given VARTYPE
plus the sub-VARTYPE if the given VARTYPE is VT_ARRAY.
Use:
(1) Create an instance of this class.
(2) Call GetTypeString to get the string version of the given VARTYPE. For
example, GetTypeString(VT_BSTR) will return L"VT_BSTR", and GetTypeString(VT_ARRAY, VT_BSTR)
will return L"VT_ARRAY(VT_BSTR)"
*/
class CMapVtToString
{
public:
CMapVtToString(DWORD dwCount, VtTypeStruct* pInfoArray);
LPCWSTR GetTypeString(VARTYPE vt, VARTYPE vtSub);
LPCWSTR GetTypeString(VARTYPE vt);
private:
typedef std::map<VARTYPE, LPCWSTR> MapVtToString;
MapVtToString m_Map;
};