URL Open Stream Functions
"...pass in a URL, get a stream..."
NOTE: THIS DOCUMENT IS AN EARLY RELEASE OF THE FINAL SPECIFICATION. IT IS MEANT TO SPECIFY AND ACCOMPANY SOFTWARE THAT IS STILL IN DEVELOPMENT. SOME OF THE INFORMATION IN THIS DOCUMENTATION MAY BE INACCURATE OR MAY NOT BE AN ACCURATE REPRESENTATION OF THE FUNCTIONALITY OF THE FINAL SPECIFICATION OR SOFTWARE. MICROSOFT ASSUMES NO RESPONSIBILITY FOR ANY DAMAGES THAT MIGHT OCCUR EITHER DIRECTLY OR INDIRECTLY FROM THESE INACCURACIES. MICROSOFT MAY HAVE TRADEMARKS, COPYRIGHTS, PATENTS OR PENDING PATENT APPLICATIONS, OR OTHER INTELLECTUAL PROPERTY RIGHTS COVERING SUBJECT MATTER IN THIS DOCUMENT. THE FURNISHING OF THIS DOCUMENT DOES NOT GIVE YOU A LICENSE TO THESE TRADEMARKS, COPYRIGHTS, PATENTS, OR OTHER INTELLECTUAL PROPERTY RIGHTS.
Contents
- Overview
- IBindStatusCallback
- URLDownloadToCacheFile
- URLDownloadToFile
- URLOpenStream
- URLOpenBlockingStream
- URLOpenPullStream
RELEASE NOTE FOR BETA2: Microsoft has found problems with
the beta version of URLOpenBlockingStream. Also, the beta version of
URLDownloadToCacheFile does not work with relative URLs.
Both problems will be fixed in the final release.
Without a doubt the easiest, most efficient and most powerful way to download
data from the Internet is using the new URL Open Stream (UOS) functions.
Before jumping into the specifications, let's cover a
few of the high-level features and the philosophy behind the creation of
these functions. The UOS functions are the newest addition to the ActiveX(TM) extensions to
the Win32 API. They combine the familiarity of C-style programming with
the power of COM. These functions work equally well inside an
ActiveX framework (for example, a component, a
document or frame window, a subcomponent, or a scriptable object) or
completely standalone.
Unlike other more complex interface negotiations, using these functions requires
knowledge of no more than two COM interfaces, IStream and
IBindStatusCallback.
Because these functions use services from URL monikers and WinInet,
all the caching and thread synchronization features of those components
are in use whenever you call these functions. In addition, the UOS functions handle
all the host binding operations if your code is in an ActiveX container: the UOS
functions automatically do the right thing to manage the download in the ActiveX
client framework.
Every UOS function works in the same basic way: the caller implements an
IBindStatusCallback interface (optional in some cases), then calls the
function. The URLOpenStream and
URLOpenPullStream functions require
the caller to be on a thread that has a message loop
(GetMessage/DispatchMessage). In the case of an ActiveX component,
a message loop is a given if this function is called from the main thread. For a standalone
application without a user interface, a message loop is still necessary for these functions.
With the URL Open Stream functions, you can:
- Download a URL to a file with a single function call. You can
optionally get progress notifications in the background.
- Create a blocking-type stream with a single function that will
block when you call IStream::Read. You can optionally get progress
notifications in the background.
- Post an Internet query (using the HTTP POST verb) with a single call and
get the results in a stream.
- Optionally hook into the ActiveX client framework simply by passing
your this pointer.
- Configure callbacks using either the push or pull model.
IBindStatusCallback
Callbacks are issued on an IBindStatusCallback interface that is implemented
on the caller. This is a simple
callback interface to implement, because most of the methods on the
interface are optional (for example, OnStartBinding, GetPriority, OnStopBinding)
and can simply return S_OK or E_NOTIMPL. Although clients may choose to implement
many of the IBindStatusCallback methods, the only callback required
to do anything for the UOS functions to work correctly is
OnDataAvailable for the URLOpenStream
and URLOpenPullStream functions.
In fact, for some UOS functions (URLDownloadToFile,
URLDownloadToCacheFile,
and URLOpenBlockingStream),
OnDataAvailable is never called because it is unnecessary. Furthermore,
GetBindInfo is never invoked for UOS clients, because
the bind information is determined according to which UOS function is being called.
The UOS programming model is straightforward because there are no special flags to pass to
the functions.
The URL Open Stream functions are described below:
HRESULT URLDownloadToCacheFile(
LPUNKNOWN pCaller,
LPCWSTR szURL,
LPTSTR szFileName,
DWORD fCache,
DWORD dwResv,
LPBINDSTATUSCALLBACK lpfnCB);
URLDownloadToCacheFile downloads data into the Internet cache
and returns the filename of the cache location for retrieving the bits.
The client can optionally be notified of progress via a notification callback.
This function will always return a filename if the download operation succeeds.
If the given URL is a "file:" URL, URLDownloadToCacheFile will directly return the
filename for the "file:" URL rather than making a copy to the
cache. If the given URL is an Internet URL ("http:", "ftp:"), URLDownloadToCacheFile
will download this file and return the local filename of the cached copy.
Using this function ensures that a filename is returned without unnecessary copying of data.
LPUNKNOWN pCaller
Pointer to the controlling IUnknown of the calling
ActiveX component (if the caller is an ActiveX component).
If the caller is not an ActiveX component, this value may
be set to NULL. Otherwise, the caller is a COM object that
is contained in another component (such as an ActiveX Control
in the context of an HTML page). The parameter
represents the outermost IUnknown of the calling component.
The function will attempt the download in the context of the
ActiveX client framework and allow the caller's container to
receive callbacks on the progress of the download.
LPCWSTR szURL
The URL to be downloaded. Cannot be NULL.
LPTSTR szFileName
If the call succeeds then it returns the name of the cached file. The user should pass a buffer to be filled. It is
preferred that the user allocate a buffer of maximum path size using MAX_PATH.
DWORD dwBufLen
The size of the buffer passed in szFileName.
DWORD dwResv
Reserved for future use; must be zero.
LPBINDSTATUSCALLBACK lpfnCB
Pointer to the IBindStatusCallback interface pointer on the caller.
URLDownloadToCacheFile calls this interface's OnProgress method
on some connection activity, including the arrival of data. OnDataAvailable
is never called. Implementing OnProgress allows a caller to implement some user
interface or other progress monitoring functionality. It also allows the
download operation to be completely canceled by returning E_ABORT from
the OnProgress call. Can be NULL.
URLDownloadToFile(
LPUNKNOWN pCaller,
LPCWSTR szURL,
LPCTSTR szFileName,
DWORD dwResv,
LPBINDSTATUSCALLBACK lpfnCB);
URLDownloadToFile downloads bits from the Internet and saves them to a
file. The client can optionally be notified of progress via a notification
callback.
LPUNKNOWN pCaller
Pointer to the controlling IUnknown of the calling
ActiveX component (if the caller is an ActiveX component).
If the caller is not an ActiveX component, this value may
be set to NULL. Otherwise, the caller is a COM object that
is contained in another component (such as an ActiveX Control
in the context of an HTML page). The parameter
represents the outermost IUnknown of the calling component.
The function will attempt the download in the context of the
ActiveX client framework and allow the caller's container to
receive callbacks on the progress of the download.
LPCWSTR szURL
The URL to be downloaded. Cannot be NULL.
LPCTSTR szFileName
Name of the file to create with bits that come from the download.
DWORD dwResv
Reserved for future use; must be zero.
LPBINDSTATUSCALLBACK lpfnCB
Pointer to the IBindStatusCallback interface pointer on the caller.
URLDownloadToFile calls this interface's OnProgress method
on some connection activity, including the arrival of data. OnDataAvailable
is never called. Implementing OnProgress allows a caller to implement some user
interface or other progress monitoring functionality. It also allows the
download operation to be completely canceled by returning E_ABORT from
the OnProgress call. Can be NULL.
URLOpenStream(
LPUNKNOWN pCaller,
LPCWSTR szURL,
DWORD dwResv,
LPBINDSTATUSCALLBACK lpfnCB);
URLOpenStream creates a push-type stream object from a URL. The data
is downloaded
from the Internet as fast as possible. Every time data is available, it
is "pushed" at the client through a notification callback.
LPUNKNOWN pCaller
Pointer to the controlling IUnknown of the calling
ActiveX component (if the caller is an ActiveX component).
If the caller is not an ActiveX component, this value may
be set to NULL. Otherwise, the caller is a COM object that
is contained in another component (such as an ActiveX Control
in the context of an HTML page). The parameter
represents the outermost IUnknown of the calling component.
The function will attempt the download in the context of the
ActiveX client framework and allow the caller's container to
receive callbacks on the progress of the download.
LPCWSTR szURL
The URL to be converted to a stream object. Cannot be NULL.
DWORD dwResv
Reserved for future use; must be zero.
LPBINDSTATUSCALLBACK lpfnCB
Pointer to caller's IBindStatusCallback interface, on which
URLOpenStream calls OnDataAvailable every time data arrives
from the Internet. OnDataAvailable can return E_ABORT to abort
the download. When the callback is invoked and the pstm member of
the STGMEDIUM structure is not NULL, the caller can read from the stream the
amount of data specified in the dwSize argument passed with the
OnDataAvailable call (delta anything that has been read on previous
calls to OnDataAvailable).
If the caller does not read the full amount or does not call pstm->Read at all,
OnDataAvailable will still be called the next time data arrives, as
long the grfBSCF flags do not indicate BINDF_LASTDATANOTIFICATION. In
that case, no more data will be downloaded. Any data that is not read at any
given time will still be available the next time OnDataAvailable is called.
The logic in the following code fragment is a typical implementation of
OnDataAvailable as it is used by the URLOpenStream function:
HRESULT MyBindStatusCallback::OnDataAvailable
(
DWORD grfBSCF, DWORD dwSize, ..., STGMEDIUM * pstgmed
)
{
if( dwSize < sizeof(BITMAPINFOHEADER) )
return(NOERROR); // not enough has been read yet, just return
if( !g_bGotInfoHeader ) // did we get info before?
{
// No, go ahead, read now...
DWORD dwRead;
HRESULT hr = pstgmed->pstm->Read( &bmih, sizeof(bmih), &dwRead);
if( SUCCEEDED(hr) )
{
// now we got it... we can return
g_bGotInfoHeader = TRUE;
return(hr);
}
}
}
URLOpenBlockingStream(
LPUNKNOWN pCaller,
LPCWSTR szURL,
LPSTREAM *ppStream,
DWORD dwResv,
LPBINDSTATUSCALLBACK lpfnCB);
URLOpenBlockingStream creates a blocking-type stream object
from a URL. The data is
downloaded from the Internet on demand by a call to IStream::Read.
The Read call will block until enough data has arrived.
LPUNKNOWN pCaller
Pointer to the controlling IUnknown of the calling
ActiveX component (if the caller is an ActiveX component).
If the caller is not an ActiveX component, this value may
be set to NULL. Otherwise, the caller is a COM object that
is contained in another component (such as an ActiveX Control
in the context of an HTML page). The parameter
represents the outermost IUnknown of the calling component.
The function will attempt the download in the context of the
ActiveX client framework and allow the caller's container to
receive callbacks on the progress of the download.
LPCWSTR szURL
The URL to be converted to a stream object. Cannot be NULL.
LPSTREAM * ppStream
Pointer to the IStream interface pointer on the stream object created
by this function. The caller can read from the stream as soon as it has this
pointer. If the
data requested has not yet been downloaded, the Read method will
block until enough data has been downloaded. The following
is a code fragment that logically does this:
IStream * pStream;
URLOpenStream( 0, L"http://www.msn.com/", &pStream, 0, 0);
char buffer[0x100];
DWORD dwGot;
HRESULT hr = NOERROR;
do {
hr = pStream->Read( buffer, sizeof(buffer), &dwGot );
.. do something with contents of buffer ...
} while( SUCCEEDED(hr) );
DWORD dwResv
Reserved for future use; must be zero.
LPBINDSTATUSCALLBACK lpfnCB
Pointer to the IBindStatusCallback interface pointer on the caller.
URLOpenBlockingStream calls this interface's OnProgress method
on some connection activity, including the arrival of data. OnDataAvailable
is never called. Implementing OnProgress allows a caller to implement some user
interface or other progress monitoring functionality. It also allows the
download operation to be completely canceled by returning E_ABORT from
the OnProgress call. Can be NULL.
URLOpenPullStream(LPUNKNOWN pCaller,
LPCWSTR szURL,
DWORD dwResv,
LPBINDSTATUSCALLBACK lpfnCB);
URLOpenPullStream creates a pull-type stream object from a URL. The
data is downloaded from the
Internet on demand. If not enough data is available locally to satisfy
the requests, the IStream::Read call will not block until enough data has arrived.
Instead, Read will immediately return E_PENDING, and URLOpenPullStream will request
the next packet of data from the Internet server.
LPUNKNOWN pCaller
Pointer to the controlling IUnknown of the calling
ActiveX component (if the caller is an ActiveX component).
If the caller is not an ActiveX component, this value may
be set to NULL. Otherwise, the caller is a COM object that
is contained in another component (such as an ActiveX Control
in the context of an HTML page). The parameter
represents the outermost IUnknown of the calling component.
The function will attempt the download in the context of the
ActiveX client framework and allow the caller's container to
receive callbacks on the progress of the download.
LPCWSTR szURL
The URL to be converted to a stream object. Cannot be NULL.
DWORD dwResv
Reserved for future use; must be zero.
LPBINDSTATUSCALLBACK lpfnCB
Pointer to caller's IBindStatusCallback interface, on which
URLOpenPullStream calls OnDataAvailable every time data arrives
from the Internet. OnDataAvailable can return E_ABORT to abort
the download. When the callback is invoked and the pstm member of
the STGMEDIUM structure is not NULL, the caller can read from the stream the
amount of data specified in the dwSize argument passed with the
OnDataAvailable call (delta anything that has been read on previous
calls to OnDataAvailable).
If the caller does not read the full amount or does not call pstm->Read at all,
OnDataAvailable will not be
called again until this happens and Read returns E_PENDING.
The pull model is slightly more cumbersome than the push model, but it gives total
control to the client over the amount of Internet access for the
download.
The logic in the following code fragment is a typical implementation of
OnDataAvailable as it is used by the URLOpenPullStream function:
HRESULT CMyBindStatusCallback::OnDataAvailable( ...)
{
HRESULT hr = NOERROR;
DWORD dwAmountToRead = dwSize - g_readSoFar;
BYTE * buffer = new BYTE[ dwAmountToRead ];
while( TRUE )
{
DWORD dwRead;
hr = pstgmed->pstrm->Read( buffer, dwAmountToRead, &dwRead );
if( hr == E_PENDING )
{
// we'll get notified again when more data comes
return(NOERROR);
}
if( SUCCEEDED(hr) )
{
// ok, process bits ....
// keep looping
}
else
{
// we have an error...
return(hr);
}
}
}