1 /*
2 * Copyright 2008 Piotr Caban
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #define COBJMACROS
20 #define NONAMELESSUNION
21
22 #include "config.h"
23
24 #include <stdarg.h>
25 #include <assert.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "msxml2.h"
31 #include "wininet.h"
32 #include "urlmon.h"
33 #include "winreg.h"
34 #include "shlwapi.h"
35
36 #include "wine/debug.h"
37
38 #include "msxml_private.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
41
42 struct bsc_t {
43 const struct IBindStatusCallbackVtbl *lpVtbl;
44
45 LONG ref;
46
47 void *obj;
48 HRESULT (*onDataAvailable)(void*,char*,DWORD);
49
50 IBinding *binding;
51 IStream *memstream;
52 };
53
54 static inline bsc_t *impl_from_IBindStatusCallback( IBindStatusCallback *iface )
55 {
56 return (bsc_t *)((char*)iface - FIELD_OFFSET(bsc_t, lpVtbl));
57 }
58
59 static HRESULT WINAPI bsc_QueryInterface(
60 IBindStatusCallback *iface,
61 REFIID riid,
62 LPVOID *ppobj )
63 {
64 if (IsEqualGUID(riid, &IID_IUnknown) ||
65 IsEqualGUID(riid, &IID_IBindStatusCallback))
66 {
67 IBindStatusCallback_AddRef( iface );
68 *ppobj = iface;
69 return S_OK;
70 }
71
72 TRACE("interface %s not implemented\n", debugstr_guid(riid));
73 return E_NOINTERFACE;
74 }
75
76 static ULONG WINAPI bsc_AddRef(
77 IBindStatusCallback *iface )
78 {
79 bsc_t *This = impl_from_IBindStatusCallback(iface);
80 LONG ref = InterlockedIncrement(&This->ref);
81
82 TRACE("(%p) ref=%d\n", This, ref);
83
84 return ref;
85 }
86
87 static ULONG WINAPI bsc_Release(
88 IBindStatusCallback *iface )
89 {
90 bsc_t *This = impl_from_IBindStatusCallback(iface);
91 LONG ref = InterlockedDecrement(&This->ref);
92
93 TRACE("(%p) ref=%d\n", This, ref);
94
95 if(!ref) {
96 if(This->binding)
97 IBinding_Release(This->binding);
98 if(This->memstream)
99 IStream_Release(This->memstream);
100 HeapFree(GetProcessHeap(), 0, This);
101 }
102
103 return ref;
104 }
105
106 static HRESULT WINAPI bsc_OnStartBinding(
107 IBindStatusCallback* iface,
108 DWORD dwReserved,
109 IBinding* pib)
110 {
111 bsc_t *This = impl_from_IBindStatusCallback(iface);
112 HRESULT hr;
113
114 TRACE("(%p)->(%x %p)\n", This, dwReserved, pib);
115
116 This->binding = pib;
117 IBinding_AddRef(pib);
118
119 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->memstream);
120 if(FAILED(hr))
121 return hr;
122
123 return S_OK;
124 }
125
126 static HRESULT WINAPI bsc_GetPriority(
127 IBindStatusCallback* iface,
128 LONG* pnPriority)
129 {
130 return S_OK;
131 }
132
133 static HRESULT WINAPI bsc_OnLowResource(
134 IBindStatusCallback* iface,
135 DWORD reserved)
136 {
137 return S_OK;
138 }
139
140 static HRESULT WINAPI bsc_OnProgress(
141 IBindStatusCallback* iface,
142 ULONG ulProgress,
143 ULONG ulProgressMax,
144 ULONG ulStatusCode,
145 LPCWSTR szStatusText)
146 {
147 return S_OK;
148 }
149
150 static HRESULT WINAPI bsc_OnStopBinding(
151 IBindStatusCallback* iface,
152 HRESULT hresult,
153 LPCWSTR szError)
154 {
155 bsc_t *This = impl_from_IBindStatusCallback(iface);
156 HRESULT hr = S_OK;
157
158 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
159
160 if(This->binding) {
161 IBinding_Release(This->binding);
162 This->binding = NULL;
163 }
164
165 if(This->obj && SUCCEEDED(hresult)) {
166 HGLOBAL hglobal;
167 hr = GetHGlobalFromStream(This->memstream, &hglobal);
168 if(SUCCEEDED(hr))
169 {
170 DWORD len = GlobalSize(hglobal);
171 char *ptr = GlobalLock(hglobal);
172
173 hr = This->onDataAvailable(This->obj, ptr, len);
174
175 GlobalUnlock(hglobal);
176 }
177 }
178
179 return hr;
180 }
181
182 static HRESULT WINAPI bsc_GetBindInfo(
183 IBindStatusCallback* iface,
184 DWORD* grfBINDF,
185 BINDINFO* pbindinfo)
186 {
187 *grfBINDF = BINDF_GETNEWESTVERSION|BINDF_PULLDATA|BINDF_RESYNCHRONIZE|BINDF_PRAGMA_NO_CACHE;
188
189 return S_OK;
190 }
191
192 static HRESULT WINAPI bsc_OnDataAvailable(
193 IBindStatusCallback* iface,
194 DWORD grfBSCF,
195 DWORD dwSize,
196 FORMATETC* pformatetc,
197 STGMEDIUM* pstgmed)
198 {
199 bsc_t *This = impl_from_IBindStatusCallback(iface);
200 BYTE buf[4096];
201 DWORD read, written;
202 HRESULT hr;
203
204 TRACE("(%p)->(%x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
205
206 do
207 {
208 hr = IStream_Read(pstgmed->u.pstm, buf, sizeof(buf), &read);
209 if(FAILED(hr))
210 break;
211
212 hr = IStream_Write(This->memstream, buf, read, &written);
213 } while(SUCCEEDED(hr) && written != 0 && read != 0);
214
215 return S_OK;
216 }
217
218 static HRESULT WINAPI bsc_OnObjectAvailable(
219 IBindStatusCallback* iface,
220 REFIID riid,
221 IUnknown* punk)
222 {
223 return S_OK;
224 }
225
226 static const struct IBindStatusCallbackVtbl bsc_vtbl =
227 {
228 bsc_QueryInterface,
229 bsc_AddRef,
230 bsc_Release,
231 bsc_OnStartBinding,
232 bsc_GetPriority,
233 bsc_OnLowResource,
234 bsc_OnProgress,
235 bsc_OnStopBinding,
236 bsc_GetBindInfo,
237 bsc_OnDataAvailable,
238 bsc_OnObjectAvailable
239 };
240
241 HRESULT bind_url(LPCWSTR url, HRESULT (*onDataAvailable)(void*,char*,DWORD), void *obj, bsc_t **ret)
242 {
243 WCHAR fileUrl[INTERNET_MAX_URL_LENGTH];
244 bsc_t *bsc;
245 IBindCtx *pbc;
246 HRESULT hr;
247
248 TRACE("%s\n", debugstr_w(url));
249
250 if(!PathIsURLW(url))
251 {
252 WCHAR fullpath[MAX_PATH];
253 DWORD needed = sizeof(fileUrl)/sizeof(WCHAR);
254
255 if(!PathSearchAndQualifyW(url, fullpath, sizeof(fullpath)/sizeof(WCHAR)))
256 {
257 WARN("can't find path\n");
258 return E_FAIL;
259 }
260
261 if(FAILED(UrlCreateFromPathW(url, fileUrl, &needed, 0)))
262 {
263 ERR("can't create url from path\n");
264 return E_FAIL;
265 }
266 url = fileUrl;
267 }
268
269 hr = CreateBindCtx(0, &pbc);
270 if(FAILED(hr))
271 return hr;
272
273 bsc = HeapAlloc(GetProcessHeap(), 0, sizeof(bsc_t));
274
275 bsc->lpVtbl = &bsc_vtbl;
276 bsc->ref = 1;
277 bsc->obj = obj;
278 bsc->onDataAvailable = onDataAvailable;
279 bsc->binding = NULL;
280 bsc->memstream = NULL;
281
282 hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)&bsc->lpVtbl, NULL, 0);
283 if(SUCCEEDED(hr))
284 {
285 IMoniker *moniker;
286
287 hr = CreateURLMoniker(NULL, url, &moniker);
288 if(SUCCEEDED(hr))
289 {
290 IStream *stream;
291 hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
292 IMoniker_Release(moniker);
293 if(stream)
294 IStream_Release(stream);
295 }
296 IBindCtx_Release(pbc);
297 }
298
299 if(FAILED(hr))
300 {
301 IBindStatusCallback_Release((IBindStatusCallback*)&bsc->lpVtbl);
302 bsc = NULL;
303 }
304
305 *ret = bsc;
306 return hr;
307 }
308
309 void detach_bsc(bsc_t *bsc)
310 {
311 if(bsc->binding)
312 IBinding_Abort(bsc->binding);
313
314 bsc->obj = NULL;
315 IBindStatusCallback_Release((IBindStatusCallback*)&bsc->lpVtbl);
316 }
317
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.