Alexandre Julliard <julliard@winehq.org>
authorGé van Geldorp <ge@gse.nl>
Sat, 28 May 2005 21:44:21 +0000 (21:44 +0000)
committerGé van Geldorp <ge@gse.nl>
Sat, 28 May 2005 21:44:21 +0000 (21:44 +0000)
- 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.

svn path=/trunk/; revision=15625

reactos/lib/urlmon/Makefile.in
reactos/lib/urlmon/sec_mgr.c
reactos/lib/urlmon/umon.c
reactos/lib/urlmon/umstream.c [new file with mode: 0644]
reactos/lib/urlmon/urlmon.spec
reactos/lib/urlmon/urlmon.xml
reactos/lib/urlmon/urlmon_main.c
reactos/lib/urlmon/urlmon_main.h

index 95aaaf5..d5aa7c7 100644 (file)
@@ -3,6 +3,7 @@ TOPOBJDIR = ../..
 SRCDIR    = @srcdir@\r
 VPATH     = @srcdir@\r
 MODULE    = urlmon.dll\r
+IMPORTLIB = liburlmon.$(IMPLIBEXT)\r
 IMPORTS   = cabinet ole32 shlwapi wininet user32 advapi32 kernel32 ntdll\r
 EXTRALIBS = -luuid\r
 \r
@@ -10,6 +11,7 @@ C_SRCS = \
        regsvr.c \\r
        sec_mgr.c \\r
        umon.c \\r
+       umstream.c \\r
        urlmon_main.c\r
 \r
 SUBDIRS = tests\r
index 99162c4..ed55773 100644 (file)
@@ -352,6 +352,21 @@ static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicy(IInternetZoneManager* ifac
     return E_NOTIMPL;\r
 }\r
 \r
+/********************************************************************\r
+ *      IInternetZoneManager_PromptAction\r
+ */\r
+static HRESULT WINAPI ZoneMgrImpl_PromptAction(IInternetZoneManager* iface,\r
+                                               DWORD dwAction,\r
+                                               HWND hwndParent,\r
+                                               LPCWSTR pwszUrl,\r
+                                               LPCWSTR pwszText,\r
+                                               DWORD dwPromptFlags)\r
+{\r
+    FIXME("%p %08lx %p %s %s %08lx\n", iface, dwAction, hwndParent,\r
+          debugstr_w(pwszUrl), debugstr_w(pwszText), dwPromptFlags );\r
+    return E_NOTIMPL;\r
+}\r
+\r
 /********************************************************************\r
  *      IInternetZoneManager_LogAction\r
  */\r
@@ -425,12 +440,14 @@ static IInternetZoneManagerVtbl ZoneMgrImplVtbl = {
     ZoneMgrImpl_SetZoneCustomPolicy,\r
     ZoneMgrImpl_GetZoneActionPolicy,\r
     ZoneMgrImpl_SetZoneActionPolicy,\r
+    ZoneMgrImpl_PromptAction,\r
     ZoneMgrImpl_LogAction,\r
     ZoneMgrImpl_CreateZoneEnumerator,\r
     ZoneMgrImpl_GetZoneAt,\r
     ZoneMgrImpl_DestroyZoneEnumerator,\r
     ZoneMgrImpl_CopyTemplatePoliciesToZone,\r
 };\r
+\r
 HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)\r
 {\r
     ZoneMgrImpl* ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ZoneMgrImpl));\r
index 7436ed2..d8d85e3 100644 (file)
@@ -48,19 +48,252 @@ static const WCHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e',
 \r
 /*static BOOL registered_wndclass = FALSE;*/\r
 \r
