Creates a property store backed by a XML document
Syntax
HRESULT WINAPI SHCreatePropertyStoreOnXML (
IXMLDOMNode* pXmlDomNode,
DWORD gfrMode,
IPropertyBag* pPropBagInit,
REFIID riid,
PVOID* ppv
)
Parameters
- pXmlDomNode
- A root node under which to start reading and writing properties. Can be NULL.
- gfrMode
- Can be STGM_READ, STGM_WRITE, or STGM_READWRITE to indicate whether the underlying XML is modifiable. Used only if pXmlDomNode is not NULL.
- pPropBagInit
- A property bag to be queried for its underlying registry key. Can be NULL.
- riid
- IID of the requested interface to return in *ppv
- ppv
- A pointer to a pointer that receives the interface represented by riid
Return Value
S_OK on success, standard COM error on failure
Remarks
The interfaces that can be queried by the riid parameter are IInitializeWithStream, IPersistPropertyBag, INamedPropertyStore and IPropertyStore along with the following undocumented interfaces:
MIDL_INTERFACE("37941AB6-DADC-47a5-8F42-3F9EE5966224") struct IObjectWithClassIdentity : public IUnknown { // returns a string identifier for the object // The retuned string must be freed with CoTaskMemFree when no longer needed virtual STDMETHODIMP GetClassIdentity(LPWSTR* ppwszIdentity) = 0; }; MIDL_INTERFACE("482df151-d135-439a-badd-3b4b4b986caf") struct IXMLPropertyStoreInit : public IUnknown { // This method is called internally if you supply the pXMLDOMNode argument // It allows you you to do the same init as it does at a later time virtual STDMETHODIMP Initialize(IXMLDOMNode* pXMLDOMNode, DWORD grfMode) = 0; };To store any changes made to the property store, IPropertyStore::Commit() must be called. IPersistPropertyBag::Save() is unimplemented and returns E_FAIL. If the property store is initialized with IInitializeWithStream, the changes will be written out to that stream. Likewise if the property store is initiliazed with IXMLPropertyStoreInit or passed the pXMLDOMNode argument to the function, the changes will be written out to the nodes owning XML document.
If the pPropBagInit parameter is not NULL, it is queried for a IObjectWithRegistryKey interface. If successful the registry key it represents is saved. When reading and writing properties using IPropertyStore, the key is queried for 'VT' and 'XPath' representing the type of the property id and its XPath location in the XML document.
One of IInitializeWithStream, IXMLPropertyStoreInit, or the pXMLDOMNode parameter must be used to initialize the property store. Any attempt to read or write properties without doing this will return STGM_E_ACCESSDENIED.
If using IPropertyStore to read and write parameters, the pPropBagInit parameter, or calling IPersistPropertyBag::Load is required. If not, GetValue and SetValue will return E_FAIL.
Example
#define WIN32_LEAN_AND_MEAN #include <windows.h> #include <shlwapi.h> #include <ole2.h> #include <msxml6.h> #pragma comment(lib, "msxml6.lib") typedef HRESULT (WINAPI*pfnSHCreateXMLPropStore)(IXMLDOMNode* pXmlNode, DWORD grfMode, IPropertyBag* pPropBagInit, REFIID riid, PVOID* ppv); int main() { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); // create an XML document IXMLDOMDocument2* pDoc = NULL; CoCreateInstance(CLSID_DOMDocument2, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&pDoc)); // create a root node VARIANT nodeType; V_VT(&nodeType) = VT_I4; V_I4(&nodeType) = NODE_ELEMENT; IXMLDOMNode* pNode = NULL; pDoc->createNode(nodeType, L"MyRootNode", NULL, &pNode); // attach it to the document pDoc->appendChild(pNode, NULL); // get the function ptr HMODULE hMod = LoadLibraryW(L"shlwapi.dll"); pfnSHCreateXMLPropStore sHCreateXMLPropStore = (pfnShell)GetProcAddress(hMod, (LPCSTR)621); // call the function requesting the named property store interface INamedPropertyStore* pProps = NULL; hr4 = sHCreateXMLPropStore(pNode, STGM_READWRITE, NULL, IID_PPV_ARGS(&pProps)); // the function takes it's own reference on the node // so we can get rid of ours now that we no longer need it pNode->Release(); // set a named property PROPVARIANT propVar = {0}; propVar.vt = VT_UI4; propVar.uiVal = 9; pProps->SetNamedValue(L"MyNamedProperty", propVar); // get the IPropertyStore interface so we can commit (flush) the changes // back to the source IPropertyStore* pStore = NULL; pProps->QueryInterface(&pStore); pStore->Commit(); // we no longer need the interfaces pStore->Release(); pProps->Release(); // save the xml document VARIANT name; V_VT(&name) = VT_BSTR; V_BSTR(&name) = L"test.xml"; pDoc->save(name); // final cleanup pDoc->Release(); CoUninitialize(); return 0; }OUTPUT - test.xml ------ <MyRootNode> <MicrosoftProperties> <NamedProperties> <Property Name="MyNamedProperty" type="uint32">9</Property> </NamedProperties> </MicrosoftProperties> </MyRootNode>This function is also known as _SHCreatePropertyStoreOnXML@20.