Author: winesync
Date: Fri Apr  4 09:41:46 2008
New Revision: 32859
URL: 
http://svn.reactos.org/svn/reactos?rev=32859&view=rev
Log:
Autosyncing with Wine HEAD
Added:
    trunk/reactos/dll/win32/urlmon/download.c   (with props)
Modified:
    trunk/reactos/dll/win32/urlmon/binding.c
    trunk/reactos/dll/win32/urlmon/file.c
    trunk/reactos/dll/win32/urlmon/http.c
    trunk/reactos/dll/win32/urlmon/mk.c
    trunk/reactos/dll/win32/urlmon/regsvr.c
    trunk/reactos/dll/win32/urlmon/sec_mgr.c
    trunk/reactos/dll/win32/urlmon/session.c
    trunk/reactos/dll/win32/urlmon/umon.c
    trunk/reactos/dll/win32/urlmon/umstream.c
    trunk/reactos/dll/win32/urlmon/urlmon.rbuild
    trunk/reactos/dll/win32/urlmon/urlmon.spec
    trunk/reactos/dll/win32/urlmon/urlmon_main.c
    trunk/reactos/dll/win32/urlmon/urlmon_main.h
Modified: trunk/reactos/dll/win32/urlmon/binding.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/binding.c…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/binding.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/binding.c [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -38,17 +38,33 @@
 } task_header_t;
 typedef struct {
-    const IStreamVtbl *lpStreamVtbl;
+    const IUnknownVtbl *lpUnknownVtbl;
     LONG ref;
     IInternetProtocol *protocol;
     BYTE buf[1024*8];
-    DWORD buf_size;
-    BOOL init_buf;
+    DWORD size;
+    BOOL init;
     HRESULT hres;
-} ProtocolStream;
+
+    LPWSTR cache_file;
+} stgmed_buf_t;
+
+typedef struct _stgmed_obj_t stgmed_obj_t;
+
+typedef struct {
+    void (*release)(stgmed_obj_t*);
+    HRESULT (*fill_stgmed)(stgmed_obj_t*,STGMEDIUM*);
+    void *(*get_result)(stgmed_obj_t*);
+} stgmed_obj_vtbl;
+
+struct _stgmed_obj_t {
+    const stgmed_obj_vtbl *vtbl;
+};
+
+#define STGMEDUNK(x)  ((IUnknown*) &(x)->lpUnknownVtbl)
 typedef enum {
     BEFORE_DOWNLOAD,
@@ -71,7 +87,9 @@
     IBindStatusCallback *callback;
     IInternetProtocol *protocol;
     IServiceProvider *service_provider;
-    ProtocolStream *stream;
+
+    stgmed_buf_t *stgmed_buf;
+    stgmed_obj_t *stgmed_obj;
     BINDINFO bindinfo;
     DWORD bindf;
@@ -92,8 +110,6 @@
     DWORD apartment_thread;
     HWND notif_hwnd;
-    STGMEDIUM stgmed;
-
     task_header_t *task_queue_head, *task_queue_tail;
     CRITICAL_SECTION section;
 };
@@ -143,18 +159,18 @@
     return ret;
 }
-static void fill_stream_buffer(ProtocolStream *This)
+static void fill_stgmed_buffer(stgmed_buf_t *buf)
 {
     DWORD read = 0;
-    if(sizeof(This->buf) == This->buf_size)
+    if(sizeof(buf->buf) == buf->size)
         return;
-    This->hres = IInternetProtocol_Read(This->protocol,
This->buf+This->buf_size,
-            sizeof(This->buf)-This->buf_size, &read);
-    This->buf_size += read;
+    buf->hres = IInternetProtocol_Read(buf->protocol, buf->buf+buf->size,
+            sizeof(buf->buf)-buf->size, &read);
+    buf->size += read;
     if(read > 0)
-        This->init_buf = TRUE;
+        buf->init = TRUE;
 }
 static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -281,9 +297,9 @@
     if(verify) {
         LPWSTR mime = NULL;
-        fill_stream_buffer(binding->stream);
-        FindMimeFromData(NULL, binding->url, binding->stream->buf,
-                         min(binding->stream->buf_size, 255), binding->mime, 0,
&mime, 0);
+        fill_stgmed_buffer(binding->stgmed_buf);
+        FindMimeFromData(NULL, binding->url, binding->stgmed_buf->buf,
+                         min(binding->stgmed_buf->size, 255), binding->mime, 0,
&mime, 0);
         heap_free(binding->mime);
         binding->mime = heap_strdupW(mime);
@@ -404,31 +420,17 @@
         FIXME("Load failed: %08x\n", hres);
 }
-static void create_object(Binding *binding)
+static HRESULT create_mime_object(Binding *binding, const CLSID *clsid, LPCWSTR
clsid_str)
 {
     IPersistMoniker *persist;
-    LPWSTR clsid_str;
-    CLSID clsid;
     HRESULT hres;
-    if(!binding->mime) {
-        FIXME("MIME unavailable\n");
-        return;
-    }
-
-    if(!(clsid_str = get_mime_clsid(binding->mime, &clsid))) {
-        FIXME("Could not find object for MIME %s\n",
debugstr_w(binding->mime));
-        return;
-    }
-
-    IBindStatusCallback_OnProgress(binding->callback, 0, 0,
BINDSTATUS_CLASSIDAVAILABLE, clsid_str);
-
-    IBindStatusCallback_OnProgress(binding->callback, 0, 0,
BINDSTATUS_BEGINSYNCOPERATION, NULL);
-
-    hres = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
+    hres = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
                             &binding->iid, (void**)&binding->obj);
-    if(FAILED(hres))
-        FIXME("CoCreateInstance failed: %08x\n", hres);
+    if(FAILED(hres)) {
+        WARN("CoCreateInstance failed: %08x\n", hres);
+        return INET_E_CANNOT_INSTANTIATE_OBJECT;
+    }
     binding->state |= BINDING_OBJAVAIL;
@@ -451,14 +453,123 @@
         /* FIXME: Try query IPersistFile */
     }
+    IBindStatusCallback_OnObjectAvailable(binding->callback, &binding->iid,
binding->obj);
+
+    return S_OK;
+}
+
+static void create_object(Binding *binding)
+{
+    LPWSTR clsid_str;
+    CLSID clsid;
+    HRESULT hres;
+
+    if(!binding->mime) {
+        FIXME("MIME not available\n");
+        return;
+    }
+
+    if(!(clsid_str = get_mime_clsid(binding->mime, &clsid))) {
+        FIXME("Could not find object for MIME %s\n",
debugstr_w(binding->mime));
+        return;
+    }
+
+    IBindStatusCallback_OnProgress(binding->callback, 0, 0,
BINDSTATUS_CLASSIDAVAILABLE, clsid_str);
+    IBindStatusCallback_OnProgress(binding->callback, 0, 0,
BINDSTATUS_BEGINSYNCOPERATION, NULL);
+
+    hres = create_mime_object(binding, &clsid, clsid_str);
     heap_free(clsid_str);
-    IBindStatusCallback_OnObjectAvailable(binding->callback, &binding->iid,
binding->obj);
-
     IBindStatusCallback_OnProgress(binding->callback, 0, 0,
BINDSTATUS_ENDSYNCOPERATION, NULL);
-    stop_binding(binding, S_OK, NULL);
-}
+    stop_binding(binding, hres, NULL);
+    if(FAILED(hres))
+        IInternetProtocol_Terminate(binding->protocol, 0);
+}
+
+#define STGMEDUNK_THIS(iface) DEFINE_THIS(stgmed_buf_t, Unknown, iface)
+
+static HRESULT WINAPI StgMedUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+    stgmed_buf_t *This = STGMEDUNK_THIS(iface);
+
+    *ppv = NULL;
+
+    if(IsEqualGUID(riid, &IID_IUnknown)) {
+        TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+
+        *ppv = STGMEDUNK(This);
+        IUnknown_AddRef(STGMEDUNK(This));
+        return S_OK;
+    }
+
+    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI StgMedUnk_AddRef(IUnknown *iface)
+{
+    stgmed_buf_t *This = STGMEDUNK_THIS(iface);
+    LONG ref = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p) ref=%d\n", This, ref);
+
+    return ref;
+}
+
+static ULONG WINAPI StgMedUnk_Release(IUnknown *iface)
+{
+    stgmed_buf_t *This = STGMEDUNK_THIS(iface);
+    LONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p) ref=%d\n", This, ref);
+
+    if(!ref) {
+        IInternetProtocol_Release(This->protocol);
+        heap_free(This->cache_file);
+        heap_free(This);
+
+        URLMON_UnlockModule();
+    }
+
+    return ref;
+}
+
+#undef STGMEDUNK_THIS
+
+static const IUnknownVtbl StgMedUnkVtbl = {
+    StgMedUnk_QueryInterface,
+    StgMedUnk_AddRef,
+    StgMedUnk_Release
+};
+
+static stgmed_buf_t *create_stgmed_buf(IInternetProtocol *protocol)
+{
+    stgmed_buf_t *ret = heap_alloc(sizeof(*ret));
+
+    ret->lpUnknownVtbl = &StgMedUnkVtbl;
+    ret->ref = 1;
+    ret->size = 0;
+    ret->init = FALSE;
+    ret->hres = S_OK;
+    ret->cache_file = NULL;
+
+    IInternetProtocol_AddRef(protocol);
+    ret->protocol = protocol;
+
+    URLMON_LockModule();
+
+    return ret;
+}
+
+typedef struct {
+    stgmed_obj_t stgmed_obj;
+    const IStreamVtbl *lpStreamVtbl;
+
+    LONG ref;
+
+    stgmed_buf_t *buf;
+} ProtocolStream;
 #define STREAM_THIS(iface) DEFINE_THIS(ProtocolStream, Stream, iface)
@@ -507,7 +618,7 @@
     TRACE("(%p) ref=%d\n", This, ref);
     if(!ref) {
-        IInternetProtocol_Release(This->protocol);
+        IUnknown_Release(STGMEDUNK(This->buf));
         heap_free(This);
         URLMON_UnlockModule();
@@ -517,24 +628,25 @@
 }
 static HRESULT WINAPI ProtocolStream_Read(IStream *iface, void *pv,
-                                         ULONG cb, ULONG *pcbRead)
+                                          ULONG cb, ULONG *pcbRead)
 {
     ProtocolStream *This = STREAM_THIS(iface);
     DWORD read = 0, pread = 0;
+    HRESULT hres;
     TRACE("(%p)->(%p %d %p)\n", This, pv, cb, pcbRead);
-    if(This->buf_size) {
+    if(This->buf->size) {
         read = cb;
-        if(read > This->buf_size)
-            read = This->buf_size;
-
-        memcpy(pv, This->buf, read);
-
-        if(read < This->buf_size)
-            memmove(This->buf, This->buf+read, This->buf_size-read);
-        This->buf_size -= read;
+        if(read > This->buf->size)
+            read = This->buf->size;
+
+        memcpy(pv, This->buf->buf, read);
+
+        if(read < This->buf->size)
+            memmove(This->buf->buf, This->buf->buf+read,
This->buf->size-read);
+        This->buf->size -= read;
     }
     if(read == cb) {
@@ -543,14 +655,14 @@
         return S_OK;
     }
-    This->hres = IInternetProtocol_Read(This->protocol, (PBYTE)pv+read, cb-read,
&pread);
+    hres = This->buf->hres = IInternetProtocol_Read(This->buf->protocol,
(PBYTE)pv+read, cb-read, &pread);
     if (pcbRead)
         *pcbRead = read + pread;
-    if(This->hres == E_PENDING)
+    if(hres == E_PENDING)
         return E_PENDING;
-    else if(FAILED(This->hres))
-        FIXME("Read failed: %08x\n", This->hres);
+    else if(FAILED(hres))
+        FIXME("Read failed: %08x\n", hres);
     return read || pread ? S_OK : S_FALSE;
 }
@@ -656,25 +768,117 @@
     ProtocolStream_Clone
 };