-/* filemoniker data structure */\r
-typedef struct URLMonikerImpl{\r
+typedef struct {\r
+    IBindingVtbl *lpVtbl;\r
 \r
-    IMonikerVtbl*  lpvtbl1;  /* VTable relative to the IMoniker interface.*/\r
-    IBindingVtbl*  lpvtbl2;  /* VTable to IBinding interface */\r
+    ULONG ref;\r
 \r
-    ULONG ref; /* reference counter for this object */\r
-\r
-    LPOLESTR URLName; /* URL string identified by this URLmoniker */\r
+    LPWSTR URLName;\r
 \r
     HWND hwndCallback;\r
     IBindCtx *pBC;\r
     HINTERNET hinternet, hconnect, hrequest;\r
+    HANDLE hCacheFile;\r
+    IUMCacheStream *pstrCache;\r
+    IBindStatusCallback *pbscb;\r
+    DWORD total_read, expected_size;\r
+} Binding;\r
+\r
+static HRESULT WINAPI Binding_QueryInterface(IBinding* iface, REFIID riid, void **ppvObject)\r
+{\r
+    Binding *This = (Binding*)iface;\r
+\r
+    TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject);\r
+\r
+    if((This == NULL) || (ppvObject == NULL))\r
+       return E_INVALIDARG;\r
+\r
+    if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IBinding, riid)) {\r
+        *ppvObject = iface;\r
+        IBinding_AddRef(iface);\r
+        return S_OK;\r
+    }\r
+\r
+    *ppvObject = NULL;\r
+    return E_NOINTERFACE;\r
+}\r
+\r
+static ULONG WINAPI Binding_AddRef(IBinding* iface)\r
+{\r
+    Binding *This = (Binding*)iface;\r
+    ULONG ref = InterlockedIncrement(&This->ref);\r
+\r
+    TRACE("(%p) ref=%ld\n", This, ref);\r
+\r
+    return ref;\r
+}\r
+\r
+static ULONG WINAPI Binding_Release(IBinding* iface)\r
+{\r
+    Binding *This = (Binding*)iface;\r
+    ULONG ref = InterlockedDecrement(&This->ref);\r
+\r
+    TRACE("(%p) ref=%ld\n",This, ref);\r
+\r
+    if(!ref) {\r
+        HeapFree(GetProcessHeap(), 0, This->URLName);\r
+        if (This->hCacheFile)\r
+            CloseHandle(This->hCacheFile);\r
+        if (This->pstrCache)\r
+        {\r
+            UMCloseCacheFileStream(This->pstrCache);\r
+            IStream_Release((IStream *)This->pstrCache);\r
+        }\r
+        if (This->pbscb)\r
+            IBindStatusCallback_Release(This->pbscb);\r
+\r
+        HeapFree(GetProcessHeap(), 0, This);\r
+\r
+        URLMON_UnlockModule();\r
+    }\r
+\r
+    return ref;\r
+}\r
+\r
+static HRESULT WINAPI Binding_Abort(IBinding* iface)\r
+{\r
+    Binding *This = (Binding*)iface;\r
+\r
+    FIXME("(%p): stub\n", This);\r
+\r
+    return E_NOTIMPL;\r
+}\r
+\r
+static HRESULT WINAPI Binding_GetBindResult(IBinding* iface, CLSID* pclsidProtocol, DWORD* pdwResult, LPOLESTR* pszResult, DWORD* pdwReserved)\r
+{\r
+    Binding *This = (Binding*)iface;\r
+\r
+    FIXME("(%p)->(%p, %p, %p, %p): stub\n", This, pclsidProtocol, pdwResult, pszResult, pdwReserved);\r
+\r
+    return E_NOTIMPL;\r
+}\r
+\r
+static HRESULT WINAPI Binding_GetPriority(IBinding* iface, LONG* pnPriority)\r
+{\r
+    Binding *This = (Binding*)iface;\r
+\r
+    FIXME("(%p)->(%p): stub\n", This, pnPriority);\r
+\r
+    return E_NOTIMPL;\r
+}\r
+\r
+static HRESULT WINAPI Binding_Resume(IBinding* iface)\r
+{\r
+    Binding *This = (Binding*)iface;\r
+\r
+    FIXME("(%p): stub\n", This);\r
+\r
+    return E_NOTIMPL;\r
+}\r
+\r
+static HRESULT WINAPI Binding_SetPriority(IBinding* iface, LONG nPriority)\r
+{\r
+    Binding *This = (Binding*)iface;\r
+\r
+    FIXME("(%p)->(%ld): stub\n", This, nPriority);\r
+\r
+    return E_NOTIMPL;\r
+}\r
+\r
+static HRESULT WINAPI Binding_Suspend(IBinding* iface)\r
+{\r
+    Binding *This = (Binding*)iface;\r
+\r
+    FIXME("(%p): stub\n", This);\r
+\r
+    return E_NOTIMPL;\r
+}\r
+\r
+static void Binding_CloseCacheDownload(Binding *This)\r
+{\r
+    CloseHandle(This->hCacheFile);\r
+    This->hCacheFile = 0;\r
+    UMCloseCacheFileStream(This->pstrCache);\r
+    IStream_Release((IStream *)This->pstrCache);\r
+    This->pstrCache = 0;\r
+}\r
+\r
+static HRESULT Binding_MoreCacheData(Binding *This, char *buf, DWORD dwBytes)\r
+{\r
+    DWORD written;\r
+\r
+    if (WriteFile(This->hCacheFile, buf, dwBytes, &written, NULL) && written == dwBytes)\r
+    {\r
+       HRESULT hr;\r
+\r
+       This->total_read += written;\r
+        hr = IBindStatusCallback_OnProgress(This->pbscb,\r
+                                           This->total_read + written,\r
+                                           This->expected_size,\r
+                                           (This->total_read == written) ?\r
+                                               BINDSTATUS_BEGINDOWNLOADDATA :\r
+                                               BINDSTATUS_DOWNLOADINGDATA,\r
+                                           NULL);\r
+       if (!hr)\r
+       {\r
+           STGMEDIUM stg;\r
+           FORMATETC fmt;\r
+\r
+            fmt.cfFormat = 0;\r
+            fmt.ptd = NULL;\r
+            fmt.dwAspect = 0;\r
+            fmt.lindex = -1;\r
+            fmt.tymed = TYMED_ISTREAM;\r
+\r
+           stg.tymed = TYMED_ISTREAM;\r
+           stg.u.pstm = (IStream *)This->pstrCache;\r
+           stg.pUnkForRelease = NULL;\r
+\r
+            hr = IBindStatusCallback_OnDataAvailable(This->pbscb,\r
+                                                    (This->total_read == written) ?\r
+                                                        BSCF_FIRSTDATANOTIFICATION :\r
+                                                        BSCF_INTERMEDIATEDATANOTIFICATION,\r
+                                                    This->total_read + written,\r
+                                                     &fmt,\r
+                                                    &stg);\r
+       }\r
+       if (written < dwBytes)\r
+           return STG_E_MEDIUMFULL;\r
+       else\r
+           return hr;\r
+    }\r
+    return HRESULT_FROM_WIN32(GetLastError());\r
+}\r
+\r
+static void Binding_FinishedDownload(Binding *This, HRESULT hr)\r
+{\r
+    STGMEDIUM stg;\r
+    FORMATETC fmt;\r
+\r
+    fmt.ptd = NULL;\r
+    fmt.dwAspect = 0;\r
+    fmt.lindex = -1;\r
+    fmt.tymed = TYMED_ISTREAM;\r
+\r
+    stg.tymed = TYMED_ISTREAM;\r
+    stg.u.pstm = (IStream *)This->pstrCache;\r
+    stg.pUnkForRelease = NULL;\r
+\r
+    IBindStatusCallback_OnProgress(This->pbscb, This->total_read, This->expected_size, BINDSTATUS_ENDDOWNLOADDATA, NULL);\r
+    IBindStatusCallback_OnDataAvailable(This->pbscb, BSCF_LASTDATANOTIFICATION, This->total_read, &fmt, &stg);\r
+    if (hr)\r
+    {\r
+       WCHAR *pwchError = 0;\r
+\r
+        FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |\r
+                        FORMAT_MESSAGE_ALLOCATE_BUFFER,\r
+                        NULL, (DWORD) hr,\r
+                       0, (LPWSTR) &pwchError,\r
+                       0, NULL);\r
+       if (!pwchError)\r
+       {\r
+           static WCHAR achFormat[] = { '%', '0', '8', 'x', 0 };\r
+\r
+           pwchError =(WCHAR *) LocalAlloc(LMEM_FIXED, sizeof(WCHAR) * 9);\r
+           wsprintfW(pwchError, achFormat, hr);\r
+       }\r
+        IBindStatusCallback_OnStopBinding(This->pbscb, hr, pwchError);\r
+       LocalFree(pwchError);\r
+    }\r
+    else\r
+    {\r
+        IBindStatusCallback_OnStopBinding(This->pbscb, hr, NULL);\r
+    }\r
+    IBindStatusCallback_Release(This->pbscb);\r
+    This->pbscb = 0;\r
+}\r
+\r
+static IBindingVtbl BindingVtbl =\r
+{\r
+    Binding_QueryInterface,\r
+    Binding_AddRef,\r
+    Binding_Release,\r
+    Binding_Abort,\r
+    Binding_Suspend,\r
+    Binding_Resume,\r
+    Binding_SetPriority,\r
+    Binding_GetPriority,\r
+    Binding_GetBindResult\r
+};\r
+\r
+/* filemoniker data structure */\r
+typedef struct {\r
+\r
+    IMonikerVtbl*  lpvtbl;  /* VTable relative to the IMoniker interface.*/\r
+\r
+    ULONG ref; /* reference counter for this object */\r
+\r
+    LPOLESTR URLName; /* URL string identified by this URLmoniker */\r
 } URLMonikerImpl;\r
 \r
 /*******************************************************************************\r
@@ -133,6 +366,7 @@ static ULONG WINAPI URLMonikerImpl_Release(IMoniker* iface)
     return refCount;\r
 }\r
 \r
+\r
 /******************************************************************************\r
  *        URLMoniker_GetClassID\r
  ******************************************************************************/\r
