Release 9.12.
[wine.git] / dlls / msxml3 / bsc.c
blob0263f5d0edfd11f31c5059f2fa0f06ef6856fe84
1 /*
2 * Copyright 2008 Piotr Caban
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 #define COBJMACROS
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
27 #include "msxml6.h"
28 #include "wininet.h"
29 #include "urlmon.h"
30 #include "winreg.h"
31 #include "shlwapi.h"
33 #include "wine/debug.h"
35 #include "msxml_dispex.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
39 struct bsc_t {
40 IBindStatusCallback IBindStatusCallback_iface;
42 LONG ref;
44 void *obj;
45 HRESULT (*onDataAvailable)(void*,char*,DWORD);
47 IBinding *binding;
48 IStream *memstream;
49 HRESULT hres;
52 static inline bsc_t *impl_from_IBindStatusCallback( IBindStatusCallback *iface )
54 return CONTAINING_RECORD(iface, bsc_t, IBindStatusCallback_iface);
57 static HRESULT WINAPI bsc_QueryInterface(
58 IBindStatusCallback *iface,
59 REFIID riid,
60 LPVOID *ppobj )
62 if (IsEqualGUID(riid, &IID_IUnknown) ||
63 IsEqualGUID(riid, &IID_IBindStatusCallback))
65 IBindStatusCallback_AddRef( iface );
66 *ppobj = iface;
67 return S_OK;
70 TRACE("interface %s not implemented\n", debugstr_guid(riid));
71 *ppobj = NULL;
72 return E_NOINTERFACE;
75 static ULONG WINAPI bsc_AddRef(
76 IBindStatusCallback *iface )
78 bsc_t *bsc = impl_from_IBindStatusCallback(iface);
79 LONG ref = InterlockedIncrement(&bsc->ref);
81 TRACE("%p, refcount %ld.\n", iface, ref);
83 return ref;
86 static ULONG WINAPI bsc_Release(
87 IBindStatusCallback *iface )
89 bsc_t *bsc = impl_from_IBindStatusCallback(iface);
90 LONG ref = InterlockedDecrement(&bsc->ref);
92 TRACE("%p, refcount %ld.\n", iface, ref);
94 if (!ref)
96 if (bsc->binding)
97 IBinding_Release(bsc->binding);
98 if (bsc->memstream)
99 IStream_Release(bsc->memstream);
100 free(bsc);
103 return ref;
106 static HRESULT WINAPI bsc_OnStartBinding(
107 IBindStatusCallback* iface,
108 DWORD dwReserved,
109 IBinding* pib)
111 bsc_t *This = impl_from_IBindStatusCallback(iface);
112 HRESULT hr;
114 TRACE("%p, %lx, %p.\n", iface, dwReserved, pib);
116 This->binding = pib;
117 IBinding_AddRef(pib);
119 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->memstream);
120 if(FAILED(hr))
121 return hr;
123 return S_OK;
126 static HRESULT WINAPI bsc_GetPriority(
127 IBindStatusCallback* iface,
128 LONG* pnPriority)
130 return S_OK;
133 static HRESULT WINAPI bsc_OnLowResource(
134 IBindStatusCallback* iface,
135 DWORD reserved)
137 return S_OK;
140 static HRESULT WINAPI bsc_OnProgress(
141 IBindStatusCallback* iface,
142 ULONG ulProgress,
143 ULONG ulProgressMax,
144 ULONG ulStatusCode,
145 LPCWSTR szStatusText)
147 return S_OK;
150 static HRESULT WINAPI bsc_OnStopBinding(
151 IBindStatusCallback* iface,
152 HRESULT hresult,
153 LPCWSTR szError)
155 bsc_t *This = impl_from_IBindStatusCallback(iface);
156 HRESULT hr = S_OK;
158 TRACE("%p, %#lx, %s.\n", iface, hresult, debugstr_w(szError));
160 if(This->binding) {
161 IBinding_Release(This->binding);
162 This->binding = NULL;
165 if(This->obj && SUCCEEDED(hresult)) {
166 HGLOBAL hglobal;
167 hr = GetHGlobalFromStream(This->memstream, &hglobal);
168 if(SUCCEEDED(hr))
170 DWORD len = GlobalSize(hglobal);
171 char *ptr = GlobalLock(hglobal);
173 This->hres = This->onDataAvailable(This->obj, ptr, len);
175 GlobalUnlock(hglobal);
179 return hr;
182 static HRESULT WINAPI bsc_GetBindInfo(
183 IBindStatusCallback* iface,
184 DWORD* grfBINDF,
185 BINDINFO* pbindinfo)
187 *grfBINDF = BINDF_GETNEWESTVERSION|BINDF_PULLDATA|BINDF_RESYNCHRONIZE|BINDF_PRAGMA_NO_CACHE;
189 return S_OK;
192 static HRESULT WINAPI bsc_OnDataAvailable(
193 IBindStatusCallback* iface,
194 DWORD grfBSCF,
195 DWORD dwSize,
196 FORMATETC* pformatetc,
197 STGMEDIUM* pstgmed)
199 bsc_t *bsc = impl_from_IBindStatusCallback(iface);
200 BYTE buf[4096];
201 DWORD read, written;
202 HRESULT hr;
204 TRACE("%p, %lx, %lu, %p, %p.\n", iface, grfBSCF, dwSize, pformatetc, pstgmed);
208 hr = IStream_Read(pstgmed->pstm, buf, sizeof(buf), &read);
209 if(FAILED(hr))
210 break;
212 hr = IStream_Write(bsc->memstream, buf, read, &written);
213 } while(SUCCEEDED(hr) && written != 0 && read != 0);
215 return S_OK;
218 static HRESULT WINAPI bsc_OnObjectAvailable(
219 IBindStatusCallback* iface,
220 REFIID riid,
221 IUnknown* punk)
223 return S_OK;
226 static const struct IBindStatusCallbackVtbl bsc_vtbl =
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
241 HRESULT create_uri(IUri *base, const WCHAR *url, IUri **uri)
243 WCHAR fileUrl[INTERNET_MAX_URL_LENGTH];
244 HRESULT hr;
246 TRACE("%s\n", debugstr_w(url));
248 if (!PathIsURLW(url))
250 WCHAR fullpath[MAX_PATH];
251 DWORD needed = ARRAY_SIZE(fileUrl);
253 lstrcpynW(fileUrl, url, ARRAY_SIZE(fileUrl));
254 UrlUnescapeW(fileUrl, NULL, NULL, URL_UNESCAPE_INPLACE);
256 if (!PathSearchAndQualifyW(fileUrl, fullpath, ARRAY_SIZE(fullpath)))
258 WARN("can't find path\n");
259 return E_FAIL;
262 if (FAILED(UrlApplySchemeW(fullpath, fileUrl, &needed, URL_APPLY_GUESSSCHEME | URL_APPLY_GUESSFILE |
263 URL_APPLY_DEFAULT)))
265 ERR("Failed to apply url scheme.\n");
266 return E_FAIL;
268 url = fileUrl;
271 hr = CreateUri(url, Uri_CREATE_ALLOW_RELATIVE | Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, uri);
272 if (hr == S_OK && base)
274 IUri *rebased_uri;
276 hr = CoInternetCombineIUri(base, *uri, 0, &rebased_uri, 0);
277 IUri_Release(*uri);
278 *uri = rebased_uri;
281 return hr;
284 HRESULT create_moniker_from_url(LPCWSTR url, IMoniker **mon)
286 HRESULT hr;
287 IUri *uri;
289 TRACE("%s\n", debugstr_w(url));
291 if (FAILED(hr = create_uri(NULL, url, &uri)))
292 return hr;
294 hr = CreateURLMonikerEx2(NULL, uri, mon, 0);
295 IUri_Release(uri);
296 return hr;
299 HRESULT bind_url(IMoniker *mon, HRESULT (*onDataAvailable)(void*,char*,DWORD),
300 void *obj, bsc_t **ret)
302 bsc_t *bsc;
303 IBindCtx *pbc;
304 HRESULT hr;
306 TRACE("%p\n", mon);
308 hr = CreateBindCtx(0, &pbc);
309 if(FAILED(hr))
310 return hr;
312 bsc = malloc(sizeof(bsc_t));
314 bsc->IBindStatusCallback_iface.lpVtbl = &bsc_vtbl;
315 bsc->ref = 1;
316 bsc->obj = obj;
317 bsc->onDataAvailable = onDataAvailable;
318 bsc->binding = NULL;
319 bsc->memstream = NULL;
320 bsc->hres = S_OK;
322 hr = RegisterBindStatusCallback(pbc, &bsc->IBindStatusCallback_iface, NULL, 0);
323 if(SUCCEEDED(hr))
325 IStream *stream;
326 hr = IMoniker_BindToStorage(mon, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
327 if(stream)
328 IStream_Release(stream);
329 IBindCtx_Release(pbc);
332 if(FAILED(hr))
334 IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface);
335 bsc = NULL;
338 *ret = bsc;
339 return hr;
342 HRESULT detach_bsc(bsc_t *bsc)
344 HRESULT hres;
346 if(bsc->binding)
347 IBinding_Abort(bsc->binding);
349 bsc->obj = NULL;
350 hres = bsc->hres;
351 IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface);
353 return hres;