
The following interfaces are relevant to components hosted by Internet Explorer. This section provides the details on these interfaces.
The IServiceProvider Interface
The IPersistPropertyBag Interface
The IPersistPropertyBag2 Interface
See the URL Moniker reference for information on the following interfaces:
| IBinding |
| IBindStatusCallback |
| IPersistMoniker |
This interface is implemented as a service available from a site object through which a container supplies services and information that objects require when performing an asynchronous data transfer, specifically name-to-moniker parsing and a container-initialized bind context.
IDL:
[
uuid(fc4801a1-2ba9-11cf-a229-00aa003d7352)
, object,pointer_default(unique)
]
interface IBindHost : IUnknown
{
HRESULT CreateMoniker([in] LPCOLESTR pszName, [in] IBindCtx *pBC
, [out] IMoniker** ppmk, [in] DWORD dwReserved);
HRESULT MonikerBindToStorage([in] IMoniker *pMk, [in] IBindCtx *pBC
, [in] IBindStatusCallback *pBSC, [in] REFIID riid
, [out, iid_is(riid)] void **ppvObj);
HRESULT MonikerBindToObject([in] IMoniker *pMk, [in] IBindCtx *pBC
, [in] IBindStatusCallback *pBSC, [in] REFIID riid
, [out, iid_is(riid)] void **ppvObj);
}
HRESULT CreateMoniker([in] LPCOLESTR pszName, [in] IBindCtx *pBC, [out] IMoniker **ppmk, [in] DWORD dwReserved);
CreateMoniker provides the caller with a means to turn some sort of text name into a moniker so that the caller does not have to interpret the name in any way itself. In many cases, the implementation of CreateMoniker will simply call MkParseDisplayNameEx, but this method gives the implementor of IBindHost a chance to catch host-specific strings that MkParseDisplayNameEx would not otherwise recognize.
| S_OK | The moniker was successfully obtained and the caller is responsible for the interface pointer. |
| E_OUTOFMEMORY | There is insufficient memory to create the moniker. |
| E_UNEXPECTED | An unknown error occurred. |
| MK_E_SYNTAX | The bind host was unable to parse the string into a moniker because the information in the name was unrecognizable. |
E_NOTIMPL is disalloweda bind host is responsible for providing moniker parsing services.
HRESULT MonikerBindToStorage([in] IMoniker *pMk, [in] IBindCtx *pBC, [in] IBindStatusCallback *pBSC, [in] REFIID riid, [out] void **ppvObj);
MonikerBindToStorage should be the single mechanism controls use when trying to bind to the data addressed by a moniker. This function behaves exactly the same as IMoniker::BindToStorage, except that it provides the control container (implementor of IBindHost) enough authority over the bind operation so that the control container can take charge of setting bind options and priority, while delegating all results and callbacks for the bind operation back to the control.
| S_OK | The bind operation completed synchronously and successfully. The result of the bind operation is available in ppvObj. |
| MK_S_ASYNCHRONOUS | The bind operation will complete asynchronously. Behavior matches that of IMoniker::BindToStorage. |
| E_OUTOFMEMORY | There is insufficient memory to create the moniker. |
| E_UNEXPECTED | An unknown error occurred. |
HRESULT MonikerBindToObject([in] IMoniker *pMk, [in] IBindCtx *pBC, [in] IBindStatusCallback *pBSC, [in] REFIID riid, [out] void **ppvObj);
MonikerBindToObject should be the single mechanism controls use when trying to bind to the object addressed by a moniker. This function behaves exactly the same as IMoniker::BindToObject, except that it provides the control container (implementor of IBindHost) enough authority over the bind operation so that the control container can take charge of setting bind options and priority, while delegating all results and callbacks for the bind operation back to the control.
| S_OK | The bind operation completed synchronously and successfully. The result of the bind operation is available in ppvObj. |
| MK_S_ASYNCHRONOUS | The bind operation will complete asynchronously. Behavior matches that of IMoniker::BindToObject. |
| E_OUTOFMEMORY | There is insufficient memory to create the moniker. |
| E_UNEXPECTED | An unknown error occurred. |
IServiceProvider is a generic access mechanism to locate a GUID-identified "service" that is provided through a control or any other objects that it can communicate with. For example, an embedded object (such as an OLE control) normally only communicates with its associated "client site" object in the container through the IOleClientSite interface supplied through IOleObject::SetClientSite. Such an embedded object is required to ask the client site for some other service that the container supports when that service may not necessarily be implemented in the site itself.
In this regard, the site must provide a means through which the control managed by that site can access the service when necessary. A specific example of this necessity can be found in the function IOleInPlaceSite::GetWindowContext, through which an in-place object or control can access interface pointers for the document object that contains the site and the frame object that contains the document. Because these interface pointers exists on separate objects, the control cannot call the site's QueryInterface to obtain those pointers.
The generic architecture for achieving the same ends, without requiring ad hoc solutions where the need arises, is the interface IServiceProvider whose existence says "somewhere in the code of which I'm part exists some set of services that can be accessed through this interface."
The interface itself has only one member, QueryService, through which a caller specifies the service ID (SID, a GUID), the IID of the interface desired in return, and the address of the caller's interface pointer variable.
IDL:
[
uuid(6d5140c1-7436-11ce-8034-00aa006009fa)
, object,pointer_default(unique)
]
interface IServiceProvider : IUnknown
{
HRESULT QueryService([in] REFGUID guidService
, [in] REFIID riid, [out, iid_is(riid)] void **ppv);
}
HRESULT QueryService([in] REFGUID guidService, [in] REFIID riid, [out, iid_is(riid)] void **ppv);
QueryService is the factory method for any services exposed through an implementation of IServiceProvider. It creates or accesses the implementation the service identified with guidService, returning in *ppv the address of the interface specified by riid.
| S_OK | The service was successfully created or retrieved. The caller is responsible for calling ((IUnknown *)*ppv)->Release();. |
| E_OUTOFMEMORY | There is insufficient memory to create the service. |
| E_UNEXPECTED | An unknown error occurred. |
| E_NOINTERFACE | The service exists, but the interface requested does not exist on that service. |
| SVC_E_UNKNOWNSERVICE | The service identified with guidService is not recognized. |
Because there is only one member function in this interface, E_NOTIMPL is not a valid return codeif the function is not implemented, the interface has no reason to exist.
Often, an object will need to communicate directly with a "container site" that is managing the object itself. Outside of IOleObject::SetClientSite, there is no generic means through which an object becomes aware of its site. IObjectWithSite provides simple objects with a lightweight means (lighter than IOleObject) with a siting mechanism. This interface should only be used when IOleObject is not already in use.
Through IObjectWithSite, a container can pass the IUnknown pointer of its site to the object through SetSite. Callers can also retrieve the latest site passed to SetSite through GetSite. This latter function is included as a hooking mechanism, allowing a third party to intercept calls from the object to the site.
IDL:
[
uuid(fc4801a3-2ba9-11cf-a229-00aa003d7352)
, object,pointer_default(unique)
]
interface IObjectWithSite : IUnknown
{
HRESULT SetSite([in] IUnknown *pUnkSite);
HRESULT GetSite([in] REFIID riid, [out, iid_is(riid)] void **ppvSite);
}
HRESULT SetSite([in] IUnknown *pUnkSite);
Provides the site's IUnknown pointer to the object. The object should hold onto this pointer, calling AddRef in doing so. If the object already has a site, it should first call pUnkSite->AddRef to secure the new site, call IUnknown::Release on the existing site, then save pUnkSite.
| S_OK | Returned in all circumstances |
E_NOTIMPL is disallowedwithout implementation of SetSite, the IObjectWithSite interface is unnecessary.
HRESULT GetSite([in] REFIID riid, [out, iid_is(riid)] void **ppvSite);
Retrieves the last site set with IObjectWithSite::SetSite. If there's no known site, the object returns a failure code.
| S_OK | The site was returned successfully and the caller is responsible for calling ((IUnknown *)(*ppvSite))->Release() when the site is no longer needed. |
| E_FAIL | There is no site; in that case, *ppvSite contains NULL on return. |
| E_NOINTERFACE | There is a site, but it does not support the interface requested by riid. |
E_NOTIMPL is disallowedany object implementing this interface must be able to return the last site seen in SetSite.
IPersistMemory operates exactly as IPersistStreamInit, except that it allows the caller to provide a fixed-size memory block (identified with a void *) as opposed to IPersistStreamInit, which involves an arbitrarily expandable IStream.
IDL:
[
uuid(BD1AE5E0-A6AE-11CE-BD37-504200C10000)
, object, pointer_default(unique)
]
interface IPersistMemory : IPersist
{
HRESULT IsDirty(void);
HRESULT Load([in, size_is(cbSize)] void *pvMem, [in] ULONG cbSize);
HRESULT Save([in,out, size_is(cbSize)] void *pvMem, [in] BOOL fClearDirty, [in] ULONG cbSize);
HRESULT GetSizeMax([out] ULONG* pcbSize);
HRESULT InitNew(void);
};
The cbSize argument to Load and Save indicate the amount of memory accessible through pvMem.
The IsDirty, GetSizeMax, and InitNew members are semantically and syntactically identical to those in IPersistStreamInit. Only Load and Save differ as described below.
HRESULT IPersistMemory::Load([in] void *pvMem, [in] ULONG cbSize);
Instructs the object to load its persistent data from the memory pointed to by pvMem where cbSize indicates the amount of memory at pvMem. The object must not read past the address (BYTE*)((BYTE *)pvMem+cbSize).
| S_OK | The object successfully loaded its data. |
| E_UNEXPECTED | This member was called after the object was already initialized with IPersistMemory::Load. Only one initialization is allowed per instance. |
| E_POINTER | The pointer in pvMem is NULL. |
Any object that implements IPersistMemory has some information to load persistently; therefore, E_NOTIMPL is not a valid return code.
HRESULT IPersistMemory::Save([in] void *pvMem, [in] BOOL fClearDirty, [in] ULONG cbSize);
Instructs the object to save its persistent data to the memory pointed to by pvMem where cbSize indicates the amount of memory available at pvMem. The object must not write past the address (BYTE*)((BYTE *)pvMem+cbSize). The fClearDirty flag determines whether the object is to clear its dirty state after the save is complete.
| S_OK | The object successfully initialized itself. |
| E_UNEXPECTED | This member was called before the object was initialized with IPersistMemory::InitNew or IPersistMemory::Load. |
| E_INVALIDARG | The number of bytes indicated by cbSize is too small to allow the object to save itself completely. |
| E_POINTER | The pointer in pvMem is NULL. |
Any object that implements IPersistMemory has some information to save persistently; therefore, E_NOTIMPL is not a valid return code.
The caller should ideally allocate as many bytes as the object returns from IPersistMemory::GetSizeMax.
The IPersistPropertyBag interface works in conjunction with IPropertyBag (see below) and IErrorLog (see below) to define an individual property-based persistence mechanism. Whereas a mechanism like IPersistStream gives an object an IStream in which to store its binary data, IPersistPropertyBag provides an object with an IPropertyBag interface through which it can save and load individual properties. The implementor of IPropertyBag can then save those properties in whatever way it chooses, such as name/value pairs in a text file. Errors encountered in the process (on either side) are recorded in an "error log" through IErrorLog. This error reporting mechanism works on a per-property basis instead of an "all properties as a whole" basis through just the return value of IPersist*::Load or IPersist*::Save.
IDL:
[
uuid(37D84F60-42CB-11CE-8135-00AA004BB851)
, object, pointer_default(unique)
]
interface IPersistPropertyBag : IPersist
{
HRESULT InitNew(void);
HRESULT Load([in] IPropertyBag *pPropBag, [in] IErrorLog *pErrorLog);
HRESULT Save([in] IPropertyBag *pPropBag, [in] BOOL fClearDirty
, [in] BOOL fSaveAllProperties);
};
The basic mechanism is that a container tells the object to save or load its properties through IPersistPropertyBag. For each property, the object calls the container's IPropertyBag interface passed to the IPersistPropertyBag members. IPropertyBag::Write obviously saves a property in whatever place the container wants to put it, and IPropertyBag::Read retrieves a property.
This protocol is essentially a means of sequentially communicating individual property values from the object to the container, which is useful for doing save-as-text operations and the like. The object gives the container the choice of the format in which each property is saved, while retaining itself the decision as to which properties are saved or loaded.
HRESULT InitNew(void);
Informs the object that it is being initialized as a newly created object.
| S_OK | The object successfully initialized itself. This should be returned even if the object doesn't do anything in the function. |
| E_UNEXPECTED | This member was called after IPersistPropertyBag::Load or IPersistPropertyBag::Save. |
E_NOTIMPL should not be returneduse S_OK when the object has nothing to do in the function.
HRESULT Load([in] IPropertyBag *pPropBag, [in] IErrorLog *pErrorLog);
Instructs the object to initialize itself using the properties available in the property bag, notifying the provided error log object when errors occur. All property loading must take place within this function call because the object cannot hold the IPropertyBag pointer.
| S_OK | The object successfully initialized itself. |
| E_UNEXPECTED | This member was called after IPersistPropertyBag::InitNew has already been called. They two initialization methods are mutually exclusive. |
| E_POINTER | The address in pPropBag is not valid (such as NULL,) and, therefore, the object cannot initialize itself. |
| E_FAIL | The object was unable to retrieve a critical property that is necessary for the object's successful operation. The object was, therefore, unable to initialize itself completely. |
E_NOTIMPL is not a valid return code because any object implementing this interface must support the entire functionality of the interface.
HRESULT Save([in] IPropertyBag *pPropBag, [in] BOOL fClearDirty, [in] BOOL fSaveAllProperties);
Instructs the object to save its properties to the given property bag, optionally clearing the object's "dirty" flag. The caller can request that the object save all properties or that the object save only those that are known to have changed.
| S_OK | The object successfully saved the requested properties itself. |
| E_FAIL | There was a problem saving one of the properties. The object can choose to fail only if a necessary property could not be saved, meaning that the object can assume default property values if a given property is not seen through Load at some later time. |
| E_POINTER | The address in pPropBag is not valid (such as NULL) and therefore the object cannot initialize itself. |
E_NOTIMPL is not a valid return code as any object implementing this interface must support the entire functionality of the interface.
When a client wants to have exact control over how individually named properties of an object are saved, it would attempt to use an object's IPersistPropertyBag interface as a persistence mechanism. In that case, the client supplies a "property bag" to the object in the form of an IPropertyBag interface.
IDL:
[
uuid(55272A00-42CB-11CE-8135-00AA004BB851)
, object, pointer_default(unique)
]
interface IPropertyBag : IUnknown
{
HRESULT Read([in] LPCOLESTR pszPropName, [in,out] VARIANT *pVar
, [in,out] IErrorLog *pErrorLog);
HRESULT Write([in] LPCOLESTR pszPropName, [in] VARIANT *pVar);
};
When the object wishes to read a property in IPersistPropertyBag::Load, it will call IPropertyBag::Read. When the object is saving properties in IPersistPropertyBag::Save, it will call IPropertyBag::Write. Each property is described with a name in pszPropName whose value is exchanged in a VARIANT. This information allows a client to save the property values as text, for instance, which is the primary reason why a client might choose to support IPersistPropertyBag.
The client records errors that occur during Read into the supplied "error log."
HRESULT Read([in] LPCOLESTR pszPropName, [in,out] VARIANT *pVar, [in,out] IErrorLog *pErrorLog);
Asks the property bag to read the property named with pszPropName into the caller-initialized VARIANT in pVar. Errors that occur are logged in the error log pointed to by pErrorLog. When pVar->vt specifies another object pointer (VT_UNKNOWN), the property bag is responsible for creating and initializing the object described by pszPropName. See IPropertyBag::Write for more information.
| S_OK | The property was read successfully. The caller becomes responsible for any allocations that are contained in the VARIANT in pVar. |
| E_POINTER | The address in pszPropName is not valid (such as NULL). |
| E_INVALIDARG | The property named with pszPropName does not exist in the property bag. |
| E_FAIL | The property bag was unable to read the specified property, such as if the caller specified a data type to which the property bag could not coerce the known value. If the caller supplied an error log, a more descriptive error was sent there. |
E_NOTIMPL is not a valid return code because any object implementing this interface must support the entire functionality of the interface.
HRESULT Write([in] LPCOLESTR pszPropName, [in] VARIANT *pVar);
Asks the property bag to save the property named with pszPropName using the type and value in the caller-initialized VARIANT in pVar. In some cases, the caller may be asking the property bag to save another objectthat is, when pVar->vt is VT_UNKNOWN. In such cases, the property bag queries this object pointer for some persistence interface, like IPersistStream or even IPersistPropertyBag again, and has that object save its data as well. Usually this results in the property bag having some byte array for this object which can be saved as encoded text (hex string, MIME, and so on). When the property bag is later used to reinitialize a control, the client that owns the property bag must recreate the object when the caller asks for it, initializing that object with the previously saved bits.
This allows very efficient persistence operations for large BLOB properties like a picture, where the owner of the property bag itself directly asks the picture object (managed as a property in the control being saved) to save into a specific location. This avoids potential extra copy operations that would be involved with other property-based persistence mechanisms.
| S_OK | The property bag successfully saved the requested property. |
| E_FAIL | There was a problem writing the property. It is possible that the property bag does not understand how to save a particular VARIANT type. |
| E_POINTER | The address in pszPropName or pVar is not valid (such as NULL). The caller must supply both. |
E_NOTIMPL is not a valid return code because any object implementing this interface must support the entire functionality of the interface.
The IPersistPropertyBag2 interface works in conjunction with the IPropertyBag2 and IErrorLog interfaces to define an individual property-based persistence mechanism. This interface is similar to IPersistPropertyBag, but allows the object to support property bags that implement IPropertyBag2.
Whereas a mechanism like IPersistStream gives an object an IStream in which to store its binary data, IPersistPropertyBag2 provides an object with an IPropertyBag2 interface through which it can save and load individual properties. The implementor of IPropertyBag2 can then save those properties in whatever way it chooses, such as name/value pairs in a text file. Errors encountered in the process (on either side) are recorded in an "error log" through IErrorLog. This error reporting mechanism work on a per-property basis instead of an "all properties as a whole" basis through just the return value of IPersist*::Load or IPersist*::Save.
When requesting a persistent property bag interface, a property bag that supports IPropertyBag2 will attempt to obtain the object's IPersistPropertyBag2 interface before attempting to obtain the object's IPersistPropertyBag interface. This allows objects that support either interface to communicate with the property bag.
IDL:
[object, uuid(22F55881-280B-11d0-A8A9-00A0C90C2004), pointer_default(unique)]
interface IPersistPropertyBag2 : IPersist
{
typedef [unique] IPersistPropertyBag2 *LPPERSISTPROPERTYBAG2;
HRESULT InitNew();
HRESULT Load(
[in]IPropertyBag2 * pPropBag,
[in]IErrorLog * pErrLog);
HRESULT Save(
[in]IPropertyBag2 * pPropBag,
[in]BOOL fClearDirty,
[in]BOOL fSaveAllProperties);
HRESULT IsDirty();
}
The basic mechanism is that a container tells the object to save or load its properties through IPersistPropertyBag2. For each property, the object calls the container's IPropertyBag2 interface passed to the IPersistPropertyBag members. IPropertyBag2::Write saves a property in whatever place the container wants to put it, and IPropertyBag2::Read retrieves a property.
This protocol is essentially a means of sequentially communicating individual property values from the object to the container, which is useful for doing save-as-text operations and the like. The object gives the container the choice of the format in which each property is saved, while retaining itself the decision as to which properties are saved or loaded.
HRESULT InitNew(void);
Informs the object that it is being initialized as a newly created object.
| S_OK | The object successfully initialized itself. This should be returned even if the object doesn't do anything in the function. |
| E_UNEXPECTED | This member was called after IPersistPropertyBag2::Load or IPersistPropertyBag2::Save. |
E_NOTIMPL should not be returned. Return S_OK even if the object does not perform any function in this method.
HRESULT IsDirty(void);
Indicates if one or more properties have changed since the last initialization or save operation.
| S_OK | One or more properties has changed. |
| S_FALSE | None of the properties has changed. |
E_NOTIMPL is not a valid return code because any object implementing this interface must support the entire functionality of the interface.
HRESULT Load(
[in] IPropertyBag2 *pPropBag,
[in] IErrorLog *pErrorLog
);
Instructs the object to initialize itself using the properties available in the property bag, notifying the provided error log object when errors occur. All property storage must take place within this function call as the object cannot keep the IPropertyBag2 interface pointer passed in pPropBag.
| S_OK | The object successfully initialized itself. |
| E_UNEXPECTED | This member was called after IPersistPropertyBag2::InitNew has already been called. The two initialization methods are mutually exclusive. |
| E_POINTER | The address in pPropBag is not valid (such as NULL) and therefore the object cannot initialize itself. |
| E_FAIL | The object was unable to retrieve a critical property that is necessary for the object's successful operation. The object was, therefore, unable to initialize itself completely. |
E_NOTIMPL is not a valid return code because any object implementing this interface must support the entire functionality of the interface.
HRESULT Save(
[in] IPropertyBag *pPropBag,
[in] BOOL fClearDirty,
[in] BOOL fSaveAllProperties
);
Instructs the object to save its properties to the given property bag, optionally clearing the object's "dirty" flag. The caller can request that the object save all properties or that the object save only those known to have changed.
| S_OK | The object successfully saved the requested properties itself. |
| E_FAIL | One or more essential properties could not be saved. The object can choose to succeed (return S_OK) if all essential properties could be saved but one or more non-essential properties could not be saved. |
| E_POINTER | The address in pPropBag is not valid (such as NULL) and, therefore, the object cannot initialize itself. |
E_NOTIMPL is not a valid return code because any object implementing this interface must support the entire functionality of the interface.
When a client wants to have exact control over how individually named properties of an object are saved, it will attempt to use an object's IPersistPropertyBag2 interface as a persistence mechanism. In that case, the client supplies a "property bag" to the object in the form of an IPropertyBag2 interface.
IPropertyBag2 is an enhancement of the IPropertyBag interface. IPropertyBag2 allows the object to obtain type information for each property through the use of the CountProperties and GetPropertyInfo methods. A property bag that implements IPropertyBag2 must also support IPropertyBag so that objects that only support IPropertyBag can access their properties. Likewise, an object that supports IPropertyBag2 must also support IPropertyBag so that it can communicate with property bags that only support IPropertyBag.
IDL:
[object, uuid(22F55882-280B-11d0-A8A9-00A0C90C2004), pointer_default(unique)]
interface IPropertyBag2 : IUnknown
{
typedef [unique]IPropertyBag2 *LPPROPERTYBAG2;
HRESULT Read(
[in] ULONG cProperties,
[in] PROPBAG2 * pPropBag,
[in] IErrorLog * pErrLog,
[out] VARIANT * pvarValue,
[out] HRESULT * phrError);
HRESULT Write(
[in] ULONG cProperties,
[in] PROPBAG2 * pPropBag,
[in] VARIANT * pvarValue);
HRESULT CountProperties(
[out] ULONG * pcProperties);
HRESULT GetPropertyInfo(
[in] ULONG iProperty,
[in] ULONG cProperties,
[out] PROPBAG2 * pPropBag,
[out] ULONG * pcProperties);
HRESULT LoadObject(
[in] LPCOLESTR pstrName,
[in] DWORD dwHint,
[in] IUnknown * pUnkObject,
[in] IErrorLog * pErrLog);
}
When the object wants to read a property in IPersistPropertyBag2::Load, it will call IPropertyBag2::Read. When the object is saving properties in IPersistPropertyBag2::Save, it will call IPropertyBag2::Write.
The client records errors that occur during Read with the supplied IErrorLog interface.
HRESULT CountProperties(
[out] ULONG *pcProperties
);
Retrieves the number of properties in the property bag.
| S_OK | The method was successful. |
| E_POINTER | pcProperties is not valid. |
HRESULT GetPropertyInfo(
[in] ULONG iProperty,
[in] ULONG cProperties,
[out] PROPBAG2 * pPropBag,
[out] ULONG * pcProperties
);
Retrieves information for properties in a property bag without actually retrieving the properties themselves.
| S_OK | Information was successfully retrieved for all of the requested properties. |
| E_INVALIDARG | iProperty is greater than the number of properties in the property bag. |
| E_OUTOFMEMORY | A memory allocation error occurred. |
HRESULT LoadObject(
[in] LPCOLESTR pstrName,
[in] DWORD dwHint,
[in] IUnknown * pUnkObject,
[in] IErrorLog * pErrLog);
Causes the property bag to instruct a previously created and initialized property object to read its persistent properties.
| S_OK | The object successfully retrieved its properties. |
| E_INVALIDARG | One or more of the arguments is not valid. |
LoadObject allows the calling application to participate in the creation and initialization of a property object. When using the IPropertyBag interface, it is possible to load a property object using the IPropertyBag::Read method with VT_UNKNOWN. The IPropertyBag method does not, however, allow the property object to be initialized by the calling application before the property object reads its own persistent data. LoadObject allows the property object to be created and initialized by the calling application instead of having the property bag create and initialize it.
To use LoadObject, the property object's name and CLSID are retrieved using GetPropertyInfo. The property object is then created and initialized. LoadObject is then used in lieu of IPropertyBag2::Read to cause the property object to read its persistent data.
HRESULT Read(
[in] ULONG cProperties,
[in] PROPBAG2 * pPropBag,
[in] IErrorLog * pErrLog,
[out] VARIANT * pvarValue,
[out] HRESULT * phrError
);
Causes one or more properties to be read from the property bag.
| S_OK | All of the properties were successfully read. |
| E_FAIL | One or more of the properties was not successfully read. It is possible that one or more properties were successfully read. The array at phrError will contain a success or error code for each property. If the caller supplied an IErrorLog for pErrLog, a more descriptive error will be added. |
HRESULT Write(
[in] ULONG cProperties,
[in] PROPBAG2 * pPropBag,
[in] VARIANT * pvarValue
);
Causes one or more properties to be saved into the property bag.
| S_OK | The property bag successfully saved all of the properties. |
| E_FAIL | One or more of the properties could not be saved. |
typedef struct _tagPROPBAG2{
DWORD dwType;
VARTYPE vt;
CLIPFORMAT cfType;
DWORD dwHint;
LPOLESTR pstrName;
CLSID clsid;
} PROPBAG2;
Contains or receives property information. This structure is used with the IPropertyBag2::GetPropertyInfo, IPropertyBag2::Read, and IPropertyBag2::Write methods.
typedef enum _tagPROPBAG2_TYPE{
PROPBAG2_TYPE_UNDEFINED = 0,
PROPBAG2_TYPE_DATA = 1,
PROPBAG2_TYPE_URL = 2,
PROPBAG2_TYPE_OBJECT = 3,
PROPBAG2_TYPE_STREAM = 4,
PROPBAG2_TYPE_STORAGE = 5,
PROPBAG2_TYPE_MONIKER = 6
} PROPBAG2_TYPE;
Identifies the type of data contained in a PROPBAG2 structure.
The IErrorLog interface is an abstraction for an "error log" that is used to communicate detailed error information between a client and an object. The caller of the single interface member, AddError, simply "logs" an error where the error is an EXCEPINFO structure attached to a specific property. The implementor of the interface is responsible for handling the error in whatever way it desires.
IErrorLog is used in the protocol between a client that implements IPropertyBag and an object that implements IPersistPropertyBag.
IDL:
[
uuid(3127CA40-446E-11CE-8135-00AA004BB851)
, object, pointer_default(unique)
]
interface IErrorLog : IUnknown
{
HRESULT AddError([in] LPCOLESTR pszPropName, [in] LPEXCEPINFO pExcepInfo);
};
HRESULT AddError([in] LPCOLESTR pszPropName, [in] LPEXCEPINFO pExcepInfo);
Logs an error (an EXCEPINFO structure) in the error log for a named property.
| S_OK | The error was logged successfully. |
| E_FAIL | There was a problem logging the error. |
| E_OUTOFMEMORY | There was not enough memory to log the error. |
| E_POINTER | The address in pszPropName or pExcepInfo is not valid (such as NULL). The caller must supply both. |
E_NOTIMPL is not a valid return code because the member function is the only one in the entire interface.
The IPersistHistory interface provides a mechanism for a component to persist its state within its containing application during the current session.
IDL:
[
uuid(91A565C1-E38F-11d0-94BF-00A0C9055CBF),
object, pointer_default(unique)
]
interface IPersistHistory : IPersist
{
typedef [unique] IPersistHistory *LPPERSISTHISTORY;
HRESULT LoadHistory(
[in]IStream *pStream,
[in]IBindCtx *pbc);
HRESULT SaveHistory(
[in]IStream *pStream);
HRESULT SetPositionCookie(
[in]DWORD dwPositioncookie);
HRESULT GetPositionCookie(
[out]DWORD *pdwPositioncookie);
}
When to Implement
This interface is implemented by a component that wishes to maintain its state across navigations in a Web browser. Take the following example: a user enters data into a Web-based form containing intrinsic controls as well as a custom edit control. The user navigates away from the page and later returns during the current browser session to find that the data entered into the custom component is lost while the intrinsic controls have maintained their state.
In Internet Explorer 4.0, when a user navigates away from a page, all controls on the page are queried for IPersistHistory. Those that implement the interface are handed a stream through the SaveHistory method into which they can store their current state. If the page is loaded again during the current browser session, each control is handed a stream through the LoadHistory method from which they can reload their previous state.
Warning
Internet Explorer 4.0 caches up to 2 MB of persistent data for all controls. When this limit is exceeded data is discarded on a least recently used basis. Component developers should respect the needs of other controls and limit their use of the history cache.
Historical Note
This interface replaces the four-page cache implemented by Internet Explorer 3.0x; Internet Explorer 4.0 does not implement the four-page cache.
HRESULT SaveHistory(
[in]IStream *pStream);
The container calls this method to request that the component save its state.
| S_OK | The component successfully saved its state to the supplied stream. |
| E_FAIL | The component was unable to save its state. |
| E_POINTER | The stream pointer was invalid. |
The component should under no circumstances add a reference to the supplied stream. The stream should not be cached by the component.
HRESULT LoadHistory(
[in]IStream *pStream,
[in]IBindCtx *pbc);
The container calls this method to request that the component restore its state.
| S_OK | The component was able to reload its persistent state. |
| E_FAIL | The component was unable to reload its persistent state. |
| E_OUTOFMEMORY | There was not enough memory to reload the persistent state of the component. |
| E_POINTER | The stream or the bind context supplied by the container were invalid. |
The component should under no circumstances add a reference to the supplied stream. The stream should not be cached by the component.
HRESULT SetPositionCookie(
[in]DWORD dwPositioncookie);
Reserved for future use. Components are not required to implement this method.
| E_NOTIMPL | The component does not implement this method. |
HRESULT GetPositionCookie(
[out]DWORD *pdwPositioncookie);
Reserved for future use. Components are not required to implement this method.
| E_NOTIMPL | The component does not implement this method. |
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.