@@ -310,6 +544,8 @@ static void CALLBACK URLMON_InternetCallback(HINTERNET hinet, /*DWORD_PTR*/ DWOR
     return;\r
 }\r
 #endif\r
+\r
+\r
 /******************************************************************************\r
  *        URLMoniker_BindToStorage\r
  ******************************************************************************/\r
@@ -321,12 +557,12 @@ static HRESULT WINAPI URLMonikerImpl_BindToStorage(IMoniker* iface,
 {\r
     URLMonikerImpl *This = (URLMonikerImpl *)iface;\r
     HRESULT hres;\r
-    IBindStatusCallback *pbscb;\r
     BINDINFO bi;\r
     DWORD bindf;\r
-    IStream *pstr;\r
+    WCHAR szFileName[MAX_PATH + 1];\r
+    Binding *bind;\r
+    int len;\r
 \r
-    FIXME("(%p)->(%p,%p,%s,%p): stub\n",This,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);\r
     if(pmkToLeft) {\r
        FIXME("pmkToLeft != NULL\n");\r
        return E_NOTIMPL;\r
@@ -336,122 +572,288 @@ static HRESULT WINAPI URLMonikerImpl_BindToStorage(IMoniker* iface,
        return E_NOTIMPL;\r
     }\r
 \r
-    /* FIXME This is a bad hack (tm).  We should clearly download to a temporary file.\r
-       We also need to implement IStream ourselves so that IStream_Read can return\r
-       E_PENDING */\r
+    bind = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Binding));\r
+    bind->lpVtbl = &BindingVtbl;\r
+    bind->ref = 1;\r
+    URLMON_LockModule();\r
+\r
+    len = lstrlenW(This->URLName)+1;\r
+    bind->URLName = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));\r
+    memcpy(bind->URLName, This->URLName, len*sizeof(WCHAR));\r
 \r
