push 87b6981010d7405c33b14cddcceec21b47729eba
[wine/hacks.git] / dlls / msxml3 / bsc.c
blobb24e04ca25aaf017a01ae28e3ca6e495ba4ef177
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
20 #define NONAMELESSUNION
22 #include "config.h"
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"
36 #include "wine/debug.h"
38 #include "msxml_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
42 struct bsc_t {
43 const struct IBindStatusCallbackVtbl *lpVtbl;
45 LONG ref;
47 void *obj;
48 HRESULT (*onDataAvailable)(void*,char*,DWORD);
50 IBinding *binding;
51 IStream *memstream;
54 static inline bsc_t *impl_from_IBindStatusCallback( IBindStatusCallback *iface )
56 return (bsc_t *)((char*)iface - FIELD_OFFSET(bsc_t, lpVtbl));
59 static HRESULT WINAPI bsc_QueryInterface(
60 IBindStatusCallback *iface,
61 REFIID riid,
62 LPVOID *ppobj )
64 if (IsEqualGUID(riid, &IID_IUnknown) ||
65 IsEqualGUID(riid, &IID_IBindStatusCallback))
67 IBindStatusCallback_AddRef( iface );
68 *ppobj = iface;
69 return S_OK;
72 TRACE("interface %s not implemented\n", debugstr_guid(riid));
73 return E_NOINTERFACE;
76 static ULONG WINAPI bsc_AddRef(
77 IBindStatusCallback *iface )
79 bsc_t *This = impl_from_IBindStatusCallback(iface);
80 LONG ref = InterlockedIncrement(&This->ref);
82 TRACE("(%p) ref=%d\n", This, ref);
84 return ref;
87 static ULONG WINAPI bsc_Release(
88 IBindStatusCallback *iface )
90 bsc_t *This = impl_from_IBindStatusCallback(iface);
91 LONG ref = InterlockedDecrement(&This->ref);
93 TRACE("(%p) ref=%d\n", This, ref);
95 if(!ref) {
96 if (This->binding) IBinding_Release(This->binding);
97 if (This->memstream) IStream_Release(This->memstream);
98 heap_free(This);
101 return ref;
104 static HRESULT WINAPI bsc_OnStartBinding(
105 IBindStatusCallback* iface,
106 DWORD dwReserved,
107 IBinding* pib)
109 bsc_t *This = impl_from_IBindStatusCallback(iface);
110 HRESULT hr;
112 TRACE("(%p)->(%x %p)\n", This, dwReserved, pib);
114 This->binding = pib;
115 IBinding_AddRef(pib);
117 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->memstream);
118 if(FAILED(hr))
119 return hr;
121 return S_OK;
124 static HRESULT WINAPI bsc_GetPriority(
125 IBindStatusCallback* iface,
126 LONG* pnPriority)
128 return S_OK;
131 static HRESULT WINAPI bsc_OnLowResource(
132 IBindStatusCallback* iface,
133 DWORD reserved)
135 return S_OK;
138 static HRESULT WINAPI bsc_OnProgress(
139 IBindStatusCallback* iface,
140 ULONG ulProgress,
141 ULONG ulProgressMax,
142 ULONG ulStatusCode,
143 LPCWSTR szStatusText)
145 return S_OK;
148 static HRESULT WINAPI bsc_OnStopBinding(
149 IBindStatusCallback* iface,
150 HRESULT hresult,
151 LPCWSTR szError)
153 bsc_t *This = impl_from_IBindStatusCallback(iface);
154 HRESULT hr = S_OK;
156 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
158 if(This->binding) {
159 IBinding_Release(This->binding);
160 This->binding = NULL;
163 if(This->obj && SUCCEEDED(hresult)) {
164 HGLOBAL hglobal;
165 hr = GetHGlobalFromStream(This->memstream, &hglobal);
166 if(SUCCEEDED(hr))
168 DWORD len = GlobalSize(hglobal);
169 char *ptr = GlobalLock(hglobal);
171 hr = This->onDataAvailable(This->obj, ptr, len);
173 GlobalUnlock(hglobal);
177 return hr;
180 static HRESULT WINAPI bsc_GetBindInfo(
181 IBindStatusCallback* iface,
182 DWORD* grfBINDF,
183 BINDINFO* pbindinfo)
185 *grfBINDF = BINDF_GETNEWESTVERSION|BINDF_PULLDATA|BINDF_RESYNCHRONIZE|BINDF_PRAGMA_NO_CACHE;
187 return S_OK;
190 static HRESULT WINAPI bsc_OnDataAvailable(
191 IBindStatusCallback* iface,
192 DWORD grfBSCF,
193 DWORD dwSize,
194 FORMATETC* pformatetc,
195 STGMEDIUM* pstgmed)
197 bsc_t *This = impl_from_IBindStatusCallback(iface);
198 BYTE buf[4096];
199 DWORD read, written;
200 HRESULT hr;
202 TRACE("(%p)->(%x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
206 hr = IStream_Read(pstgmed->u.pstm, buf, sizeof(buf), &read);
207 if(FAILED(hr))
208 break;
210 hr = IStream_Write(This->memstream, buf, read, &written);
211 } while(SUCCEEDED(hr) && written != 0 && read != 0);
213 return S_OK;
216 static HRESULT WINAPI bsc_OnObjectAvailable(
217 IBindStatusCallback* iface,
218 REFIID riid,
219 IUnknown* punk)
221 return S_OK;
224 static const struct IBindStatusCallbackVtbl bsc_vtbl =
226 bsc_QueryInterface,
227 bsc_AddRef,
228 bsc_Release,
229 bsc_OnStartBinding,
230 bsc_GetPriority,
231 bsc_OnLowResource,
232 bsc_OnProgress,
233 bsc_OnStopBinding,
234 bsc_GetBindInfo,
235 bsc_OnDataAvailable,
236 bsc_OnObjectAvailable
239 HRESULT bind_url(LPCWSTR url, HRESULT (*onDataAvailable)(void*,char*,DWORD), void *obj, bsc_t **ret)
241 WCHAR fileUrl[INTERNET_MAX_URL_LENGTH];
242 bsc_t *bsc;
243 IBindCtx *pbc;
244 HRESULT hr;
246 TRACE("%s\n", debugstr_w(url));
248 if(!PathIsURLW(url))
250 WCHAR fullpath[MAX_PATH];
251 DWORD needed = sizeof(fileUrl)/sizeof(WCHAR);
253 if(!PathSearchAndQualifyW(url, fullpath, sizeof(fullpath)/sizeof(WCHAR)))
255 WARN("can't find path\n");
256 return E_FAIL;
259 if(FAILED(UrlCreateFromPathW(url, fileUrl, &needed, 0)))
261 ERR("can't create url from path\n");
262 return E_FAIL;
264 url = fileUrl;
267 hr = CreateBindCtx(0, &pbc);
268 if(FAILED(hr))
269 return hr;
271 bsc = heap_alloc(sizeof(bsc_t));
273 bsc->lpVtbl = &bsc_vtbl;
274 bsc->ref = 1;
275 bsc->obj = obj;
276 bsc->onDataAvailable = onDataAvailable;
277 bsc->binding = NULL;
278 bsc->memstream = NULL;
280 hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)&bsc->lpVtbl, NULL, 0);
281 if(SUCCEEDED(hr))
283 IMoniker *moniker;
285 hr = CreateURLMoniker(NULL, url, &moniker);
286 if(SUCCEEDED(hr))
288 IStream *stream;
289 hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
290 IMoniker_Release(moniker);
291 if(stream)
292 IStream_Release(stream);
294 IBindCtx_Release(pbc);
297 if(FAILED(hr))
299 IBindStatusCallback_Release((IBindStatusCallback*)&bsc->lpVtbl);
300 bsc = NULL;
303 *ret = bsc;
304 return hr;
307 void detach_bsc(bsc_t *bsc)
309 if(bsc->binding)
310 IBinding_Abort(bsc->binding);
312 bsc->obj = NULL;
313 IBindStatusCallback_Release((IBindStatusCallback*)&bsc->lpVtbl);