Alexandre Julliard <julliard@winehq.org>
- Added rules for building import libraries in the individual dll
  makefiles, and added support for building a .def.a static import
  library too.
Troy Rollo <wine@troy.rollo.name>
- Implement URLMonikerImpl_BindToStorage.
- Correct bug truncating downloaded files to 4096 bytes.
Jacek Caban <jack@itma.pwr.wroc.pl>
- Separated IBinding and IMoniker interfaces.
Mike McCormack <mike@codeweavers.com>
- Add the missing interface method PromptAction to
  IInternetZoneManager.
- Stub implementation for GetSoftwareUpdateInfo.
Francois Gouget <fgouget@free.fr>
- Update win32.api to match the current sources.
- Declare CoGetClassObjectFromURL() in urlmon.h.
Christian Costa <titan.costa@wanadoo.fr>
- Added stub implementation for CoGetClassObjectFromURL.
Modified: trunk/reactos/lib/urlmon/Makefile.in
Modified: trunk/reactos/lib/urlmon/sec_mgr.c
Modified: trunk/reactos/lib/urlmon/umon.c
Added: trunk/reactos/lib/urlmon/umstream.c
Modified: trunk/reactos/lib/urlmon/urlmon.spec
Modified: trunk/reactos/lib/urlmon/urlmon.xml
Modified: trunk/reactos/lib/urlmon/urlmon_main.c
Modified: trunk/reactos/lib/urlmon/urlmon_main.h

Modified: trunk/reactos/lib/urlmon/Makefile.in
--- trunk/reactos/lib/urlmon/Makefile.in	2005-05-28 21:40:01 UTC (rev 15624)
+++ trunk/reactos/lib/urlmon/Makefile.in	2005-05-28 21:44:21 UTC (rev 15625)
@@ -3,6 +3,7 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = urlmon.dll
+IMPORTLIB = liburlmon.$(IMPLIBEXT)
 IMPORTS   = cabinet ole32 shlwapi wininet user32 advapi32 kernel32 ntdll
 EXTRALIBS = -luuid
 
@@ -10,6 +11,7 @@
 	regsvr.c \
 	sec_mgr.c \
 	umon.c \
+	umstream.c \
 	urlmon_main.c
 
 SUBDIRS = tests

Modified: trunk/reactos/lib/urlmon/sec_mgr.c
--- trunk/reactos/lib/urlmon/sec_mgr.c	2005-05-28 21:40:01 UTC (rev 15624)
+++ trunk/reactos/lib/urlmon/sec_mgr.c	2005-05-28 21:44:21 UTC (rev 15625)
@@ -353,6 +353,21 @@
 }
 
 /********************************************************************
+ *      IInternetZoneManager_PromptAction
+ */
+static HRESULT WINAPI ZoneMgrImpl_PromptAction(IInternetZoneManager* iface,
+                                               DWORD dwAction,
+                                               HWND hwndParent,
+                                               LPCWSTR pwszUrl,
+                                               LPCWSTR pwszText,
+                                               DWORD dwPromptFlags)
+{
+    FIXME("%p %08lx %p %s %s %08lx\n", iface, dwAction, hwndParent,
+          debugstr_w(pwszUrl), debugstr_w(pwszText), dwPromptFlags );
+    return E_NOTIMPL;
+}
+
+/********************************************************************
  *      IInternetZoneManager_LogAction
  */
 static HRESULT WINAPI ZoneMgrImpl_LogAction(IInternetZoneManager* iface,
@@ -425,12 +440,14 @@
     ZoneMgrImpl_SetZoneCustomPolicy,
     ZoneMgrImpl_GetZoneActionPolicy,
     ZoneMgrImpl_SetZoneActionPolicy,
+    ZoneMgrImpl_PromptAction,
     ZoneMgrImpl_LogAction,
     ZoneMgrImpl_CreateZoneEnumerator,
     ZoneMgrImpl_GetZoneAt,
     ZoneMgrImpl_DestroyZoneEnumerator,
     ZoneMgrImpl_CopyTemplatePoliciesToZone,
 };
+
 HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
 {
     ZoneMgrImpl* ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ZoneMgrImpl));

Modified: trunk/reactos/lib/urlmon/umon.c
--- trunk/reactos/lib/urlmon/umon.c	2005-05-28 21:40:01 UTC (rev 15624)
+++ trunk/reactos/lib/urlmon/umon.c	2005-05-28 21:44:21 UTC (rev 15625)
@@ -48,19 +48,252 @@
 
 /*static BOOL registered_wndclass = FALSE;*/
 