-    hres = CreateStreamOnHGlobal(0, TRUE, &pstr);\r
+    hres = UMCreateStreamOnCacheFile(bind->URLName, 0, szFileName, &bind->hCacheFile, &bind->pstrCache);\r
 \r
     if(SUCCEEDED(hres)) {\r
-        TRACE("Created dummy stream...\n");\r
+        TRACE("Created stream...\n");\r
+\r
+        *ppvObject = (void *) bind->pstrCache;\r
+        IStream_AddRef((IStream *) bind->pstrCache);\r
 \r
-        hres = IBindCtx_GetObjectParam(pbc, (LPOLESTR)BSCBHolder, (IUnknown**)&pbscb);\r
+        hres = IBindCtx_GetObjectParam(pbc, (LPOLESTR)BSCBHolder, (IUnknown**)&bind->pbscb);\r
         if(SUCCEEDED(hres)) {\r
             TRACE("Got IBindStatusCallback...\n");\r
 \r
             memset(&bi, 0, sizeof(bi));\r
             bi.cbSize = sizeof(bi);\r
             bindf = 0;\r
-            hres = IBindStatusCallback_GetBindInfo(pbscb, &bindf, &bi);\r
+            hres = IBindStatusCallback_GetBindInfo(bind->pbscb, &bindf, &bi);\r
             if(SUCCEEDED(hres)) {\r
+                WCHAR *urlcopy, *tmpwc;\r
                 URL_COMPONENTSW url;\r
-                WCHAR *host, *path;\r
-                DWORD len, lensz = sizeof(len), total_read = 0;\r
-                LARGE_INTEGER last_read_pos;\r
-                FORMATETC fmt;\r
-                STGMEDIUM stg;\r
+                WCHAR *host, *path, *user, *pass;\r
+                DWORD lensz = sizeof(bind->expected_size);\r
+                DWORD dwService = 0;\r
+                BOOL bSuccess;\r
 \r
                 TRACE("got bindinfo. bindf = %08lx extrainfo = %s bindinfof = %08lx bindverb = %08lx iid %s\n",\r
                       bindf, debugstr_w(bi.szExtraInfo), bi.grfBindInfoF, bi.dwBindVerb, debugstr_guid(&bi.iid));\r
-                hres = IBindStatusCallback_OnStartBinding(pbscb, 0, (IBinding*)&This->lpvtbl2);\r
+                hres = IBindStatusCallback_OnStartBinding(bind->pbscb, 0, (IBinding*)bind);\r
                 TRACE("OnStartBinding rets %08lx\n", hres);\r
 \r
+                /* This class will accept URLs with the backslash in them. But InternetCrackURL will not - it\r
+                 * requires forward slashes (this is the behaviour of Microsoft's INETAPI). So we need to make\r
+                 * a copy of the URL here and change the backslash to a forward slash everywhere it appears -\r
+                 * but only before any '#' or '?', after which backslash should be left alone.\r
+                 */\r
+                urlcopy = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * (lstrlenW(bind->URLName) + 1));\r
+                lstrcpyW(urlcopy, bind->URLName);\r
+                for (tmpwc = urlcopy; *tmpwc && *tmpwc != '#' && *tmpwc != '?'; ++tmpwc)\r
+                    if (*tmpwc == '\\')\r
+                            *tmpwc = '/';\r
+\r
 #if 0\r
-               if(!registered_wndclass) {\r
+                if(!registered_wndclass) {\r
                     WNDCLASSA urlmon_wndclass = {0, URLMON_WndProc,0, 0, URLMON_hInstance, 0, 0, 0, NULL, "URLMON_Callback_Window_Class"};\r
-                   RegisterClassA(&urlmon_wndclass);\r
-                   registered_wndclass = TRUE;\r
-               }\r
+                    RegisterClassA(&urlmon_wndclass);\r
+                    registered_wndclass = TRUE;\r
+                }\r
 \r
-               This->hwndCallback = CreateWindowA("URLMON_Callback_Window_Class", NULL, 0, 0, 0, 0, 0, 0, 0,\r
-                                                  URLMON_hInstance, NULL);\r
+                This->hwndCallback = CreateWindowA("URLMON_Callback_Window_Class", NULL, 0, 0, 0, 0, 0, 0, 0,\r
+                                                   URLMON_hInstance, NULL);\r
 \r
 #endif\r
+                bind->expected_size = 0;\r
+                bind->total_read = 0;\r
+\r
                 memset(&url, 0, sizeof(url));\r
                 url.dwStructSize = sizeof(url);\r
-                url.dwSchemeLength = url.dwHostNameLength = url.dwUrlPathLength = 1;\r
-                InternetCrackUrlW(This->URLName, 0, 0, &url);\r
+                url.dwSchemeLength = url.dwHostNameLength = url.dwUrlPathLength = url.dwUserNameLength = url.dwPasswordLength = 1;\r
+                InternetCrackUrlW(urlcopy, 0, 0, &url);\r
                 host = HeapAlloc(GetProcessHeap(), 0, (url.dwHostNameLength + 1) * sizeof(WCHAR));\r
                 memcpy(host, url.lpszHostName, url.dwHostNameLength * sizeof(WCHAR));\r
                 host[url.dwHostNameLength] = '\0';\r
                 path = HeapAlloc(GetProcessHeap(), 0, (url.dwUrlPathLength + 1) * sizeof(WCHAR));\r
                 memcpy(path, url.lpszUrlPath, url.dwUrlPathLength * sizeof(WCHAR));\r
                 path[url.dwUrlPathLength] = '\0';\r
+                if (url.dwUserNameLength)\r
+                {\r
+                    user = HeapAlloc(GetProcessHeap(), 0, ((url.dwUserNameLength + 1) * sizeof(WCHAR)));\r
+                    memcpy(user, url.lpszUserName, url.dwUserNameLength * sizeof(WCHAR));\r
+                    user[url.dwUserNameLength] = 0;\r
+                }\r
+                else\r
+                {\r
+                    user = 0;\r
+                }\r
+                if (url.dwPasswordLength)\r
+                {\r
+                    pass = HeapAlloc(GetProcessHeap(), 0, ((url.dwPasswordLength + 1) * sizeof(WCHAR)));\r
+                    memcpy(pass, url.lpszPassword, url.dwPasswordLength * sizeof(WCHAR));\r
+                    pass[url.dwPasswordLength] = 0;\r
+                }\r
+                else\r
+                {\r
+                    pass = 0;\r
+                }\r
 \r
-                This->hinternet = InternetOpenA("User Agent", 0, NULL, NULL, 0 /*INTERNET_FLAG_ASYNC*/);\r
-/*              InternetSetStatusCallback(This->hinternet, URLMON_InternetCallback);*/\r
-\r
-                This->hconnect = InternetConnectW(This->hinternet, host, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,\r
-                                                  INTERNET_SERVICE_HTTP, 0, (DWORD)This);\r
-                This->hrequest = HttpOpenRequestW(This->hconnect, NULL, path, NULL, NULL, NULL, 0, (DWORD)This);\r
-\r
-                hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, 0x22, NULL);\r
-                hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_FINDINGRESOURCE, NULL);\r
-                hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_CONNECTING, NULL);\r
-                hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_SENDINGREQUEST, NULL);\r
-                hres = E_OUTOFMEMORY; /* FIXME */\r
-                if(HttpSendRequestW(This->hrequest, NULL, 0, NULL, 0)) {\r
-                    len = 0;\r
-                    HttpQueryInfoW(This->hrequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &len, &lensz, NULL);\r
-\r
-                    TRACE("res = %ld gle = %08lx url len = %ld\n", hres, GetLastError(), len);\r
-\r
-                    last_read_pos.u.LowPart = last_read_pos.u.HighPart = 0;\r
-                    fmt.cfFormat = 0;\r
-                    fmt.ptd = NULL;\r
-                    fmt.dwAspect = 0;\r
-                    fmt.lindex = -1;\r
-                    fmt.tymed = TYMED_ISTREAM;\r
-                    stg.tymed = TYMED_ISTREAM;\r
-                    stg.u.pstm = pstr;\r
-                    stg.pUnkForRelease = NULL;\r
-\r
-                    while(1) {\r
-                        char buf[4096];\r
-                        DWORD bufread;\r
-                        DWORD written;\r
-                        if(InternetReadFile(This->hrequest, buf, sizeof(buf), &bufread)) {\r
-                            TRACE("read %ld bytes %s...\n", bufread, debugstr_an(buf, 10));\r
-                            if(bufread == 0) break;\r
-                            IStream_Write(pstr, buf, bufread, &written);\r
-                            total_read += bufread;\r
-                            IStream_Seek(pstr, last_read_pos, STREAM_SEEK_SET, NULL);\r
-                            hres = IBindStatusCallback_OnProgress(pbscb, total_read, len, (total_read == bufread) ?\r
-                                                                  BINDSTATUS_BEGINDOWNLOADDATA :\r
-                                                                  BINDSTATUS_DOWNLOADINGDATA, NULL);\r
-                            hres = IBindStatusCallback_OnDataAvailable(pbscb,\r
-                                                                       (total_read == bufread) ? BSCF_FIRSTDATANOTIFICATION :\r
-                                                                       BSCF_INTERMEDIATEDATANOTIFICATION,\r
-                                                                       total_read, &fmt, &stg);\r
-                            last_read_pos.u.LowPart += bufread; /* FIXME */\r
-                        } else\r
+                switch ((DWORD) url.nScheme)\r
+                {\r
+                case INTERNET_SCHEME_FTP:\r
+                case INTERNET_SCHEME_GOPHER:\r
+                case INTERNET_SCHEME_HTTP:\r
+                case INTERNET_SCHEME_HTTPS:\r
+\r
+                    bind->hinternet = InternetOpenA("User Agent", 0, NULL, NULL, 0 /*INTERNET_FLAG_ASYNC*/);\r
+/*                  InternetSetStatusCallback(bind->hinternet, URLMON_InternetCallback);*/\r
+                    if (!bind->hinternet)\r
+                    {\r
+                            hres = HRESULT_FROM_WIN32(GetLastError());\r
                             break;\r
-                   }\r
-                    hres = IBindStatusCallback_OnProgress(pbscb, total_read, len, BINDSTATUS_ENDDOWNLOADDATA, NULL);\r
-                    hres = IBindStatusCallback_OnDataAvailable(pbscb, BSCF_LASTDATANOTIFICATION, total_read, &fmt, &stg);\r
-                    TRACE("OnDataAvail rets %08lx\n", hres);\r
-                    hres = IBindStatusCallback_OnStopBinding(pbscb, S_OK, NULL);\r
-                    TRACE("OnStop rets %08lx\n", hres);\r
-                    hres = S_OK;\r
+                    }\r
+\r
+                    switch ((DWORD) url.nScheme)\r
+                    {\r
+                    case INTERNET_SCHEME_FTP:\r
+                        if (!url.nPort)\r
+                            url.nPort = INTERNET_DEFAULT_FTP_PORT;\r
+                        dwService = INTERNET_SERVICE_FTP;\r
+                        break;\r
+    \r
+                    case INTERNET_SCHEME_GOPHER:\r
+                        if (!url.nPort)\r
+                            url.nPort = INTERNET_DEFAULT_GOPHER_PORT;\r
+                        dwService = INTERNET_SERVICE_GOPHER;\r
+                        break;\r
+\r
+                    case INTERNET_SCHEME_HTTP:\r
+                        if (!url.nPort)\r
+                            url.nPort = INTERNET_DEFAULT_HTTP_PORT;\r
+                        dwService = INTERNET_SERVICE_HTTP;\r
+                        break;\r
+\r
+                    case INTERNET_SCHEME_HTTPS:\r
+                        if (!url.nPort)\r
+                            url.nPort = INTERNET_DEFAULT_HTTPS_PORT;\r
+                        dwService = INTERNET_SERVICE_HTTP;\r
+                        break;\r
+                    }\r
+\r
+                    bind->hconnect = InternetConnectW(bind->hinternet, host, url.nPort, user, pass,\r
+                                                      dwService, 0, (DWORD)bind);\r
+                    if (!bind->hconnect)\r
+                    {\r
+                            hres = HRESULT_FROM_WIN32(GetLastError());\r
+                            CloseHandle(bind->hinternet);\r
+                            break;\r
+                    }\r
+\r
+                    hres = IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, 0x22, NULL);\r
+                    hres = IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_FINDINGRESOURCE, NULL);\r
+                    hres = IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_CONNECTING, NULL);\r
+                    hres = IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_SENDINGREQUEST, NULL);\r
+\r
+                    bSuccess = FALSE;\r
+\r
+                    switch (dwService)\r
+                    {\r
+                    case INTERNET_SERVICE_GOPHER:\r
+                        bind->hrequest = GopherOpenFileW(bind->hconnect,\r
+                                                         path,\r
+                                                         0,\r
+                                                         INTERNET_FLAG_RELOAD,\r
+                                                         0);\r
+                        if (bind->hrequest)\r
+                                bSuccess = TRUE;\r
+                        else\r
+                                hres = HRESULT_FROM_WIN32(GetLastError());\r
+                        break;\r
+\r
+                    case INTERNET_SERVICE_FTP:\r
+                        bind->hrequest = FtpOpenFileW(bind->hconnect,\r
+                                                      path,\r
+                                                      GENERIC_READ,\r
+                                                      FTP_TRANSFER_TYPE_BINARY |\r
+                                                       INTERNET_FLAG_TRANSFER_BINARY |\r
+                                                       INTERNET_FLAG_RELOAD,\r
+                                                      0);\r
+                        if (bind->hrequest)\r
+                                bSuccess = TRUE;\r
+                        else\r
+                                hres = HRESULT_FROM_WIN32(GetLastError());\r
+                        break;\r
+\r
+                    case INTERNET_SERVICE_HTTP:\r
+                        bind->hrequest = HttpOpenRequestW(bind->hconnect, NULL, path, NULL, NULL, NULL, 0, (DWORD)bind);\r
+                        if (!bind->hrequest)\r
+                        {\r
+                                hres = HRESULT_FROM_WIN32(GetLastError());\r
+                        }\r
+                        else if (!HttpSendRequestW(bind->hrequest, NULL, 0, NULL, 0))\r
+                        {\r
+                                hres = HRESULT_FROM_WIN32(GetLastError());\r
+                                InternetCloseHandle(bind->hrequest);\r
+                        }\r
+                        else\r
+                        {\r
+                                HttpQueryInfoW(bind->hrequest,\r
+                                               HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,\r
+                                               &bind->expected_size,\r
+                                               &lensz,\r
+                                               NULL);\r
+                                bSuccess = TRUE;\r
+                        }\r
+                        break;\r
+                    }\r
+                    if(bSuccess)\r
+                    {\r
+                        TRACE("res = %ld gle = %08lx url len = %ld\n", hres, GetLastError(), bind->expected_size);\r
+\r
+                        IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_CACHEFILENAMEAVAILABLE, szFileName);\r
+\r
+                        while(1) {\r
+                            char buf[4096];\r
+                            DWORD bufread;\r
+                            if(InternetReadFile(bind->hrequest, buf, sizeof(buf), &bufread)) {\r
+                                TRACE("read %ld bytes %s...\n", bufread, debugstr_an(buf, 10));\r
+                                if(bufread == 0) break;\r
+                                hres = Binding_MoreCacheData(bind, buf, bufread);\r
+                            } else\r
+                                break;\r
+                        }\r
+                        InternetCloseHandle(bind->hrequest);\r
+                            hres = S_OK;\r
+                    }\r
+            \r
+                    InternetCloseHandle(bind->hconnect);\r
+                    InternetCloseHandle(bind->hinternet);\r
+                    break;\r
+\r
+                case INTERNET_SCHEME_FILE:\r
+                    path = bind->URLName + 5; /* Skip the "file:" part */\r
+                    if ((path[0] != '/' && path[0] != '\\') ||\r
+                        (path[1] != '/' && path[1] != '\\'))\r
+                    {\r
+                        hres = E_FAIL;\r
+                    }\r
+                    else\r
+                    {\r
+                        HANDLE h;\r
+\r
+                        path += 2;\r
+                        if (path[0] == '/' || path[0] == '\\')\r
+                            ++path;\r
+                        h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );\r
+                        if (h == (HANDLE) HFILE_ERROR)\r
+                        {\r
+                            hres = HRESULT_FROM_WIN32(GetLastError());\r
+                        }\r
+                        else\r
+                        {\r
+                            char buf[4096];\r
+                            DWORD bufread;\r
+\r
+                            IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_CACHEFILENAMEAVAILABLE, szFileName);\r
+\r
+                            while (ReadFile(h, buf, sizeof(buf), &bufread, NULL) && bufread > 0)\r
+                                hres = Binding_MoreCacheData(bind, buf, bufread);\r
+\r
+                            CloseHandle(h);\r
+                            hres = S_OK;\r
+                        }\r
+                    }\r
+                        \r
+                    break;\r
+\r
+                default:\r
+                    FIXME("Unsupported URI scheme");\r
+                    break;\r
                 }\r
