2 * Copyright 2007 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "urlmon_main.h"
20 #include "wine/debug.h"
22 #define NO_SHLWAPI_REG
25 WINE_DEFAULT_DEBUG_CHANNEL(urlmon
);
28 IUnknown IUnknown_inner
;
29 IInternetProtocolEx IInternetProtocolEx_iface
;
37 static inline MkProtocol
*impl_from_IUnknown(IUnknown
*iface
)
39 return CONTAINING_RECORD(iface
, MkProtocol
, IUnknown_inner
);
42 static inline MkProtocol
*impl_from_IInternetProtocolEx(IInternetProtocolEx
*iface
)
44 return CONTAINING_RECORD(iface
, MkProtocol
, IInternetProtocolEx_iface
);
47 static HRESULT WINAPI
MkProtocolUnk_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
49 MkProtocol
*This
= impl_from_IUnknown(iface
);
51 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
52 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
53 *ppv
= &This
->IUnknown_inner
;
54 }else if(IsEqualGUID(&IID_IInternetProtocolRoot
, riid
)) {
55 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This
, ppv
);
56 *ppv
= &This
->IInternetProtocolEx_iface
;
57 }else if(IsEqualGUID(&IID_IInternetProtocol
, riid
)) {
58 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This
, ppv
);
59 *ppv
= &This
->IInternetProtocolEx_iface
;
60 }else if(IsEqualGUID(&IID_IInternetProtocolEx
, riid
)) {
61 TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This
, ppv
);
62 *ppv
= &This
->IInternetProtocolEx_iface
;
65 WARN("not supported interface %s\n", debugstr_guid(riid
));
69 IUnknown_AddRef((IUnknown
*)*ppv
);
73 static ULONG WINAPI
MkProtocolUnk_AddRef(IUnknown
*iface
)
75 MkProtocol
*This
= impl_from_IUnknown(iface
);
76 LONG ref
= InterlockedIncrement(&This
->ref
);
77 TRACE("(%p) ref=%ld\n", This
, ref
);
81 static ULONG WINAPI
MkProtocolUnk_Release(IUnknown
*iface
)
83 MkProtocol
*This
= impl_from_IUnknown(iface
);
84 LONG ref
= InterlockedDecrement(&This
->ref
);
86 TRACE("(%p) ref=%ld\n", This
, ref
);
90 IStream_Release(This
->stream
);
94 URLMON_UnlockModule();
100 static const IUnknownVtbl MkProtocolUnkVtbl
= {
101 MkProtocolUnk_QueryInterface
,
102 MkProtocolUnk_AddRef
,
103 MkProtocolUnk_Release
106 static HRESULT WINAPI
MkProtocol_QueryInterface(IInternetProtocolEx
*iface
, REFIID riid
, void **ppv
)
108 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
109 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
110 return IUnknown_QueryInterface(This
->outer
, riid
, ppv
);
113 static ULONG WINAPI
MkProtocol_AddRef(IInternetProtocolEx
*iface
)
115 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
116 TRACE("(%p)\n", This
);
117 return IUnknown_AddRef(This
->outer
);
120 static ULONG WINAPI
MkProtocol_Release(IInternetProtocolEx
*iface
)
122 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
123 TRACE("(%p)\n", This
);
124 return IUnknown_Release(This
->outer
);
127 static HRESULT
report_result(IInternetProtocolSink
*sink
, HRESULT hres
, DWORD dwError
)
129 IInternetProtocolSink_ReportResult(sink
, hres
, dwError
, NULL
);
133 static HRESULT WINAPI
MkProtocol_Start(IInternetProtocolEx
*iface
, LPCWSTR szUrl
,
134 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
135 DWORD grfPI
, HANDLE_PTR dwReserved
)
137 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
141 TRACE("(%p)->(%s %p %p %08lx %Ix)\n", This
, debugstr_w(szUrl
), pOIProtSink
,
142 pOIBindInfo
, grfPI
, dwReserved
);
144 hres
= CreateUri(szUrl
, 0, 0, &uri
);
148 hres
= IInternetProtocolEx_StartEx(&This
->IInternetProtocolEx_iface
, uri
, pOIProtSink
,
149 pOIBindInfo
, grfPI
, (HANDLE
*)dwReserved
);
155 static HRESULT WINAPI
MkProtocol_Continue(IInternetProtocolEx
*iface
, PROTOCOLDATA
*pProtocolData
)
157 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
158 FIXME("(%p)->(%p)\n", This
, pProtocolData
);
162 static HRESULT WINAPI
MkProtocol_Abort(IInternetProtocolEx
*iface
, HRESULT hrReason
,
165 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
166 FIXME("(%p)->(%08lx %08lx)\n", This
, hrReason
, dwOptions
);
170 static HRESULT WINAPI
MkProtocol_Terminate(IInternetProtocolEx
*iface
, DWORD dwOptions
)
172 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
174 TRACE("(%p)->(%08lx)\n", This
, dwOptions
);
179 static HRESULT WINAPI
MkProtocol_Suspend(IInternetProtocolEx
*iface
)
181 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
182 FIXME("(%p)\n", This
);
186 static HRESULT WINAPI
MkProtocol_Resume(IInternetProtocolEx
*iface
)
188 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
189 FIXME("(%p)\n", This
);
193 static HRESULT WINAPI
MkProtocol_Read(IInternetProtocolEx
*iface
, void *pv
,
194 ULONG cb
, ULONG
*pcbRead
)
196 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
198 TRACE("(%p)->(%p %lu %p)\n", This
, pv
, cb
, pcbRead
);
203 return IStream_Read(This
->stream
, pv
, cb
, pcbRead
);
206 static HRESULT WINAPI
MkProtocol_Seek(IInternetProtocolEx
*iface
, LARGE_INTEGER dlibMove
,
207 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
209 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
210 FIXME("(%p)->(%ld %ld %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
214 static HRESULT WINAPI
MkProtocol_LockRequest(IInternetProtocolEx
*iface
, DWORD dwOptions
)
216 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
218 TRACE("(%p)->(%08lx)\n", This
, dwOptions
);
223 static HRESULT WINAPI
MkProtocol_UnlockRequest(IInternetProtocolEx
*iface
)
225 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
227 TRACE("(%p)\n", This
);
232 static HRESULT WINAPI
MkProtocol_StartEx(IInternetProtocolEx
*iface
, IUri
*pUri
,
233 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
234 DWORD grfPI
, HANDLE
*dwReserved
)
236 MkProtocol
*This
= impl_from_IInternetProtocolEx(iface
);
237 LPWSTR mime
, progid
, display_name
, colon_ptr
;
238 DWORD bindf
=0, eaten
=0, scheme
=0, len
;
239 BSTR url
, path
= NULL
;
240 IParseDisplayName
*pdn
;
247 TRACE("(%p)->(%p %p %p %08lx %p)\n", This
, pUri
, pOIProtSink
,
248 pOIBindInfo
, grfPI
, dwReserved
);
250 hres
= IUri_GetScheme(pUri
, &scheme
);
253 if(scheme
!= URL_SCHEME_MK
)
254 return INET_E_INVALID_URL
;
256 memset(&bindinfo
, 0, sizeof(bindinfo
));
257 bindinfo
.cbSize
= sizeof(BINDINFO
);
258 hres
= IInternetBindInfo_GetBindInfo(pOIBindInfo
, &bindf
, &bindinfo
);
260 WARN("GetBindInfo failed: %08lx\n", hres
);
264 ReleaseBindInfo(&bindinfo
);
266 IInternetProtocolSink_ReportProgress(pOIProtSink
, BINDSTATUS_SENDINGREQUEST
, NULL
);
268 hres
= IUri_GetDisplayUri(pUri
, &url
);
271 hres
= FindMimeFromData(NULL
, url
, NULL
, 0, NULL
, 0, &mime
, 0);
273 if(SUCCEEDED(hres
)) {
274 IInternetProtocolSink_ReportProgress(pOIProtSink
, BINDSTATUS_MIMETYPEAVAILABLE
, mime
);
278 hres
= IUri_GetPath(pUri
, &path
);
281 len
= SysStringLen(path
)+1;
282 hres
= UrlUnescapeW(path
, NULL
, &len
, URL_UNESCAPE_INPLACE
);
285 return report_result(pOIProtSink
, INET_E_RESOURCE_NOT_FOUND
, ERROR_INVALID_PARAMETER
);
288 progid
= path
+1; /* skip '@' symbol */
289 colon_ptr
= wcschr(path
, ':');
292 return report_result(pOIProtSink
, INET_E_RESOURCE_NOT_FOUND
, ERROR_INVALID_PARAMETER
);
295 len
= lstrlenW(path
);
296 display_name
= heap_alloc((len
+1)*sizeof(WCHAR
));
297 memcpy(display_name
, path
, (len
+1)*sizeof(WCHAR
));
299 progid
[colon_ptr
-progid
] = 0; /* overwrite ':' with NULL terminator */
300 hres
= CLSIDFromProgID(progid
, &clsid
);
304 heap_free(display_name
);
305 return report_result(pOIProtSink
, INET_E_RESOURCE_NOT_FOUND
, ERROR_INVALID_PARAMETER
);
308 hres
= CoCreateInstance(&clsid
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
309 &IID_IParseDisplayName
, (void**)&pdn
);
311 WARN("Could not create object %s\n", debugstr_guid(&clsid
));
312 heap_free(display_name
);
313 return report_result(pOIProtSink
, hres
, ERROR_INVALID_PARAMETER
);
316 hres
= IParseDisplayName_ParseDisplayName(pdn
, NULL
/* FIXME */, display_name
, &eaten
, &mon
);
317 heap_free(display_name
);
318 IParseDisplayName_Release(pdn
);
320 WARN("ParseDisplayName failed: %08lx\n", hres
);
321 return report_result(pOIProtSink
, hres
, ERROR_INVALID_PARAMETER
);
325 IStream_Release(This
->stream
);
329 hres
= IMoniker_BindToStorage(mon
, NULL
/* FIXME */, NULL
, &IID_IStream
, (void**)&This
->stream
);
330 IMoniker_Release(mon
);
332 WARN("BindToStorage failed: %08lx\n", hres
);
333 return report_result(pOIProtSink
, hres
, ERROR_INVALID_PARAMETER
);
336 hres
= IStream_Stat(This
->stream
, &statstg
, STATFLAG_NONAME
);
338 WARN("Stat failed: %08lx\n", hres
);
339 return report_result(pOIProtSink
, hres
, ERROR_INVALID_PARAMETER
);
342 IInternetProtocolSink_ReportData(pOIProtSink
,
343 BSCF_FIRSTDATANOTIFICATION
| BSCF_LASTDATANOTIFICATION
,
344 statstg
.cbSize
.u
.LowPart
, statstg
.cbSize
.u
.LowPart
);
345 return report_result(pOIProtSink
, S_OK
, ERROR_SUCCESS
);
348 static const IInternetProtocolExVtbl MkProtocolVtbl
= {
349 MkProtocol_QueryInterface
,
355 MkProtocol_Terminate
,
360 MkProtocol_LockRequest
,
361 MkProtocol_UnlockRequest
,
365 HRESULT
MkProtocol_Construct(IUnknown
*outer
, void **ppv
)
369 TRACE("(%p %p)\n", outer
, ppv
);
373 ret
= heap_alloc(sizeof(MkProtocol
));
375 ret
->IUnknown_inner
.lpVtbl
= &MkProtocolUnkVtbl
;
376 ret
->IInternetProtocolEx_iface
.lpVtbl
= &MkProtocolVtbl
;
378 ret
->outer
= outer
? outer
: &ret
->IUnknown_inner
;
382 * Native returns NULL ppobj and S_OK in CreateInstance if called with IID_IUnknown riid and no outer.
384 *ppv
= &ret
->IUnknown_inner
;