+typedef struct {
+    IBindingVtbl *lpVtbl;
+
+    ULONG ref;
+
+    LPWSTR URLName;
+
+    HWND hwndCallback;
+    IBindCtx *pBC;
+    HINTERNET hinternet, hconnect, hrequest;
+    HANDLE hCacheFile;
+    IUMCacheStream *pstrCache;
+    IBindStatusCallback *pbscb;
+    DWORD total_read, expected_size;
+} Binding;
+
+static HRESULT WINAPI Binding_QueryInterface(IBinding* iface, REFIID riid, void **ppvObject)
+{
+    Binding *This = (Binding*)iface;
+
+    TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject);
+
+    if((This == NULL) || (ppvObject == NULL))
+	return E_INVALIDARG;
+
+    if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IBinding, riid)) {
+        *ppvObject = iface;
+        IBinding_AddRef(iface);
+        return S_OK;
+    }
+
+    *ppvObject = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Binding_AddRef(IBinding* iface)
+{
+    Binding *This = (Binding*)iface;
+    ULONG ref = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p) ref=%ld\n", This, ref);
+
+    return ref;
+}
+
+static ULONG WINAPI Binding_Release(IBinding* iface)
+{
+    Binding *This = (Binding*)iface;
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p) ref=%ld\n",This, ref);
+
+    if(!ref) {
+        HeapFree(GetProcessHeap(), 0, This->URLName);
+        if (This->hCacheFile)
+            CloseHandle(This->hCacheFile);
+        if (This->pstrCache)
+        {
+            UMCloseCacheFileStream(This->pstrCache);
+            IStream_Release((IStream *)This->pstrCache);
+        }
+        if (This->pbscb)
+            IBindStatusCallback_Release(This->pbscb);
+
+        HeapFree(GetProcessHeap(), 0, This);
+
+        URLMON_UnlockModule();
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI Binding_Abort(IBinding* iface)
+{
+    Binding *This = (Binding*)iface;
+
+    FIXME("(%p): stub\n", This);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Binding_GetBindResult(IBinding* iface, CLSID* pclsidProtocol, DWORD* pdwResult, LPOLESTR* pszResult, DWORD* pdwReserved)
+{
+    Binding *This = (Binding*)iface;
+
+    FIXME("(%p)->(%p, %p, %p, %p): stub\n", This, pclsidProtocol, pdwResult, pszResult, pdwReserved);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Binding_GetPriority(IBinding* iface, LONG* pnPriority)
+{
+    Binding *This = (Binding*)iface;
+
+    FIXME("(%p)->(%p): stub\n", This, pnPriority);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Binding_Resume(IBinding* iface)
+{
+    Binding *This = (Binding*)iface;
+
+    FIXME("(%p): stub\n", This);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Binding_SetPriority(IBinding* iface, LONG nPriority)
+{
+    Binding *This = (Binding*)iface;
+
+    FIXME("(%p)->(%ld): stub\n", This, nPriority);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Binding_Suspend(IBinding* iface)
+{
+    Binding *This = (Binding*)iface;
+
+    FIXME("(%p): stub\n", This);
+
+    return E_NOTIMPL;
+}
+
+static void Binding_CloseCacheDownload(Binding *This)
+{
+    CloseHandle(This->hCacheFile);
+    This->hCacheFile = 0;
+    UMCloseCacheFileStream(This->pstrCache);
+    IStream_Release((IStream *)This->pstrCache);
+    This->pstrCache = 0;
+}
+
+static HRESULT Binding_MoreCacheData(Binding *This, char *buf, DWORD dwBytes)
+{
+    DWORD written;
+
+    if (WriteFile(This->hCacheFile, buf, dwBytes, &written, NULL) && written == dwBytes)
+    {
+	HRESULT hr;
+
+	This->total_read += written;
+        hr = IBindStatusCallback_OnProgress(This->pbscb,
+					    This->total_read + written,
+					    This->expected_size,
+					    (This->total_read == written) ?
+					        BINDSTATUS_BEGINDOWNLOADDATA :
+					        BINDSTATUS_DOWNLOADINGDATA,
+					    NULL);
+	if (!hr)
+	{
+	    STGMEDIUM stg;
+	    FORMATETC fmt;
+
+            fmt.cfFormat = 0;
+            fmt.ptd = NULL;
+            fmt.dwAspect = 0;
+            fmt.lindex = -1;
+            fmt.tymed = TYMED_ISTREAM;
+
+	    stg.tymed = TYMED_ISTREAM;
+	    stg.u.pstm = (IStream *)This->pstrCache;
+	    stg.pUnkForRelease = NULL;
+
+            hr = IBindStatusCallback_OnDataAvailable(This->pbscb,
+			    			     (This->total_read == written) ?
+							 BSCF_FIRSTDATANOTIFICATION :
+						         BSCF_INTERMEDIATEDATANOTIFICATION,
+						     This->total_read + written,
+                                                     &fmt,
+						     &stg);
+	}
+	if (written < dwBytes)
+	    return STG_E_MEDIUMFULL;
+	else
+	    return hr;
+    }
+    return HRESULT_FROM_WIN32(GetLastError());
+}
+
+static void Binding_FinishedDownload(Binding *This, HRESULT hr)
+{
+    STGMEDIUM stg;
+    FORMATETC fmt;
+
+    fmt.ptd = NULL;
+    fmt.dwAspect = 0;
+    fmt.lindex = -1;
+    fmt.tymed = TYMED_ISTREAM;
+
+    stg.tymed = TYMED_ISTREAM;
+    stg.u.pstm = (IStream *)This->pstrCache;
+    stg.pUnkForRelease = NULL;
+
+    IBindStatusCallback_OnProgress(This->pbscb, This->total_read, This->expected_size, BINDSTATUS_ENDDOWNLOADDATA, NULL);
+    IBindStatusCallback_OnDataAvailable(This->pbscb, BSCF_LASTDATANOTIFICATION, This->total_read, &fmt, &stg);
+    if (hr)
+    {
+	WCHAR *pwchError = 0;
+
+        FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |
+	                 FORMAT_MESSAGE_ALLOCATE_BUFFER,
+                        NULL, (DWORD) hr,
+		        0, (LPWSTR) &pwchError,
+		        0, NULL);
+	if (!pwchError)
+	{
+	    static WCHAR achFormat[] = { '%', '0', '8', 'x', 0 };
+
+	    pwchError =(WCHAR *) LocalAlloc(LMEM_FIXED, sizeof(WCHAR) * 9);
+	    wsprintfW(pwchError, achFormat, hr);
+	}
+        IBindStatusCallback_OnStopBinding(This->pbscb, hr, pwchError);
+	LocalFree(pwchError);
+    }
+    else
+    {
+        IBindStatusCallback_OnStopBinding(This->pbscb, hr, NULL);
+    }
+    IBindStatusCallback_Release(This->pbscb);
+    This->pbscb = 0;
+}
+
+static IBindingVtbl BindingVtbl =
+{
+    Binding_QueryInterface,
+    Binding_AddRef,
+    Binding_Release,
+    Binding_Abort,
+    Binding_Suspend,
+    Binding_Resume,
+    Binding_SetPriority,
+    Binding_GetPriority,
+    Binding_GetBindResult
+};
+
 /* filemoniker data structure */
-typedef struct URLMonikerImpl{
+typedef struct {
 
-    IMonikerVtbl*  lpvtbl1;  /* VTable relative to the IMoniker interface.*/
-    IBindingVtbl*  lpvtbl2;  /* VTable to IBinding interface */
+    IMonikerVtbl*  lpvtbl;  /* VTable relative to the IMoniker interface.*/
 
     ULONG ref; /* reference counter for this object */
 
     LPOLESTR URLName; /* URL string identified by this URLmoniker */
-
-    HWND hwndCallback;
-    IBindCtx *pBC;
-    HINTERNET hinternet, hconnect, hrequest;
 } URLMonikerImpl;
 
 /*******************************************************************************
@@ -133,6 +366,7 @@
     return refCount;
 }
 
+
 /******************************************************************************
  *        URLMoniker_GetClassID
  ******************************************************************************/
@@ -310,6 +544,8 @@
     return;
 }
 #endif
+
+
 /******************************************************************************
  *        URLMoniker_BindToStorage
  ******************************************************************************/
@@ -321,12 +557,12 @@
 {
     URLMonikerImpl *This = (URLMonikerImpl *)iface;
     HRESULT hres;
-    IBindStatusCallback *pbscb;
     BINDINFO bi;
     DWORD bindf;
-    IStream *pstr;
+    WCHAR szFileName[MAX_PATH + 1];
+    Binding *bind;
+    int len;
 
-    FIXME("(%p)->(%p,%p,%s,%p): stub\n",This,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
     if(pmkToLeft) {
 	FIXME("pmkToLeft != NULL\n");
 	return E_NOTIMPL;
@@ -336,122 +572,288 @@
 	return E_NOTIMPL;
     }
 
-    /* FIXME This is a bad hack (tm).  We should clearly download to a temporary file.
-       We also need to implement IStream ourselves so that IStream_Read can return
-       E_PENDING */
+    bind = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Binding));
+    bind->lpVtbl = &BindingVtbl;
+    bind->ref = 1;
+    URLMON_LockModule();
 
-    hres = CreateStreamOnHGlobal(0, TRUE, &pstr);
+    len = lstrlenW(This->URLName)+1;
+    bind->URLName = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
+    memcpy(bind->URLName, This->URLName, len*sizeof(WCHAR));
 
+    hres = UMCreateStreamOnCacheFile(bind->URLName, 0, szFileName, &bind->hCacheFile, &bind->pstrCache);
+
     if(SUCCEEDED(hres)) {
-        TRACE("Created dummy stream...\n");
+        TRACE("Created stream...\n");
 
-        hres = IBindCtx_GetObjectParam(pbc, (LPOLESTR)BSCBHolder, (IUnknown**)&pbscb);
+        *ppvObject = (void *) bind->pstrCache;
+        IStream_AddRef((IStream *) bind->pstrCache);
+
+        hres = IBindCtx_GetObjectParam(pbc, (LPOLESTR)BSCBHolder, (IUnknown**)&bind->pbscb);
         if(SUCCEEDED(hres)) {
             TRACE("Got IBindStatusCallback...\n");
 
             memset(&bi, 0, sizeof(bi));
             bi.cbSize = sizeof(bi);
             bindf = 0;
-            hres = IBindStatusCallback_GetBindInfo(pbscb, &bindf, &bi);
+            hres = IBindStatusCallback_GetBindInfo(bind->pbscb, &bindf, &bi);
             if(SUCCEEDED(hres)) {
+                WCHAR *urlcopy, *tmpwc;
                 URL_COMPONENTSW url;
-                WCHAR *host, *path;
-                DWORD len, lensz = sizeof(len), total_read = 0;
-                LARGE_INTEGER last_read_pos;
-                FORMATETC fmt;
-                STGMEDIUM stg;
+                WCHAR *host, *path, *user, *pass;
+                DWORD lensz = sizeof(bind->expected_size);
+                DWORD dwService = 0;
+                BOOL bSuccess;
 
                 TRACE("got bindinfo. bindf = %08lx extrainfo = %s bindinfof = %08lx bindverb = %08lx iid %s\n",
                       bindf, debugstr_w(bi.szExtraInfo), bi.grfBindInfoF, bi.dwBindVerb, debugstr_guid(&bi.iid));
-                hres = IBindStatusCallback_OnStartBinding(pbscb, 0, (IBinding*)&This->lpvtbl2);
+                hres = IBindStatusCallback_OnStartBinding(bind->pbscb, 0, (IBinding*)bind);
                 TRACE("OnStartBinding rets %08lx\n", hres);
 
+                /* This class will accept URLs with the backslash in them. But InternetCrackURL will not - it
+                 * requires forward slashes (this is the behaviour of Microsoft's INETAPI). So we need to make
+                 * a copy of the URL here and change the backslash to a forward slash everywhere it appears -
+                 * but only before any '#' or '?', after which backslash should be left alone.
+                 */
+                urlcopy = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * (lstrlenW(bind->URLName) + 1));
+                lstrcpyW(urlcopy, bind->URLName);
+                for (tmpwc = urlcopy; *tmpwc && *tmpwc != '#' && *tmpwc != '?'; ++tmpwc)
+                    if (*tmpwc == '\\')
+                            *tmpwc = '/';
+
 #if 0
-		if(!registered_wndclass) {
+                if(!registered_wndclass) {
                     WNDCLASSA urlmon_wndclass = {0, URLMON_WndProc,0, 0, URLMON_hInstance, 0, 0, 0, NULL, "URLMON_Callback_Window_Class"};
-		    RegisterClassA(&urlmon_wndclass);
-		    registered_wndclass = TRUE;
-		}
+                    RegisterClassA(&urlmon_wndclass);
+                    registered_wndclass = TRUE;
+                }
 
-		This->hwndCallback = CreateWindowA("URLMON_Callback_Window_Class", NULL, 0, 0, 0, 0, 0, 0, 0,
-						   URLMON_hInstance, NULL);
+                This->hwndCallback = CreateWindowA("URLMON_Callback_Window_Class", NULL, 0, 0, 0, 0, 0, 0, 0,
+                                                   URLMON_hInstance, NULL);
 
 #endif
+                bind->expected_size = 0;
+                bind->total_read = 0;
+
                 memset(&url, 0, sizeof(url));
                 url.dwStructSize = sizeof(url);
-                url.dwSchemeLength = url.dwHostNameLength = url.dwUrlPathLength = 1;
-                InternetCrackUrlW(This->URLName, 0, 0, &url);
+                url.dwSchemeLength = url.dwHostNameLength = url.dwUrlPathLength = url.dwUserNameLength = url.dwPasswordLength = 1;
+                InternetCrackUrlW(urlcopy, 0, 0, &url);
                 host = HeapAlloc(GetProcessHeap(), 0, (url.dwHostNameLength + 1) * sizeof(WCHAR));
                 memcpy(host, url.lpszHostName, url.dwHostNameLength * sizeof(WCHAR));
                 host[url.dwHostNameLength] = '\0';
                 path = HeapAlloc(GetProcessHeap(), 0, (url.dwUrlPathLength + 1) * sizeof(WCHAR));
                 memcpy(path, url.lpszUrlPath, url.dwUrlPathLength * sizeof(WCHAR));
                 path[url.dwUrlPathLength] = '\0';
+                if (url.dwUserNameLength)
+                {
+                    user = HeapAlloc(GetProcessHeap(), 0, ((url.dwUserNameLength + 1) * sizeof(WCHAR)));
+                    memcpy(user, url.lpszUserName, url.dwUserNameLength * sizeof(WCHAR));
+                    user[url.dwUserNameLength] = 0;
+                }
+                else
+                {
+                    user = 0;
+                }
+                if (url.dwPasswordLength)
+                {
+                    pass = HeapAlloc(GetProcessHeap(), 0, ((url.dwPasswordLength + 1) * sizeof(WCHAR)));
+                    memcpy(pass, url.lpszPassword, url.dwPasswordLength * sizeof(WCHAR));
+                    pass[url.dwPasswordLength] = 0;
+                }
+                else
+                {
+                    pass = 0;
+                }
 
-                This->hinternet = InternetOpenA("User Agent", 0, NULL, NULL, 0 /*INTERNET_FLAG_ASYNC*/);
-/*              InternetSetStatusCallback(This->hinternet, URLMON_InternetCallback);*/
+                switch ((DWORD) url.nScheme)
+                {
+                case INTERNET_SCHEME_FTP:
+                case INTERNET_SCHEME_GOPHER:
+                case INTERNET_SCHEME_HTTP:
+                case INTERNET_SCHEME_HTTPS:
 
-                This->hconnect = InternetConnectW(This->hinternet, host, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
-                                                  INTERNET_SERVICE_HTTP, 0, (DWORD)This);
-                This->hrequest = HttpOpenRequestW(This->hconnect, NULL, path, NULL, NULL, NULL, 0, (DWORD)This);
+                    bind->hinternet = InternetOpenA("User Agent", 0, NULL, NULL, 0 /*INTERNET_FLAG_ASYNC*/);
+/*                  InternetSetStatusCallback(bind->hinternet, URLMON_InternetCallback);*/
+                    if (!bind->hinternet)
+                    {
+                            hres = HRESULT_FROM_WIN32(GetLastError());
+                            break;
+                    }
 
-                hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, 0x22, NULL);
-                hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_FINDINGRESOURCE, NULL);
-                hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_CONNECTING, NULL);
-                hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_SENDINGREQUEST, NULL);
-                hres = E_OUTOFMEMORY; /* FIXME */
-                if(HttpSendRequestW(This->hrequest, NULL, 0, NULL, 0)) {
-                    len = 0;
-                    HttpQueryInfoW(This->hrequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &len, &lensz, NULL);
+                    switch ((DWORD) url.nScheme)
+                    {
+                    case INTERNET_SCHEME_FTP:
+                        if (!url.nPort)
+                            url.nPort = INTERNET_DEFAULT_FTP_PORT;
+                        dwService = INTERNET_SERVICE_FTP;
+                        break;
+    
+                    case INTERNET_SCHEME_GOPHER:
+                        if (!url.nPort)
+                            url.nPort = INTERNET_DEFAULT_GOPHER_PORT;
+                        dwService = INTERNET_SERVICE_GOPHER;
+                        break;
 
-                    TRACE("res = %ld gle = %08lx url len = %ld\n", hres, GetLastError(), len);
+                    case INTERNET_SCHEME_HTTP:
+                        if (!url.nPort)
+                            url.nPort = INTERNET_DEFAULT_HTTP_PORT;
+                        dwService = INTERNET_SERVICE_HTTP;
+                        break;
 
-                    last_read_pos.u.LowPart = last_read_pos.u.HighPart = 0;
-                    fmt.cfFormat = 0;
-                    fmt.ptd = NULL;
-                    fmt.dwAspect = 0;
-                    fmt.lindex = -1;
-                    fmt.tymed = TYMED_ISTREAM;
-                    stg.tymed = TYMED_ISTREAM;
-                    stg.u.pstm = pstr;
-                    stg.pUnkForRelease = NULL;
+                    case INTERNET_SCHEME_HTTPS:
+                        if (!url.nPort)
+                            url.nPort = INTERNET_DEFAULT_HTTPS_PORT;
+                        dwService = INTERNET_SERVICE_HTTP;
+                        break;
+                    }
 
-                    while(1) {
-                        char buf[4096];
-                        DWORD bufread;
-                        DWORD written;
-                        if(InternetReadFile(This->hrequest, buf, sizeof(buf), &bufread)) {
-                            TRACE("read %ld bytes %s...\n", bufread, debugstr_an(buf, 10));
-                            if(bufread == 0) break;
-                            IStream_Write(pstr, buf, bufread, &written);
-                            total_read += bufread;
-                            IStream_Seek(pstr, last_read_pos, STREAM_SEEK_SET, NULL);
-                            hres = IBindStatusCallback_OnProgress(pbscb, total_read, len, (total_read == bufread) ?
-                                                                  BINDSTATUS_BEGINDOWNLOADDATA :
-                                                                  BINDSTATUS_DOWNLOADINGDATA, NULL);
-                            hres = IBindStatusCallback_OnDataAvailable(pbscb,
-                                                                       (total_read == bufread) ? BSCF_FIRSTDATANOTIFICATION :
-                                                                       BSCF_INTERMEDIATEDATANOTIFICATION,
-                                                                       total_read, &fmt, &stg);
-                            last_read_pos.u.LowPart += bufread; /* FIXME */
-                        } else
+                    bind->hconnect = InternetConnectW(bind->hinternet, host, url.nPort, user, pass,
+                                                      dwService, 0, (DWORD)bind);
+                    if (!bind->hconnect)
+                    {
+                            hres = HRESULT_FROM_WIN32(GetLastError());
+                            CloseHandle(bind->hinternet);
                             break;
-		    }
-                    hres = IBindStatusCallback_OnProgress(pbscb, total_read, len, BINDSTATUS_ENDDOWNLOADDATA, NULL);
-                    hres = IBindStatusCallback_OnDataAvailable(pbscb, BSCF_LASTDATANOTIFICATION, total_read, &fmt, &stg);
-                    TRACE("OnDataAvail rets %08lx\n", hres);
-                    hres = IBindStatusCallback_OnStopBinding(pbscb, S_OK, NULL);
-                    TRACE("OnStop rets %08lx\n", hres);
-                    hres = S_OK;
+                    }
+
+                    hres = IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, 0x22, NULL);
+                    hres = IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_FINDINGRESOURCE, NULL);
+                    hres = IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_CONNECTING, NULL);
+                    hres = IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_SENDINGREQUEST, NULL);
+
+                    bSuccess = FALSE;
+
+                    switch (dwService)
+                    {
+                    case INTERNET_SERVICE_GOPHER:
+                        bind->hrequest = GopherOpenFileW(bind->hconnect,
+                                                         path,
+                                                         0,
+                                                         INTERNET_FLAG_RELOAD,
+                                                         0);
+                        if (bind->hrequest)
+                                bSuccess = TRUE;
+                        else
+                                hres = HRESULT_FROM_WIN32(GetLastError());
+                        break;
+
+                    case INTERNET_SERVICE_FTP:
+                        bind->hrequest = FtpOpenFileW(bind->hconnect,
+                                                      path,
+                                                      GENERIC_READ,
+                                                      FTP_TRANSFER_TYPE_BINARY |
+                                                       INTERNET_FLAG_TRANSFER_BINARY |
+                                                       INTERNET_FLAG_RELOAD,
+                                                      0);
+                        if (bind->hrequest)
+                                bSuccess = TRUE;
+                        else
+                                hres = HRESULT_FROM_WIN32(GetLastError());
+                        break;
+
+                    case INTERNET_SERVICE_HTTP:
+                        bind->hrequest = HttpOpenRequestW(bind->hconnect, NULL, path, NULL, NULL, NULL, 0, (DWORD)bind);
+                        if (!bind->hrequest)
+                        {
+                                hres = HRESULT_FROM_WIN32(GetLastError());
+                        }
+                        else if (!HttpSendRequestW(bind->hrequest, NULL, 0, NULL, 0))
+                        {
+                                hres = HRESULT_FROM_WIN32(GetLastError());
+                                InternetCloseHandle(bind->hrequest);
+                        }
+                        else
+                        {
+                                HttpQueryInfoW(bind->hrequest,
+                                               HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
+                                               &bind->expected_size,
+                                               &lensz,
+                                               NULL);
+                                bSuccess = TRUE;
+                        }
+                        break;
+                    }
+                    if(bSuccess)
+                    {
+                        TRACE("res = %ld gle = %08lx url len = %ld\n", hres, GetLastError(), bind->expected_size);
+
+                        IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_CACHEFILENAMEAVAILABLE, szFileName);
+
+                        while(1) {
+                            char buf[4096];
+                            DWORD bufread;
+                            if(InternetReadFile(bind->hrequest, buf, sizeof(buf), &bufread)) {
+                                TRACE("read %ld bytes %s...\n", bufread, debugstr_an(buf, 10));
+                                if(bufread == 0) break;
+                                hres = Binding_MoreCacheData(bind, buf, bufread);
+                            } else
+                                break;
+                        }
+                        InternetCloseHandle(bind->hrequest);
+                            hres = S_OK;
+                    }
+            
+                    InternetCloseHandle(bind->hconnect);
+                    InternetCloseHandle(bind->hinternet);
+                    break;
+
+                case INTERNET_SCHEME_FILE:
+                    path = bind->URLName + 5; /* Skip the "file:" part */
+                    if ((path[0] != '/' && path[0] != '\\') ||
+                        (path[1] != '/' && path[1] != '\\'))
+                    {
+                        hres = E_FAIL;
+                    }
+                    else
+                    {
+                        HANDLE h;
+
+                        path += 2;
+                        if (path[0] == '/' || path[0] == '\\')
+                            ++path;
+                        h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
+                        if (h == (HANDLE) HFILE_ERROR)
+                        {
+                            hres = HRESULT_FROM_WIN32(GetLastError());
+                        }
+                        else
+                        {
+                            char buf[4096];
+                            DWORD bufread;
+
+                            IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_CACHEFILENAMEAVAILABLE, szFileName);
+
+                            while (ReadFile(h, buf, sizeof(buf), &bufread, NULL) && bufread > 0)
+                                hres = Binding_MoreCacheData(bind, buf, bufread);
+
+                            CloseHandle(h);
+                            hres = S_OK;
+                        }
+                    }
+                        
+                    break;
+
+                default:
+                    FIXME("Unsupported URI scheme");
+                    break;
                 }