-                InternetCloseHandle(This->hrequest);\r
-                InternetCloseHandle(This->hconnect);\r
-                InternetCloseHandle(This->hinternet);\r
-                IBindStatusCallback_Release(pbscb);\r
+                Binding_CloseCacheDownload(bind);\r
+                Binding_FinishedDownload(bind, hres);\r
+\r
+                if (user)\r
+                    HeapFree(GetProcessHeap(), 0, user);\r
+                if (pass)\r
+                    HeapFree(GetProcessHeap(), 0, pass);\r
+                HeapFree(GetProcessHeap(), 0, path);\r
+                HeapFree(GetProcessHeap(), 0, host);\r
+                HeapFree(GetProcessHeap(), 0, urlcopy);\r
             }\r
         }\r
     }\r
-    *ppvObject = (VOID*)pstr;\r
+\r
+    IBinding_Release((IBinding*)bind);\r
+\r
     return hres;\r
 }\r
 \r
@@ -698,98 +1100,6 @@ static HRESULT WINAPI URLMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdM
     return S_OK;\r
 }\r
 \r
-static HRESULT WINAPI URLMonikerImpl_IBinding_QueryInterface(IBinding* iface,REFIID riid,void** ppvObject)\r
-{\r
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);\r
-\r
-    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);\r
-\r
-    /* Perform a sanity check on the parameters.*/\r
-    if ( (This==0) || (ppvObject==0) )\r
-       return E_INVALIDARG;\r
-\r
-    /* Initialize the return parameter */\r
-    *ppvObject = 0;\r
-\r
-    /* Compare the riid with the interface IDs implemented by this object.*/\r
-    if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IBinding, riid))\r
-        *ppvObject = iface;\r
-\r
-    /* Check that we obtained an interface.*/\r
-    if ((*ppvObject)==0)\r
-        return E_NOINTERFACE;\r
-\r
-    /* Query Interface always increases the reference count by one when it is successful */\r
-    IBinding_AddRef(iface);\r
-\r
-    return S_OK;\r
-\r
-}\r
-\r
-static ULONG WINAPI URLMonikerImpl_IBinding_AddRef(IBinding* iface)\r
-{\r
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);\r
-    TRACE("(%p)\n",This);\r
-\r
-    return URLMonikerImpl_AddRef((IMoniker*)This);\r
-}\r
-\r
-static ULONG WINAPI URLMonikerImpl_IBinding_Release(IBinding* iface)\r
-{\r
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);\r
-    TRACE("(%p)\n",This);\r
-\r
-    return URLMonikerImpl_Release((IMoniker*)This);\r
-}\r
-\r
-static HRESULT WINAPI URLMonikerImpl_IBinding_Abort(IBinding* iface)\r
-{\r
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);\r
-    FIXME("(%p): stub\n", This);\r
-\r
-    return E_NOTIMPL;\r
-}\r
-\r
-static HRESULT WINAPI URLMonikerImpl_IBinding_GetBindResult(IBinding* iface, CLSID* pclsidProtocol, DWORD* pdwResult, LPOLESTR* pszResult, DWORD* pdwReserved)\r
-{\r
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);\r
-    FIXME("(%p)->(%p, %p, %p, %p): stub\n", This, pclsidProtocol, pdwResult, pszResult, pdwReserved);\r
-\r
-    return E_NOTIMPL;\r
-}\r
-\r
-static HRESULT WINAPI URLMonikerImpl_IBinding_GetPriority(IBinding* iface, LONG* pnPriority)\r
-{\r
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);\r
-    FIXME("(%p)->(%p): stub\n", This, pnPriority);\r
-\r
-    return E_NOTIMPL;\r
-}\r
-\r
-static HRESULT WINAPI URLMonikerImpl_IBinding_Resume(IBinding* iface)\r
-{\r
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);\r
-    FIXME("(%p): stub\n", This);\r
-\r
-    return E_NOTIMPL;\r
-}\r
-\r
-static HRESULT WINAPI URLMonikerImpl_IBinding_SetPriority(IBinding* iface, LONG nPriority)\r
-{\r
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);\r
-    FIXME("(%p)->(%ld): stub\n", This, nPriority);\r
-\r
-    return E_NOTIMPL;\r
-}\r
-\r
-static HRESULT WINAPI URLMonikerImpl_IBinding_Suspend(IBinding* iface)\r
-{\r
-    ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface);\r
-    FIXME("(%p): stub\n", This);\r
-\r
-    return E_NOTIMPL;\r
-}\r
-\r
 /********************************************************************************/\r
 /* Virtual function table for the URLMonikerImpl class which  include IPersist,*/\r
 /* IPersistStream and IMoniker functions.                                       */\r
