ws2_32: Return a valid value for WSAIoctl SIO_IDEAL_SEND_BACKLOG_QUERY.
[wine.git] / dlls / msxml3 / bsc.c
blob5e3b60d92b5d989082dbce8980b7ff85a016c0b3
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 <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
28 #include "msxml6.h"
29 #include "wininet.h"
30 #include "urlmon.h"
31 #include "winreg.h"
32 #include "shlwapi.h"
34 #include "wine/debug.h"
36 #include "msxml_dispex.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
40 struct bsc_t {
41 IBindStatusCallback IBindStatusCallback_iface;
43 LONG ref;
45 void *obj;
46 HRESULT (*onDataAvailable)(void*,char*,DWORD);
48 IBinding *binding;
49 IStream *memstream;
50 HRESULT hres;
53 static inline bsc_t *impl_from_IBindStatusCallback( IBindStatusCallback *iface )
55 return CONTAINING_RECORD(iface, bsc_t, IBindStatusCallback_iface);
58 static HRESULT WINAPI bsc_QueryInterface(
59 IBindStatusCallback *iface,
60 REFIID riid,
61 LPVOID *ppobj )
63 if (IsEqualGUID(riid, &IID_IUnknown) ||
64 IsEqualGUID(riid, &IID_IBindStatusCallback))
66 IBindStatusCallback_AddRef( iface );
67 *ppobj = iface;
68 return S_OK;
71 TRACE("interface %s not implemented\n", debugstr_guid(riid));
72 *ppobj = NULL;
73 return E_NOINTERFACE;
76 static ULONG WINAPI bsc_AddRef(
77 IBindStatusCallback *iface )
79 bsc_t *bsc = impl_from_IBindStatusCallback(iface);
80 LONG ref = InterlockedIncrement(&bsc->ref);
82 TRACE("%p, refcount %ld.\n", iface, ref);
84 return ref;
87 static ULONG WINAPI bsc_Release(
88 IBindStatusCallback *iface )
90 bsc_t *bsc = impl_from_IBindStatusCallback(iface);
91 LONG ref = InterlockedDecrement(&bsc->ref);
93 TRACE("%p, refcount %ld.\n", iface, ref);
95 if (!ref)
97 if (bsc->binding)
98 IBinding_Release(bsc->binding);
99 if (bsc->memstream)
100 IStream_Release(bsc->memstream);
101 heap_free(bsc);
104 return ref;
107 static HRESULT WINAPI bsc_OnStartBinding(
108 IBindStatusCallback* iface,
109 DWORD dwReserved,
110 IBinding* pib)
112 bsc_t *This = impl_from_IBindStatusCallback(iface);
113 HRESULT hr;
115 TRACE("%p, %lx, %p.\n", iface, dwReserved, pib);
117 This->binding = pib;
118 IBinding_AddRef(pib);
120 hr = CreateStreamOnHGlobal(NULL, TRUE, &This->memstream);
121 if(FAILED(hr))
122 return hr;
124 return S_OK;
127 static HRESULT WINAPI bsc_GetPriority(
128 IBindStatusCallback* iface,
129 LONG* pnPriority)
131 return S_OK;
134 static HRESULT WINAPI bsc_OnLowResource(
135 IBindStatusCallback* iface,
136 DWORD reserved)
138 return S_OK;
141 static HRESULT WINAPI bsc_OnProgress(
142 IBindStatusCallback* iface,
143 ULONG ulProgress,
144 ULONG ulProgressMax,
145 ULONG ulStatusCode,
146 LPCWSTR szStatusText)
148 return S_OK;
151 static HRESULT WINAPI bsc_OnStopBinding(
152 IBindStatusCallback* iface,
153 HRESULT hresult,
154 LPCWSTR szError)
156 bsc_t *This = impl_from_IBindStatusCallback(iface);
157 HRESULT hr = S_OK;
159 TRACE("%p, %#lx, %s.\n", iface, hresult, debugstr_w(szError));
161 if(This->binding) {
162 IBinding_Release(This->binding);
163 This->binding = NULL;
166 if(This->obj && SUCCEEDED(hresult)) {
167 HGLOBAL hglobal;
168 hr = GetHGlobalFromStream(This->memstream, &hglobal);
169 if(SUCCEEDED(hr))
171 DWORD len = GlobalSize(hglobal);
172 char *ptr = GlobalLock(hglobal);
174 This->hres = This->onDataAvailable(This->obj, ptr, len);
176 GlobalUnlock(hglobal);
180 return hr;
183 static HRESULT WINAPI bsc_GetBindInfo(
184 IBindStatusCallback* iface,
185 DWORD* grfBINDF,
186 BINDINFO* pbindinfo)
188 *grfBINDF = BINDF_GETNEWESTVERSION|BINDF_PULLDATA|BINDF_RESYNCHRONIZE|BINDF_PRAGMA_NO_CACHE;
190 return S_OK;
193 static HRESULT WINAPI bsc_OnDataAvailable(
194 IBindStatusCallback* iface,
195 DWORD grfBSCF,
196 DWORD dwSize,
197 FORMATETC* pformatetc,
198 STGMEDIUM* pstgmed)
200 bsc_t *bsc = impl_from_IBindStatusCallback(iface);
201 BYTE buf[4096];
202 DWORD read, written;
203 HRESULT hr;
205 TRACE("%p, %lx, %lu, %p, %p.\n", iface, grfBSCF, dwSize, pformatetc, pstgmed);
209 hr = IStream_Read(pstgmed->u.pstm, buf, sizeof(buf), &read);
210 if(FAILED(hr))
211 break;
213 hr = IStream_Write(bsc->memstream, buf, read, &written);
214 } while(SUCCEEDED(hr) && written != 0 && read != 0);
216 return S_OK;
219 static HRESULT WINAPI bsc_OnObjectAvailable(
220 IBindStatusCallback* iface,
221 REFIID riid,
222 IUnknown* punk)
224 return S_OK;
227 static const struct IBindStatusCallbackVtbl bsc_vtbl =
229 bsc_QueryInterface,
230 bsc_AddRef,
231 bsc_Release,
232 bsc_OnStartBinding,
233 bsc_GetPriority,
234 bsc_OnLowResource,
235 bsc_OnProgress,
236 bsc_OnStopBinding,
237 bsc_GetBindInfo,
238 bsc_OnDataAvailable,
239 bsc_OnObjectAvailable
242 HRESULT create_uri(IUri *base, const WCHAR *url, IUri **uri)
244 WCHAR fileUrl[INTERNET_MAX_URL_LENGTH];
245 HRESULT hr;
247 TRACE("%s\n", debugstr_w(url));
249 if (!PathIsURLW(url))
251 WCHAR fullpath[MAX_PATH];
252 DWORD needed = ARRAY_SIZE(fileUrl);
254 lstrcpynW(fileUrl, url, ARRAY_SIZE(fileUrl));
255 UrlUnescapeW(fileUrl, NULL, NULL, URL_UNESCAPE_INPLACE);
257 if (!PathSearchAndQualifyW(fileUrl, fullpath, ARRAY_SIZE(fullpath)))
259 WARN("can't find path\n");
260 return E_FAIL;
263 if (FAILED(UrlApplySchemeW(fullpath, fileUrl, &needed, URL_APPLY_GUESSSCHEME | URL_APPLY_GUESSFILE |
264 URL_APPLY_DEFAULT)))
266 ERR("Failed to apply url scheme.\n");
267 return E_FAIL;
269 url = fileUrl;
272 hr = CreateUri(url, Uri_CREATE_ALLOW_RELATIVE | Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, uri);
273 if (hr == S_OK && base)
275 IUri *rebased_uri;
277 hr = CoInternetCombineIUri(base, *uri, 0, &rebased_uri, 0);
278 IUri_Release(*uri);
279 *uri = rebased_uri;
282 return hr;
285 HRESULT create_moniker_from_url(LPCWSTR url, IMoniker **mon)
287 HRESULT hr;
288 IUri *uri;
290 TRACE("%s\n", debugstr_w(url));
292 if (FAILED(hr = create_uri(NULL, url, &uri)))
293 return hr;
295 hr = CreateURLMonikerEx2(NULL, uri, mon, 0);
296 IUri_Release(uri);
297 return hr;
300 HRESULT bind_url(IMoniker *mon, HRESULT (*onDataAvailable)(void*,char*,DWORD),
301 void *obj, bsc_t **ret)
303 bsc_t *bsc;
304 IBindCtx *pbc;
305 HRESULT hr;
307 TRACE("%p\n", mon);
309 hr = CreateBindCtx(0, &pbc);
310 if(FAILED(hr))
311 return hr;
313 bsc = heap_alloc(sizeof(bsc_t));
315 bsc->IBindStatusCallback_iface.lpVtbl = &bsc_vtbl;
316 bsc->ref = 1;
317 bsc->obj = obj;
318 bsc->onDataAvailable = onDataAvailable;
319 bsc->binding = NULL;
320 bsc->memstream = NULL;
321 bsc->hres = S_OK;
323 hr = RegisterBindStatusCallback(pbc, &bsc->IBindStatusCallback_iface, NULL, 0);
324 if(SUCCEEDED(hr))
326 IStream *stream;
327 hr = IMoniker_BindToStorage(mon, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
328 if(stream)
329 IStream_Release(stream);
330 IBindCtx_Release(pbc);
333 if(FAILED(hr))
335 IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface);
336 bsc = NULL;
339 *ret = bsc;
340 return hr;
343 HRESULT detach_bsc(bsc_t *bsc)
345 HRESULT hres;
347 if(bsc->binding)
348 IBinding_Abort(bsc->binding);
350 bsc->obj = NULL;
351 hres = bsc->hres;
352 IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface);
354 return hres;