-                InternetCloseHandle(This->hrequest);
-                InternetCloseHandle(This->hconnect);
-                InternetCloseHandle(This->hinternet);
-                IBindStatusCallback_Release(pbscb);
+                Binding_CloseCacheDownload(bind);
+                Binding_FinishedDownload(bind, hres);
+
+                if (user)
+                    HeapFree(GetProcessHeap(), 0, user);
+                if (pass)
+                    HeapFree(GetProcessHeap(), 0, pass);
+                HeapFree(GetProcessHeap(), 0, path);
+                HeapFree(GetProcessHeap(), 0, host);
+                HeapFree(GetProcessHeap(), 0, urlcopy);
             }
         }
     }
-    *ppvObject = (VOID*)pstr;
+
+    IBinding_Release((IBinding*)bind);
+
     return hres;
 }
 
@@ -698,98 +1100,6 @@
     return S_OK;
 }
 
-static HRESULT WINAPI URLMonikerImpl_IBinding_QueryInterface(IBinding* iface,REFIID riid,void** ppvObject)
-{
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);
-
-    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
-
-    /* Perform a sanity check on the parameters.*/
-    if ( (This==0) || (ppvObject==0) )
-	return E_INVALIDARG;
-
-    /* Initialize the return parameter */
-    *ppvObject = 0;
-
-    /* Compare the riid with the interface IDs implemented by this object.*/
-    if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IBinding, riid))
-        *ppvObject = iface;
-
-    /* Check that we obtained an interface.*/
-    if ((*ppvObject)==0)
-        return E_NOINTERFACE;
-
-    /* Query Interface always increases the reference count by one when it is successful */
-    IBinding_AddRef(iface);
-
-    return S_OK;
-
-}
-
-static ULONG WINAPI URLMonikerImpl_IBinding_AddRef(IBinding* iface)
-{
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);
-    TRACE("(%p)\n",This);
-
-    return URLMonikerImpl_AddRef((IMoniker*)This);
-}
-
-static ULONG WINAPI URLMonikerImpl_IBinding_Release(IBinding* iface)
-{
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);
-    TRACE("(%p)\n",This);
-
-    return URLMonikerImpl_Release((IMoniker*)This);
-}
-
-static HRESULT WINAPI URLMonikerImpl_IBinding_Abort(IBinding* iface)
-{
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);
-    FIXME("(%p): stub\n", This);
-
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI URLMonikerImpl_IBinding_GetBindResult(IBinding* iface, CLSID* pclsidProtocol, DWORD* pdwResult, LPOLESTR* pszResult, DWORD* pdwReserved)
-{
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);
-    FIXME("(%p)->(%p, %p, %p, %p): stub\n", This, pclsidProtocol, pdwResult, pszResult, pdwReserved);
-
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI URLMonikerImpl_IBinding_GetPriority(IBinding* iface, LONG* pnPriority)
-{
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);
-    FIXME("(%p)->(%p): stub\n", This, pnPriority);
-
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI URLMonikerImpl_IBinding_Resume(IBinding* iface)
-{
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);
-    FIXME("(%p): stub\n", This);
-
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI URLMonikerImpl_IBinding_SetPriority(IBinding* iface, LONG nPriority)
-{
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);
-    FIXME("(%p)->(%ld): stub\n", This, nPriority);
-
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI URLMonikerImpl_IBinding_Suspend(IBinding* iface)
-{
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);
-    FIXME("(%p): stub\n", This);
-
-    return E_NOTIMPL;
-}
-
 /********************************************************************************/
 /* Virtual function table for the URLMonikerImpl class which  include IPersist,*/
 /* IPersistStream and IMoniker functions.                                       */
