2 * Copyright 2006 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
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(itss
);
37 const IInternetProtocolVtbl
*lpInternetProtocolVtbl
;
42 struct chmFile
*chm_file
;
43 struct chmUnitInfo chm_object
;
46 #define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
48 static void release_chm(ITSProtocol
*This
)
51 chm_close(This
->chm_file
);
52 This
->chm_file
= NULL
;
57 #define PROTOCOL_THIS(iface) DEFINE_THIS(ITSProtocol, InternetProtocol, iface)
59 static HRESULT WINAPI
ITSProtocol_QueryInterface(IInternetProtocol
*iface
, REFIID riid
, void **ppv
)
61 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
64 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
65 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
66 *ppv
= PROTOCOL(This
);
67 }else if(IsEqualGUID(&IID_IInternetProtocolRoot
, riid
)) {
68 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This
, ppv
);
69 *ppv
= PROTOCOL(This
);
70 }else if(IsEqualGUID(&IID_IInternetProtocol
, riid
)) {
71 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This
, ppv
);
72 *ppv
= PROTOCOL(This
);
76 IInternetProtocol_AddRef(iface
);
80 WARN("not supported interface %s\n", debugstr_guid(riid
));
84 static ULONG WINAPI
ITSProtocol_AddRef(IInternetProtocol
*iface
)
86 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
87 LONG ref
= InterlockedIncrement(&This
->ref
);
88 TRACE("(%p) ref=%d\n", This
, ref
);
92 static ULONG WINAPI
ITSProtocol_Release(IInternetProtocol
*iface
)
94 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
95 LONG ref
= InterlockedDecrement(&This
->ref
);
97 TRACE("(%p) ref=%d\n", This
, ref
);
101 HeapFree(GetProcessHeap(), 0, This
);
109 static LPCWSTR
skip_schema(LPCWSTR url
)
111 static const WCHAR its_schema
[] = {'i','t','s',':'};
112 static const WCHAR msits_schema
[] = {'m','s','-','i','t','s',':'};
113 static const WCHAR mk_schema
[] = {'m','k',':','@','M','S','I','T','S','t','o','r','e',':'};
115 if(!strncmpiW(its_schema
, url
, sizeof(its_schema
)/sizeof(WCHAR
)))
116 return url
+sizeof(its_schema
)/sizeof(WCHAR
);
117 if(!strncmpiW(msits_schema
, url
, sizeof(msits_schema
)/sizeof(WCHAR
)))
118 return url
+sizeof(msits_schema
)/sizeof(WCHAR
);
119 if(!strncmpiW(mk_schema
, url
, sizeof(mk_schema
)/sizeof(WCHAR
)))
120 return url
+sizeof(mk_schema
)/sizeof(WCHAR
);
125 static HRESULT
report_result(IInternetProtocolSink
*sink
, HRESULT hres
)
127 IInternetProtocolSink_ReportResult(sink
, hres
, 0, NULL
);
131 static HRESULT WINAPI
ITSProtocol_Start(IInternetProtocol
*iface
, LPCWSTR szUrl
,
132 IInternetProtocolSink
*pOIProtSink
, IInternetBindInfo
*pOIBindInfo
,
133 DWORD grfPI
, DWORD dwReserved
)
135 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
137 DWORD bindf
= 0, len
;
138 LPWSTR file_name
, mime
;
139 LPCWSTR object_name
, path
;
140 struct chmFile
*chm_file
;
141 struct chmUnitInfo chm_object
;
145 static const WCHAR separator
[] = {':',':',0};
147 TRACE("(%p)->(%s %p %p %08x %d)\n", This
, debugstr_w(szUrl
), pOIProtSink
,
148 pOIBindInfo
, grfPI
, dwReserved
);
150 path
= skip_schema(szUrl
);
152 return INET_E_USE_DEFAULT_PROTOCOLHANDLER
;
154 memset(&bindinfo
, 0, sizeof(bindinfo
));
155 bindinfo
.cbSize
= sizeof(BINDINFO
);
156 hres
= IInternetBindInfo_GetBindInfo(pOIBindInfo
, &bindf
, &bindinfo
);
158 WARN("GetBindInfo failed: %08x\n", hres
);
162 ReleaseBindInfo(&bindinfo
);
164 object_name
= strstrW(path
, separator
);
166 WARN("invalid url\n");
167 return report_result(pOIProtSink
, STG_E_FILENOTFOUND
);
170 len
= object_name
-path
;
171 file_name
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
172 memcpy(file_name
, path
, len
*sizeof(WCHAR
));
174 chm_file
= chm_openW(file_name
);
176 WARN("Could not open chm file\n");
177 return report_result(pOIProtSink
, STG_E_FILENOTFOUND
);
181 memset(&chm_object
, 0, sizeof(chm_object
));
182 res
= chm_resolve_object(chm_file
, object_name
, &chm_object
);
183 if(res
!= CHM_RESOLVE_SUCCESS
) {
184 WARN("Could not resolve chm object\n");
186 return report_result(pOIProtSink
, STG_E_FILENOTFOUND
);
189 IInternetProtocolSink_ReportProgress(pOIProtSink
, BINDSTATUS_SENDINGREQUEST
, object_name
+1);
191 /* FIXME: Native doesn't use FindMimeFromData */
192 hres
= FindMimeFromData(NULL
, szUrl
, NULL
, 0, NULL
, 0, &mime
, 0);
193 if(SUCCEEDED(hres
)) {
194 IInternetProtocolSink_ReportProgress(pOIProtSink
, BINDSTATUS_MIMETYPEAVAILABLE
, mime
);
198 hres
= IInternetProtocolSink_ReportData(pOIProtSink
,
199 BSCF_FIRSTDATANOTIFICATION
|BSCF_DATAFULLYAVAILABLE
,
200 chm_object
.length
, chm_object
.length
);
202 WARN("ReportData failed: %08x\n", hres
);
204 return report_result(pOIProtSink
, hres
);
207 hres
= IInternetProtocolSink_ReportProgress(pOIProtSink
, BINDSTATUS_BEGINDOWNLOADDATA
, NULL
);
209 release_chm(This
); /* Native leaks handle here */
210 This
->chm_file
= chm_file
;
211 memcpy(&This
->chm_object
, &chm_object
, sizeof(chm_object
));
213 return report_result(pOIProtSink
, hres
);
216 static HRESULT WINAPI
ITSProtocol_Continue(IInternetProtocol
*iface
, PROTOCOLDATA
*pProtocolData
)
218 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
219 FIXME("(%p)->(%p)\n", This
, pProtocolData
);
223 static HRESULT WINAPI
ITSProtocol_Abort(IInternetProtocol
*iface
, HRESULT hrReason
,
226 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
227 FIXME("(%p)->(%08x %08x)\n", This
, hrReason
, dwOptions
);
231 static HRESULT WINAPI
ITSProtocol_Terminate(IInternetProtocol
*iface
, DWORD dwOptions
)
233 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
235 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
240 static HRESULT WINAPI
ITSProtocol_Suspend(IInternetProtocol
*iface
)
242 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
243 FIXME("(%p)\n", This
);
247 static HRESULT WINAPI
ITSProtocol_Resume(IInternetProtocol
*iface
)
249 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
250 FIXME("(%p)\n", This
);
254 static HRESULT WINAPI
ITSProtocol_Read(IInternetProtocol
*iface
, void *pv
,
255 ULONG cb
, ULONG
*pcbRead
)
257 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
259 TRACE("(%p)->(%p %u %p)\n", This
, pv
, cb
, pcbRead
);
262 return INET_E_DATA_NOT_AVAILABLE
;
264 *pcbRead
= chm_retrieve_object(This
->chm_file
, &This
->chm_object
, pv
, This
->offset
, cb
);
265 This
->offset
+= *pcbRead
;
267 return *pcbRead
? S_OK
: S_FALSE
;
270 static HRESULT WINAPI
ITSProtocol_Seek(IInternetProtocol
*iface
, LARGE_INTEGER dlibMove
,
271 DWORD dwOrigin
, ULARGE_INTEGER
*plibNewPosition
)
273 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
274 FIXME("(%p)->(%d %d %p)\n", This
, dlibMove
.u
.LowPart
, dwOrigin
, plibNewPosition
);
278 static HRESULT WINAPI
ITSProtocol_LockRequest(IInternetProtocol
*iface
, DWORD dwOptions
)
280 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
282 TRACE("(%p)->(%08x)\n", This
, dwOptions
);
287 static HRESULT WINAPI
ITSProtocol_UnlockRequest(IInternetProtocol
*iface
)
289 ITSProtocol
*This
= PROTOCOL_THIS(iface
);
291 TRACE("(%p)\n", This
);
298 static const IInternetProtocolVtbl ITSProtocolVtbl
= {
299 ITSProtocol_QueryInterface
,
303 ITSProtocol_Continue
,
305 ITSProtocol_Terminate
,
310 ITSProtocol_LockRequest
,
311 ITSProtocol_UnlockRequest
314 HRESULT
ITSProtocol_create(IUnknown
*pUnkOuter
, LPVOID
*ppobj
)
318 TRACE("(%p %p)\n", pUnkOuter
, ppobj
);
322 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ITSProtocol
));
324 ret
->lpInternetProtocolVtbl
= &ITSProtocolVtbl
;
327 *ppobj
= PROTOCOL(ret
);