How Asynchronous Binding and Storage Work
When a user clicks a link representing a document embedded in a Web page, the following steps occur:
-
The browser calls the MkParseDisplayName function, passing the link's URL.
-
MkParseDisplayName parses the URL, creates a corresponding aynchronous moniker, and returns a pointer to the moniker's IMoniker interface.
-
The browser calls IsAsyncMoniker to determine if the moniker is asynchronous, creates a bind context, registers the IBindStatusCallback interface with the bind context (only if the moniker is asynchronous), and calls IMoniker::BindToObject, passing the bind context.
-
The moniker binds to the object and queries it for the IPersistMoniker interface, which indicates whether the object supports asynchronous binding and storage. If the object returns a pointer to IPersistMoniker:
-
The URL moniker calls IPersistMoniker::Load, passing its own IMoniker pointer to the object.
-
The object modifies the bind context, chooses whether it wants a blocking or non-blocking storage, registers its own IBindStatusCallback and calls IMoniker::BindToStorage on the pointer it received through IPersistMoniker::Load.
-
The moniker creates an asynchronous storage, keeps a reference to the wrapper object's IFillLockBytes interface, registers the IProgressNotify interface on the root storage, and calls IPersistStorage::Load, passing the asynchronous storage's IStorage pointer. As data arrives (on a background thread) the moniker calls IFillLockBytes to fill the ILockBytes on the temp file.
-
The object reads data from the storage and returns from IPersistMoniker::Load when it has received sufficient data to consider itself initialized. If the object attempts to read data that has not yet been downloaded, the downloader receives a notification on IProgressNotify. Inside the IProgressNotify::OnProgress method, the downloading thread either blocks in a modal message loop, or causes the asynchronous storage to return E_PENDING, depending on whether the object has requested a blocking or nonblocking storage.
-
If the object does not implement IPersistMoniker, the moniker queries for IPersistStorage, which indicates that the object's persistent state is stored in a storage object. If the object returns a pointer to IPersistStorage:
-
The Moniker calls IMoniker::BindToStorage on itself, requesting a blocking IStorage (because the object is not asynchronous-aware), creates an asynchronous storage, keeps a reference to the wrapper object's IFillLockBytes interface, registers the IProgressNotify interface on the root storage, and calls IPersistStorage::Load, passing the asynchronous storage's IStorage pointer. As data arrives (on a background thread) the moniker calls IFillLockBytes to fill the ILockBytes on the temp file.
-
The object reads data from storage and returns from IPersistStorage::Load when it has received sufficient data to consider itself initialized. If the object attempts to read data that has not yet been downloaded, it receives a notification on IProgressNotify. Inside the IProgressNotify::OnProgress method, the downloading thread always blocks in a modal message loop.
-
Regardless whether the download is synchronous or asynchronous, the moniker returns from IMoniker::BindToObject, and the browser receives the initialized object it asked for.
-
The browser queries for IOleObject and hosts the object as a Document Object. (At this point the object may not be initialized completely, but only enough to display something useful, in which case downloading continues in the background.)