@@ -820,19 +1130,6 @@
     URLMonikerImpl_IsSystemMoniker
 };
 
-static IBindingVtbl VTBinding_URLMonikerImpl =
-{
-    URLMonikerImpl_IBinding_QueryInterface,
-    URLMonikerImpl_IBinding_AddRef,
-    URLMonikerImpl_IBinding_Release,
-    URLMonikerImpl_IBinding_Abort,
-    URLMonikerImpl_IBinding_Suspend,
-    URLMonikerImpl_IBinding_Resume,
-    URLMonikerImpl_IBinding_SetPriority,
-    URLMonikerImpl_IBinding_GetPriority,
-    URLMonikerImpl_IBinding_GetBindResult
-};
-
 /******************************************************************************
  *         URLMoniker_Construct (local function)
  *******************************************************************************/
@@ -845,9 +1142,8 @@
     memset(This, 0, sizeof(*This));
 
     /* Initialize the virtual function table. */
-    This->lpvtbl1      = &VT_URLMonikerImpl;
-    This->lpvtbl2      = &VTBinding_URLMonikerImpl;
-    This->ref          = 0;
+    This->lpvtbl = &VT_URLMonikerImpl;
+    This->ref = 0;
 
     if(lpszLeftURLName) {
         hres = UrlCombineW(lpszLeftURLName, lpszURLName, NULL, &sizeStr, 0);

Copied: trunk/reactos/lib/urlmon/umstream.c (from rev 15623, vendor/wine/dlls/urlmon/current/umstream.c)
Property changes on: trunk/reactos/lib/urlmon/umstream.c ___________________________________________________________________ Name: svn:keywords   + Author Date Id Revision Name: svn:eol-style   + native
Modified: trunk/reactos/lib/urlmon/urlmon.spec
--- trunk/reactos/lib/urlmon/urlmon.spec	2005-05-28 21:40:01 UTC (rev 15624)
+++ trunk/reactos/lib/urlmon/urlmon.spec	2005-05-28 21:44:21 UTC (rev 15625)
@@ -8,7 +8,7 @@
 @ stub AsyncGetClassBits
 @ stub AsyncInstallDistributionUnit
 @ stub BindAsyncMoniker
-@ stub CoGetClassObjectFromURL
+@ stdcall CoGetClassObjectFromURL(ptr wstr long long wstr ptr long ptr ptr ptr)
 @ stub CoInstall
 @ stdcall CoInternetCombineUrl(wstr wstr long wstr long ptr long)
 @ stdcall CoInternetCompareUrl(wstr wstr long)

Modified: trunk/reactos/lib/urlmon/urlmon.xml
--- trunk/reactos/lib/urlmon/urlmon.xml	2005-05-28 21:40:01 UTC (rev 15624)
+++ trunk/reactos/lib/urlmon/urlmon.xml	2005-05-28 21:44:21 UTC (rev 15625)
@@ -23,6 +23,7 @@
 	<file>regsvr.c</file>
 	<file>sec_mgr.c</file>
 	<file>umon.c</file>
+	<file>umstream.c</file>
 	<file>urlmon_main.c</file>
 	<file>urlmon.spec</file>
 </module>

Modified: trunk/reactos/lib/urlmon/urlmon_main.c
--- trunk/reactos/lib/urlmon/urlmon_main.c	2005-05-28 21:40:01 UTC (rev 15624)
+++ trunk/reactos/lib/urlmon/urlmon_main.c	2005-05-28 21:44:21 UTC (rev 15625)
@@ -341,3 +341,17 @@
     FIXME("%p %p %p %08lx\n", hwnd, pClassSpec, pQuery, flags);
     return E_NOTIMPL;
 }