@@ -820,19 +1130,6 @@ static IMonikerVtbl VT_URLMonikerImpl =
     URLMonikerImpl_IsSystemMoniker\r
 };\r
 \r
-static IBindingVtbl VTBinding_URLMonikerImpl =\r
-{\r
-    URLMonikerImpl_IBinding_QueryInterface,\r
-    URLMonikerImpl_IBinding_AddRef,\r
-    URLMonikerImpl_IBinding_Release,\r
-    URLMonikerImpl_IBinding_Abort,\r
-    URLMonikerImpl_IBinding_Suspend,\r
-    URLMonikerImpl_IBinding_Resume,\r
-    URLMonikerImpl_IBinding_SetPriority,\r
-    URLMonikerImpl_IBinding_GetPriority,\r
-    URLMonikerImpl_IBinding_GetBindResult\r
-};\r
-\r
 /******************************************************************************\r
  *         URLMoniker_Construct (local function)\r
  *******************************************************************************/\r
@@ -845,9 +1142,8 @@ static HRESULT URLMonikerImpl_Construct(URLMonikerImpl* This, LPCOLESTR lpszLeft
     memset(This, 0, sizeof(*This));\r
 \r
     /* Initialize the virtual function table. */\r
-    This->lpvtbl1      = &VT_URLMonikerImpl;\r
-    This->lpvtbl2      = &VTBinding_URLMonikerImpl;\r
-    This->ref          = 0;\r
+    This->lpvtbl = &VT_URLMonikerImpl;\r
+    This->ref = 0;\r
 \r
     if(lpszLeftURLName) {\r
         hres = UrlCombineW(lpszLeftURLName, lpszURLName, NULL, &sizeStr, 0);\r
diff --git a/reactos/lib/urlmon/umstream.c b/reactos/lib/urlmon/umstream.c
new file mode 100644 (file)
index 0000000..da9e8f2
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * Based on ../shell32/memorystream.c
+ *
+ * Copyright 1999 Juergen Schmied
+ * Copyright 2003 Mike McCormack 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winternl.h"
+#include "winuser.h"
+#include "objbase.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "ole2.h"
+#include "urlmon.h"
+#include "wininet.h"
+#include "shlwapi.h"
+#include "urlmon_main.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
+
+static const IStreamVtbl stvt;
+
+HRESULT UMCreateStreamOnCacheFile(LPCWSTR pszURL,
+                                  DWORD dwSize,
+                                  LPWSTR pszFileName,
+                                  HANDLE *phfile,
+                                  IUMCacheStream **ppstr)
+{
+    IUMCacheStream* ucstr;
+    HANDLE handle;
+    LPWSTR ext;
+    LPCWSTR c;
+    LPCWSTR eloc = 0;
+    HRESULT hr;
+
+    for (c = pszURL; *c && *c != '#' && *c != '?'; ++c)
+    {
+        if (*c == '.')
+           eloc = c + 1;
+        else if (*c == '/' || *c == '\\')
+           eloc = 0;
+    }
+
+    if (!eloc)
+       eloc = c;
+
+    ext = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * (c - eloc + 1));
+    memcpy(ext, eloc, sizeof(WCHAR) * (c - eloc));
+    ext[c - eloc] = 0;
+
+    if(!CreateUrlCacheEntryW(pszURL, dwSize, ext, pszFileName, 0))
+       hr = HRESULT_FROM_WIN32(GetLastError());
+    else
+       hr = 0;
+
+    HeapFree(GetProcessHeap(), 0, ext);
+
+    if (hr)
+       return hr;
+
+    TRACE("Opening %s\n", debugstr_w(pszFileName) );
+
+    handle = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL );
+    if( handle == INVALID_HANDLE_VALUE )
+       return HRESULT_FROM_WIN32(GetLastError());
+
+    if (phfile)
+    {
+       /* Call CreateFileW again because we need a handle with its own file pointer, and DuplicateHandle will return
+        * a handle that shares its file pointer with the original.
+        */
+           *phfile = CreateFileW( pszFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
+
+       if (*phfile == (HANDLE) HFILE_ERROR)
+       {
+           DWORD dwError = GetLastError();
+
+           CloseHandle(handle);
+           return HRESULT_FROM_WIN32(dwError);
+       }
+    }
+
+    ucstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,sizeof(IUMCacheStream));
+    if(ucstr )
+    {
+       ucstr->pszURL = HeapAlloc(GetProcessHeap(),
+                                 HEAP_ZERO_MEMORY,
+                                 sizeof(WCHAR) * (lstrlenW(pszURL) + 1));
+       if (ucstr->pszURL)
+       {
+            ucstr->pszFileName = HeapAlloc(GetProcessHeap(),
+                                           HEAP_ZERO_MEMORY,
+                                           sizeof(WCHAR) * (lstrlenW(pszFileName) + 1));
+           if (ucstr->pszFileName)
+           {
+              ucstr->lpVtbl=&stvt;
+              ucstr->ref = 1;
+              ucstr->handle = handle;
+              ucstr->closed = 0;
+              lstrcpyW(ucstr->pszURL, pszURL);
+              lstrcpyW(ucstr->pszFileName, pszFileName);
+
+              *ppstr = ucstr;
+
+              return S_OK;
+           }
+           HeapFree(GetProcessHeap(), 0, ucstr->pszURL);
+       }
+       HeapFree(GetProcessHeap(), 0, ucstr);
+    }
+    CloseHandle(handle);
+    if (phfile)
+       CloseHandle(*phfile);
+    return E_OUTOFMEMORY;
+}
+
+void UMCloseCacheFileStream(IUMCacheStream *This)
+{
+    if (!This->closed)
+    {
+       FILETIME ftZero;
+
+       ftZero.dwLowDateTime = ftZero.dwHighDateTime = 0;
+
+       This->closed = 1;
+       CommitUrlCacheEntryW(This->pszURL,
+                            This->pszFileName,
+                            ftZero,
+                            ftZero,
+                            NORMAL_CACHE_ENTRY,
+                            0,
+                            0,
+                            0,
+                            0);
+    }
+}
+
+/**************************************************************************
+*  IStream_fnQueryInterface
+*/
+static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface,
+                                               REFIID riid,
+                                               LPVOID *ppvObj)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+
+    TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
+
+    *ppvObj = NULL;
+
+    if(IsEqualIID(riid, &IID_IUnknown) ||
+       IsEqualIID(riid, &IID_IStream))
+    {
+      *ppvObj = This;
+    }
+
+    if(*ppvObj)
+    {
+      IStream_AddRef((IStream*)*ppvObj);
+      TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
+      return S_OK;
+    }
+    TRACE("-- Interface: E_NOINTERFACE\n");
+    return E_NOINTERFACE;
+}
+
+/**************************************************************************
+*  IStream_fnAddRef
+*/
+static ULONG WINAPI IStream_fnAddRef(IStream *iface)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+    ULONG refCount = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
+
+    return refCount;
+}
+
+/**************************************************************************
+*  IStream_fnRelease
+*/
+static ULONG WINAPI IStream_fnRelease(IStream *iface)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+    ULONG refCount = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p)->(count=%lu)\n", This, refCount + 1);
+
+    if (!refCount)
+    {
+       TRACE(" destroying UMCacheStream (%p)\n",This);
+       UMCloseCacheFileStream(This);
+       CloseHandle(This->handle);
+       HeapFree(GetProcessHeap(), 0, This->pszFileName);
+       HeapFree(GetProcessHeap(), 0, This->pszURL);
+       HeapFree(GetProcessHeap(),0,This);
+    }
+    return refCount;
+}
+
+static HRESULT WINAPI IStream_fnRead (IStream * iface, 
+                                      void* pv,
+                                      ULONG cb,
+                                      ULONG* pcbRead)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+
+    TRACE("(%p)->(%p,0x%08lx,%p)\n",This, pv, cb, pcbRead);
+
+    if ( !pv )
+       return STG_E_INVALIDPOINTER;
+
+    if ( ! ReadFile( This->handle, pv, cb, pcbRead, NULL ) )
+       return S_FALSE;
+
+    if (!*pcbRead)
+        return This->closed ? S_FALSE : E_PENDING;
+    return S_OK;
+}
+
+static HRESULT WINAPI IStream_fnWrite (IStream * iface,
+                                       const void* pv,
+                                       ULONG cb,
+                                       ULONG* pcbWritten)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IStream_fnSeek (       IStream * iface,
+                                   LARGE_INTEGER dlibMove,
+                                   DWORD dwOrigin,
+                                   ULARGE_INTEGER* plibNewPosition)
+{
+    DWORD pos, newposlo, newposhi;
+
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+
+    TRACE("(%p)\n",This);
+
+    pos = dlibMove.QuadPart; /* FIXME: truncates */
+    newposhi = 0;
+    newposlo = SetFilePointer( This->handle, pos, &newposhi, dwOrigin );
+    if( newposlo == INVALID_SET_FILE_POINTER )
+       return E_FAIL;
+
+    if (plibNewPosition)
+        plibNewPosition->QuadPart = newposlo | ( (LONGLONG)newposhi<<32);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI IStream_fnSetSize (IStream * iface,
+                                         ULARGE_INTEGER libNewSize)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+
+    TRACE("(%p)\n",This);
+
+    if( ! SetFilePointer( This->handle, libNewSize.QuadPart, NULL, FILE_BEGIN ) )
+       return E_FAIL;
+
+    if( ! SetEndOfFile( This->handle ) )
+       return E_FAIL;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI IStream_fnCopyTo (IStream * iface,
+                                   IStream* pstm,
+                                   ULARGE_INTEGER cb,
+                                   ULARGE_INTEGER* pcbRead,
+                                   ULARGE_INTEGER* pcbWritten)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+
+    TRACE("(%p)\n",This);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IStream_fnCommit (IStream * iface,
+                                   DWORD grfCommitFlags)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+
+    TRACE("(%p)\n",This);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IStream_fnRevert (IStream * iface)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+
+    TRACE("(%p)\n",This);
+
+    return E_NOTIMPL;
+}
+static HRESULT WINAPI IStream_fnLockRegion (IStream * iface,
+                                            ULARGE_INTEGER libOffset,
+                                            ULARGE_INTEGER cb,
+                                            DWORD dwLockType)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+
+    TRACE("(%p)\n",This);
+
+    return E_NOTIMPL;
+}
+static HRESULT WINAPI IStream_fnUnlockRegion (IStream * iface,
+                                              ULARGE_INTEGER libOffset,
+                                              ULARGE_INTEGER cb,
+                                              DWORD dwLockType)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+
+    TRACE("(%p)\n",This);
+
+    return E_NOTIMPL;
+}
+static HRESULT WINAPI IStream_fnStat (IStream * iface,
+                                      STATSTG*   pstatstg,
+                                      DWORD grfStatFlag)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+
+    TRACE("(%p)\n",This);
+
+    return E_NOTIMPL;
+}
+static HRESULT WINAPI IStream_fnClone (IStream * iface,
+                                       IStream** ppstm)
+{
+    IUMCacheStream *This = (IUMCacheStream *)iface;
+
+    TRACE("(%p)\n",This);
+
+    return E_NOTIMPL;
+}
+
+static const IStreamVtbl stvt =
+{
+    IStream_fnQueryInterface,
+    IStream_fnAddRef,
+    IStream_fnRelease,
+    IStream_fnRead,
+    IStream_fnWrite,
+    IStream_fnSeek,
+    IStream_fnSetSize,
+    IStream_fnCopyTo,
+    IStream_fnCommit,
+    IStream_fnRevert,
+    IStream_fnLockRegion,
+    IStream_fnUnlockRegion,
+    IStream_fnStat,
+    IStream_fnClone
+
+};
index 0a7b1b2..aaa7a37 100644 (file)
@@ -8,7 +8,7 @@
 @ stub AsyncGetClassBits\r
 @ stub AsyncInstallDistributionUnit\r
 @ stub BindAsyncMoniker\r
