xref: /reactos/dll/win32/urlmon/file.c (revision 6c3c2e33)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Copyright 2005 Jacek Caban
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck  *
9c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12c2c66affSColin Finck  * Lesser General Public License for more details.
13c2c66affSColin Finck  *
14c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17c2c66affSColin Finck  */
18c2c66affSColin Finck 
19c2c66affSColin Finck #include "urlmon_main.h"
20143d4fdbSAmine Khaldi #include "winreg.h"
21143d4fdbSAmine Khaldi #include "shlwapi.h"
22143d4fdbSAmine Khaldi 
23143d4fdbSAmine Khaldi #include "wine/debug.h"
24143d4fdbSAmine Khaldi 
25143d4fdbSAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
26c2c66affSColin Finck 
27c2c66affSColin Finck typedef struct {
28*6c3c2e33SAmine Khaldi     IUnknown            IUnknown_inner;
29c2c66affSColin Finck     IInternetProtocolEx IInternetProtocolEx_iface;
30c2c66affSColin Finck     IInternetPriority   IInternetPriority_iface;
31c2c66affSColin Finck 
32d0eebfbdSAmine Khaldi     IUnknown *outer;
33d0eebfbdSAmine Khaldi 
34c2c66affSColin Finck     HANDLE file;
35c2c66affSColin Finck     ULONG size;
36c2c66affSColin Finck     LONG priority;
37c2c66affSColin Finck 
38c2c66affSColin Finck     LONG ref;
39c2c66affSColin Finck } FileProtocol;
40c2c66affSColin Finck 
impl_from_IUnknown(IUnknown * iface)41d0eebfbdSAmine Khaldi static inline FileProtocol *impl_from_IUnknown(IUnknown *iface)
42d0eebfbdSAmine Khaldi {
43*6c3c2e33SAmine Khaldi     return CONTAINING_RECORD(iface, FileProtocol, IUnknown_inner);
44d0eebfbdSAmine Khaldi }
45d0eebfbdSAmine Khaldi 
impl_from_IInternetProtocolEx(IInternetProtocolEx * iface)46c2c66affSColin Finck static inline FileProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
47c2c66affSColin Finck {
48c2c66affSColin Finck     return CONTAINING_RECORD(iface, FileProtocol, IInternetProtocolEx_iface);
49c2c66affSColin Finck }
50c2c66affSColin Finck 
impl_from_IInternetPriority(IInternetPriority * iface)51c2c66affSColin Finck static inline FileProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
52c2c66affSColin Finck {
53c2c66affSColin Finck     return CONTAINING_RECORD(iface, FileProtocol, IInternetPriority_iface);
54c2c66affSColin Finck }
55c2c66affSColin Finck 
FileProtocolUnk_QueryInterface(IUnknown * iface,REFIID riid,void ** ppv)56d0eebfbdSAmine Khaldi static HRESULT WINAPI FileProtocolUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
57c2c66affSColin Finck {
58d0eebfbdSAmine Khaldi     FileProtocol *This = impl_from_IUnknown(iface);
59c2c66affSColin Finck 
60c2c66affSColin Finck     *ppv = NULL;
61c2c66affSColin Finck     if(IsEqualGUID(&IID_IUnknown, riid)) {
62c2c66affSColin Finck         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
63*6c3c2e33SAmine Khaldi         *ppv = &This->IUnknown_inner;
64c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
65c2c66affSColin Finck         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
66c2c66affSColin Finck         *ppv = &This->IInternetProtocolEx_iface;
67c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
68c2c66affSColin Finck         TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
69c2c66affSColin Finck         *ppv = &This->IInternetProtocolEx_iface;
70c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
71c2c66affSColin Finck         TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
72c2c66affSColin Finck         *ppv = &This->IInternetProtocolEx_iface;
73c2c66affSColin Finck     }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
74c2c66affSColin Finck         TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
75c2c66affSColin Finck         *ppv = &This->IInternetPriority_iface;
76c2c66affSColin Finck     }
77c2c66affSColin Finck 
78c2c66affSColin Finck     if(*ppv) {
79d0eebfbdSAmine Khaldi         IUnknown_AddRef((IUnknown*)*ppv);
80c2c66affSColin Finck         return S_OK;
81c2c66affSColin Finck     }
82c2c66affSColin Finck 
83c2c66affSColin Finck     WARN("not supported interface %s\n", debugstr_guid(riid));
84c2c66affSColin Finck     return E_NOINTERFACE;
85c2c66affSColin Finck }
86c2c66affSColin Finck 
FileProtocolUnk_AddRef(IUnknown * iface)87d0eebfbdSAmine Khaldi static ULONG WINAPI FileProtocolUnk_AddRef(IUnknown *iface)
88c2c66affSColin Finck {
89d0eebfbdSAmine Khaldi     FileProtocol *This = impl_from_IUnknown(iface);
90c2c66affSColin Finck     LONG ref = InterlockedIncrement(&This->ref);
91c2c66affSColin Finck     TRACE("(%p) ref=%d\n", This, ref);
92c2c66affSColin Finck     return ref;
93c2c66affSColin Finck }
94c2c66affSColin Finck 
FileProtocolUnk_Release(IUnknown * iface)95d0eebfbdSAmine Khaldi static ULONG WINAPI FileProtocolUnk_Release(IUnknown *iface)
96c2c66affSColin Finck {
97d0eebfbdSAmine Khaldi     FileProtocol *This = impl_from_IUnknown(iface);
98c2c66affSColin Finck     LONG ref = InterlockedDecrement(&This->ref);
99c2c66affSColin Finck 
100c2c66affSColin Finck     TRACE("(%p) ref=%d\n", This, ref);
101c2c66affSColin Finck 
102c2c66affSColin Finck     if(!ref) {
103c2c66affSColin Finck         if(This->file != INVALID_HANDLE_VALUE)
104c2c66affSColin Finck             CloseHandle(This->file);
105c2c66affSColin Finck         heap_free(This);
106c2c66affSColin Finck 
107c2c66affSColin Finck         URLMON_UnlockModule();
108c2c66affSColin Finck     }
109c2c66affSColin Finck 
110c2c66affSColin Finck     return ref;
111c2c66affSColin Finck }
112c2c66affSColin Finck 
113d0eebfbdSAmine Khaldi static const IUnknownVtbl FileProtocolUnkVtbl = {
114d0eebfbdSAmine Khaldi     FileProtocolUnk_QueryInterface,
115d0eebfbdSAmine Khaldi     FileProtocolUnk_AddRef,
116d0eebfbdSAmine Khaldi     FileProtocolUnk_Release
117d0eebfbdSAmine Khaldi };
118d0eebfbdSAmine Khaldi 
FileProtocol_QueryInterface(IInternetProtocolEx * iface,REFIID riid,void ** ppv)119d0eebfbdSAmine Khaldi static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
120d0eebfbdSAmine Khaldi {
121d0eebfbdSAmine Khaldi     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
122d0eebfbdSAmine Khaldi     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
123d0eebfbdSAmine Khaldi     return IUnknown_QueryInterface(This->outer, riid, ppv);
124d0eebfbdSAmine Khaldi }
125d0eebfbdSAmine Khaldi 
FileProtocol_AddRef(IInternetProtocolEx * iface)126d0eebfbdSAmine Khaldi static ULONG WINAPI FileProtocol_AddRef(IInternetProtocolEx *iface)
127d0eebfbdSAmine Khaldi {
128d0eebfbdSAmine Khaldi     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
129d0eebfbdSAmine Khaldi     TRACE("(%p)\n", This);
130d0eebfbdSAmine Khaldi     return IUnknown_AddRef(This->outer);
131d0eebfbdSAmine Khaldi }
132d0eebfbdSAmine Khaldi 
FileProtocol_Release(IInternetProtocolEx * iface)133d0eebfbdSAmine Khaldi static ULONG WINAPI FileProtocol_Release(IInternetProtocolEx *iface)
134d0eebfbdSAmine Khaldi {
135d0eebfbdSAmine Khaldi     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
136d0eebfbdSAmine Khaldi     TRACE("(%p)\n", This);
137d0eebfbdSAmine Khaldi     return IUnknown_Release(This->outer);
138d0eebfbdSAmine Khaldi }
139d0eebfbdSAmine Khaldi 
FileProtocol_Start(IInternetProtocolEx * iface,LPCWSTR szUrl,IInternetProtocolSink * pOIProtSink,IInternetBindInfo * pOIBindInfo,DWORD grfPI,HANDLE_PTR dwReserved)140c2c66affSColin Finck static HRESULT WINAPI FileProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
141c2c66affSColin Finck         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
142c2c66affSColin Finck         DWORD grfPI, HANDLE_PTR dwReserved)
143c2c66affSColin Finck {
144c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
145c2c66affSColin Finck     IUri *uri;
146c2c66affSColin Finck     HRESULT hres;
147c2c66affSColin Finck 
148c2c66affSColin Finck     TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
149c2c66affSColin Finck             pOIBindInfo, grfPI, dwReserved);
150c2c66affSColin Finck 
151c2c66affSColin Finck     hres = CreateUri(szUrl, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
152c2c66affSColin Finck     if(FAILED(hres))
153c2c66affSColin Finck         return hres;
154c2c66affSColin Finck 
155c2c66affSColin Finck     hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink,
156c2c66affSColin Finck             pOIBindInfo, grfPI, (HANDLE*)dwReserved);
157c2c66affSColin Finck 
158c2c66affSColin Finck     IUri_Release(uri);
159c2c66affSColin Finck     return hres;
160c2c66affSColin Finck }
161c2c66affSColin Finck 
FileProtocol_Continue(IInternetProtocolEx * iface,PROTOCOLDATA * pProtocolData)162c2c66affSColin Finck static HRESULT WINAPI FileProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
163c2c66affSColin Finck {
164c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
165c2c66affSColin Finck     FIXME("(%p)->(%p)\n", This, pProtocolData);
166c2c66affSColin Finck     return E_NOTIMPL;
167c2c66affSColin Finck }
168c2c66affSColin Finck 
FileProtocol_Abort(IInternetProtocolEx * iface,HRESULT hrReason,DWORD dwOptions)169c2c66affSColin Finck static HRESULT WINAPI FileProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
170c2c66affSColin Finck         DWORD dwOptions)
171c2c66affSColin Finck {
172c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
173c2c66affSColin Finck     FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
174c2c66affSColin Finck     return E_NOTIMPL;
175c2c66affSColin Finck }
176c2c66affSColin Finck 
FileProtocol_Terminate(IInternetProtocolEx * iface,DWORD dwOptions)177c2c66affSColin Finck static HRESULT WINAPI FileProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
178c2c66affSColin Finck {
179c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
180c2c66affSColin Finck 
181c2c66affSColin Finck     TRACE("(%p)->(%08x)\n", This, dwOptions);
182c2c66affSColin Finck 
183c2c66affSColin Finck     return S_OK;
184c2c66affSColin Finck }
185c2c66affSColin Finck 
FileProtocol_Suspend(IInternetProtocolEx * iface)186c2c66affSColin Finck static HRESULT WINAPI FileProtocol_Suspend(IInternetProtocolEx *iface)
187c2c66affSColin Finck {
188c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
189c2c66affSColin Finck     FIXME("(%p)\n", This);
190c2c66affSColin Finck     return E_NOTIMPL;
191c2c66affSColin Finck }
192c2c66affSColin Finck 
FileProtocol_Resume(IInternetProtocolEx * iface)193c2c66affSColin Finck static HRESULT WINAPI FileProtocol_Resume(IInternetProtocolEx *iface)
194c2c66affSColin Finck {
195c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
196c2c66affSColin Finck     FIXME("(%p)\n", This);
197c2c66affSColin Finck     return E_NOTIMPL;
198c2c66affSColin Finck }
199c2c66affSColin Finck 
FileProtocol_Read(IInternetProtocolEx * iface,void * pv,ULONG cb,ULONG * pcbRead)200c2c66affSColin Finck static HRESULT WINAPI FileProtocol_Read(IInternetProtocolEx *iface, void *pv,
201c2c66affSColin Finck         ULONG cb, ULONG *pcbRead)
202c2c66affSColin Finck {
203c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
204c2c66affSColin Finck     DWORD read = 0;
205c2c66affSColin Finck 
206c2c66affSColin Finck     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
207c2c66affSColin Finck 
208c2c66affSColin Finck     if (pcbRead)
209c2c66affSColin Finck         *pcbRead = 0;
210c2c66affSColin Finck 
211c2c66affSColin Finck     if(This->file == INVALID_HANDLE_VALUE)
212c2c66affSColin Finck         return INET_E_DATA_NOT_AVAILABLE;
213c2c66affSColin Finck 
214c2c66affSColin Finck     if (!ReadFile(This->file, pv, cb, &read, NULL))
215c2c66affSColin Finck         return INET_E_DOWNLOAD_FAILURE;
216c2c66affSColin Finck 
217c2c66affSColin Finck     if(pcbRead)
218c2c66affSColin Finck         *pcbRead = read;
219c2c66affSColin Finck 
220c2c66affSColin Finck     return cb == read ? S_OK : S_FALSE;
221c2c66affSColin Finck }
222c2c66affSColin Finck 
FileProtocol_Seek(IInternetProtocolEx * iface,LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER * plibNewPosition)223c2c66affSColin Finck static HRESULT WINAPI FileProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
224c2c66affSColin Finck         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
225c2c66affSColin Finck {
226c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
227c2c66affSColin Finck     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
228c2c66affSColin Finck     return E_NOTIMPL;
229c2c66affSColin Finck }
230c2c66affSColin Finck 
FileProtocol_LockRequest(IInternetProtocolEx * iface,DWORD dwOptions)231c2c66affSColin Finck static HRESULT WINAPI FileProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
232c2c66affSColin Finck {
233c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
234c2c66affSColin Finck 
235c2c66affSColin Finck     TRACE("(%p)->(%08x)\n", This, dwOptions);
236c2c66affSColin Finck 
237c2c66affSColin Finck     return S_OK;
238c2c66affSColin Finck }
239c2c66affSColin Finck 
FileProtocol_UnlockRequest(IInternetProtocolEx * iface)240c2c66affSColin Finck static HRESULT WINAPI FileProtocol_UnlockRequest(IInternetProtocolEx *iface)
241c2c66affSColin Finck {
242c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
243c2c66affSColin Finck 
244c2c66affSColin Finck     TRACE("(%p)\n", This);
245c2c66affSColin Finck 
246c2c66affSColin Finck     return S_OK;
247c2c66affSColin Finck }
248c2c66affSColin Finck 
report_result(IInternetProtocolSink * protocol_sink,HRESULT hres,DWORD res)249c2c66affSColin Finck static inline HRESULT report_result(IInternetProtocolSink *protocol_sink, HRESULT hres, DWORD res)
250c2c66affSColin Finck {
251c2c66affSColin Finck     IInternetProtocolSink_ReportResult(protocol_sink, hres, res, NULL);
252c2c66affSColin Finck     return hres;
253c2c66affSColin Finck }
254c2c66affSColin Finck 
FileProtocol_StartEx(IInternetProtocolEx * iface,IUri * pUri,IInternetProtocolSink * pOIProtSink,IInternetBindInfo * pOIBindInfo,DWORD grfPI,HANDLE * dwReserved)255c2c66affSColin Finck static HRESULT WINAPI FileProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
256c2c66affSColin Finck         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
257c2c66affSColin Finck         DWORD grfPI, HANDLE *dwReserved)
258c2c66affSColin Finck {
259c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetProtocolEx(iface);
260c2c66affSColin Finck     WCHAR path[MAX_PATH], *ptr;
261c2c66affSColin Finck     LARGE_INTEGER file_size;
262c2c66affSColin Finck     HANDLE file_handle;
263c2c66affSColin Finck     BINDINFO bindinfo;
264c2c66affSColin Finck     DWORD grfBINDF = 0;
265c2c66affSColin Finck     DWORD scheme, size;
266c2c66affSColin Finck     LPWSTR mime = NULL;
267c2c66affSColin Finck     WCHAR null_char = 0;
268c2c66affSColin Finck     BSTR ext;
269c2c66affSColin Finck     HRESULT hres;
270c2c66affSColin Finck 
271c2c66affSColin Finck     TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink,
272c2c66affSColin Finck             pOIBindInfo, grfPI, dwReserved);
273c2c66affSColin Finck 
274c2c66affSColin Finck     if(!pUri)
275c2c66affSColin Finck         return E_INVALIDARG;
276c2c66affSColin Finck 
277c2c66affSColin Finck     scheme = 0;
278c2c66affSColin Finck     hres = IUri_GetScheme(pUri, &scheme);
279c2c66affSColin Finck     if(FAILED(hres))
280c2c66affSColin Finck         return hres;
281c2c66affSColin Finck     if(scheme != URL_SCHEME_FILE)
282c2c66affSColin Finck         return E_INVALIDARG;
283c2c66affSColin Finck 
284c2c66affSColin Finck     memset(&bindinfo, 0, sizeof(bindinfo));
285c2c66affSColin Finck     bindinfo.cbSize = sizeof(BINDINFO);
286c2c66affSColin Finck     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo);
287c2c66affSColin Finck     if(FAILED(hres)) {
288c2c66affSColin Finck         WARN("GetBindInfo failed: %08x\n", hres);
289c2c66affSColin Finck         return hres;
290c2c66affSColin Finck     }
291c2c66affSColin Finck 
292c2c66affSColin Finck     ReleaseBindInfo(&bindinfo);
293c2c66affSColin Finck 
294c2c66affSColin Finck     if(!(grfBINDF & BINDF_FROMURLMON))
295c2c66affSColin Finck         IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DIRECTBIND, NULL);
296c2c66affSColin Finck 
297c2c66affSColin Finck     if(This->file != INVALID_HANDLE_VALUE) {
298c2c66affSColin Finck         IInternetProtocolSink_ReportData(pOIProtSink,
299c2c66affSColin Finck                 BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION,
300c2c66affSColin Finck                 This->size, This->size);
301c2c66affSColin Finck         return S_OK;
302c2c66affSColin Finck     }
303c2c66affSColin Finck 
304c2c66affSColin Finck     IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, &null_char);
305c2c66affSColin Finck 
306c2c66affSColin Finck     size = 0;
307ad73c0a0SAmine Khaldi     hres = CoInternetParseIUri(pUri, PARSE_PATH_FROM_URL, 0, path, ARRAY_SIZE(path), &size, 0);
308c2c66affSColin Finck     if(FAILED(hres)) {
309c2c66affSColin Finck         WARN("CoInternetParseIUri failed: %08x\n", hres);
310c2c66affSColin Finck         return report_result(pOIProtSink, hres, 0);
311c2c66affSColin Finck     }
312c2c66affSColin Finck 
313c2c66affSColin Finck     file_handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
314c2c66affSColin Finck             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
315*6c3c2e33SAmine Khaldi     if(file_handle == INVALID_HANDLE_VALUE && (ptr = wcsrchr(path, '#'))) {
316c2c66affSColin Finck         /* If path contains fragment part, try without it. */
317c2c66affSColin Finck         *ptr = 0;
318c2c66affSColin Finck         file_handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
319c2c66affSColin Finck                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
320c2c66affSColin Finck     }
321c2c66affSColin Finck     if(file_handle == INVALID_HANDLE_VALUE)
322c2c66affSColin Finck         return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, GetLastError());
323c2c66affSColin Finck 
324c2c66affSColin Finck     if(!GetFileSizeEx(file_handle, &file_size)) {
325c2c66affSColin Finck         CloseHandle(file_handle);
326c2c66affSColin Finck         return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, GetLastError());
327c2c66affSColin Finck     }
328c2c66affSColin Finck 
329c2c66affSColin Finck     This->file = file_handle;
330c2c66affSColin Finck     This->size = file_size.u.LowPart;
331c2c66affSColin Finck     IInternetProtocolSink_ReportProgress(pOIProtSink,  BINDSTATUS_CACHEFILENAMEAVAILABLE, path);
332c2c66affSColin Finck 
333c2c66affSColin Finck     hres = IUri_GetExtension(pUri, &ext);
334c2c66affSColin Finck     if(SUCCEEDED(hres)) {
335c2c66affSColin Finck         if(hres == S_OK && *ext) {
336*6c3c2e33SAmine Khaldi             if((ptr = wcschr(ext, '#')))
337c2c66affSColin Finck                 *ptr = 0;
338c2c66affSColin Finck             hres = find_mime_from_ext(ext, &mime);
339c2c66affSColin Finck             if(SUCCEEDED(hres)) {
340c2c66affSColin Finck                 IInternetProtocolSink_ReportProgress(pOIProtSink,
341c2c66affSColin Finck                         (grfBINDF & BINDF_FROMURLMON) ?
342c2c66affSColin Finck                         BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE : BINDSTATUS_MIMETYPEAVAILABLE,
343c2c66affSColin Finck                         mime);
344c2c66affSColin Finck                 CoTaskMemFree(mime);
345c2c66affSColin Finck             }
346c2c66affSColin Finck         }
347c2c66affSColin Finck         SysFreeString(ext);
348c2c66affSColin Finck     }
349c2c66affSColin Finck 
350c2c66affSColin Finck     IInternetProtocolSink_ReportData(pOIProtSink,
351c2c66affSColin Finck             BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION,
352c2c66affSColin Finck             This->size, This->size);
353c2c66affSColin Finck 
354c2c66affSColin Finck     return report_result(pOIProtSink, S_OK, 0);
355c2c66affSColin Finck }
356c2c66affSColin Finck 
357c2c66affSColin Finck static const IInternetProtocolExVtbl FileProtocolExVtbl = {
358c2c66affSColin Finck     FileProtocol_QueryInterface,
359c2c66affSColin Finck     FileProtocol_AddRef,
360c2c66affSColin Finck     FileProtocol_Release,
361c2c66affSColin Finck     FileProtocol_Start,
362c2c66affSColin Finck     FileProtocol_Continue,
363c2c66affSColin Finck     FileProtocol_Abort,
364c2c66affSColin Finck     FileProtocol_Terminate,
365c2c66affSColin Finck     FileProtocol_Suspend,
366c2c66affSColin Finck     FileProtocol_Resume,
367c2c66affSColin Finck     FileProtocol_Read,
368c2c66affSColin Finck     FileProtocol_Seek,
369c2c66affSColin Finck     FileProtocol_LockRequest,
370c2c66affSColin Finck     FileProtocol_UnlockRequest,
371c2c66affSColin Finck     FileProtocol_StartEx
372c2c66affSColin Finck };
373c2c66affSColin Finck 
FilePriority_QueryInterface(IInternetPriority * iface,REFIID riid,void ** ppv)374c2c66affSColin Finck static HRESULT WINAPI FilePriority_QueryInterface(IInternetPriority *iface,
375c2c66affSColin Finck                                                   REFIID riid, void **ppv)
376c2c66affSColin Finck {
377c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetPriority(iface);
378c2c66affSColin Finck     return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
379c2c66affSColin Finck }
380c2c66affSColin Finck 
FilePriority_AddRef(IInternetPriority * iface)381c2c66affSColin Finck static ULONG WINAPI FilePriority_AddRef(IInternetPriority *iface)
382c2c66affSColin Finck {
383c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetPriority(iface);
384c2c66affSColin Finck     return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
385c2c66affSColin Finck }
386c2c66affSColin Finck 
FilePriority_Release(IInternetPriority * iface)387c2c66affSColin Finck static ULONG WINAPI FilePriority_Release(IInternetPriority *iface)
388c2c66affSColin Finck {
389c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetPriority(iface);
390c2c66affSColin Finck     return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
391c2c66affSColin Finck }
392c2c66affSColin Finck 
FilePriority_SetPriority(IInternetPriority * iface,LONG nPriority)393c2c66affSColin Finck static HRESULT WINAPI FilePriority_SetPriority(IInternetPriority *iface, LONG nPriority)
394c2c66affSColin Finck {
395c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetPriority(iface);
396c2c66affSColin Finck 
397c2c66affSColin Finck     TRACE("(%p)->(%d)\n", This, nPriority);
398c2c66affSColin Finck 
399c2c66affSColin Finck     This->priority = nPriority;
400c2c66affSColin Finck     return S_OK;
401c2c66affSColin Finck }
402c2c66affSColin Finck 
FilePriority_GetPriority(IInternetPriority * iface,LONG * pnPriority)403c2c66affSColin Finck static HRESULT WINAPI FilePriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
404c2c66affSColin Finck {
405c2c66affSColin Finck     FileProtocol *This = impl_from_IInternetPriority(iface);
406c2c66affSColin Finck 
407c2c66affSColin Finck     TRACE("(%p)->(%p)\n", This, pnPriority);
408c2c66affSColin Finck 
409c2c66affSColin Finck     *pnPriority = This->priority;
410c2c66affSColin Finck     return S_OK;
411c2c66affSColin Finck }
412c2c66affSColin Finck 
413c2c66affSColin Finck static const IInternetPriorityVtbl FilePriorityVtbl = {
414c2c66affSColin Finck     FilePriority_QueryInterface,
415c2c66affSColin Finck     FilePriority_AddRef,
416c2c66affSColin Finck     FilePriority_Release,
417c2c66affSColin Finck     FilePriority_SetPriority,
418c2c66affSColin Finck     FilePriority_GetPriority
419c2c66affSColin Finck };
420c2c66affSColin Finck 
FileProtocol_Construct(IUnknown * outer,LPVOID * ppobj)421d0eebfbdSAmine Khaldi HRESULT FileProtocol_Construct(IUnknown *outer, LPVOID *ppobj)
422c2c66affSColin Finck {
423c2c66affSColin Finck     FileProtocol *ret;
424c2c66affSColin Finck 
425d0eebfbdSAmine Khaldi     TRACE("(%p %p)\n", outer, ppobj);
426c2c66affSColin Finck 
427c2c66affSColin Finck     URLMON_LockModule();
428c2c66affSColin Finck 
429c2c66affSColin Finck     ret = heap_alloc(sizeof(FileProtocol));
430c2c66affSColin Finck 
431*6c3c2e33SAmine Khaldi     ret->IUnknown_inner.lpVtbl = &FileProtocolUnkVtbl;
432c2c66affSColin Finck     ret->IInternetProtocolEx_iface.lpVtbl = &FileProtocolExVtbl;
433c2c66affSColin Finck     ret->IInternetPriority_iface.lpVtbl = &FilePriorityVtbl;
434c2c66affSColin Finck     ret->file = INVALID_HANDLE_VALUE;
435c2c66affSColin Finck     ret->priority = 0;
436c2c66affSColin Finck     ret->ref = 1;
437*6c3c2e33SAmine Khaldi     ret->outer = outer ? outer : &ret->IUnknown_inner;
438c2c66affSColin Finck 
439*6c3c2e33SAmine Khaldi     *ppobj = &ret->IUnknown_inner;
440c2c66affSColin Finck     return S_OK;
441c2c66affSColin Finck }
442