-#define BINDING_THIS(iface) DEFINE_THIS(Binding, Binding, iface)
-
-static ProtocolStream *create_stream(IInternetProtocol *protocol)
+static void stgmed_stream_release(stgmed_obj_t *obj)
+{
+    ProtocolStream *stream = (ProtocolStream*)obj;
+    IStream_Release(STREAM(stream));
+}
+
+static HRESULT stgmed_stream_fill_stgmed(stgmed_obj_t *obj, STGMEDIUM *stgmed)
+{
+    ProtocolStream *stream = (ProtocolStream*)obj;
+
+    stgmed->tymed = TYMED_ISTREAM;
+    stgmed->u.pstm = STREAM(stream);
+    stgmed->pUnkForRelease = STGMEDUNK(stream->buf);
+
+    return S_OK;
+}
+
+static void *stgmed_stream_get_result(stgmed_obj_t *obj)
+{
+    ProtocolStream *stream = (ProtocolStream*)obj;
+
+    IStream_AddRef(STREAM(stream));
+    return STREAM(stream);
+}
+
+static const stgmed_obj_vtbl stgmed_stream_vtbl = {
+    stgmed_stream_release,
+    stgmed_stream_fill_stgmed,
+    stgmed_stream_get_result
+};
+
+typedef struct {
+    stgmed_obj_t stgmed_obj;
+    stgmed_buf_t *buf;
+} stgmed_file_obj_t;
+
+static stgmed_obj_t *create_stgmed_stream(stgmed_buf_t *buf)
 {
     ProtocolStream *ret = heap_alloc(sizeof(ProtocolStream));
+    ret->stgmed_obj.vtbl = &stgmed_stream_vtbl;
     ret->lpStreamVtbl = &ProtocolStreamVtbl;
     ret->ref = 1;
-    ret->buf_size = 0;
-    ret->init_buf = FALSE;
-    ret->hres = S_OK;
-
-    IInternetProtocol_AddRef(protocol);
-    ret->protocol = protocol;
+
+    IUnknown_AddRef(STGMEDUNK(buf));
+    ret->buf = buf;
     URLMON_LockModule();
-    return ret;
-}
+    return &ret->stgmed_obj;
+}
+
+static void stgmed_file_release(stgmed_obj_t *obj)
+{
+    stgmed_file_obj_t *file_obj = (stgmed_file_obj_t*)obj;
+
+    IUnknown_Release(STGMEDUNK(file_obj->buf));
+    heap_free(file_obj);
+}
+
+static HRESULT stgmed_file_fill_stgmed(stgmed_obj_t *obj, STGMEDIUM *stgmed)
+{
+    stgmed_file_obj_t *file_obj = (stgmed_file_obj_t*)obj;
+
+    if(!file_obj->buf->cache_file) {
+        WARN("cache_file not set\n");
+        return INET_E_DATA_NOT_AVAILABLE;
+    }
+
+    fill_stgmed_buffer(file_obj->buf);
+    if(file_obj->buf->size == sizeof(file_obj->buf->buf)) {
+        BYTE buf[1024];
+        DWORD read;
+        HRESULT hres;
+
+        do {
+            hres = IInternetProtocol_Read(file_obj->buf->protocol, buf,
sizeof(buf), &read);
+        }while(hres == S_OK);
+    }
+
+    stgmed->tymed = TYMED_FILE;
+    stgmed->u.lpszFileName = file_obj->buf->cache_file;
+    stgmed->pUnkForRelease = STGMEDUNK(file_obj->buf);
+
+    return S_OK;
+}
+
+static void *stgmed_file_get_result(stgmed_obj_t *obj)
+{
+    return NULL;
+}
+
+static const stgmed_obj_vtbl stgmed_file_vtbl = {
+    stgmed_file_release,
+    stgmed_file_fill_stgmed,
+    stgmed_file_get_result
+};
+
+static stgmed_obj_t *create_stgmed_file(stgmed_buf_t *buf)
+{
+    stgmed_file_obj_t *ret = heap_alloc(sizeof(*ret));
+
+    ret->stgmed_obj.vtbl = &stgmed_file_vtbl;
+
+    IUnknown_AddRef(STGMEDUNK(buf));
+    ret->buf = buf;
+
+    return &ret->stgmed_obj;
+}
+
+#define BINDING_THIS(iface) DEFINE_THIS(Binding, Binding, iface)
 static HRESULT WINAPI Binding_QueryInterface(IBinding *iface, REFIID riid, void **ppv)
 {
@@ -736,8 +940,10 @@
             IInternetProtocol_Release(This->protocol);
         if(This->service_provider)
             IServiceProvider_Release(This->service_provider);
-        if(This->stream)
-            IStream_Release(STREAM(This->stream));
+        if(This->stgmed_buf)
+            IUnknown_Release(STGMEDUNK(This->stgmed_buf));
+        if(This->stgmed_obj)
+            This->stgmed_obj->vtbl->release(This->stgmed_obj);
         if(This->obj)
             IUnknown_Release(This->obj);
         if(This->bctx)
@@ -877,7 +1083,7 @@
     TRACE("(%p)->(%p)\n", This, pProtocolData);
     task = heap_alloc(sizeof(switch_task_t));
-    memcpy(&task->data, pProtocolData, sizeof(PROTOCOLDATA));
+    task->data = *pProtocolData;
     push_task(This, &task->header, switch_proc);
@@ -957,7 +1163,7 @@
         on_progress(This, 0, 0, BINDSTATUS_CONNECTING, szStatusText);
         break;
     case BINDSTATUS_BEGINDOWNLOADDATA:
-        fill_stream_buffer(This->stream);
+        fill_stgmed_buffer(This->stgmed_buf);
         break;
     case BINDSTATUS_MIMETYPEAVAILABLE:
         set_binding_mime(This, szStatusText);
@@ -971,6 +1177,8 @@
         mime_available(This, szStatusText, FALSE);
         break;
     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
+        heap_free(This->stgmed_buf->cache_file);
+        This->stgmed_buf->cache_file = heap_strdupW(szStatusText);
         break;
     case BINDSTATUS_DIRECTBIND:
         This->report_mime = FALSE;
@@ -1000,15 +1208,19 @@
         mime_available(This, NULL, TRUE);
     if(This->download_state == BEFORE_DOWNLOAD) {
-        fill_stream_buffer(This->stream);
+        fill_stgmed_buffer(This->stgmed_buf);
         This->download_state = DOWNLOADING;
         sent_begindownloaddata = TRUE;
         IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
                 BINDSTATUS_BEGINDOWNLOADDATA, This->url);
-    }
-
-    if(This->stream->hres == S_FALSE || (bscf & BSCF_LASTDATANOTIFICATION)) {
+
+        if(This->stgmed_buf->cache_file)
+            IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
+                    BINDSTATUS_CACHEFILENAMEAVAILABLE,
This->stgmed_buf->cache_file);
+    }
+
+    if(This->stgmed_buf->hres == S_FALSE || (bscf & BSCF_LASTDATANOTIFICATION))
{
         This->download_state = END_DOWNLOAD;
         IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
                 BINDSTATUS_ENDDOWNLOADDATA, This->url);
@@ -1021,15 +1233,26 @@
         if(!(This->state & BINDING_OBJAVAIL))
             create_object(This);
     }else {
+        STGMEDIUM stgmed;
+        HRESULT hres;
+
         if(!(This->state & BINDING_LOCKED)) {
             HRESULT hres = IInternetProtocol_LockRequest(This->protocol, 0);
             if(SUCCEEDED(hres))
                 This->state |= BINDING_LOCKED;
         }
+        hres = This->stgmed_obj->vtbl->fill_stgmed(This->stgmed_obj,
&stgmed);
+        if(FAILED(hres)) {
+            stop_binding(This, hres, NULL);
+            return;
+        }
+
+        formatetc.tymed = stgmed.tymed;
         formatetc.cfFormat = This->clipboard_format;
+
         IBindStatusCallback_OnDataAvailable(This->callback, bscf, progress,
-                &formatetc, &This->stgmed);
+                &formatetc, &stgmed);
         if(This->download_state == END_DOWNLOAD)
             stop_binding(This, S_OK, NULL);
@@ -1159,7 +1382,7 @@
     *grfBINDF = This->bindf;
-    memcpy(pbindinfo, &This->bindinfo, sizeof(BINDINFO));
+    *pbindinfo = This->bindinfo;
     if(pbindinfo->szExtraInfo || pbindinfo->szCustomVerb)
         FIXME("copy strings\n");
@@ -1283,7 +1506,7 @@
         IUnknown_Release(unk);
     }
-    return SUCCEEDED(hres) ? S_OK : MK_E_SYNTAX;
+    return SUCCEEDED(hres) ? S_OK : INET_E_DATA_NOT_AVAILABLE;
 }
 static BOOL is_urlmon_protocol(LPCWSTR url)
@@ -1326,11 +1549,6 @@
     Binding *ret;
     HRESULT hres;
-    if(!to_obj && !IsEqualGUID(&IID_IStream, riid)) {
-        FIXME("Unsupported riid %s\n", debugstr_guid(riid));
-        return E_NOTIMPL;
-    }
-
     URLMON_LockModule();
     ret = heap_alloc_zero(sizeof(Binding));
@@ -1406,15 +1624,25 @@
     ret->url = heap_strdupW(url);
     if(binding_ctx) {
-        ret->stream = binding_ctx->stream;
-        IStream_AddRef(STREAM(ret->stream));
+        ret->stgmed_buf = binding_ctx->stgmed_buf;
+        IUnknown_AddRef(STGMEDUNK(ret->stgmed_buf));
         ret->clipboard_format = binding_ctx->clipboard_format;
     }else {
-        ret->stream = create_stream(ret->protocol);
-    }
-    ret->stgmed.tymed = TYMED_ISTREAM;
-    ret->stgmed.u.pstm = STREAM(ret->stream);
-    ret->stgmed.pUnkForRelease = (IUnknown*)BINDING(ret); /* NOTE: Windows uses other
IUnknown */
+        ret->stgmed_buf = create_stgmed_buf(ret->protocol);
+    }
+
+    if(to_obj) {
+        ret->stgmed_obj = NULL;
+    }else if(IsEqualGUID(&IID_IStream, riid)) {
+        ret->stgmed_obj = create_stgmed_stream(ret->stgmed_buf);
+    }else if(IsEqualGUID(&IID_IUnknown, riid)) {
+        ret->bindf |= BINDF_NEEDFILE;
+        ret->stgmed_obj = create_stgmed_file(ret->stgmed_buf);
+    }else {
+        FIXME("Unsupported riid %s\n", debugstr_guid(riid));
+        IBinding_Release(BINDING(ret));
+        return E_NOTIMPL;
+    }
     *binding = ret;
     return S_OK;
