URLMON: Added file protocol implementation
Jacek Caban
jack at itma.pwr.wroc.pl
Sat Sep 3 14:22:52 CDT 2005
Changelog:
Added file protocol implementation
-------------- next part --------------
? dlls/urlmon/file.c
? dlls/urlmon/tests/protocol.c
? dlls/urlmon/tests/protocol.ok
Index: dlls/urlmon/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/urlmon/Makefile.in,v
retrieving revision 1.26
diff -u -p -r1.26 Makefile.in
--- dlls/urlmon/Makefile.in 2 Sep 2005 12:17:30 -0000 1.26
+++ dlls/urlmon/Makefile.in 3 Sep 2005 17:19:23 -0000
@@ -8,6 +8,7 @@ IMPORTS = cabinet ole32 shlwapi winine
EXTRALIBS = -luuid
C_SRCS = \
+ file.c \
format.c \
regsvr.c \
sec_mgr.c \
Index: dlls/urlmon/urlmon_main.c
===================================================================
RCS file: /home/wine/wine/dlls/urlmon/urlmon_main.c,v
retrieving revision 1.31
diff -u -p -r1.31 urlmon_main.c
--- dlls/urlmon/urlmon_main.c 8 Aug 2005 17:37:40 -0000 1.31
+++ dlls/urlmon/urlmon_main.c 3 Sep 2005 17:19:23 -0000
@@ -101,6 +101,7 @@ struct object_creation_info
static const struct object_creation_info object_creation[] =
{
+ { &CLSID_FileProtocol, FileProtocol_Construct },
{ &CLSID_InternetSecurityManager, &SecManagerImpl_Construct },
{ &CLSID_InternetZoneManager, ZoneMgrImpl_Construct }
};
Index: dlls/urlmon/urlmon_main.h
===================================================================
RCS file: /home/wine/wine/dlls/urlmon/urlmon_main.h,v
retrieving revision 1.11
diff -u -p -r1.11 urlmon_main.h
--- dlls/urlmon/urlmon_main.h 5 Jul 2005 14:06:43 -0000 1.11
+++ dlls/urlmon/urlmon_main.h 3 Sep 2005 17:19:23 -0000
@@ -27,6 +27,7 @@
extern HINSTANCE URLMON_hInstance;
extern HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
extern HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
+extern HRESULT FileProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
/**********************************************************************
* Dll lifetime tracking declaration for urlmon.dll
@@ -36,6 +37,7 @@ static inline void URLMON_LockModule(voi
static inline void URLMON_UnlockModule(void) { InterlockedDecrement( &URLMON_refCount ); }
#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
+#define DEFINE_THIS(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,lp ## ifc ## Vtbl)))
typedef struct
{
Index: dlls/urlmon/tests/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/urlmon/tests/Makefile.in,v
retrieving revision 1.6
diff -u -p -r1.6 Makefile.in
--- dlls/urlmon/tests/Makefile.in 3 Sep 2005 09:36:12 -0000 1.6
+++ dlls/urlmon/tests/Makefile.in 3 Sep 2005 17:19:23 -0000
@@ -9,6 +9,7 @@ EXTRALIBS = -luuid
CTESTS = \
generated.c \
misc.c \
+ protocol.c \
url.c
@MAKE_TEST_RULES@
--- /dev/null 2005-09-03 09:18:53.484530250 +0000
+++ dlls/urlmon/file.c 2005-09-03 19:18:25.000000000 +0000
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2005 Jacek Caban
+ *
+ * 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 "winuser.h"
+#include "ole2.h"
+#include "urlmon.h"
+#include "urlmon_main.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
+
+typedef struct {
+ const IInternetProtocolVtbl *lpInternetProtocolVtbl;
+
+ HANDLE file;
+
+ LONG ref;
+} FileProtocol;
+
+#define PROTOCOL_THIS(iface) DEFINE_THIS(FileProtocol, InternetProtocol, iface)
+
+#define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
+
+static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+
+ *ppv = NULL;
+ if(IsEqualGUID(&IID_IUnknown, riid)) {
+ TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+ *ppv = PROTOCOL(This);
+ }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
+ TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
+ *ppv = PROTOCOL(This);
+ }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
+ TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
+ *ppv = PROTOCOL(This);
+ }
+
+ if(*ppv) {
+ IInternetProtocol_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("not supported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI FileProtocol_AddRef(IInternetProtocol *iface)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+ TRACE("(%p) ref=%ld\n", This, ref);
+ return ref;
+}
+
+static ULONG WINAPI FileProtocol_Release(IInternetProtocol *iface)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+ LONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ref=%ld\n", This, ref);
+
+ if(!ref) {
+ if(This->file)
+ CloseHandle(This->file);
+ HeapFree(GetProcessHeap(), 0, This);
+
+ URLMON_UnlockModule();
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI FileProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
+ IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
+ DWORD grfPI, DWORD dwReserved)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+ BINDINFO bindinfo;
+ DWORD grfBINDF = 0;
+ LARGE_INTEGER size;
+
+ static const WCHAR wszFile[] = {'f','i','l','e',':'};
+
+ TRACE("(%p)->(%s %p %p %08lx %ld)\n", This, debugstr_w(szUrl), pOIProtSink,
+ pOIBindInfo, grfPI, dwReserved);
+
+ memset(&bindinfo, 0, sizeof(bindinfo));
+ bindinfo.cbSize = sizeof(BINDINFO);
+ IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo);
+
+ if(lstrlenW(szUrl) < sizeof(wszFile)/sizeof(WCHAR)
+ || memcmp(szUrl, wszFile, sizeof(wszFile)))
+ return MK_E_SYNTAX;
+
+ /* FIXME:
+ * Implement MIME type checking
+ */
+
+ if(!This->file) {
+ This->file = CreateFileW(szUrl+sizeof(wszFile)/sizeof(WCHAR), GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if(This->file == INVALID_HANDLE_VALUE) {
+ This->file = NULL;
+ IInternetProtocolSink_ReportResult(pOIProtSink, INET_E_RESOURCE_NOT_FOUND,
+ GetLastError(), NULL);
+ return INET_E_RESOURCE_NOT_FOUND;
+ }
+
+ IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_CACHEFILENAMEAVAILABLE,
+ szUrl+sizeof(wszFile)/sizeof(WCHAR));
+ IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
+ }
+
+ if(GetFileSizeEx(This->file, &size))
+ IInternetProtocolSink_ReportData(pOIProtSink,
+ BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION,
+ size.u.LowPart, size.u.LowPart);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI FileProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+ FIXME("(%p)->(%p)\n", This, pProtocolData);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FileProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
+ DWORD dwOptions)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+ FIXME("(%p)->(%08lx %08lx)\n", This, hrReason, dwOptions);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FileProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+
+ TRACE("(%p)->(%08lx)\n", This, dwOptions);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI FileProtocol_Suspend(IInternetProtocol *iface)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+ FIXME("(%p)\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FileProtocol_Resume(IInternetProtocol *iface)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+ FIXME("(%p)\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FileProtocol_Read(IInternetProtocol *iface, void *pv,
+ ULONG cb, ULONG *pcbRead)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+ DWORD read = 0;
+
+ TRACE("(%p)->(%p %lu %p)\n", This, pv, cb, pcbRead);
+
+ if(!This->file)
+ return INET_E_DATA_NOT_AVAILABLE;
+
+ ReadFile(This->file, pv, cb, &read, NULL);
+
+ if(pcbRead)
+ *pcbRead = read;
+
+ return cb == read ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI FileProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
+ DWORD dwOrgin, ULARGE_INTEGER *plibNewPosition)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+ FIXME("(%p)->(%ld %ld %p)\n", This, dlibMove.u.LowPart, dwOrgin, plibNewPosition);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FileProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+
+ TRACE("(%p)->(%08lx)\n", This, dwOptions);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI FileProtocol_UnlockRequest(IInternetProtocol *iface)
+{
+ FileProtocol *This = PROTOCOL_THIS(iface);
+
+ TRACE("(%p)\n", This);
+
+ return S_OK;
+}
+
+#undef PROTOCOL_THIS
+
+static const IInternetProtocolVtbl FileProtocolVtbl = {
+ FileProtocol_QueryInterface,
+ FileProtocol_AddRef,
+ FileProtocol_Release,
+ FileProtocol_Start,
+ FileProtocol_Continue,
+ FileProtocol_Abort,
+ FileProtocol_Terminate,
+ FileProtocol_Suspend,
+ FileProtocol_Resume,
+ FileProtocol_Read,
+ FileProtocol_Seek,
+ FileProtocol_LockRequest,
+ FileProtocol_UnlockRequest
+};
+
+HRESULT FileProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
+{
+ FileProtocol *ret;
+
+ TRACE("(%p %p)\n", pUnkOuter, ppobj);
+
+ URLMON_LockModule();
+
+ ret = HeapAlloc(GetProcessHeap(), 0, sizeof(FileProtocol));
+
+ ret->lpInternetProtocolVtbl = &FileProtocolVtbl;
+ ret->file = NULL;
+ ret->ref = 1;
+
+ *ppobj = PROTOCOL(ret);
+
+ return S_OK;
+}
--- /dev/null 2005-09-03 09:18:53.484530250 +0000
+++ dlls/urlmon/tests/protocol.c 2005-09-03 19:21:29.000000000 +0000
@@ -0,0 +1,409 @@
+/*
+ * Copyright 2005 Jacek Caban
+ *
+ * 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
+ */
+
+#define COBJMACROS
+
+#include <wine/test.h>
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "ole2.h"
+#include "urlmon.h"
+
+#include "initguid.h"
+
+DEFINE_GUID(CLSID_FileProtocol, 0x79EAC9E7, 0xBAF9, 0x11CE, 0x8C,0x82, 0x00,0xAA,0x00,0x4B,0xA9,0x0B);
+
+#define DEFINE_EXPECT(func) \
+ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
+
+#define SET_EXPECT(func) \
+ expect_ ## func = TRUE
+
+#define CHECK_EXPECT(func) \
+ ok(expect_ ##func, "unexpected call\n"); \
+ expect_ ## func = FALSE; \
+ called_ ## func = TRUE
+
+#define CHECK_EXPECT2(func) \
+ ok(expect_ ##func, "unexpected call\n"); \
+ called_ ## func = TRUE
+
+#define CHECK_CALLED(func) \
+ ok(called_ ## func, "expected " #func "\n"); \
+ expect_ ## func = called_ ## func = FALSE
+
+DEFINE_EXPECT(GetBindInfo);
+DEFINE_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
+DEFINE_EXPECT(ReportProgress_DIRECTBIND);
+DEFINE_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
+DEFINE_EXPECT(ReportData);
+DEFINE_EXPECT(ReportResult);
+
+static HRESULT expect_hrResult;
+static LPCWSTR file_name;
+
+static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
+{
+ if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
+ *ppv = iface;
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
+ LPCWSTR szStatusText)
+{
+ static const WCHAR text_html[] = {'t','e','x','t','/','h','t','m','l',0};
+
+ switch(ulStatusCode) {
+ case BINDSTATUS_MIMETYPEAVAILABLE:
+ CHECK_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
+ if(szStatusText)
+ ok(!lstrcmpW(szStatusText, text_html), "szStatusText != text/html\n");
+ case BINDSTATUS_DIRECTBIND:
+ CHECK_EXPECT2(ReportProgress_DIRECTBIND);
+ if(szStatusText)
+ ok(!lstrcmpW(szStatusText, text_html), "szStatusText != text/html\n");
+ break;
+ case BINDSTATUS_CACHEFILENAMEAVAILABLE:
+ CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
+ if(szStatusText)
+ ok(!lstrcmpW(szStatusText, file_name), "szStatusText != file_name\n");
+ break;
+ };
+
+ return S_OK;
+}
+
+static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
+ ULONG ulProgress, ULONG ulProgressMax)
+{
+ CHECK_EXPECT(ReportData);
+
+ ok(ulProgress == ulProgressMax, "ulProgress != ulProgressMax\n");
+ ok(ulProgressMax == 13, "ulProgressMax=%ld, expected 13\n", ulProgressMax);
+ ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION),
+ "grcf = %08lx\n", grfBSCF);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
+ DWORD dwError, LPCWSTR szResult)
+{
+ CHECK_EXPECT(ReportResult);
+
+ ok(hrResult == expect_hrResult, "hrResult = %08lx, expected: %08lx\n",
+ hrResult, expect_hrResult);
+ if(SUCCEEDED(hrResult))
+ ok(dwError == ERROR_SUCCESS, "dwError = %ld, expected ERROR_SUCCESS\n", dwError);
+ else
+ ok(dwError != ERROR_SUCCESS, "dwError == ERROR_SUCCESS\n");
+ ok(!szResult, "szResult != NULL\n");
+
+ return S_OK;
+}
+
+static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
+ ProtocolSink_QueryInterface,
+ ProtocolSink_AddRef,
+ ProtocolSink_Release,
+ ProtocolSink_Switch,
+ ProtocolSink_ReportProgress,
+ ProtocolSink_ReportData,
+ ProtocolSink_ReportResult
+};
+
+static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl };
+
+static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
+{
+ if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
+ *ppv = iface;
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
+{
+ CHECK_EXPECT(GetBindInfo);
+
+ ok(grfBINDF != NULL, "grfBINDF == NULL\n");
+ if(grfBINDF)
+ ok(!*grfBINDF, "*grfBINDF != 0\n");
+ ok(pbindinfo != NULL, "pbindinfo == NULL\n");
+ ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %ld\n", pbindinfo->cbSize);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType,
+ LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static IInternetBindInfoVtbl bind_info_vtbl = {
+ BindInfo_QueryInterface,
+ BindInfo_AddRef,
+ BindInfo_Release,
+ BindInfo_GetBindInfo,
+ BindInfo_GetBindString
+};
+
+static IInternetBindInfo bind_info = { &bind_info_vtbl };
+
+static void file_protocol_start(IInternetProtocol *protocol, LPCWSTR url, BOOL is_first)
+{
+ HRESULT hres;
+
+ SET_EXPECT(GetBindInfo);
+ SET_EXPECT(ReportProgress_DIRECTBIND);
+ if(is_first) {
+ SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
+ SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
+ SET_EXPECT(ReportResult);
+ }
+ SET_EXPECT(ReportData);
+ expect_hrResult = S_OK;
+
+ hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
+ ok(hres == S_OK, "Start failed: %08lx\n", hres);
+
+ CHECK_CALLED(GetBindInfo);
+ todo_wine { CHECK_CALLED(ReportProgress_DIRECTBIND); }
+ if(is_first) {
+ CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
+ todo_wine { CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE); }
+ CHECK_CALLED(ReportResult);
+ }
+ CHECK_CALLED(ReportData);
+}
+
+static void test_file_protocol_url(LPCWSTR url)
+{
+ IInternetProtocolInfo *protocol_info;
+ IUnknown *unk;
+ IClassFactory *factory;
+ HRESULT hres;
+
+ hres = CoGetClassObject(&CLSID_FileProtocol, CLSCTX_INPROC_SERVER, NULL,
+ &IID_IUnknown, (void**)&unk);
+ ok(hres == S_OK, "CoGetClassObject failed: %08lx\n", hres);
+ if(!SUCCEEDED(hres))
+ return;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
+ ok(hres == E_NOINTERFACE,
+ "Could not get IInternetProtocolInfo interface: %08lx, expected E_NOINTERFACE\n", hres);
+
+ hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
+ ok(hres == S_OK, "Could not get IClassFactory interface\n");
+ if(SUCCEEDED(hres)) {
+ IInternetProtocol *protocol;
+ BYTE buf[512];
+ ULONG cb;
+ hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
+ ok(hres == S_OK, "Could not get IInternetProtocol: %08lx\n", hres);
+
+ if(SUCCEEDED(hres)) {
+ file_protocol_start(protocol, url, TRUE);
+ hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
+ ok(hres == S_OK, "Read failed: %08lx\n", hres);
+ ok(cb == 2, "cb=%lu expected 2\n", cb);
+ hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
+ ok(hres == S_FALSE, "Read failed: %08lx\n", hres);
+ hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
+ ok(hres == S_FALSE, "Read failed: %08lx expected S_FALSE\n", hres);
+ ok(cb == 0, "cb=%lu expected 0\n", cb);
+ hres = IInternetProtocol_UnlockRequest(protocol);
+ ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres);
+
+ file_protocol_start(protocol, url, FALSE);
+ hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
+ ok(hres == S_FALSE, "Read failed: %08lx\n", hres);
+ hres = IInternetProtocol_LockRequest(protocol, 0);
+ ok(hres == S_OK, "LockRequest failed: %08lx\n", hres);
+ hres = IInternetProtocol_UnlockRequest(protocol);
+ ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres);
+
+ IInternetProtocol_Release(protocol);
+ }
+
+ hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
+ ok(hres == S_OK, "Could not get IInternetProtocol: %08lx\n", hres);
+
+ if(SUCCEEDED(hres)) {
+ file_protocol_start(protocol, url, TRUE);
+ hres = IInternetProtocol_LockRequest(protocol, 0);
+ ok(hres == S_OK, "LockRequest failed: %08lx\n", hres);
+ hres = IInternetProtocol_Terminate(protocol, 0);
+ ok(hres == S_OK, "Terminate failed: %08lx\n", hres);
+ hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
+ ok(hres == S_OK, "Read failed: %08lx\n\n", hres);
+ hres = IInternetProtocol_UnlockRequest(protocol);
+ ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres);
+ hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
+ ok(hres == S_OK, "Read failed: %08lx\n", hres);
+ hres = IInternetProtocol_Terminate(protocol, 0);
+ ok(hres == S_OK, "Terminate failed: %08lx\n", hres);
+
+ IInternetProtocol_Release(protocol);
+ }
+
+ hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
+ ok(hres == S_OK, "Could not get IInternetProtocol: %08lx\n", hres);
+
+ if(SUCCEEDED(hres)) {
+ file_protocol_start(protocol, url, TRUE);
+ hres = IInternetProtocol_Terminate(protocol, 0);
+ ok(hres == S_OK, "Terminate failed: %08lx\n", hres);
+ hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
+ ok(hres == S_OK, "Read failed: %08lx\n", hres);
+ ok(cb == 2, "cb=%lu expected 2\n", cb);
+
+ IInternetProtocol_Release(protocol);
+ }
+
+ IClassFactory_Release(factory);
+ }
+
+ IUnknown_Release(unk);
+}
+
+static void test_file_protocol(void) {
+ IInternetProtocol *protocol;
+ WCHAR buf[MAX_PATH];
+ ULONG len;
+ HANDLE file;
+ HRESULT hres;
+
+ static const WCHAR index_url[] =
+ {'f','i','l','e',':','i','n','d','e','x','.','h','t','m','l',0};
+ static const WCHAR index_url2[] =
+ {'f','i','l','e',':','/','/','i','n','d','e','x','.','h','t','m','l',0};
+ static const WCHAR wszFile[] = {'f','i','l','e',':',0};
+ static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
+ static const char html_doc[] = "<HTML></HTML>";
+
+ file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ ok(file != NULL, "CreateFile failed\n");
+ if(!file)
+ return;
+ WriteFile(file, html_doc, sizeof(html_doc)-1, NULL, NULL);
+ CloseHandle(file);
+
+ file_name = wszIndexHtml;
+ test_file_protocol_url(index_url);
+
+ memcpy(buf, wszFile, sizeof(wszFile));
+ len = sizeof(wszFile)/sizeof(WCHAR)-1;
+ len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
+ buf[len++] = '\\';
+ memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
+
+ file_name = buf + sizeof(wszFile)/sizeof(WCHAR)-1;
+ test_file_protocol_url(buf);
+
+ DeleteFileW(wszIndexHtml);
+
+ hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
+ &IID_IInternetProtocol, (void**)&protocol);
+ ok(hres == S_OK, "CoCreateInstance failed: %08lx\n", hres);
+ if(FAILED(hres))
+ return;
+
+ SET_EXPECT(GetBindInfo);
+ expect_hrResult = MK_E_SYNTAX;
+ hres = IInternetProtocol_Start(protocol, wszIndexHtml, &protocol_sink, &bind_info, 0, 0);
+ ok(hres == MK_E_SYNTAX, "Start failed: %08lx, expected MK_E_SYNTAX\n", hres);
+ CHECK_CALLED(GetBindInfo);
+
+ SET_EXPECT(GetBindInfo);
+ SET_EXPECT(ReportProgress_DIRECTBIND);
+ SET_EXPECT(ReportResult);
+ expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
+ hres = IInternetProtocol_Start(protocol, index_url, &protocol_sink, &bind_info, 0, 0);
+ ok(hres == INET_E_RESOURCE_NOT_FOUND,
+ "Start failed: %08lx expected INET_E_RESOURCE_NOT_FOUND\n", hres);
+ CHECK_CALLED(GetBindInfo);
+ todo_wine { CHECK_CALLED(ReportProgress_DIRECTBIND); }
+ CHECK_CALLED(ReportResult);
+
+ IInternetProtocol_Release(protocol);
+
+ hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
+ &IID_IInternetProtocol, (void**)&protocol);
+ ok(hres == S_OK, "CoCreateInstance failed: %08lx\n", hres);
+ if(FAILED(hres))
+ return;
+
+ SET_EXPECT(GetBindInfo);
+ SET_EXPECT(ReportProgress_DIRECTBIND);
+ SET_EXPECT(ReportResult);
+ expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
+ hres = IInternetProtocol_Start(protocol, index_url2, &protocol_sink, &bind_info, 0, 0);
+ ok(hres == INET_E_RESOURCE_NOT_FOUND,
+ "Start failed: %08lx, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
+ CHECK_CALLED(GetBindInfo);
+ todo_wine { CHECK_CALLED(ReportProgress_DIRECTBIND); }
+ CHECK_CALLED(ReportResult);
+
+ IInternetProtocol_Release(protocol);
+}
+
+START_TEST(protocol)
+{
+ OleInitialize(NULL);
+
+ test_file_protocol();
+
+ OleUninitialize();
+}
More information about the wine-patches
mailing list