-@ stub CoGetClassObjectFromURL\r
+@ stdcall CoGetClassObjectFromURL(ptr wstr long long wstr ptr long ptr ptr ptr)\r
 @ stub CoInstall\r
 @ stdcall CoInternetCombineUrl(wstr wstr long wstr long ptr long)\r
 @ stdcall CoInternetCompareUrl(wstr wstr long)\r
index 5253d0c..4a75006 100644 (file)
@@ -23,6 +23,7 @@
        <file>regsvr.c</file>\r
        <file>sec_mgr.c</file>\r
        <file>umon.c</file>\r
+       <file>umstream.c</file>\r
        <file>urlmon_main.c</file>\r
        <file>urlmon.spec</file>\r
 </module>\r
index a02ab48..641df1c 100644 (file)
@@ -341,3 +341,17 @@ HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
     FIXME("%p %p %p %08lx\n", hwnd, pClassSpec, pQuery, flags);\r
     return E_NOTIMPL;\r
 }\r
+\r
+/**************************************************************************\r
+ *                 CoGetClassObjectFromURL (URLMON.@)\r
+ */\r
+HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,\r
+                                        DWORD dwFileVersionLS, LPCWSTR szContentType,\r
+                                        LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,\r
+                                        REFIID riid, LPVOID *ppv )\r
+{\r
+    FIXME("(%s %s %ld %ld %s %p %ld %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),\r
+       dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,\r
+       debugstr_guid(riid), ppv);\r
+    return E_NOINTERFACE;\r
+}\r
index 4f9dc6e..5e01edb 100644 (file)
@@ -37,4 +37,17 @@ static inline void URLMON_UnlockModule() { InterlockedDecrement( &URLMON_refCoun
 \r
 #define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))\r
 \r
+typedef struct\r
+{      \r
+       const IStreamVtbl       *lpVtbl;\r
+       DWORD           ref;\r
+       HANDLE          handle;\r
+       BOOL            closed;\r
+       WCHAR           *pszFileName;\r
+       WCHAR           *pszURL;\r
+} IUMCacheStream;\r
+\r
+HRESULT        UMCreateStreamOnCacheFile(LPCWSTR pszURL, DWORD dwSize, LPWSTR pszFileName, HANDLE *phfile, IUMCacheStream **ppstr);\r
+void   UMCloseCacheFileStream(IUMCacheStream *pstr);\r
+\r
 #endif /* __WINE_URLMON_MAIN_H */\r