@@ -1434,7 +1662,7 @@
     hres = IBindStatusCallback_OnStartBinding(binding->callback, 0, BINDING(binding));
     if(FAILED(hres)) {
         WARN("OnStartBinding failed: %08x\n", hres);
-        stop_binding(binding, 0x800c0008, NULL);
+        stop_binding(binding, INET_E_DOWNLOAD_FAILURE, NULL);
         IBinding_Release(BINDING(binding));
         return hres;
     }
@@ -1448,7 +1676,7 @@
         TRACE("start ret %08x\n", hres);
-        if(FAILED(hres)) {
+        if(FAILED(hres) && hres != E_PENDING) {
             stop_binding(binding, hres, NULL);
             IBinding_Release(BINDING(binding));
@@ -1484,23 +1712,16 @@
     if(FAILED(hres))
         return hres;
-    if(binding->hres != S_OK) {
-        hres = SUCCEEDED(binding->hres) ? S_OK : binding->hres;
-    }else if(binding->stream->init_buf) {
+    if(binding->hres == S_OK && binding->stgmed_buf->init) {
         if((binding->state & BINDING_STOPPED) && (binding->state &
BINDING_LOCKED))
             IInternetProtocol_UnlockRequest(binding->protocol);
-        IStream_AddRef(STREAM(binding->stream));
-        *ppv = binding->stream;
-
-        hres = S_OK;
-    }else {
-        hres = MK_S_ASYNCHRONOUS;
+        *ppv = binding->stgmed_obj->vtbl->get_result(binding->stgmed_obj);
     }
     IBinding_Release(BINDING(binding));
-    return hres;
+    return *ppv ? S_OK : MK_S_ASYNCHRONOUS;
 }
 HRESULT bind_to_object(IMoniker *mon, LPCWSTR url, IBindCtx *pbc, REFIID riid, void
**ppv)
Added: trunk/reactos/dll/win32/urlmon/download.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/download.…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/download.c (added)
+++ trunk/reactos/dll/win32/urlmon/download.c [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -1,0 +1,406 @@
+/*
+ * Copyright 2008 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "urlmon_main.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
+
+typedef struct {
+    const IBindStatusCallbackVtbl  *lpBindStatusCallbackVtbl;
+    const IServiceProviderVtbl     *lpServiceProviderVtbl;
+
+    LONG ref;
+
+    IBindStatusCallback *callback;
+    LPWSTR file_name;
+    LPWSTR cache_file;
+} DownloadBSC;
+
+#define STATUSCLB(x)     ((IBindStatusCallback*)  &(x)->lpBindStatusCallbackVtbl)
+#define SERVPROV(x)      ((IServiceProvider*)     &(x)->lpServiceProviderVtbl)
+
+#define STATUSCLB_THIS(iface) DEFINE_THIS(DownloadBSC, BindStatusCallback, iface)
+
+static HRESULT WINAPI DownloadBSC_QueryInterface(IBindStatusCallback *iface,
+        REFIID riid, void **ppv)
+{
+    DownloadBSC *This = STATUSCLB_THIS(iface);
+
+    *ppv = NULL;
+
+    if(IsEqualGUID(&IID_IUnknown, riid)) {
+        TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
+        *ppv = STATUSCLB(This);
+    }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
+        TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
+        *ppv = STATUSCLB(This);
+    }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
+        TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
+        *ppv = SERVPROV(This);
+    }
+
+    if(*ppv) {
+        IBindStatusCallback_AddRef((IUnknown*)*ppv);
+        return S_OK;
+    }
+
+    TRACE("Unsupported riid = %s\n", debugstr_guid(riid));
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI DownloadBSC_AddRef(IBindStatusCallback *iface)
+{
+    DownloadBSC *This = STATUSCLB_THIS(iface);
+    LONG ref = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p) ref = %d\n", This, ref);
+
+    return ref;
+}
+
+static ULONG WINAPI DownloadBSC_Release(IBindStatusCallback *iface)
+{
+    DownloadBSC *This = STATUSCLB_THIS(iface);
+    LONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p) ref = %d\n", This, ref);
+
+    if(!ref) {
+        if(This->callback)
+            IBindStatusCallback_Release(This->callback);
+        heap_free(This->file_name);
+        heap_free(This->cache_file);
+        heap_free(This);
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI DownloadBSC_OnStartBinding(IBindStatusCallback *iface,
+        DWORD dwReserved, IBinding *pbind)
+{
+    DownloadBSC *This = STATUSCLB_THIS(iface);
+
+    TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
+
+    if(This->callback)
+        IBindStatusCallback_OnStartBinding(This->callback, dwReserved, pbind);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI DownloadBSC_GetPriority(IBindStatusCallback *iface, LONG
*pnPriority)
+{
+    DownloadBSC *This = STATUSCLB_THIS(iface);
+    FIXME("(%p)->(%p)\n", This, pnPriority);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DownloadBSC_OnLowResource(IBindStatusCallback *iface, DWORD
reserved)
+{
+    DownloadBSC *This = STATUSCLB_THIS(iface);
+    FIXME("(%p)->(%d)\n", This, reserved);
+    return E_NOTIMPL;
+}
+
+static void on_progress(DownloadBSC *This, ULONG progress, ULONG progress_max, ULONG
status_code, LPCWSTR status_text)
+{
+    HRESULT hres;
+
+    if(!This->callback)
+        return;
+
+    hres = IBindStatusCallback_OnProgress(This->callback, progress, progress_max,
status_code, status_text);
+    if(FAILED(hres))
+        FIXME("OnProgress failed: %08x\n", hres);
+}
+
+static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG
ulProgress,
+        ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
+{
+    DownloadBSC *This = STATUSCLB_THIS(iface);
+
+    TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax,
ulStatusCode,
+            debugstr_w(szStatusText));
+
+    switch(ulStatusCode) {
+    case BINDSTATUS_BEGINDOWNLOADDATA:
+    case BINDSTATUS_DOWNLOADINGDATA:
+    case BINDSTATUS_ENDDOWNLOADDATA:
+    case BINDSTATUS_SENDINGREQUEST:
+    case BINDSTATUS_MIMETYPEAVAILABLE:
+        on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
+        break;
+
+    case BINDSTATUS_CACHEFILENAMEAVAILABLE:
+        on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
+        This->cache_file = heap_strdupW(szStatusText);
+        break;
+
+    case BINDSTATUS_FINDINGRESOURCE:
+    case BINDSTATUS_CONNECTING:
+        break;
+
+    default:
+        FIXME("Unsupported status %u\n", ulStatusCode);
+    }
+
+    return S_OK;
+}
+
+static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface,
+        HRESULT hresult, LPCWSTR szError)
+{
+    DownloadBSC *This = STATUSCLB_THIS(iface);
+
+    TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
+
+    if(This->cache_file) {
+        BOOL b;
+
+        b = CopyFileW(This->cache_file, This->file_name, FALSE);
+        if(!b)
+            FIXME("CopyFile failed: %u\n", GetLastError());
+    }else {
+        FIXME("No cache file\n");
+    }
+
+    if(This->callback)
+        IBindStatusCallback_OnStopBinding(This->callback, hresult, szError);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI DownloadBSC_GetBindInfo(IBindStatusCallback *iface,
+        DWORD *grfBINDF, BINDINFO *pbindinfo)
+{
+    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DWORD bindf = 0;
+
+    TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
+
+    if(This->callback) {
+        BINDINFO bindinfo;
+        HRESULT hres;
+
+        memset(&bindinfo, 0, sizeof(bindinfo));
+        bindinfo.cbSize = sizeof(bindinfo);
+
+        hres = IBindStatusCallback_GetBindInfo(This->callback, &bindf,
&bindinfo);
+        if(SUCCEEDED(hres))
+            ReleaseBindInfo(&bindinfo);
+    }
+
+    *grfBINDF = BINDF_PULLDATA | BINDF_NEEDFILE | (bindf & BINDF_ENFORCERESTRICTED);
+    return S_OK;
+}
+
+static HRESULT WINAPI DownloadBSC_OnDataAvailable(IBindStatusCallback *iface,
+        DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
+{
+    DownloadBSC *This = STATUSCLB_THIS(iface);
+
+    TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc,
pstgmed);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI DownloadBSC_OnObjectAvailable(IBindStatusCallback *iface,
+        REFIID riid, IUnknown *punk)
+{
+    DownloadBSC *This = STATUSCLB_THIS(iface);
+    FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
+    return E_NOTIMPL;
+}
+
+#undef STATUSCLB_THIS
+
+static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
+    DownloadBSC_QueryInterface,
+    DownloadBSC_AddRef,
+    DownloadBSC_Release,
+    DownloadBSC_OnStartBinding,
+    DownloadBSC_GetPriority,
+    DownloadBSC_OnLowResource,
+    DownloadBSC_OnProgress,
+    DownloadBSC_OnStopBinding,
+    DownloadBSC_GetBindInfo,
+    DownloadBSC_OnDataAvailable,
+    DownloadBSC_OnObjectAvailable
+};
+
+#define SERVPROV_THIS(iface) DEFINE_THIS(DownloadBSC, ServiceProvider, iface)
+
+static HRESULT WINAPI DwlServiceProvider_QueryInterface(IServiceProvider *iface,
+        REFIID riid, void **ppv)
+{
+    DownloadBSC *This = SERVPROV_THIS(iface);
+    return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
+}
+
+static ULONG WINAPI DwlServiceProvider_AddRef(IServiceProvider *iface)
+{
+    DownloadBSC *This = SERVPROV_THIS(iface);
+    return IBindStatusCallback_AddRef(STATUSCLB(This));
+}
+
+static ULONG WINAPI DwlServiceProvider_Release(IServiceProvider *iface)
+{
+    DownloadBSC *This = SERVPROV_THIS(iface);
+    return IBindStatusCallback_Release(STATUSCLB(This));
+}
+
+static HRESULT WINAPI DwlServiceProvider_QueryService(IServiceProvider *iface,
+        REFGUID guidService, REFIID riid, void **ppv)
+{
+    DownloadBSC *This = SERVPROV_THIS(iface);
+    IServiceProvider *serv_prov;
+    HRESULT hres;
+
+    TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService),
debugstr_guid(riid), ppv);
+
+    if(!This->callback)
+        return E_NOINTERFACE;
+
+    hres = IBindStatusCallback_QueryInterface(This->callback, riid, ppv);
+    if(SUCCEEDED(hres))
+        return S_OK;
+
+    hres = IBindStatusCallback_QueryInterface(This->callback,
&IID_IServiceProvider, (void**)&serv_prov);
+    if(SUCCEEDED(hres)) {
+        hres = IServiceProvider_QueryService(serv_prov, guidService, riid, ppv);
+        IServiceProvider_Release(serv_prov);
+        return hres;
+    }
+
+    return E_NOINTERFACE;
+}
+
+#undef SERVPROV_THIS
+
+static const IServiceProviderVtbl ServiceProviderVtbl = {
+    DwlServiceProvider_QueryInterface,
+    DwlServiceProvider_AddRef,
+    DwlServiceProvider_Release,
+    DwlServiceProvider_QueryService
+};
+
+static IBindStatusCallback *DownloadBSC_Create(IBindStatusCallback *callback, LPCWSTR
file_name)
+{
+    DownloadBSC *ret = heap_alloc(sizeof(*ret));
+
+    ret->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl;
+    ret->lpServiceProviderVtbl    = &ServiceProviderVtbl;
+    ret->ref = 1;
+    ret->file_name = heap_strdupW(file_name);
+    ret->cache_file = NULL;
+
+    if(callback)
+        IBindStatusCallback_AddRef(callback);
+    ret->callback = callback;
+
+    return STATUSCLB(ret);
+}
+
+/***********************************************************************
+ *           URLDownloadToFileW (URLMON.@)
+ *
+ * Downloads URL szURL to file szFileName and call lpfnCB callback to
+ * report progress.
+ *
+ * PARAMS
+ *  pCaller    [I] controlling IUnknown interface.
+ *  szURL      [I] URL of the file to download
+ *  szFileName [I] file name to store the content of the URL
+ *  dwReserved [I] reserved - set to 0
+ *  lpfnCB     [I] callback for progress report
+ *
+ * RETURNS
+ *  S_OK on success
+ */
+HRESULT WINAPI URLDownloadToFileW(LPUNKNOWN pCaller, LPCWSTR szURL, LPCWSTR szFileName,
+        DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB)
+{
+    IBindStatusCallback *callback;
+    IUnknown *unk;
+    IMoniker *mon;
+    IBindCtx *bindctx;
+    HRESULT hres;
+
+    TRACE("(%p %s %s %d %p)\n", pCaller, debugstr_w(szURL),
debugstr_w(szFileName), dwReserved, lpfnCB);
+
+    if(pCaller)
+        FIXME("pCaller not supported\n");
+
+    callback = DownloadBSC_Create(lpfnCB, szFileName);
+    hres = CreateAsyncBindCtx(0, callback, NULL, &bindctx);
+    IBindStatusCallback_Release(callback);
+    if(FAILED(hres))
+        return hres;
+
+    hres = CreateURLMoniker(NULL, szURL, &mon);
+    if(FAILED(hres)) {
+        IBindCtx_Release(bindctx);
+        return hres;
+    }
+
+    hres = IMoniker_BindToStorage(mon, bindctx, NULL, &IID_IUnknown,
(void**)&unk);
+    IMoniker_Release(mon);
+    IBindCtx_Release(bindctx);
+
+    if(unk)
+        IUnknown_Release(unk);
+
+    return hres == MK_S_ASYNCHRONOUS ? S_OK : hres;
+}
+
+/***********************************************************************
+ *           URLDownloadToFileA (URLMON.@)
+ *
+ * Downloads URL szURL to rile szFileName and call lpfnCB callback to
+ * report progress.
+ *
+ * PARAMS
+ *  pCaller    [I] controlling IUnknown interface.
+ *  szURL      [I] URL of the file to download
+ *  szFileName [I] file name to store the content of the URL
+ *  dwReserved [I] reserved - set to 0
+ *  lpfnCB     [I] callback for progress report
+ *
+ * RETURNS
+ *  S_OK on success
+ */
+HRESULT WINAPI URLDownloadToFileA(LPUNKNOWN pCaller, LPCSTR szURL, LPCSTR szFileName,
DWORD dwReserved,
+        LPBINDSTATUSCALLBACK lpfnCB)
+{
+    LPWSTR urlW, file_nameW;
+    HRESULT hres;
+
+    TRACE("(%p %s %s %d %p)\n", pCaller, debugstr_a(szURL),
debugstr_a(szFileName), dwReserved, lpfnCB);
+
+    urlW = heap_strdupAtoW(szURL);
+    file_nameW = heap_strdupAtoW(szFileName);
+
+    hres = URLDownloadToFileW(pCaller, urlW, file_nameW, dwReserved, lpfnCB);
+
+    heap_free(urlW);
+    heap_free(file_nameW);
+
+    return hres;
+}
Propchange: trunk/reactos/dll/win32/urlmon/download.c
------------------------------------------------------------------------------
    svn:eol-style = native
Modified: trunk/reactos/dll/win32/urlmon/file.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/file.c?re…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/file.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/file.c [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -229,10 +229,14 @@
     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
+    if (pcbRead)
+        *pcbRead = 0;
+
     if(!This->file)
         return INET_E_DATA_NOT_AVAILABLE;
-    ReadFile(This->file, pv, cb, &read, NULL);
+    if (!ReadFile(This->file, pv, cb, &read, NULL))
+        return INET_E_DOWNLOAD_FAILURE;
     if(pcbRead)
         *pcbRead = read;
Modified: trunk/reactos/dll/win32/urlmon/http.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/http.c?re…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/http.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/http.c [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -380,7 +380,7 @@
             if (!(user_agent = CoTaskMemAlloc((len)*sizeof(WCHAR))))
                 WARN("Out of memory\n");
             else
-                MultiByteToWideChar(CP_ACP, 0, user_agenta, -1, user_agent,
len*sizeof(WCHAR));
+                MultiByteToWideChar(CP_ACP, 0, user_agenta, -1, user_agent, len);
         }
         heap_free(user_agenta);
     }
@@ -419,6 +419,8 @@
     if (This->grfBINDF & BINDF_NOWRITECACHE)
         request_flags |= INTERNET_FLAG_NO_CACHE_WRITE;
+    if (This->grfBINDF & BINDF_NEEDFILE)
+        request_flags |= INTERNET_FLAG_NEED_FILE;
     This->request = HttpOpenRequestW(This->connect, This->bind_info.dwBindVerb
< BINDVERB_CUSTOM ?
                                      wszBindVerb[This->bind_info.dwBindVerb] :
                                      This->bind_info.szCustomVerb,
@@ -655,6 +657,21 @@
         {
             This->content_length = atoiW(content_length);
         }
+
+    if(This->grfBINDF & BINDF_NEEDFILE) {
+        WCHAR cache_file[MAX_PATH];
+        DWORD buflen = sizeof(cache_file);
+
+        if(InternetQueryOptionW(This->request, INTERNET_OPTION_DATAFILE_NAME,
+                                cache_file, &buflen))
+        {
+            IInternetProtocolSink_ReportProgress(This->protocol_sink,
+                                                 BINDSTATUS_CACHEFILENAMEAVAILABLE,
+                                                 cache_file);
+        }else {
+            FIXME("Could not get cache file\n");
+        }
+    }
         This->flags |= FLAG_FIRST_CONTINUE_COMPLETE;
     }
Modified: trunk/reactos/dll/win32/urlmon/mk.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/mk.c?rev=…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/mk.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/mk.c [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -124,7 +124,6 @@
     ReleaseBindInfo(&bindinfo);
-    IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DIRECTBIND, NULL);
     IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, NULL);
     hres = FindMimeFromData(NULL, szUrl, NULL, 0, NULL, 0, &mime, 0);
Modified: trunk/reactos/dll/win32/urlmon/regsvr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/regsvr.c?…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/regsvr.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/regsvr.c [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -522,7 +522,7 @@
 {
     HRESULT hres;
     HMODULE hAdvpack;
-    typeof(RegInstallA) *pRegInstall;
+    HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA*
pstTable);
     STRTABLEA strtable;
     STRENTRYA pse[7];
     static CLSID const *clsids[34];
@@ -550,7 +550,7 @@
     strtable.pse = pse;
     hAdvpack = LoadLibraryW(wszAdvpack);
-    pRegInstall = (typeof(RegInstallA)*)GetProcAddress(hAdvpack, "RegInstall");
+    pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
     hres = pRegInstall(URLMON_hInstance, doregister ? "RegisterDll" :
"UnregisterDll", &strtable);
Modified: trunk/reactos/dll/win32/urlmon/sec_mgr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/sec_mgr.c…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/sec_mgr.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/sec_mgr.c [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -23,65 +23,27 @@
 #include "urlmon_main.h"
 #include "winreg.h"
+#include "wininet.h"
 #include "wine/debug.h"
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
-/***********************************************************************
- *           InternetSecurityManager implementation
- *
- */
-typedef struct {
-    const IInternetSecurityManagerVtbl* lpInternetSecurityManagerVtbl;
-
-    LONG ref;
-
-    IInternetSecurityMgrSite *mgrsite;
-    IInternetSecurityManager *custom_manager;
-} SecManagerImpl;
-
-#define SECMGR_THIS(iface) DEFINE_THIS(SecManagerImpl, InternetSecurityManager, iface)
-
-static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone)
-{
-    WCHAR schema[64];
-    DWORD res, size=0;
+static const WCHAR fileW[] = {'f','i','l','e',0};
+
+static HRESULT get_zone_from_reg(LPCWSTR schema, DWORD *zone)
+{
+    DWORD res, size;
     HKEY hkey;
-    HRESULT hres;
     static const WCHAR wszZoneMapProtocolKey[] =
{'S','o','f','t','w','a','r','e','\\',
-
'M','i','c','r','o','s','o','f','t','\\',
-
'W','i','n','d','o','w','s','\\',
-
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
-
'I','n','t','e','r','n','e','t','
','S','e','t','t','i','n','g','s','\\',
-
'Z','o','n','e','M','a','p','\\',
-
'P','r','o','t','o','c','o','l','D','e','f','a','u','l','t','s',0};
-    static const WCHAR wszFile[] = {'f','i','l','e',0};
-
-    *zone = -1;
-
-    hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(WCHAR),
&size, 0);
-    if(FAILED(hres))
-        return hres;
-    if(!*schema)
-        return 0x80041001;
-
-    /* file protocol is a special case */
-    if(!strcmpW(schema, wszFile)) {
-        WCHAR path[MAX_PATH];
-
-        hres = CoInternetParseUrl(url, PARSE_PATH_FROM_URL, 0, path,
-                sizeof(path)/sizeof(WCHAR), &size, 0);
-
-        if(SUCCEEDED(hres) && strchrW(path, '\\')) {
-            *zone = 0;
-            return S_OK;
-        }
-    }
-
-    WARN("domains are not yet implemented\n");
+
'M','i','c','r','o','s','o','f','t','\\',
+
'W','i','n','d','o','w','s','\\',
+
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+
'I','n','t','e','r','n','e','t','
','S','e','t','t','i','n','g','s','\\',
+
'Z','o','n','e','M','a','p','\\',
+
'P','r','o','t','o','c','o','l','D','e','f','a','u','l','t','s',0};
     res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapProtocolKey, &hkey);
     if(res != ERROR_SUCCESS) {
@@ -110,6 +72,171 @@
     *zone = 3;
     return S_OK;
 }
+
+static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
+{
+    LPWSTR secur_url;
+    WCHAR schema[64];
+    DWORD size=0;
+    HRESULT hres;
+
+    secur_url = heap_alloc(INTERNET_MAX_URL_LENGTH*sizeof(WCHAR));
+    *zone = -1;
+
+    hres = CoInternetParseUrl(url, PARSE_SECURITY_URL, 0, secur_url,
INTERNET_MAX_URL_LENGTH, &size, 0);
+    if(hres != S_OK)
+        strcpyW(secur_url, url);
+
+    hres = CoInternetParseUrl(secur_url, PARSE_SCHEMA, 0, schema,
sizeof(schema)/sizeof(WCHAR), &size, 0);
+    if(FAILED(hres) || !*schema) {
+        heap_free(secur_url);
+        return E_INVALIDARG;
+    }
+
+    /* file protocol is a special case */
+    if(!strcmpW(schema, fileW)) {
+        WCHAR path[MAX_PATH], root[20];
+        WCHAR *ptr;
+
+        hres = CoInternetParseUrl(secur_url, PARSE_PATH_FROM_URL, 0, path,
+                sizeof(path)/sizeof(WCHAR), &size, 0);
+
+        if(SUCCEEDED(hres) && (ptr = strchrW(path, '\\')) &&
ptr-path < sizeof(root)/sizeof(WCHAR)) {
+            UINT type;
+
+            memcpy(root, path, (ptr-path)*sizeof(WCHAR));
+            root[ptr-path] = 0;
+
+            type = GetDriveTypeW(root);
+
+            switch(type) {
+            case DRIVE_UNKNOWN:
+            case DRIVE_NO_ROOT_DIR:
+                break;
+            case DRIVE_REMOVABLE:
+            case DRIVE_FIXED:
+            case DRIVE_CDROM:
+            case DRIVE_RAMDISK:
+                *zone = 0;
+                hres = S_OK;
+                break;
+            case DRIVE_REMOTE:
+                *zone = 3;
+                hres = S_OK;
+                break;
+            default:
+                FIXME("unsupported drive type %d\n", type);
+            }
+        }
+    }
+
+    if(*zone == -1) {
+        WARN("domains are not yet implemented\n");
+        hres = get_zone_from_reg(schema, zone);
+    }
+
+    if(FAILED(hres) || !ret_url)
+        heap_free(secur_url);
+    else
+        *ret_url = secur_url;
+
+    return hres;
+}
+
+static HRESULT open_zone_key(HKEY parent_key, DWORD zone, HKEY *hkey)
+{
+    static const WCHAR wszZonesKey[] =
+
{'S','o','f','t','w','a','r','e','\\',
+
'M','i','c','r','o','s','o','f','t','\\',
+
'W','i','n','d','o','w','s','\\',
+
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+
'I','n','t','e','r','n','e','t','
','S','e','t','t','i','n','g','s','\\',
+         'Z','o','n','e','s','\\',0};
+    static const WCHAR wszFormat[] =
{'%','s','%','l','d',0};
+
+    WCHAR key_name[sizeof(wszZonesKey)/sizeof(WCHAR)+8];
+    DWORD res;
+
+    wsprintfW(key_name, wszFormat, wszZonesKey, zone);
+
+    res = RegOpenKeyW(parent_key, key_name, hkey);
+
+    if(res != ERROR_SUCCESS) {
+        WARN("RegOpenKey failed\n");
+        return E_INVALIDARG;
+    }
+
+    return S_OK;
+}
+
+static HRESULT get_action_policy(DWORD zone, DWORD action, BYTE *policy, DWORD size,
URLZONEREG zone_reg)
+{
+    HKEY parent_key;
+    HKEY hkey;
+    LONG res;
+    HRESULT hres;
+
+    switch(action) {
+    case URLACTION_SCRIPT_OVERRIDE_SAFETY:
+        *(DWORD*)policy = URLPOLICY_DISALLOW;
+        return S_OK;
+    }
+
+    switch(zone_reg) {
+    case URLZONEREG_DEFAULT:
+    case URLZONEREG_HKCU:
+        parent_key = HKEY_CURRENT_USER;
+        break;
+    case URLZONEREG_HKLM:
+        parent_key = HKEY_LOCAL_MACHINE;
+        break;
+    default:
+        WARN("Unknown URLZONEREG: %d\n", zone_reg);
+        return E_FAIL;
+    };
+
+    hres = open_zone_key(parent_key, zone, &hkey);
+    if(SUCCEEDED(hres)) {
+        WCHAR action_str[16];
+        DWORD len = size;
+
+        static const WCHAR formatW[] = {'%','X',0};
+
+        wsprintfW(action_str, formatW, action);
+
+        res = RegQueryValueExW(hkey, action_str, NULL, NULL, policy, &len);
+        if(res == ERROR_MORE_DATA) {
+            hres = E_INVALIDARG;
+        }else if(res == ERROR_FILE_NOT_FOUND) {
+            hres = E_FAIL;
+        }else if(res != ERROR_SUCCESS) {
+            ERR("RegQueryValue failed: %d\n", res);
+            hres = E_UNEXPECTED;
+        }
+
+        RegCloseKey(hkey);
+    }
+
+    if(FAILED(hres) && zone_reg == URLZONEREG_DEFAULT)
+        return get_action_policy(zone, action, policy, size, URLZONEREG_HKLM);
+
+    return hres;
+}
+
+/***********************************************************************
+ *           InternetSecurityManager implementation
+ *
+ */
+typedef struct {
+    const IInternetSecurityManagerVtbl* lpInternetSecurityManagerVtbl;
+
+    LONG ref;
+
+    IInternetSecurityMgrSite *mgrsite;
+    IInternetSecurityManager *custom_manager;
+} SecManagerImpl;
+
+#define SECMGR_THIS(iface) DEFINE_THIS(SecManagerImpl, InternetSecurityManager, iface)
 static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManager*
iface,REFIID riid,void** ppvObject)
 {
@@ -230,8 +357,6 @@
                                                   DWORD dwFlags)
 {
     SecManagerImpl *This = SECMGR_THIS(iface);
-    LPWSTR url;
-    DWORD size;
     HRESULT hres;
     TRACE("(%p)->(%s %p %08x)\n", iface, debugstr_w(pwszUrl), pdwZone,
dwFlags);
@@ -251,26 +376,15 @@
     if(dwFlags)
         FIXME("not supported flags: %08x\n", dwFlags);
-    size = (strlenW(pwszUrl)+16) * sizeof(WCHAR);
-    url = heap_alloc(size);
-
-    hres = CoInternetParseUrl(pwszUrl, PARSE_SECURITY_URL, 0, url, size/sizeof(WCHAR),
&size, 0);
-    if(FAILED(hres))
-        memcpy(url, pwszUrl, size);
-
-    hres = map_url_to_zone(url, pdwZone);
-
-    heap_free(url);
-
-    return hres;
+    return map_url_to_zone(pwszUrl, pdwZone, NULL);
 }
 static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *iface,
         LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
 {
     SecManagerImpl *This = SECMGR_THIS(iface);
-    LPWSTR buf, ptr, ptr2;
-    DWORD size, zone, len;
+    LPWSTR url, ptr, ptr2;
+    DWORD zone, len;
     HRESULT hres;
     static const WCHAR wszFile[] =
{'f','i','l','e',':'};
@@ -291,26 +405,17 @@
     if(dwReserved)
         FIXME("dwReserved is not supported\n");
-    len = strlenW(pwszUrl)+1;
-    buf = heap_alloc((len+16)*sizeof(WCHAR));
-
-    hres = CoInternetParseUrl(pwszUrl, PARSE_SECURITY_URL, 0, buf, len, &size, 0);
+    hres = map_url_to_zone(pwszUrl, &zone, &url);
     if(FAILED(hres))
-        memcpy(buf, pwszUrl, len*sizeof(WCHAR));
-
-    hres = map_url_to_zone(buf, &zone);
-    if(FAILED(hres)) {
-        heap_free(buf);
         return hres == 0x80041001 ? E_INVALIDARG : hres;
-    }
     /* file protocol is a special case */
-    if(strlenW(pwszUrl) >= sizeof(wszFile)/sizeof(WCHAR)
-            && !memcmp(buf, wszFile, sizeof(wszFile))) {
+    if(strlenW(url) >= sizeof(wszFile)/sizeof(WCHAR)
+            && !memcmp(url, wszFile, sizeof(wszFile)) && strchrW(url,
'\\')) {
         static const BYTE secidFile[] =
{'f','i','l','e',':'};
-        heap_free(buf);
+        heap_free(url);
         if(*pcbSecurityId < sizeof(secidFile)+sizeof(zone))
             return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
@@ -322,7 +427,7 @@
         return S_OK;
     }
-    ptr = strchrW(buf, ':');
+    ptr = strchrW(url, ':');
     ptr2 = ++ptr;
     while(*ptr2 == '/')
         ptr2++;
@@ -333,15 +438,15 @@
     if(ptr)
         *ptr = 0;
-    len = WideCharToMultiByte(CP_ACP, 0, buf, -1, NULL, 0, NULL, NULL)-1;
+    len = WideCharToMultiByte(CP_ACP, 0, url, -1, NULL, 0, NULL, NULL)-1;
     if(len+sizeof(DWORD) > *pcbSecurityId) {
-        heap_free(buf);
+        heap_free(url);
         return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
     }
-    WideCharToMultiByte(CP_ACP, 0, buf, -1, (LPSTR)pbSecurityId, -1, NULL, NULL);
-    heap_free(buf);
+    WideCharToMultiByte(CP_ACP, 0, url, -1, (LPSTR)pbSecurityId, len, NULL, NULL);
+    heap_free(url);
     *(DWORD*)(pbSecurityId+len) = zone;
@@ -358,6 +463,7 @@
                                                       DWORD dwFlags, DWORD dwReserved)
 {
     SecManagerImpl *This = SECMGR_THIS(iface);
+    DWORD zone, policy;
     HRESULT hres;
     TRACE("(%p)->(%s %08x %p %08x %p %08x %08x %08x)\n", iface,
debugstr_w(pwszUrl), dwAction,
@@ -370,8 +476,36 @@
             return hres;
     }
-    FIXME("Default action is not implemented\n");
-    return E_NOTIMPL;
+    if(pContext || cbContext || dwFlags || dwReserved)
+        FIXME("Unsupported arguments\n");
+
+    if(!pwszUrl)
+        return E_INVALIDARG;
+
+    hres = map_url_to_zone(pwszUrl, &zone, NULL);
+    if(FAILED(hres))
+        return hres;
+
+    hres = get_action_policy(zone, dwAction, (BYTE*)&policy, sizeof(policy),
URLZONEREG_DEFAULT);
+    if(FAILED(hres))
+        return hres;
+
+    TRACE("policy %x\n", policy);
+
+    switch(GetUrlPolicyPermissions(policy)) {
+    case URLPOLICY_ALLOW:
+    case URLPOLICY_CHANNEL_SOFTDIST_PRECACHE:
+        return S_OK;
+    case URLPOLICY_DISALLOW:
+        return S_FALSE;
+    case URLPOLICY_QUERY:
+        FIXME("URLPOLICY_QUERY not implemented\n");
+        return E_FAIL;
+    default:
+        FIXME("Not implemented policy %x\n", policy);
+    }
+
+    return E_FAIL;
 }
@@ -481,46 +615,6 @@
     LONG ref;
 } ZoneMgrImpl;
-static HRESULT open_zone_key(DWORD zone, HKEY *hkey, URLZONEREG zone_reg)
-{
-    static const WCHAR wszZonesKey[] =
-
{'S','o','f','t','w','a','r','e','\\',
-
'M','i','c','r','o','s','o','f','t','\\',
-
'W','i','n','d','o','w','s','\\',
-
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
-
'I','n','t','e','r','n','e','t','
','S','e','t','t','i','n','g','s','\\',
-            'Z','o','n','e','s','\\',0};
-    static const WCHAR wszFormat[] =
{'%','s','%','l','d',0};
-
-    WCHAR key_name[sizeof(wszZonesKey)/sizeof(WCHAR)+8];
-    HKEY parent_key;
-    DWORD res;
-
-    switch(zone_reg) {
-    case URLZONEREG_DEFAULT: /* FIXME: TEST */
-    case URLZONEREG_HKCU:
-        parent_key = HKEY_CURRENT_USER;
-        break;
-    case URLZONEREG_HKLM:
-        parent_key = HKEY_LOCAL_MACHINE;
-        break;
-    default:
-        WARN("Unknown URLZONEREG: %d\n", zone_reg);
-        return E_FAIL;
-    };
-
-    wsprintfW(key_name, wszFormat, wszZonesKey, zone);
-
-    res = RegOpenKeyW(parent_key, key_name, hkey);
-
-    if(res != ERROR_SUCCESS) {
-        WARN("RegOpenKey failed\n");
-        return E_INVALIDARG;
-    }
-
-    return S_OK;
-}
-
 /********************************************************************
  *      IInternetZoneManager_QueryInterface
  */
@@ -634,39 +728,13 @@
 static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicy(IInternetZoneManager* iface,
         DWORD dwZone, DWORD dwAction, BYTE* pPolicy, DWORD cbPolicy, URLZONEREG
urlZoneReg)
 {
-    WCHAR action[16];
-    HKEY hkey;
-    LONG res;
-    DWORD size = cbPolicy;
-    HRESULT hres;
-
-    static const WCHAR wszFormat[] = {'%','l','X',0};
-
     TRACE("(%p)->(%d %08x %p %d %d)\n", iface, dwZone, dwAction, pPolicy,
             cbPolicy, urlZoneReg);
     if(!pPolicy)
         return E_INVALIDARG;
-    hres = open_zone_key(dwZone, &hkey, urlZoneReg);
-    if(FAILED(hres))
-        return hres;
-
-    wsprintfW(action, wszFormat, dwAction);
-
-    res = RegQueryValueExW(hkey, action, NULL, NULL, pPolicy, &size);
-    if(res == ERROR_MORE_DATA) {
-        hres = E_INVALIDARG;
-    }else if(res == ERROR_FILE_NOT_FOUND) {
-        hres = E_FAIL;
-    }else if(res != ERROR_SUCCESS) {
-        ERR("RegQueryValue failed: %d\n", res);
-        hres = E_UNEXPECTED;
-    }
-
-    RegCloseKey(hkey);
-
-    return hres;
+    return get_action_policy(dwZone, dwAction, pPolicy, cbPolicy, urlZoneReg);
 }
 /********************************************************************
Modified: trunk/reactos/dll/win32/urlmon/session.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/session.c…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/session.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/session.c [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -27,6 +27,7 @@
     LPWSTR protocol;
     IClassFactory *cf;
     CLSID clsid;
+    BOOL urlmon;
     struct name_space *next;
 } name_space;
@@ -41,6 +42,15 @@
 static name_space *name_space_list = NULL;
 static mime_filter *mime_filter_list = NULL;
+
+static CRITICAL_SECTION session_cs;
+static CRITICAL_SECTION_DEBUG session_cs_dbg =
+{
+    0, 0, &session_cs,
+    { &session_cs_dbg.ProcessLocksList, &session_cs_dbg.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": session") }
+};
+static CRITICAL_SECTION session_cs = { &session_cs_dbg, -1, 0, 0, 0, 0 };
 static name_space *find_name_space(LPCWSTR protocol)
 {
@@ -95,7 +105,87 @@
     if(pclsid)
         *pclsid = clsid;
+    if(!ret)
+        return S_OK;
+
     return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,
&IID_IClassFactory, (void**)ret);
+}
+
+static HRESULT register_namespace(IClassFactory *cf, REFIID clsid, LPCWSTR protocol, BOOL
urlmon_protocol)
+{
+    name_space *new_name_space;
+
+    new_name_space = heap_alloc(sizeof(name_space));
+
+    if(!urlmon_protocol)
+        IClassFactory_AddRef(cf);
+    new_name_space->cf = cf;
+    new_name_space->clsid = *clsid;
+    new_name_space->urlmon = urlmon_protocol;
+    new_name_space->protocol = heap_strdupW(protocol);
+
+    EnterCriticalSection(&session_cs);
+
+    new_name_space->next = name_space_list;
+    name_space_list = new_name_space;
+
+    LeaveCriticalSection(&session_cs);
+
+    return S_OK;
+}
+
+static HRESULT unregister_namespace(IClassFactory *cf, LPCWSTR protocol)
+{
+    name_space *iter, *last = NULL;
+
+    EnterCriticalSection(&session_cs);
+
+    for(iter = name_space_list; iter; iter = iter->next) {
+        if(iter->cf == cf && !strcmpW(iter->protocol, protocol))
+            break;
+        last = iter;
+    }
+
+    if(iter) {
+        if(last)
+            last->next = iter->next;
+        else
+            name_space_list = iter->next;
+    }
+
+    LeaveCriticalSection(&session_cs);
+
+    if(iter) {
+        if(!iter->urlmon)
+            IClassFactory_Release(iter->cf);
+        heap_free(iter->protocol);
+        heap_free(iter);
+    }
+
+    return S_OK;
+}
+
+
+void register_urlmon_namespace(IClassFactory *cf, REFIID clsid, LPCWSTR protocol, BOOL
do_register)
+{
+    if(do_register)
+        register_namespace(cf, clsid, protocol, TRUE);
+    else
+        unregister_namespace(cf, protocol);
+}
+
+BOOL is_registered_protocol(LPCWSTR url)
+{
+    DWORD schema_len;
+    WCHAR schema[64];
+    HRESULT hres;
+
+    hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, schema,
sizeof(schema)/sizeof(schema[0]),
+            &schema_len, 0);
+    if(FAILED(hres))
+        return FALSE;
+
+    return get_protocol_cf(schema, schema_len, NULL, NULL) == S_OK;
 }
 IInternetProtocolInfo *get_protocol_info(LPCWSTR url)
@@ -112,16 +202,19 @@
     if(FAILED(hres) || !schema_len)
         return NULL;
+    EnterCriticalSection(&session_cs);
+
     ns = find_name_space(schema);
-    if(ns) {
+    if(ns && !ns->urlmon) {
         hres = IClassFactory_QueryInterface(ns->cf, &IID_IInternetProtocolInfo,
(void**)&ret);
-        if(SUCCEEDED(hres))
-            return ret;
-
-        hres = IClassFactory_CreateInstance(ns->cf, NULL,
&IID_IInternetProtocolInfo, (void**)&ret);
-        if(SUCCEEDED(hres))
-            return ret;
-    }
+        if(FAILED(hres))
+            hres = IClassFactory_CreateInstance(ns->cf, NULL,
&IID_IInternetProtocolInfo, (void**)&ret);
+    }
+
+    LeaveCriticalSection(&session_cs);
+
+    if(ns && SUCCEEDED(hres))
+        return ret;
     hres = get_protocol_cf(schema, schema_len, NULL, &cf);
     if(FAILED(hres))
@@ -142,10 +235,14 @@
     DWORD schema_len;
     HRESULT hres;
+    *ret = NULL;
+
     hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, schema,
sizeof(schema)/sizeof(schema[0]),
             &schema_len, 0);
     if(FAILED(hres) || !schema_len)
         return schema_len ? hres : E_FAIL;
+
+    EnterCriticalSection(&session_cs);
     ns = find_name_space(schema);
     if(ns) {
@@ -153,8 +250,12 @@
         IClassFactory_AddRef(*ret);
         if(clsid)
             *clsid = ns->clsid;
+    }
+
+    LeaveCriticalSection(&session_cs);
+
+    if(*ret)
         return S_OK;
-    }
     return get_protocol_cf(schema, schema_len, clsid, ret);
 }
@@ -192,8 +293,6 @@
         IClassFactory *pCF, REFCLSID rclsid, LPCWSTR pwzProtocol, ULONG cPatterns,
         const LPCWSTR *ppwzPatterns, DWORD dwReserved)
 {
-    name_space *new_name_space;
-
     TRACE("(%p %s %s %d %p %d)\n", pCF, debugstr_guid(rclsid),
debugstr_w(pwzProtocol),
           cPatterns, ppwzPatterns, dwReserved);
@@ -205,47 +304,18 @@
     if(!pCF || !pwzProtocol)
         return E_INVALIDARG;
-    new_name_space = heap_alloc(sizeof(name_space));
-
-    IClassFactory_AddRef(pCF);
-    new_name_space->cf = pCF;
-    new_name_space->clsid = *rclsid;
-    new_name_space->protocol = heap_strdupW(pwzProtocol);
-
-    new_name_space->next = name_space_list;
-    name_space_list = new_name_space;
-    return S_OK;
+    return register_namespace(pCF, rclsid, pwzProtocol, FALSE);
 }
 static HRESULT WINAPI InternetSession_UnregisterNameSpace(IInternetSession *iface,
         IClassFactory *pCF, LPCWSTR pszProtocol)
 {
-    name_space *iter, *last = NULL;
-
     TRACE("(%p %s)\n", pCF, debugstr_w(pszProtocol));
     if(!pCF || !pszProtocol)
         return E_INVALIDARG;
-    for(iter = name_space_list; iter; iter = iter->next) {
-        if(iter->cf == pCF && !strcmpW(iter->protocol, pszProtocol))
-            break;
-        last = iter;
-    }
-
-    if(!iter)
-        return S_OK;
-
-    if(last)
-        last->next = iter->next;
-    else
-        name_space_list = iter->next;
-
-    IClassFactory_Release(iter->cf);
-    heap_free(iter->protocol);
-    heap_free(iter);
-
-    return S_OK;
+    return unregister_namespace(pCF, pszProtocol);
 }
 static HRESULT WINAPI InternetSession_RegisterMimeFilter(IInternetSession *iface,
@@ -262,9 +332,13 @@
     filter->clsid = *rclsid;
     filter->mime = heap_strdupW(pwzType);
+    EnterCriticalSection(&session_cs);
+
     filter->next = mime_filter_list;
     mime_filter_list = filter;
+    LeaveCriticalSection(&session_cs);
+
     return S_OK;
 }
@@ -274,6 +348,8 @@
     mime_filter *iter, *prev = NULL;
     TRACE("(%p %s)\n", pCF, debugstr_w(pwzType));
+
+    EnterCriticalSection(&session_cs);
     for(iter = mime_filter_list; iter; iter = iter->next) {
         if(iter->cf == pCF && !strcmpW(iter->mime, pwzType))
@@ -281,17 +357,20 @@
         prev = iter;
     }
-    if(!iter)
-        return S_OK;
-
-    if(prev)
-        prev->next = iter->next;
-    else
-        mime_filter_list = iter->next;
-
-    IClassFactory_Release(iter->cf);
-    heap_free(iter->mime);
-    heap_free(iter);
+    if(iter) {
+        if(prev)
+            prev->next = iter->next;
+        else
+            mime_filter_list = iter->next;
+    }
+
+    LeaveCriticalSection(&session_cs);
+
+    if(iter) {
+        IClassFactory_Release(iter->cf);
+        heap_free(iter->mime);
+        heap_free(iter);
+    }
     return S_OK;
 }
Modified: trunk/reactos/dll/win32/urlmon/umon.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/umon.c?re…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/umon.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/umon.c [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -493,10 +493,7 @@
 /******************************************************************************
  *        URLMoniker_BindToStorage
  ******************************************************************************/
-static HRESULT URLMonikerImpl_BindToStorage_hack(LPCWSTR URLName,
-                                                  IBindCtx* pbc,
-                                                  REFIID riid,
-                                                  VOID** ppvObject)
+static HRESULT URLMonikerImpl_BindToStorage_hack(LPCWSTR URLName, IBindCtx* pbc, VOID**
ppvObject)
 {
     HRESULT hres;
     BINDINFO bi;
@@ -505,12 +502,7 @@
     Binding *bind;
     int len;
-    WARN("(%s %p %s %p)\n", debugstr_w(URLName), pbc, debugstr_guid(riid),
ppvObject);
-
-    if(!IsEqualIID(&IID_IStream, riid)) {
-       FIXME("unsupported iid\n");
-       return E_NOTIMPL;
-    }
+    WARN("(%s %p %p)\n", debugstr_w(URLName), pbc, ppvObject);
     bind = heap_alloc_zero(sizeof(Binding));
     bind->lpVtbl = &BindingVtbl;
@@ -741,10 +733,11 @@
         return E_FAIL;
     }
-    if(url.nScheme== INTERNET_SCHEME_HTTPS
-       || url.nScheme== INTERNET_SCHEME_FTP
-       || url.nScheme == INTERNET_SCHEME_GOPHER)
-        return URLMonikerImpl_BindToStorage_hack(This->URLName, pbc, riid, ppvObject);
+    if(IsEqualGUID(&IID_IStream, riid) &&
+       (  url.nScheme == INTERNET_SCHEME_HTTPS
+       || url.nScheme == INTERNET_SCHEME_FTP
+       || url.nScheme == INTERNET_SCHEME_GOPHER))
+        return URLMonikerImpl_BindToStorage_hack(This->URLName, pbc, ppvObject);
     TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft,
debugstr_guid(riid), ppvObject);
@@ -1186,218 +1179,25 @@
 }
 /***********************************************************************
- *           URLDownloadToFileA (URLMON.@)
- *
- * Downloads URL szURL to rile szFileName and call lpfnCB callback to
- * report progress.
- *
- * PARAMS
- *  pCaller    [I] controlling IUnknown interface.
- *  szURL      [I] URL of the file to download
- *  szFileName [I] file name to store the content of the URL
- *  dwReserved [I] reserved - set to 0
- *  lpfnCB     [I] callback for progress report
- *
- * RETURNS
- *  S_OK on success
- *  E_OUTOFMEMORY when going out of memory
+ *           MkParseDisplayNameEx (URLMON.@)
  */