+
+/**************************************************************************
+ *                 CoGetClassObjectFromURL (URLMON.@)
+ */
+HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
+                                        DWORD dwFileVersionLS, LPCWSTR szContentType,
+                                        LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
+                                        REFIID riid, LPVOID *ppv )
+{
+    FIXME("(%s %s %ld %ld %s %p %ld %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
+	dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
+	debugstr_guid(riid), ppv);
+    return E_NOINTERFACE;
+}

Modified: trunk/reactos/lib/urlmon/urlmon_main.h
--- trunk/reactos/lib/urlmon/urlmon_main.h	2005-05-28 21:40:01 UTC (rev 15624)
+++ trunk/reactos/lib/urlmon/urlmon_main.h	2005-05-28 21:44:21 UTC (rev 15625)
@@ -37,4 +37,17 @@
 
 #define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
 
+typedef struct
+{	
+	const IStreamVtbl	*lpVtbl;
+	DWORD		ref;
+	HANDLE		handle;
+	BOOL		closed;
+	WCHAR		*pszFileName;
+	WCHAR		*pszURL;
+} IUMCacheStream;
+
+HRESULT	UMCreateStreamOnCacheFile(LPCWSTR pszURL, DWORD dwSize, LPWSTR pszFileName, HANDLE *phfile, IUMCacheStream **ppstr);
+void	UMCloseCacheFileStream(IUMCacheStream *pstr);
+
 #endif /* __WINE_URLMON_MAIN_H */