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:
-
A. The URL moniker calls IPersistMoniker::Load, passing its
own IMoniker pointer to the object.
-
B. 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.
-
C. 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.
-
D. 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:
-
A. 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.
-
B. 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.)