-HRESULT WINAPI URLDownloadToFileA(LPUNKNOWN pCaller,
-                                 LPCSTR szURL,
-                                 LPCSTR szFileName,
-                                 DWORD dwReserved,
-                                 LPBINDSTATUSCALLBACK lpfnCB)
-{
-    UNICODE_STRING szURL_w, szFileName_w;
-
-    if ((szURL == NULL) || (szFileName == NULL)) {
-       FIXME("(%p,%s,%s,%08x,%p) cannot accept NULL strings !\n", pCaller,
debugstr_a(szURL), debugstr_a(szFileName), dwReserved, lpfnCB);
-       return E_INVALIDARG; /* The error code is not specified in this case... */
-    }
-
-    if (RtlCreateUnicodeStringFromAsciiz(&szURL_w, szURL)) {
-       if (RtlCreateUnicodeStringFromAsciiz(&szFileName_w, szFileName)) {
-           HRESULT ret = URLDownloadToFileW(pCaller, szURL_w.Buffer, szFileName_w.Buffer,
dwReserved, lpfnCB);
-
-           RtlFreeUnicodeString(&szURL_w);
-           RtlFreeUnicodeString(&szFileName_w);
-
-           return ret;
-       } else {
-           RtlFreeUnicodeString(&szURL_w);
-       }
-    }
-
-    FIXME("(%p,%s,%s,%08x,%p) could not allocate W strings !\n", pCaller,
szURL, szFileName, dwReserved, lpfnCB);
-    return E_OUTOFMEMORY;
-}
-
-/***********************************************************************
- *           URLDownloadToFileW (URLMON.@)
- *
- * Downloads URL szURL to rile szFileName and call lpfnCB callback to
- * report progress.
- *
- * PARAMS
- *  pCaller    [I] controlling IUnknown interface.
- *  szURL      [I] URL of the file to download
- *  szFileName [I] file name to store the content of the URL
- *  dwReserved [I] reserved - set to 0
- *  lpfnCB     [I] callback for progress report
- *
- * RETURNS
- *  S_OK on success
- *  E_OUTOFMEMORY when going out of memory
- */
-HRESULT WINAPI URLDownloadToFileW(LPUNKNOWN pCaller,
-                                 LPCWSTR szURL,
-                                 LPCWSTR szFileName,
-                                 DWORD dwReserved,
-                                 LPBINDSTATUSCALLBACK lpfnCB)
-{
-    HINTERNET hinternet, hcon, hreq;
-    BOOL r;
-    CHAR buffer[0x1000];
-    DWORD sz, total, written;
-    DWORD total_size = 0xFFFFFFFF, arg_size = sizeof(total_size);
-    URL_COMPONENTSW url;
-    WCHAR host[0x80], path[0x100];
-    HANDLE hfile;
-    static const WCHAR
wszAppName[]={'u','r','l','m','o','n','.','d','l','l',0};
-
-    /* Note: all error codes would need to be checked agains real Windows behaviour... */
-    TRACE("(%p,%s,%s,%08x,%p) stub!\n", pCaller, debugstr_w(szURL),
debugstr_w(szFileName), dwReserved, lpfnCB);
-
-    if ((szURL == NULL) || (szFileName == NULL)) {
-       FIXME(" cannot accept NULL strings !\n");
-       return E_INVALIDARG;
-    }
-
-    /* Would be better to use the application name here rather than 'urlmon' :-/
*/
-    hinternet = InternetOpenW(wszAppName, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
-    if (hinternet == NULL) {
-       return E_OUTOFMEMORY;
-    }
-
-    memset(&url, 0, sizeof(url));
-    url.dwStructSize = sizeof(url);
-    url.lpszHostName = host;
-    url.dwHostNameLength = sizeof(host);
-    url.lpszUrlPath = path;
-    url.dwUrlPathLength = sizeof(path);
-
-    if (!InternetCrackUrlW(szURL, 0, 0, &url)) {
-       InternetCloseHandle(hinternet);
-       return E_OUTOFMEMORY;
-    }
-
-    if (lpfnCB) {
-       if (IBindStatusCallback_OnProgress(lpfnCB, 0, 0, BINDSTATUS_CONNECTING,
url.lpszHostName) == E_ABORT) {
-           InternetCloseHandle(hinternet);
-           return S_OK;
-       }
-    }
-
-    hcon = InternetConnectW(hinternet, url.lpszHostName, url.nPort,
-                            url.lpszUserName, url.lpszPassword,
-                            INTERNET_SERVICE_HTTP, 0, 0);
-    if (!hcon) {
-       InternetCloseHandle(hinternet);
-       return E_OUTOFMEMORY;
-    }
-
-    hreq = HttpOpenRequestW(hcon, NULL, url.lpszUrlPath, NULL, NULL, NULL, 0, 0);
-    if (!hreq) {
-       InternetCloseHandle(hinternet);
-       InternetCloseHandle(hcon);
-       return E_OUTOFMEMORY;
-    }
-
-    if (!HttpSendRequestW(hreq, NULL, 0, NULL, 0)) {
-       InternetCloseHandle(hinternet);
-       InternetCloseHandle(hcon);
-       InternetCloseHandle(hreq);
-       return E_OUTOFMEMORY;
-    }
-
-    if (HttpQueryInfoW(hreq, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
-                      &total_size, &arg_size, NULL)) {
-       TRACE(" total size : %d\n", total_size);
-    }
-
-    hfile = CreateFileW(szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
-                        FILE_ATTRIBUTE_NORMAL, NULL );
-    if (hfile == INVALID_HANDLE_VALUE) {
-       return E_ACCESSDENIED;
-    }
-
-    if (lpfnCB) {
-       if (IBindStatusCallback_OnProgress(lpfnCB, 0, total_size != 0xFFFFFFFF ?
total_size : 0,
-                                          BINDSTATUS_BEGINDOWNLOADDATA, szURL) ==
E_ABORT) {
-           InternetCloseHandle(hreq);
-           InternetCloseHandle(hcon);
-           InternetCloseHandle(hinternet);
-           CloseHandle(hfile);
-           return S_OK;
-       }
-    }
-
-    total = 0;
-    while (1) {
-       r = InternetReadFile(hreq, buffer, sizeof(buffer), &sz);
-       if (!r) {
-           InternetCloseHandle(hreq);
-           InternetCloseHandle(hcon);
-           InternetCloseHandle(hinternet);
-
-           CloseHandle(hfile);
-           return E_OUTOFMEMORY;
-       }
-       if (!sz)
-           break;
-
-       total += sz;
-
-       if (lpfnCB) {
-           if (IBindStatusCallback_OnProgress(lpfnCB, total, total_size != 0xFFFFFFFF ?
total_size : 0,
-                                              BINDSTATUS_DOWNLOADINGDATA, szURL) ==
E_ABORT) {
-               InternetCloseHandle(hreq);
-               InternetCloseHandle(hcon);
-               InternetCloseHandle(hinternet);
-               CloseHandle(hfile);
-               return S_OK;
-           }
-       }
-
-       if (!WriteFile(hfile, buffer, sz, &written, NULL)) {
-           InternetCloseHandle(hreq);
-           InternetCloseHandle(hcon);
-           InternetCloseHandle(hinternet);
-
-           CloseHandle(hfile);
-           return E_OUTOFMEMORY;
-       }
-    }
-
-    if (lpfnCB) {
-       if (IBindStatusCallback_OnProgress(lpfnCB, total, total_size != 0xFFFFFFFF ?
total_size : 0,
-                                          BINDSTATUS_ENDDOWNLOADDATA, szURL) == E_ABORT)
{
-           InternetCloseHandle(hreq);
-           InternetCloseHandle(hcon);
-           InternetCloseHandle(hinternet);
-           CloseHandle(hfile);
-           return S_OK;
-       }
-    }
-
-    InternetCloseHandle(hreq);
-    InternetCloseHandle(hcon);
-    InternetCloseHandle(hinternet);
-
-    CloseHandle(hfile);
-
-    return S_OK;
-}
+HRESULT WINAPI MkParseDisplayNameEx(IBindCtx *pbc, LPCWSTR szDisplayName, ULONG
*pchEaten, LPMONIKER *ppmk)
+{
+    TRACE("(%p %s %p %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
+
+    if(is_registered_protocol(szDisplayName)) {
+        HRESULT hres;
+
+        hres = CreateURLMoniker(NULL, szDisplayName, ppmk);
+        if(SUCCEEDED(hres)) {
+            *pchEaten = strlenW(szDisplayName);
+            return hres;
+        }
+    }
+
+    return MkParseDisplayName(pbc, szDisplayName, pchEaten, ppmk);
+}
+
 /***********************************************************************
  *           URLDownloadToCacheFileA (URLMON.@)
Modified: trunk/reactos/dll/win32/urlmon/umstream.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/umstream.…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/umstream.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/umstream.c [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -221,7 +221,7 @@
     if ( !pcbRead)
         pcbRead = &dwBytesRead;
-    if ( ! ReadFile( This->handle, pv, cb, (LPDWORD)pcbRead, NULL ) )
+    if ( ! ReadFile( This->handle, pv, cb, pcbRead, NULL ) )
        return S_FALSE;
     if (!*pcbRead)
Modified: trunk/reactos/dll/win32/urlmon/urlmon.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/urlmon.rb…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/urlmon.rbuild [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/urlmon.rbuild [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -9,18 +9,10 @@
        <define name="__WINESRC__" />
        <define name="WINVER">0x600</define>
        <define name="_WIN32_WINNT">0x600</define>
-       <library>wine</library>
-       <library>ole32</library>
-       <library>shlwapi</library>
-       <library>wininet</library>
-       <library>user32</library>
-       <library>advapi32</library>
-       <library>kernel32</library>
-       <library>ntdll</library>
-       <library>uuid</library>
        <file>bindctx.c</file>
        <file>binding.c</file>
        <file>bindprot.c</file>
+       <file>download.c</file>
        <file>file.c</file>
        <file>format.c</file>
        <file>ftp.c</file>
@@ -35,5 +27,14 @@
        <file>urlmon_main.c</file>
        <file>rsrc.rc</file>
        <file>urlmon.spec</file>
+       <library>wine</library>
+       <library>ole32</library>
+       <library>shlwapi</library>
+       <library>wininet</library>
+       <library>user32</library>
+       <library>advapi32</library>
+       <library>kernel32</library>
+       <library>uuid</library>
+       <library>ntdll</library>
 </module>
 </group>
Modified: trunk/reactos/dll/win32/urlmon/urlmon.spec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/urlmon.sp…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/urlmon.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/urlmon.spec [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -21,7 +21,7 @@
 @ stdcall CoInternetQueryInfo(ptr long long ptr long ptr long)
 @ stub CompareSecurityIds
 @ stub CopyBindInfo
-@ stub CopyStgMedium
+@ stdcall CopyStgMedium(ptr ptr)
 @ stdcall CreateAsyncBindCtx(long ptr ptr ptr)
 @ stdcall CreateAsyncBindCtxEx(ptr long ptr ptr ptr long)
 @ stdcall CreateFormatEnumerator(long ptr ptr)
@@ -53,7 +53,7 @@
 @ stub IsLoggingEnabledA
 @ stub IsLoggingEnabledW
 @ stdcall IsValidURL(ptr wstr long)
-@ stdcall MkParseDisplayNameEx(ptr ptr ptr ptr) ole32.MkParseDisplayName
+@ stdcall MkParseDisplayNameEx(ptr wstr ptr ptr)
 @ stdcall ObtainUserAgentString(long str ptr)
 @ stub PrivateCoInstall
 @ stdcall RegisterBindStatusCallback(ptr ptr ptr long)
Modified: trunk/reactos/dll/win32/urlmon/urlmon_main.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/urlmon_ma…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/urlmon_main.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/urlmon_main.c [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -210,31 +210,14 @@
 static void init_session(BOOL init)
 {
-    IInternetSession *session;
     int i;
-    CoInternetGetSession(0, &session, 0);
-
     for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
-        if(object_creation[i].protocol) {
-            if(init)
-            {
-                IInternetSession_RegisterNameSpace(session, object_creation[i].cf,
-                        object_creation[i].clsid, object_creation[i].protocol, 0, NULL,
0);
-                /* make sure that the AddRef on the class factory doesn't keep us
loaded */
-                URLMON_UnlockModule();
-            }
-            else
-            {
-                /* make sure that the Release on the class factory doesn't unload us
*/
-                URLMON_LockModule();
-                IInternetSession_UnregisterNameSpace(session, object_creation[i].cf,
-                        object_creation[i].protocol);
-            }
-        }
-    }
-
-    IInternetSession_Release(session);
+
+        if(object_creation[i].protocol)
+            register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
+                                      object_creation[i].protocol, init);
+    }
 }
 /*******************************************************************************
@@ -398,12 +381,51 @@
     if(offsetof(BINDINFO, szExtraInfo) < size)
         CoTaskMemFree(pbindinfo->szCustomVerb);
-
     if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
         IUnknown_Release(pbindinfo->pUnk);
     memset(pbindinfo, 0, size);
     pbindinfo->cbSize = size;
+}
+
+/***********************************************************************
+ *           CopyStgMedium (URLMON.@)
+ */
+HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
+{
+    TRACE("(%p %p)\n", src, dst);
+
+    if(!src || !dst)
+        return E_POINTER;
+
+    *dst = *src;
+
+    switch(dst->tymed) {
+    case TYMED_NULL:
+        break;
+    case TYMED_FILE:
+        if(src->u.lpszFileName && !src->pUnkForRelease) {
+            DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
+            dst->u.lpszFileName = CoTaskMemAlloc(size);
+            memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
+        }
+        break;
+    case TYMED_ISTREAM:
+        if(dst->u.pstm)
+            IStream_AddRef(dst->u.pstm);
+        break;
+    case TYMED_ISTORAGE:
+        if(dst->u.pstg)
+            IStorage_AddRef(dst->u.pstg);
+        break;
+    default:
+        FIXME("Unimplemented tymed %d\n", src->tymed);
+    }
+
+    if(dst->pUnkForRelease)
+        IUnknown_AddRef(dst->pUnkForRelease);
+
+    return S_OK;
 }
 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
@@ -430,6 +452,12 @@
     return FALSE;
 }
+static BOOL audio_basic_filter(const BYTE *b, DWORD size)
+{
+    return size > 4
+        && b[0] == '.' && b[1] == 's' && b[2] ==
'n' && b[3] == 'd';
+}
+
 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
 {
     return size > 12
@@ -574,6 +602,7 @@
         static const WCHAR wszTextHtml[] =
{'t','e','x','t','/','h','t','m','l',0};
         static const WCHAR wszTextRichtext[] =
{'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
+        static const WCHAR wszAudioBasic[] =
{'a','u','d','i','o','/','b','a','s','i','c',0};
         static const WCHAR wszAudioWav[] =
{'a','u','d','i','o','/','w','a','v',0};
         static const WCHAR wszImageGif[] =
{'i','m','a','g','e','/','g','i','f',0};
         static const WCHAR wszImagePjpeg[] =
{'i','m','a','g','e','/','p','j','p','e','g',0};
@@ -604,16 +633,25 @@
         } mime_filters[] = {
             {wszTextHtml,       text_html_filter},
             {wszTextRichtext,   text_richtext_filter},
+         /* {wszAudioXAiff,     audio_xaiff_filter}, */
+            {wszAudioBasic,     audio_basic_filter},
             {wszAudioWav,       audio_wav_filter},
             {wszImageGif,       image_gif_filter},
             {wszImagePjpeg,     image_pjpeg_filter},
             {wszImageTiff,      image_tiff_filter},
             {wszImageXPng,      image_xpng_filter},
+         /* {wszImageXBitmap,   image_xbitmap_filter}, */
             {wszImageBmp,       image_bmp_filter},
+         /* {wszImageXJg,       image_xjg_filter}, */
+         /* {wszImageXEmf,      image_xemf_filter}, */
+         /* {wszImageXWmf,      image_xwmf_filter}, */
             {wszVideoAvi,       video_avi_filter},
             {wszVideoMpeg,      video_mpeg_filter},
             {wszAppPostscript,  application_postscript_filter},
+         /* {wszAppBase64,      application_base64_filter}, */
+         /* {wszAppMacbinhex40, application_macbinhex40_filter}, */
             {wszAppPdf,         application_pdf_filter},
+         /* {wszAppXCompressed, application_xcompressed_filter}, */
             {wszAppXZip,        application_xzip_filter},
             {wszAppXGzip,       application_xgzip_filter},
             {wszAppJava,        application_java_filter},
Modified: trunk/reactos/dll/win32/urlmon/urlmon_main.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/urlmon_ma…
==============================================================================
--- trunk/reactos/dll/win32/urlmon/urlmon_main.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/urlmon_main.h [iso-8859-1] Fri Apr  4 09:41:46 2008
@@ -67,6 +67,8 @@
 IInternetProtocolInfo *get_protocol_info(LPCWSTR url);
 HRESULT get_protocol_handler(LPCWSTR url, CLSID *clsid, IClassFactory **ret);
+BOOL is_registered_protocol(LPCWSTR);
+void register_urlmon_namespace(IClassFactory*,REFIID,LPCWSTR,BOOL);
 HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv);
 HRESULT bind_to_object(IMoniker *mon, LPCWSTR url, IBindCtx *pbc, REFIID riid, void
**ppv);
@@ -109,4 +111,17 @@
     return ret;
 }
+static inline LPWSTR heap_strdupAtoW(const char *str)
+{
+    LPWSTR ret = NULL;
+
+    if(str) {
+        DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+        ret = heap_alloc(len*sizeof(WCHAR));
+        MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
+    }
+
+    return ret;
+}
+
 #endif /* __WINE_URLMON_MAIN_H */