Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenbinding.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2005-2007 Jacek Caban for CodeWeavers 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include "urlmon_main.h" 00020 #include "winreg.h" 00021 #include "shlwapi.h" 00022 00023 #include "wine/debug.h" 00024 00025 WINE_DEFAULT_DEBUG_CHANNEL(urlmon); 00026 00027 static WCHAR cbinding_contextW[] = {'C','B','i','n','d','i','n','g',' ','C','o','n','t','e','x','t',0}; 00028 static WCHAR bscb_holderW[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 }; 00029 00030 typedef struct { 00031 IUnknown IUnknown_iface; 00032 00033 LONG ref; 00034 00035 IInternetProtocolEx *protocol; 00036 00037 HANDLE file; 00038 HRESULT hres; 00039 00040 LPWSTR cache_file; 00041 } stgmed_buf_t; 00042 00043 typedef struct _stgmed_obj_t stgmed_obj_t; 00044 00045 typedef struct { 00046 void (*release)(stgmed_obj_t*); 00047 HRESULT (*fill_stgmed)(stgmed_obj_t*,STGMEDIUM*); 00048 HRESULT (*get_result)(stgmed_obj_t*,DWORD,void**); 00049 } stgmed_obj_vtbl; 00050 00051 struct _stgmed_obj_t { 00052 const stgmed_obj_vtbl *vtbl; 00053 }; 00054 00055 typedef enum { 00056 BEFORE_DOWNLOAD, 00057 DOWNLOADING, 00058 END_DOWNLOAD 00059 } download_state_t; 00060 00061 #define BINDING_LOCKED 0x0001 00062 #define BINDING_STOPPED 0x0002 00063 #define BINDING_OBJAVAIL 0x0004 00064 #define BINDING_ABORTED 0x0008 00065 00066 typedef struct { 00067 IBinding IBinding_iface; 00068 IInternetProtocolSink IInternetProtocolSink_iface; 00069 IInternetBindInfo IInternetBindInfo_iface; 00070 IWinInetHttpInfo IWinInetHttpInfo_iface; 00071 IServiceProvider IServiceProvider_iface; 00072 00073 LONG ref; 00074 00075 IBindStatusCallback *callback; 00076 IServiceProvider *service_provider; 00077 00078 BindProtocol *protocol; 00079 00080 stgmed_buf_t *stgmed_buf; 00081 stgmed_obj_t *stgmed_obj; 00082 00083 BINDINFO bindinfo; 00084 DWORD bindf; 00085 BOOL to_object; 00086 LPWSTR mime; 00087 UINT clipboard_format; 00088 LPWSTR url; 00089 LPWSTR redirect_url; 00090 IID iid; 00091 BOOL report_mime; 00092 BOOL use_cache_file; 00093 DWORD state; 00094 HRESULT hres; 00095 download_state_t download_state; 00096 IUnknown *obj; 00097 IMoniker *mon; 00098 IBindCtx *bctx; 00099 HWND notif_hwnd; 00100 00101 CRITICAL_SECTION section; 00102 } Binding; 00103 00104 static void read_protocol_data(stgmed_buf_t *stgmed_buf) 00105 { 00106 BYTE buf[8192]; 00107 DWORD read; 00108 HRESULT hres; 00109 00110 do hres = IInternetProtocol_Read(stgmed_buf->protocol, buf, sizeof(buf), &read); 00111 while(hres == S_OK); 00112 } 00113 00114 static void dump_BINDINFO(BINDINFO *bi) 00115 { 00116 static const char * const BINDINFOF_str[] = { 00117 "#0", 00118 "BINDINFOF_URLENCODESTGMEDDATA", 00119 "BINDINFOF_URLENCODEDEXTRAINFO" 00120 }; 00121 00122 static const char * const BINDVERB_str[] = { 00123 "BINDVERB_GET", 00124 "BINDVERB_POST", 00125 "BINDVERB_PUT", 00126 "BINDVERB_CUSTOM" 00127 }; 00128 00129 TRACE("\n" 00130 "BINDINFO = {\n" 00131 " %d, %s,\n" 00132 " {%d, %p, %p},\n" 00133 " %s,\n" 00134 " %s,\n" 00135 " %s,\n" 00136 " %d, %08x, %d, %d\n" 00137 " {%d %p %x},\n" 00138 " %s\n" 00139 " %p, %d\n" 00140 "}\n", 00141 00142 bi->cbSize, debugstr_w(bi->szExtraInfo), 00143 bi->stgmedData.tymed, bi->stgmedData.u.hGlobal, bi->stgmedData.pUnkForRelease, 00144 bi->grfBindInfoF > BINDINFOF_URLENCODEDEXTRAINFO 00145 ? "unknown" : BINDINFOF_str[bi->grfBindInfoF], 00146 bi->dwBindVerb > BINDVERB_CUSTOM 00147 ? "unknown" : BINDVERB_str[bi->dwBindVerb], 00148 debugstr_w(bi->szCustomVerb), 00149 bi->cbstgmedData, bi->dwOptions, bi->dwOptionsFlags, bi->dwCodePage, 00150 bi->securityAttributes.nLength, 00151 bi->securityAttributes.lpSecurityDescriptor, 00152 bi->securityAttributes.bInheritHandle, 00153 debugstr_guid(&bi->iid), 00154 bi->pUnk, bi->dwReserved 00155 ); 00156 } 00157 00158 static void mime_available(Binding *This, LPCWSTR mime) 00159 { 00160 heap_free(This->mime); 00161 This->mime = heap_strdupW(mime); 00162 00163 if(!This->mime || !This->report_mime) 00164 return; 00165 00166 IBindStatusCallback_OnProgress(This->callback, 0, 0, BINDSTATUS_MIMETYPEAVAILABLE, This->mime); 00167 00168 This->clipboard_format = RegisterClipboardFormatW(This->mime); 00169 } 00170 00171 static void stop_binding(Binding *binding, HRESULT hres, LPCWSTR str) 00172 { 00173 if(binding->state & BINDING_LOCKED) { 00174 IInternetProtocolEx_UnlockRequest(&binding->protocol->IInternetProtocolEx_iface); 00175 binding->state &= ~BINDING_LOCKED; 00176 } 00177 00178 if(!(binding->state & BINDING_STOPPED)) { 00179 binding->state |= BINDING_STOPPED; 00180 00181 IBindStatusCallback_OnStopBinding(binding->callback, hres, str); 00182 binding->hres = hres; 00183 } 00184 } 00185 00186 static LPWSTR get_mime_clsid(LPCWSTR mime, CLSID *clsid) 00187 { 00188 LPWSTR key_name, ret; 00189 DWORD res, type, size; 00190 HKEY hkey; 00191 int len; 00192 HRESULT hres; 00193 00194 static const WCHAR mime_keyW[] = 00195 {'M','I','M','E','\\','D','a','t','a','b','a','s','e','\\', 00196 'C','o','n','t','e','n','t',' ','T','y','p','e','\\'}; 00197 static const WCHAR clsidW[] = {'C','L','S','I','D',0}; 00198 00199 len = strlenW(mime)+1; 00200 key_name = heap_alloc(sizeof(mime_keyW) + len*sizeof(WCHAR)); 00201 memcpy(key_name, mime_keyW, sizeof(mime_keyW)); 00202 strcpyW(key_name + sizeof(mime_keyW)/sizeof(WCHAR), mime); 00203 00204 res = RegOpenKeyW(HKEY_CLASSES_ROOT, key_name, &hkey); 00205 heap_free(key_name); 00206 if(res != ERROR_SUCCESS) { 00207 WARN("Could not open MIME key: %x\n", res); 00208 return NULL; 00209 } 00210 00211 size = 50*sizeof(WCHAR); 00212 ret = heap_alloc(size); 00213 res = RegQueryValueExW(hkey, clsidW, NULL, &type, (LPBYTE)ret, &size); 00214 RegCloseKey(hkey); 00215 if(res != ERROR_SUCCESS) { 00216 WARN("Could not get CLSID: %08x\n", res); 00217 heap_free(ret); 00218 return NULL; 00219 } 00220 00221 hres = CLSIDFromString(ret, clsid); 00222 if(FAILED(hres)) { 00223 WARN("Could not parse CLSID: %08x\n", hres); 00224 heap_free(ret); 00225 return NULL; 00226 } 00227 00228 return ret; 00229 } 00230 00231 static void load_doc_mon(Binding *binding, IPersistMoniker *persist) 00232 { 00233 IBindCtx *bctx; 00234 HRESULT hres; 00235 00236 hres = CreateAsyncBindCtxEx(binding->bctx, 0, NULL, NULL, &bctx, 0); 00237 if(FAILED(hres)) { 00238 WARN("CreateAsyncBindCtxEx failed: %08x\n", hres); 00239 return; 00240 } 00241 00242 IBindCtx_RevokeObjectParam(bctx, bscb_holderW); 00243 IBindCtx_RegisterObjectParam(bctx, cbinding_contextW, (IUnknown*)&binding->IBinding_iface); 00244 00245 hres = IPersistMoniker_Load(persist, binding->download_state == END_DOWNLOAD, binding->mon, bctx, 0x12); 00246 IBindCtx_RevokeObjectParam(bctx, cbinding_contextW); 00247 IBindCtx_Release(bctx); 00248 if(FAILED(hres)) 00249 FIXME("Load failed: %08x\n", hres); 00250 } 00251 00252 static HRESULT create_mime_object(Binding *binding, const CLSID *clsid, LPCWSTR clsid_str) 00253 { 00254 IPersistMoniker *persist; 00255 HRESULT hres; 00256 00257 hres = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, 00258 &binding->iid, (void**)&binding->obj); 00259 if(FAILED(hres)) { 00260 WARN("CoCreateInstance failed: %08x\n", hres); 00261 return INET_E_CANNOT_INSTANTIATE_OBJECT; 00262 } 00263 00264 binding->state |= BINDING_OBJAVAIL; 00265 00266 hres = IUnknown_QueryInterface(binding->obj, &IID_IPersistMoniker, (void**)&persist); 00267 if(SUCCEEDED(hres)) { 00268 IMonikerProp *prop; 00269 00270 hres = IPersistMoniker_QueryInterface(persist, &IID_IMonikerProp, (void**)&prop); 00271 if(SUCCEEDED(hres)) { 00272 IMonikerProp_PutProperty(prop, MIMETYPEPROP, binding->mime); 00273 IMonikerProp_PutProperty(prop, CLASSIDPROP, clsid_str); 00274 IMonikerProp_Release(prop); 00275 } 00276 00277 load_doc_mon(binding, persist); 00278 00279 IPersistMoniker_Release(persist); 00280 }else { 00281 FIXME("Could not get IPersistMoniker: %08x\n", hres); 00282 /* FIXME: Try query IPersistFile */ 00283 } 00284 00285 IBindStatusCallback_OnObjectAvailable(binding->callback, &binding->iid, binding->obj); 00286 00287 return S_OK; 00288 } 00289 00290 static void create_object(Binding *binding) 00291 { 00292 LPWSTR clsid_str; 00293 CLSID clsid; 00294 HRESULT hres; 00295 00296 if(!binding->mime) { 00297 FIXME("MIME not available\n"); 00298 return; 00299 } 00300 00301 if(!(clsid_str = get_mime_clsid(binding->mime, &clsid))) { 00302 FIXME("Could not find object for MIME %s\n", debugstr_w(binding->mime)); 00303 return; 00304 } 00305 00306 IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_CLASSIDAVAILABLE, clsid_str); 00307 IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_BEGINSYNCOPERATION, NULL); 00308 00309 hres = create_mime_object(binding, &clsid, clsid_str); 00310 heap_free(clsid_str); 00311 00312 IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_ENDSYNCOPERATION, NULL); 00313 00314 stop_binding(binding, hres, NULL); 00315 if(FAILED(hres)) 00316 IInternetProtocolEx_Terminate(&binding->protocol->IInternetProtocolEx_iface, 0); 00317 } 00318 00319 static void cache_file_available(Binding *This, const WCHAR *file_name) 00320 { 00321 heap_free(This->stgmed_buf->cache_file); 00322 This->stgmed_buf->cache_file = heap_strdupW(file_name); 00323 00324 if(This->use_cache_file) { 00325 This->stgmed_buf->file = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, 00326 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 00327 if(This->stgmed_buf->file == INVALID_HANDLE_VALUE) 00328 WARN("CreateFile failed: %u\n", GetLastError()); 00329 } 00330 } 00331 00332 static inline stgmed_buf_t *impl_from_IUnknown(IUnknown *iface) 00333 { 00334 return CONTAINING_RECORD(iface, stgmed_buf_t, IUnknown_iface); 00335 } 00336 00337 static HRESULT WINAPI StgMedUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 00338 { 00339 stgmed_buf_t *This = impl_from_IUnknown(iface); 00340 00341 *ppv = NULL; 00342 00343 if(IsEqualGUID(riid, &IID_IUnknown)) { 00344 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 00345 00346 *ppv = &This->IUnknown_iface; 00347 IUnknown_AddRef(&This->IUnknown_iface); 00348 return S_OK; 00349 } 00350 00351 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 00352 return E_NOINTERFACE; 00353 } 00354 00355 static ULONG WINAPI StgMedUnk_AddRef(IUnknown *iface) 00356 { 00357 stgmed_buf_t *This = impl_from_IUnknown(iface); 00358 LONG ref = InterlockedIncrement(&This->ref); 00359 00360 TRACE("(%p) ref=%d\n", This, ref); 00361 00362 return ref; 00363 } 00364 00365 static ULONG WINAPI StgMedUnk_Release(IUnknown *iface) 00366 { 00367 stgmed_buf_t *This = impl_from_IUnknown(iface); 00368 LONG ref = InterlockedDecrement(&This->ref); 00369 00370 TRACE("(%p) ref=%d\n", This, ref); 00371 00372 if(!ref) { 00373 if(This->file != INVALID_HANDLE_VALUE) 00374 CloseHandle(This->file); 00375 IInternetProtocol_Release(This->protocol); 00376 heap_free(This->cache_file); 00377 heap_free(This); 00378 00379 URLMON_UnlockModule(); 00380 } 00381 00382 return ref; 00383 } 00384 00385 static const IUnknownVtbl StgMedUnkVtbl = { 00386 StgMedUnk_QueryInterface, 00387 StgMedUnk_AddRef, 00388 StgMedUnk_Release 00389 }; 00390 00391 static stgmed_buf_t *create_stgmed_buf(IInternetProtocolEx *protocol) 00392 { 00393 stgmed_buf_t *ret = heap_alloc(sizeof(*ret)); 00394 00395 ret->IUnknown_iface.lpVtbl = &StgMedUnkVtbl; 00396 ret->ref = 1; 00397 ret->file = INVALID_HANDLE_VALUE; 00398 ret->hres = S_OK; 00399 ret->cache_file = NULL; 00400 00401 IInternetProtocol_AddRef(protocol); 00402 ret->protocol = protocol; 00403 00404 URLMON_LockModule(); 00405 00406 return ret; 00407 } 00408 00409 typedef struct { 00410 stgmed_obj_t stgmed_obj; 00411 IStream IStream_iface; 00412 00413 LONG ref; 00414 00415 stgmed_buf_t *buf; 00416 } ProtocolStream; 00417 00418 static inline ProtocolStream *impl_from_IStream(IStream *iface) 00419 { 00420 return CONTAINING_RECORD(iface, ProtocolStream, IStream_iface); 00421 } 00422 00423 static HRESULT WINAPI ProtocolStream_QueryInterface(IStream *iface, 00424 REFIID riid, void **ppv) 00425 { 00426 ProtocolStream *This = impl_from_IStream(iface); 00427 00428 *ppv = NULL; 00429 00430 if(IsEqualGUID(&IID_IUnknown, riid)) { 00431 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 00432 *ppv = &This->IStream_iface; 00433 }else if(IsEqualGUID(&IID_ISequentialStream, riid)) { 00434 TRACE("(%p)->(IID_ISequentialStream %p)\n", This, ppv); 00435 *ppv = &This->IStream_iface; 00436 }else if(IsEqualGUID(&IID_IStream, riid)) { 00437 TRACE("(%p)->(IID_IStream %p)\n", This, ppv); 00438 *ppv = &This->IStream_iface; 00439 } 00440 00441 if(*ppv) { 00442 IStream_AddRef(&This->IStream_iface); 00443 return S_OK; 00444 } 00445 00446 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 00447 return E_NOINTERFACE; 00448 } 00449 00450 static ULONG WINAPI ProtocolStream_AddRef(IStream *iface) 00451 { 00452 ProtocolStream *This = impl_from_IStream(iface); 00453 LONG ref = InterlockedIncrement(&This->ref); 00454 00455 TRACE("(%p) ref=%d\n", This, ref); 00456 00457 return ref; 00458 } 00459 00460 static ULONG WINAPI ProtocolStream_Release(IStream *iface) 00461 { 00462 ProtocolStream *This = impl_from_IStream(iface); 00463 LONG ref = InterlockedDecrement(&This->ref); 00464 00465 TRACE("(%p) ref=%d\n", This, ref); 00466 00467 if(!ref) { 00468 IUnknown_Release(&This->buf->IUnknown_iface); 00469 heap_free(This); 00470 00471 URLMON_UnlockModule(); 00472 } 00473 00474 return ref; 00475 } 00476 00477 static HRESULT WINAPI ProtocolStream_Read(IStream *iface, void *pv, 00478 ULONG cb, ULONG *pcbRead) 00479 { 00480 ProtocolStream *This = impl_from_IStream(iface); 00481 DWORD read = 0; 00482 HRESULT hres; 00483 00484 TRACE("(%p)->(%p %d %p)\n", This, pv, cb, pcbRead); 00485 00486 if(This->buf->file == INVALID_HANDLE_VALUE) { 00487 hres = This->buf->hres = IInternetProtocol_Read(This->buf->protocol, (PBYTE)pv, cb, &read); 00488 }else { 00489 hres = ReadFile(This->buf->file, pv, cb, &read, NULL) ? S_OK : INET_E_DOWNLOAD_FAILURE; 00490 } 00491 00492 if (pcbRead) 00493 *pcbRead = read; 00494 00495 if(hres == E_PENDING) 00496 return E_PENDING; 00497 else if(FAILED(hres)) 00498 FIXME("Read failed: %08x\n", hres); 00499 00500 return read ? S_OK : S_FALSE; 00501 } 00502 00503 static HRESULT WINAPI ProtocolStream_Write(IStream *iface, const void *pv, 00504 ULONG cb, ULONG *pcbWritten) 00505 { 00506 ProtocolStream *This = impl_from_IStream(iface); 00507 00508 TRACE("(%p)->(%p %d %p)\n", This, pv, cb, pcbWritten); 00509 00510 return STG_E_ACCESSDENIED; 00511 } 00512 00513 static HRESULT WINAPI ProtocolStream_Seek(IStream *iface, LARGE_INTEGER dlibMove, 00514 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) 00515 { 00516 ProtocolStream *This = impl_from_IStream(iface); 00517 FIXME("(%p)->(%d %08x %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition); 00518 return E_NOTIMPL; 00519 } 00520 00521 static HRESULT WINAPI ProtocolStream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize) 00522 { 00523 ProtocolStream *This = impl_from_IStream(iface); 00524 FIXME("(%p)->(%d)\n", This, libNewSize.u.LowPart); 00525 return E_NOTIMPL; 00526 } 00527 00528 static HRESULT WINAPI ProtocolStream_CopyTo(IStream *iface, IStream *pstm, 00529 ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) 00530 { 00531 ProtocolStream *This = impl_from_IStream(iface); 00532 FIXME("(%p)->(%p %d %p %p)\n", This, pstm, cb.u.LowPart, pcbRead, pcbWritten); 00533 return E_NOTIMPL; 00534 } 00535 00536 static HRESULT WINAPI ProtocolStream_Commit(IStream *iface, DWORD grfCommitFlags) 00537 { 00538 ProtocolStream *This = impl_from_IStream(iface); 00539 00540 TRACE("(%p)->(%08x)\n", This, grfCommitFlags); 00541 00542 return E_NOTIMPL; 00543 } 00544 00545 static HRESULT WINAPI ProtocolStream_Revert(IStream *iface) 00546 { 00547 ProtocolStream *This = impl_from_IStream(iface); 00548 00549 TRACE("(%p)\n", This); 00550 00551 return E_NOTIMPL; 00552 } 00553 00554 static HRESULT WINAPI ProtocolStream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset, 00555 ULARGE_INTEGER cb, DWORD dwLockType) 00556 { 00557 ProtocolStream *This = impl_from_IStream(iface); 00558 FIXME("(%p)->(%d %d %d)\n", This, libOffset.u.LowPart, cb.u.LowPart, dwLockType); 00559 return E_NOTIMPL; 00560 } 00561 00562 static HRESULT WINAPI ProtocolStream_UnlockRegion(IStream *iface, 00563 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 00564 { 00565 ProtocolStream *This = impl_from_IStream(iface); 00566 FIXME("(%p)->(%d %d %d)\n", This, libOffset.u.LowPart, cb.u.LowPart, dwLockType); 00567 return E_NOTIMPL; 00568 } 00569 00570 static HRESULT WINAPI ProtocolStream_Stat(IStream *iface, STATSTG *pstatstg, 00571 DWORD dwStatFlag) 00572 { 00573 ProtocolStream *This = impl_from_IStream(iface); 00574 TRACE("(%p)->(%p %08x)\n", This, pstatstg, dwStatFlag); 00575 00576 if(!pstatstg) 00577 return E_FAIL; 00578 00579 memset(pstatstg, 0, sizeof(STATSTG)); 00580 00581 if(!(dwStatFlag&STATFLAG_NONAME) && This->buf->cache_file) { 00582 pstatstg->pwcsName = CoTaskMemAlloc((lstrlenW(This->buf->cache_file)+1)*sizeof(WCHAR)); 00583 if(!pstatstg->pwcsName) 00584 return STG_E_INSUFFICIENTMEMORY; 00585 00586 lstrcpyW(pstatstg->pwcsName, This->buf->cache_file); 00587 } 00588 00589 pstatstg->type = STGTY_STREAM; 00590 if(This->buf->file != INVALID_HANDLE_VALUE) { 00591 GetFileSizeEx(This->buf->file, (PLARGE_INTEGER)&pstatstg->cbSize); 00592 GetFileTime(This->buf->file, &pstatstg->ctime, &pstatstg->atime, &pstatstg->mtime); 00593 if(pstatstg->cbSize.QuadPart) 00594 pstatstg->grfMode = GENERIC_READ; 00595 } 00596 00597 return S_OK; 00598 } 00599 00600 static HRESULT WINAPI ProtocolStream_Clone(IStream *iface, IStream **ppstm) 00601 { 00602 ProtocolStream *This = impl_from_IStream(iface); 00603 FIXME("(%p)->(%p)\n", This, ppstm); 00604 return E_NOTIMPL; 00605 } 00606 00607 static const IStreamVtbl ProtocolStreamVtbl = { 00608 ProtocolStream_QueryInterface, 00609 ProtocolStream_AddRef, 00610 ProtocolStream_Release, 00611 ProtocolStream_Read, 00612 ProtocolStream_Write, 00613 ProtocolStream_Seek, 00614 ProtocolStream_SetSize, 00615 ProtocolStream_CopyTo, 00616 ProtocolStream_Commit, 00617 ProtocolStream_Revert, 00618 ProtocolStream_LockRegion, 00619 ProtocolStream_UnlockRegion, 00620 ProtocolStream_Stat, 00621 ProtocolStream_Clone 00622 }; 00623 00624 static void stgmed_stream_release(stgmed_obj_t *obj) 00625 { 00626 ProtocolStream *stream = (ProtocolStream*)obj; 00627 IStream_Release(&stream->IStream_iface); 00628 } 00629 00630 static HRESULT stgmed_stream_fill_stgmed(stgmed_obj_t *obj, STGMEDIUM *stgmed) 00631 { 00632 ProtocolStream *stream = (ProtocolStream*)obj; 00633 00634 stgmed->tymed = TYMED_ISTREAM; 00635 stgmed->u.pstm = &stream->IStream_iface; 00636 stgmed->pUnkForRelease = &stream->buf->IUnknown_iface; 00637 00638 return S_OK; 00639 } 00640 00641 static HRESULT stgmed_stream_get_result(stgmed_obj_t *obj, DWORD bindf, void **result) 00642 { 00643 ProtocolStream *stream = (ProtocolStream*)obj; 00644 00645 if(!(bindf & BINDF_ASYNCHRONOUS) && stream->buf->file == INVALID_HANDLE_VALUE 00646 && stream->buf->hres != S_FALSE) 00647 return INET_E_DATA_NOT_AVAILABLE; 00648 00649 IStream_AddRef(&stream->IStream_iface); 00650 *result = &stream->IStream_iface; 00651 return S_OK; 00652 } 00653 00654 static const stgmed_obj_vtbl stgmed_stream_vtbl = { 00655 stgmed_stream_release, 00656 stgmed_stream_fill_stgmed, 00657 stgmed_stream_get_result 00658 }; 00659 00660 typedef struct { 00661 stgmed_obj_t stgmed_obj; 00662 stgmed_buf_t *buf; 00663 } stgmed_file_obj_t; 00664 00665 static stgmed_obj_t *create_stgmed_stream(stgmed_buf_t *buf) 00666 { 00667 ProtocolStream *ret = heap_alloc(sizeof(ProtocolStream)); 00668 00669 ret->stgmed_obj.vtbl = &stgmed_stream_vtbl; 00670 ret->IStream_iface.lpVtbl = &ProtocolStreamVtbl; 00671 ret->ref = 1; 00672 00673 IUnknown_AddRef(&buf->IUnknown_iface); 00674 ret->buf = buf; 00675 00676 URLMON_LockModule(); 00677 00678 return &ret->stgmed_obj; 00679 } 00680 00681 static void stgmed_file_release(stgmed_obj_t *obj) 00682 { 00683 stgmed_file_obj_t *file_obj = (stgmed_file_obj_t*)obj; 00684 00685 IUnknown_Release(&file_obj->buf->IUnknown_iface); 00686 heap_free(file_obj); 00687 } 00688 00689 static HRESULT stgmed_file_fill_stgmed(stgmed_obj_t *obj, STGMEDIUM *stgmed) 00690 { 00691 stgmed_file_obj_t *file_obj = (stgmed_file_obj_t*)obj; 00692 00693 if(!file_obj->buf->cache_file) { 00694 WARN("cache_file not set\n"); 00695 return INET_E_DATA_NOT_AVAILABLE; 00696 } 00697 00698 read_protocol_data(file_obj->buf); 00699 00700 stgmed->tymed = TYMED_FILE; 00701 stgmed->u.lpszFileName = file_obj->buf->cache_file; 00702 stgmed->pUnkForRelease = &file_obj->buf->IUnknown_iface; 00703 00704 return S_OK; 00705 } 00706 00707 static HRESULT stgmed_file_get_result(stgmed_obj_t *obj, DWORD bindf, void **result) 00708 { 00709 return bindf & BINDF_ASYNCHRONOUS ? MK_S_ASYNCHRONOUS : S_OK; 00710 } 00711 00712 static const stgmed_obj_vtbl stgmed_file_vtbl = { 00713 stgmed_file_release, 00714 stgmed_file_fill_stgmed, 00715 stgmed_file_get_result 00716 }; 00717 00718 static stgmed_obj_t *create_stgmed_file(stgmed_buf_t *buf) 00719 { 00720 stgmed_file_obj_t *ret = heap_alloc(sizeof(*ret)); 00721 00722 ret->stgmed_obj.vtbl = &stgmed_file_vtbl; 00723 00724 IUnknown_AddRef(&buf->IUnknown_iface); 00725 ret->buf = buf; 00726 00727 return &ret->stgmed_obj; 00728 } 00729 00730 static inline Binding *impl_from_IBinding(IBinding *iface) 00731 { 00732 return CONTAINING_RECORD(iface, Binding, IBinding_iface); 00733 } 00734 00735 static HRESULT WINAPI Binding_QueryInterface(IBinding *iface, REFIID riid, void **ppv) 00736 { 00737 Binding *This = impl_from_IBinding(iface); 00738 00739 *ppv = NULL; 00740 00741 if(IsEqualGUID(&IID_IUnknown, riid)) { 00742 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 00743 *ppv = &This->IBinding_iface; 00744 }else if(IsEqualGUID(&IID_IBinding, riid)) { 00745 TRACE("(%p)->(IID_IBinding %p)\n", This, ppv); 00746 *ppv = &This->IBinding_iface; 00747 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) { 00748 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv); 00749 *ppv = &This->IInternetProtocolSink_iface; 00750 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) { 00751 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv); 00752 *ppv = &This->IInternetBindInfo_iface; 00753 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { 00754 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv); 00755 *ppv = &This->IServiceProvider_iface; 00756 }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) { 00757 TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv); 00758 00759 /* NOTE: This violidates COM rules, but tests prove that we should do it */ 00760 if(!This->protocol->wininet_info) 00761 return E_NOINTERFACE; 00762 00763 *ppv = &This->IWinInetHttpInfo_iface; 00764 }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) { 00765 TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv); 00766 00767 if(!This->protocol->wininet_http_info) 00768 return E_NOINTERFACE; 00769 00770 *ppv = &This->IWinInetHttpInfo_iface; 00771 } 00772 00773 if(*ppv) { 00774 IBinding_AddRef(&This->IBinding_iface); 00775 return S_OK; 00776 } 00777 00778 WARN("Unsupported interface %s\n", debugstr_guid(riid)); 00779 return E_NOINTERFACE; 00780 } 00781 00782 static ULONG WINAPI Binding_AddRef(IBinding *iface) 00783 { 00784 Binding *This = impl_from_IBinding(iface); 00785 LONG ref = InterlockedIncrement(&This->ref); 00786 00787 TRACE("(%p) ref=%d\n", This, ref); 00788 00789 return ref; 00790 } 00791 00792 static ULONG WINAPI Binding_Release(IBinding *iface) 00793 { 00794 Binding *This = impl_from_IBinding(iface); 00795 LONG ref = InterlockedDecrement(&This->ref); 00796 00797 TRACE("(%p) ref=%d\n", This, ref); 00798 00799 if(!ref) { 00800 if(This->notif_hwnd) 00801 release_notif_hwnd(This->notif_hwnd); 00802 if(This->mon) 00803 IMoniker_Release(This->mon); 00804 if(This->callback) 00805 IBindStatusCallback_Release(This->callback); 00806 if(This->protocol) 00807 IInternetProtocolEx_Release(&This->protocol->IInternetProtocolEx_iface); 00808 if(This->service_provider) 00809 IServiceProvider_Release(This->service_provider); 00810 if(This->stgmed_buf) 00811 IUnknown_Release(&This->stgmed_buf->IUnknown_iface); 00812 if(This->stgmed_obj) 00813 This->stgmed_obj->vtbl->release(This->stgmed_obj); 00814 if(This->obj) 00815 IUnknown_Release(This->obj); 00816 if(This->bctx) 00817 IBindCtx_Release(This->bctx); 00818 00819 ReleaseBindInfo(&This->bindinfo); 00820 This->section.DebugInfo->Spare[0] = 0; 00821 DeleteCriticalSection(&This->section); 00822 SysFreeString(This->url); 00823 heap_free(This->mime); 00824 heap_free(This->redirect_url); 00825 heap_free(This); 00826 00827 URLMON_UnlockModule(); 00828 } 00829 00830 return ref; 00831 } 00832 00833 static HRESULT WINAPI Binding_Abort(IBinding *iface) 00834 { 00835 Binding *This = impl_from_IBinding(iface); 00836 HRESULT hres; 00837 00838 TRACE("(%p)\n", This); 00839 00840 if(This->state & BINDING_ABORTED) 00841 return E_FAIL; 00842 00843 hres = IInternetProtocolEx_Abort(&This->protocol->IInternetProtocolEx_iface, E_ABORT, 00844 ERROR_SUCCESS); 00845 if(FAILED(hres)) 00846 return hres; 00847 00848 This->state |= BINDING_ABORTED; 00849 return S_OK; 00850 } 00851 00852 static HRESULT WINAPI Binding_Suspend(IBinding *iface) 00853 { 00854 Binding *This = impl_from_IBinding(iface); 00855 FIXME("(%p)\n", This); 00856 return E_NOTIMPL; 00857 } 00858 00859 static HRESULT WINAPI Binding_Resume(IBinding *iface) 00860 { 00861 Binding *This = impl_from_IBinding(iface); 00862 FIXME("(%p)\n", This); 00863 return E_NOTIMPL; 00864 } 00865 00866 static HRESULT WINAPI Binding_SetPriority(IBinding *iface, LONG nPriority) 00867 { 00868 Binding *This = impl_from_IBinding(iface); 00869 FIXME("(%p)->(%d)\n", This, nPriority); 00870 return E_NOTIMPL; 00871 } 00872 00873 static HRESULT WINAPI Binding_GetPriority(IBinding *iface, LONG *pnPriority) 00874 { 00875 Binding *This = impl_from_IBinding(iface); 00876 FIXME("(%p)->(%p)\n", This, pnPriority); 00877 return E_NOTIMPL; 00878 } 00879 00880 static HRESULT WINAPI Binding_GetBindResult(IBinding *iface, CLSID *pclsidProtocol, 00881 DWORD *pdwResult, LPOLESTR *pszResult, DWORD *pdwReserved) 00882 { 00883 Binding *This = impl_from_IBinding(iface); 00884 FIXME("(%p)->(%p %p %p %p)\n", This, pclsidProtocol, pdwResult, pszResult, pdwReserved); 00885 return E_NOTIMPL; 00886 } 00887 00888 static const IBindingVtbl BindingVtbl = { 00889 Binding_QueryInterface, 00890 Binding_AddRef, 00891 Binding_Release, 00892 Binding_Abort, 00893 Binding_Suspend, 00894 Binding_Resume, 00895 Binding_SetPriority, 00896 Binding_GetPriority, 00897 Binding_GetBindResult 00898 }; 00899 00900 static Binding *get_bctx_binding(IBindCtx *bctx) 00901 { 00902 IBinding *binding; 00903 IUnknown *unk; 00904 HRESULT hres; 00905 00906 hres = IBindCtx_GetObjectParam(bctx, cbinding_contextW, &unk); 00907 if(FAILED(hres)) 00908 return NULL; 00909 00910 hres = IUnknown_QueryInterface(unk, &IID_IBinding, (void**)&binding); 00911 IUnknown_Release(unk); 00912 if(FAILED(hres)) 00913 return NULL; 00914 00915 if (binding->lpVtbl != &BindingVtbl) 00916 return NULL; 00917 return impl_from_IBinding(binding); 00918 } 00919 00920 static inline Binding *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface) 00921 { 00922 return CONTAINING_RECORD(iface, Binding, IInternetProtocolSink_iface); 00923 } 00924 00925 static HRESULT WINAPI InternetProtocolSink_QueryInterface(IInternetProtocolSink *iface, 00926 REFIID riid, void **ppv) 00927 { 00928 Binding *This = impl_from_IInternetProtocolSink(iface); 00929 return IBinding_QueryInterface(&This->IBinding_iface, riid, ppv); 00930 } 00931 00932 static ULONG WINAPI InternetProtocolSink_AddRef(IInternetProtocolSink *iface) 00933 { 00934 Binding *This = impl_from_IInternetProtocolSink(iface); 00935 return IBinding_AddRef(&This->IBinding_iface); 00936 } 00937 00938 static ULONG WINAPI InternetProtocolSink_Release(IInternetProtocolSink *iface) 00939 { 00940 Binding *This = impl_from_IInternetProtocolSink(iface); 00941 return IBinding_Release(&This->IBinding_iface); 00942 } 00943 00944 static HRESULT WINAPI InternetProtocolSink_Switch(IInternetProtocolSink *iface, 00945 PROTOCOLDATA *pProtocolData) 00946 { 00947 Binding *This = impl_from_IInternetProtocolSink(iface); 00948 00949 WARN("(%p)->(%p)\n", This, pProtocolData); 00950 00951 return E_FAIL; 00952 } 00953 00954 static void on_progress(Binding *This, ULONG progress, ULONG progress_max, 00955 ULONG status_code, LPCWSTR status_text) 00956 { 00957 IBindStatusCallback_OnProgress(This->callback, progress, progress_max, 00958 status_code, status_text); 00959 } 00960 00961 static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink *iface, 00962 ULONG ulStatusCode, LPCWSTR szStatusText) 00963 { 00964 Binding *This = impl_from_IInternetProtocolSink(iface); 00965 00966 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText)); 00967 00968 switch(ulStatusCode) { 00969 case BINDSTATUS_FINDINGRESOURCE: 00970 on_progress(This, 0, 0, BINDSTATUS_FINDINGRESOURCE, szStatusText); 00971 break; 00972 case BINDSTATUS_CONNECTING: 00973 on_progress(This, 0, 0, BINDSTATUS_CONNECTING, szStatusText); 00974 break; 00975 case BINDSTATUS_REDIRECTING: 00976 heap_free(This->redirect_url); 00977 This->redirect_url = heap_strdupW(szStatusText); 00978 on_progress(This, 0, 0, BINDSTATUS_REDIRECTING, szStatusText); 00979 break; 00980 case BINDSTATUS_BEGINDOWNLOADDATA: 00981 break; 00982 case BINDSTATUS_SENDINGREQUEST: 00983 on_progress(This, 0, 0, BINDSTATUS_SENDINGREQUEST, szStatusText); 00984 break; 00985 case BINDSTATUS_PROTOCOLCLASSID: 00986 break; 00987 case BINDSTATUS_MIMETYPEAVAILABLE: 00988 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE: 00989 mime_available(This, szStatusText); 00990 break; 00991 case BINDSTATUS_CACHEFILENAMEAVAILABLE: 00992 cache_file_available(This, szStatusText); 00993 break; 00994 case BINDSTATUS_DECODING: 00995 IBindStatusCallback_OnProgress(This->callback, 0, 0, BINDSTATUS_DECODING, szStatusText); 00996 break; 00997 case BINDSTATUS_LOADINGMIMEHANDLER: 00998 on_progress(This, 0, 0, BINDSTATUS_LOADINGMIMEHANDLER, szStatusText); 00999 break; 01000 case BINDSTATUS_DIRECTBIND: /* FIXME: Handle BINDSTATUS_DIRECTBIND in BindProtocol */ 01001 This->report_mime = FALSE; 01002 break; 01003 case BINDSTATUS_ACCEPTRANGES: 01004 break; 01005 default: 01006 FIXME("Unhandled status code %d\n", ulStatusCode); 01007 return E_NOTIMPL; 01008 }; 01009 01010 return S_OK; 01011 } 01012 01013 static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progress_max) 01014 { 01015 FORMATETC formatetc = {0, NULL, 1, -1, TYMED_ISTREAM}; 01016 BOOL sent_begindownloaddata = FALSE; 01017 01018 TRACE("(%p)->(%d %u %u)\n", This, bscf, progress, progress_max); 01019 01020 if(This->download_state == END_DOWNLOAD || (This->state & BINDING_ABORTED)) { 01021 read_protocol_data(This->stgmed_buf); 01022 return; 01023 } 01024 01025 if(This->state & BINDING_STOPPED) 01026 return; 01027 01028 if(This->stgmed_buf->file != INVALID_HANDLE_VALUE) 01029 read_protocol_data(This->stgmed_buf); 01030 01031 if(This->download_state == BEFORE_DOWNLOAD) { 01032 This->download_state = DOWNLOADING; 01033 sent_begindownloaddata = TRUE; 01034 IBindStatusCallback_OnProgress(This->callback, progress, progress_max, 01035 BINDSTATUS_BEGINDOWNLOADDATA, This->url); 01036 01037 if(This->stgmed_buf->cache_file) 01038 IBindStatusCallback_OnProgress(This->callback, progress, progress_max, 01039 BINDSTATUS_CACHEFILENAMEAVAILABLE, This->stgmed_buf->cache_file); 01040 } 01041 01042 if(This->stgmed_buf->hres == S_FALSE || (bscf & BSCF_LASTDATANOTIFICATION)) { 01043 This->download_state = END_DOWNLOAD; 01044 IBindStatusCallback_OnProgress(This->callback, progress, progress_max, 01045 BINDSTATUS_ENDDOWNLOADDATA, This->url); 01046 }else if(!sent_begindownloaddata) { 01047 IBindStatusCallback_OnProgress(This->callback, progress, progress_max, 01048 BINDSTATUS_DOWNLOADINGDATA, This->url); 01049 } 01050 01051 if(This->state & (BINDING_STOPPED|BINDING_ABORTED)) 01052 return; 01053 01054 if(This->to_object) { 01055 if(!(This->state & BINDING_OBJAVAIL)) { 01056 IBinding_AddRef(&This->IBinding_iface); 01057 create_object(This); 01058 IBinding_Release(&This->IBinding_iface); 01059 } 01060 }else { 01061 STGMEDIUM stgmed; 01062 HRESULT hres; 01063 01064 if(!(This->state & BINDING_LOCKED)) { 01065 HRESULT hres = IInternetProtocolEx_LockRequest( 01066 &This->protocol->IInternetProtocolEx_iface, 0); 01067 if(SUCCEEDED(hres)) 01068 This->state |= BINDING_LOCKED; 01069 } 01070 01071 hres = This->stgmed_obj->vtbl->fill_stgmed(This->stgmed_obj, &stgmed); 01072 if(FAILED(hres)) { 01073 stop_binding(This, hres, NULL); 01074 return; 01075 } 01076 01077 formatetc.tymed = stgmed.tymed; 01078 formatetc.cfFormat = This->clipboard_format; 01079 01080 IBindStatusCallback_OnDataAvailable(This->callback, bscf, progress, 01081 &formatetc, &stgmed); 01082 01083 if(This->download_state == END_DOWNLOAD) 01084 stop_binding(This, S_OK, NULL); 01085 } 01086 } 01087 01088 static HRESULT WINAPI InternetProtocolSink_ReportData(IInternetProtocolSink *iface, 01089 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax) 01090 { 01091 Binding *This = impl_from_IInternetProtocolSink(iface); 01092 01093 TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax); 01094 01095 report_data(This, grfBSCF, ulProgress, ulProgressMax); 01096 return S_OK; 01097 } 01098 01099 static HRESULT WINAPI InternetProtocolSink_ReportResult(IInternetProtocolSink *iface, 01100 HRESULT hrResult, DWORD dwError, LPCWSTR szResult) 01101 { 01102 Binding *This = impl_from_IInternetProtocolSink(iface); 01103 01104 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult)); 01105 01106 stop_binding(This, hrResult, szResult); 01107 IInternetProtocolEx_Terminate(&This->protocol->IInternetProtocolEx_iface, 0); 01108 return S_OK; 01109 } 01110 01111 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = { 01112 InternetProtocolSink_QueryInterface, 01113 InternetProtocolSink_AddRef, 01114 InternetProtocolSink_Release, 01115 InternetProtocolSink_Switch, 01116 InternetProtocolSink_ReportProgress, 01117 InternetProtocolSink_ReportData, 01118 InternetProtocolSink_ReportResult 01119 }; 01120 01121 static inline Binding *impl_from_IInternetBindInfo(IInternetBindInfo *iface) 01122 { 01123 return CONTAINING_RECORD(iface, Binding, IInternetBindInfo_iface); 01124 } 01125 01126 static HRESULT WINAPI InternetBindInfo_QueryInterface(IInternetBindInfo *iface, 01127 REFIID riid, void **ppv) 01128 { 01129 Binding *This = impl_from_IInternetBindInfo(iface); 01130 return IBinding_QueryInterface(&This->IBinding_iface, riid, ppv); 01131 } 01132 01133 static ULONG WINAPI InternetBindInfo_AddRef(IInternetBindInfo *iface) 01134 { 01135 Binding *This = impl_from_IInternetBindInfo(iface); 01136 return IBinding_AddRef(&This->IBinding_iface); 01137 } 01138 01139 static ULONG WINAPI InternetBindInfo_Release(IInternetBindInfo *iface) 01140 { 01141 Binding *This = impl_from_IInternetBindInfo(iface); 01142 return IBinding_Release(&This->IBinding_iface); 01143 } 01144 01145 static HRESULT WINAPI InternetBindInfo_GetBindInfo(IInternetBindInfo *iface, 01146 DWORD *grfBINDF, BINDINFO *pbindinfo) 01147 { 01148 Binding *This = impl_from_IInternetBindInfo(iface); 01149 01150 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo); 01151 01152 *grfBINDF = This->bindf; 01153 01154 *pbindinfo = This->bindinfo; 01155 01156 if(pbindinfo->szExtraInfo || pbindinfo->szCustomVerb) 01157 FIXME("copy strings\n"); 01158 01159 if(pbindinfo->stgmedData.pUnkForRelease) 01160 IUnknown_AddRef(pbindinfo->stgmedData.pUnkForRelease); 01161 01162 if(pbindinfo->pUnk) 01163 IUnknown_AddRef(pbindinfo->pUnk); 01164 01165 return S_OK; 01166 } 01167 01168 static HRESULT WINAPI InternetBindInfo_GetBindString(IInternetBindInfo *iface, 01169 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched) 01170 { 01171 Binding *This = impl_from_IInternetBindInfo(iface); 01172 01173 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched); 01174 01175 switch(ulStringType) { 01176 case BINDSTRING_ACCEPT_MIMES: { 01177 static const WCHAR wszMimes[] = {'*','/','*',0}; 01178 01179 if(!ppwzStr || !pcElFetched) 01180 return E_INVALIDARG; 01181 01182 ppwzStr[0] = CoTaskMemAlloc(sizeof(wszMimes)); 01183 memcpy(ppwzStr[0], wszMimes, sizeof(wszMimes)); 01184 *pcElFetched = 1; 01185 return S_OK; 01186 } 01187 case BINDSTRING_USER_AGENT: { 01188 IInternetBindInfo *bindinfo = NULL; 01189 HRESULT hres; 01190 01191 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IInternetBindInfo, 01192 (void**)&bindinfo); 01193 if(FAILED(hres)) 01194 return hres; 01195 01196 hres = IInternetBindInfo_GetBindString(bindinfo, ulStringType, ppwzStr, 01197 cEl, pcElFetched); 01198 IInternetBindInfo_Release(bindinfo); 01199 01200 return hres; 01201 } 01202 case BINDSTRING_URL: { 01203 DWORD size = (SysStringLen(This->url)+1) * sizeof(WCHAR); 01204 01205 if(!ppwzStr || !pcElFetched) 01206 return E_INVALIDARG; 01207 01208 *ppwzStr = CoTaskMemAlloc(size); 01209 memcpy(*ppwzStr, This->url, size); 01210 *pcElFetched = 1; 01211 return S_OK; 01212 } 01213 } 01214 01215 FIXME("not supported string type %d\n", ulStringType); 01216 return E_NOTIMPL; 01217 } 01218 01219 static const IInternetBindInfoVtbl InternetBindInfoVtbl = { 01220 InternetBindInfo_QueryInterface, 01221 InternetBindInfo_AddRef, 01222 InternetBindInfo_Release, 01223 InternetBindInfo_GetBindInfo, 01224 InternetBindInfo_GetBindString 01225 }; 01226 01227 static inline Binding *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface) 01228 { 01229 return CONTAINING_RECORD(iface, Binding, IWinInetHttpInfo_iface); 01230 } 01231 01232 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv) 01233 { 01234 Binding *This = impl_from_IWinInetHttpInfo(iface); 01235 return IBinding_QueryInterface(&This->IBinding_iface, riid, ppv); 01236 } 01237 01238 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface) 01239 { 01240 Binding *This = impl_from_IWinInetHttpInfo(iface); 01241 return IBinding_AddRef(&This->IBinding_iface); 01242 } 01243 01244 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface) 01245 { 01246 Binding *This = impl_from_IWinInetHttpInfo(iface); 01247 return IBinding_Release(&This->IBinding_iface); 01248 } 01249 01250 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption, 01251 void *pBuffer, DWORD *pcbBuffer) 01252 { 01253 Binding *This = impl_from_IWinInetHttpInfo(iface); 01254 TRACE("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer); 01255 01256 if(!This->protocol->wininet_info) 01257 return E_FAIL; 01258 01259 return IWinInetInfo_QueryOption(This->protocol->wininet_info, 01260 dwOption, pBuffer, pcbBuffer); 01261 } 01262 01263 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption, 01264 void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved) 01265 { 01266 Binding *This = impl_from_IWinInetHttpInfo(iface); 01267 TRACE("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved); 01268 01269 if(!This->protocol->wininet_http_info) 01270 return E_FAIL; 01271 01272 return IWinInetHttpInfo_QueryInfo(This->protocol->wininet_http_info, 01273 dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved); 01274 } 01275 01276 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = { 01277 WinInetHttpInfo_QueryInterface, 01278 WinInetHttpInfo_AddRef, 01279 WinInetHttpInfo_Release, 01280 WinInetHttpInfo_QueryOption, 01281 WinInetHttpInfo_QueryInfo 01282 }; 01283 01284 static inline Binding *impl_from_IServiceProvider(IServiceProvider *iface) 01285 { 01286 return CONTAINING_RECORD(iface, Binding, IServiceProvider_iface); 01287 } 01288 01289 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, 01290 REFIID riid, void **ppv) 01291 { 01292 Binding *This = impl_from_IServiceProvider(iface); 01293 return IBinding_QueryInterface(&This->IBinding_iface, riid, ppv); 01294 } 01295 01296 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface) 01297 { 01298 Binding *This = impl_from_IServiceProvider(iface); 01299 return IBinding_AddRef(&This->IBinding_iface); 01300 } 01301 01302 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface) 01303 { 01304 Binding *This = impl_from_IServiceProvider(iface); 01305 return IBinding_Release(&This->IBinding_iface); 01306 } 01307 01308 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, 01309 REFGUID guidService, REFIID riid, void **ppv) 01310 { 01311 Binding *This = impl_from_IServiceProvider(iface); 01312 HRESULT hres; 01313 01314 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv); 01315 01316 if(This->service_provider) { 01317 hres = IServiceProvider_QueryService(This->service_provider, guidService, 01318 riid, ppv); 01319 if(SUCCEEDED(hres)) 01320 return hres; 01321 } 01322 01323 WARN("unknown service %s\n", debugstr_guid(guidService)); 01324 return E_NOINTERFACE; 01325 } 01326 01327 static const IServiceProviderVtbl ServiceProviderVtbl = { 01328 ServiceProvider_QueryInterface, 01329 ServiceProvider_AddRef, 01330 ServiceProvider_Release, 01331 ServiceProvider_QueryService 01332 }; 01333 01334 static HRESULT get_callback(IBindCtx *pbc, IBindStatusCallback **callback) 01335 { 01336 IUnknown *unk; 01337 HRESULT hres; 01338 01339 hres = IBindCtx_GetObjectParam(pbc, bscb_holderW, &unk); 01340 if(FAILED(hres)) 01341 return create_default_callback(callback); 01342 01343 hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)callback); 01344 IUnknown_Release(unk); 01345 return hres; 01346 } 01347 01348 static BOOL is_urlmon_protocol(IUri *uri) 01349 { 01350 DWORD scheme; 01351 HRESULT hres; 01352 01353 hres = IUri_GetScheme(uri, &scheme); 01354 if(FAILED(hres)) 01355 return FALSE; 01356 01357 switch(scheme) { 01358 case URL_SCHEME_FILE: 01359 case URL_SCHEME_FTP: 01360 case URL_SCHEME_GOPHER: 01361 case URL_SCHEME_HTTP: 01362 case URL_SCHEME_HTTPS: 01363 case URL_SCHEME_MK: 01364 return TRUE; 01365 } 01366 01367 return FALSE; 01368 } 01369 01370 static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, IUri *uri, IBindCtx *pbc, 01371 BOOL to_obj, REFIID riid, Binding **binding) 01372 { 01373 Binding *ret; 01374 HRESULT hres; 01375 01376 URLMON_LockModule(); 01377 01378 ret = heap_alloc_zero(sizeof(Binding)); 01379 01380 ret->IBinding_iface.lpVtbl = &BindingVtbl; 01381 ret->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl; 01382 ret->IInternetBindInfo_iface.lpVtbl = &InternetBindInfoVtbl; 01383 ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl; 01384 ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; 01385 01386 ret->ref = 1; 01387 01388 ret->to_object = to_obj; 01389 ret->iid = *riid; 01390 ret->notif_hwnd = get_notif_hwnd(); 01391 ret->report_mime = !binding_ctx; 01392 ret->download_state = BEFORE_DOWNLOAD; 01393 01394 if(to_obj) { 01395 IBindCtx_AddRef(pbc); 01396 ret->bctx = pbc; 01397 } 01398 01399 if(mon) { 01400 IMoniker_AddRef(mon); 01401 ret->mon = mon; 01402 } 01403 01404 ret->bindinfo.cbSize = sizeof(BINDINFO); 01405 01406 InitializeCriticalSection(&ret->section); 01407 ret->section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": Binding.section"); 01408 01409 hres = get_callback(pbc, &ret->callback); 01410 if(FAILED(hres)) { 01411 WARN("Could not get IBindStatusCallback\n"); 01412 IBinding_Release(&ret->IBinding_iface); 01413 return hres; 01414 } 01415 01416 IBindStatusCallback_QueryInterface(ret->callback, &IID_IServiceProvider, 01417 (void**)&ret->service_provider); 01418 01419 if(binding_ctx) { 01420 ret->protocol = binding_ctx->protocol; 01421 IInternetProtocolEx_AddRef(&ret->protocol->IInternetProtocolEx_iface); 01422 }else { 01423 hres = create_binding_protocol(TRUE, &ret->protocol); 01424 if(FAILED(hres)) { 01425 WARN("Could not get protocol handler\n"); 01426 IBinding_Release(&ret->IBinding_iface); 01427 return hres; 01428 } 01429 } 01430 01431 hres = IBindStatusCallback_GetBindInfo(ret->callback, &ret->bindf, &ret->bindinfo); 01432 if(FAILED(hres)) { 01433 WARN("GetBindInfo failed: %08x\n", hres); 01434 IBinding_Release(&ret->IBinding_iface); 01435 return hres; 01436 } 01437 01438 TRACE("bindf %08x\n", ret->bindf); 01439 dump_BINDINFO(&ret->bindinfo); 01440 01441 ret->bindf |= BINDF_FROMURLMON; 01442 if(to_obj) 01443 ret->bindinfo.dwOptions |= 0x100000; 01444 01445 if(!(ret->bindf & BINDF_ASYNCHRONOUS) || !(ret->bindf & BINDF_PULLDATA)) { 01446 ret->bindf |= BINDF_NEEDFILE; 01447 ret->use_cache_file = TRUE; 01448 }else if(!is_urlmon_protocol(uri)) { 01449 ret->bindf |= BINDF_NEEDFILE; 01450 } 01451 01452 hres = IUri_GetDisplayUri(uri, &ret->url); 01453 if(FAILED(hres)) { 01454 IBinding_Release(&ret->IBinding_iface); 01455 return hres; 01456 } 01457 01458 if(binding_ctx) { 01459 ret->stgmed_buf = binding_ctx->stgmed_buf; 01460 IUnknown_AddRef(&ret->stgmed_buf->IUnknown_iface); 01461 ret->clipboard_format = binding_ctx->clipboard_format; 01462 }else { 01463 ret->stgmed_buf = create_stgmed_buf(&ret->protocol->IInternetProtocolEx_iface); 01464 } 01465 01466 if(to_obj) { 01467 ret->stgmed_obj = NULL; 01468 }else if(IsEqualGUID(&IID_IStream, riid)) { 01469 ret->stgmed_obj = create_stgmed_stream(ret->stgmed_buf); 01470 }else if(IsEqualGUID(&IID_IUnknown, riid)) { 01471 ret->bindf |= BINDF_NEEDFILE; 01472 ret->stgmed_obj = create_stgmed_file(ret->stgmed_buf); 01473 }else { 01474 FIXME("Unsupported riid %s\n", debugstr_guid(riid)); 01475 IBinding_Release(&ret->IBinding_iface); 01476 return E_NOTIMPL; 01477 } 01478 01479 *binding = ret; 01480 return S_OK; 01481 } 01482 01483 static HRESULT start_binding(IMoniker *mon, Binding *binding_ctx, IUri *uri, IBindCtx *pbc, 01484 BOOL to_obj, REFIID riid, Binding **ret) 01485 { 01486 Binding *binding = NULL; 01487 HRESULT hres; 01488 MSG msg; 01489 01490 hres = Binding_Create(mon, binding_ctx, uri, pbc, to_obj, riid, &binding); 01491 if(FAILED(hres)) 01492 return hres; 01493 01494 hres = IBindStatusCallback_OnStartBinding(binding->callback, 0, &binding->IBinding_iface); 01495 if(FAILED(hres)) { 01496 WARN("OnStartBinding failed: %08x\n", hres); 01497 if(hres != E_ABORT && hres != E_NOTIMPL) 01498 hres = INET_E_DOWNLOAD_FAILURE; 01499 01500 stop_binding(binding, hres, NULL); 01501 IBinding_Release(&binding->IBinding_iface); 01502 return hres; 01503 } 01504 01505 if(binding_ctx) { 01506 set_binding_sink(binding->protocol, &binding->IInternetProtocolSink_iface, 01507 &binding->IInternetBindInfo_iface); 01508 if(binding_ctx->redirect_url) 01509 IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_REDIRECTING, binding_ctx->redirect_url); 01510 report_data(binding, BSCF_FIRSTDATANOTIFICATION | (binding_ctx->download_state == END_DOWNLOAD ? BSCF_LASTDATANOTIFICATION : 0), 01511 0, 0); 01512 }else { 01513 hres = IInternetProtocolEx_StartEx(&binding->protocol->IInternetProtocolEx_iface, uri, 01514 &binding->IInternetProtocolSink_iface, &binding->IInternetBindInfo_iface, 01515 PI_APARTMENTTHREADED|PI_MIMEVERIFICATION, 0); 01516 01517 TRACE("start ret %08x\n", hres); 01518 01519 if(FAILED(hres) && hres != E_PENDING) { 01520 stop_binding(binding, hres, NULL); 01521 IBinding_Release(&binding->IBinding_iface); 01522 01523 return hres; 01524 } 01525 } 01526 01527 while(!(binding->bindf & BINDF_ASYNCHRONOUS) && 01528 !(binding->state & BINDING_STOPPED)) { 01529 MsgWaitForMultipleObjects(0, NULL, FALSE, 5000, QS_POSTMESSAGE); 01530 while (PeekMessageW(&msg, binding->notif_hwnd, WM_USER, WM_USER+117, PM_REMOVE|PM_NOYIELD)) { 01531 TranslateMessage(&msg); 01532 DispatchMessageW(&msg); 01533 } 01534 } 01535 01536 *ret = binding; 01537 return S_OK; 01538 } 01539 01540 HRESULT bind_to_storage(IUri *uri, IBindCtx *pbc, REFIID riid, void **ppv) 01541 { 01542 Binding *binding = NULL, *binding_ctx; 01543 HRESULT hres; 01544 01545 binding_ctx = get_bctx_binding(pbc); 01546 01547 hres = start_binding(NULL, binding_ctx, uri, pbc, FALSE, riid, &binding); 01548 if(binding_ctx) 01549 IBinding_Release(&binding_ctx->IBinding_iface); 01550 if(FAILED(hres)) 01551 return hres; 01552 01553 if(binding->hres == S_OK && binding->download_state != BEFORE_DOWNLOAD /* FIXME */) { 01554 if((binding->state & BINDING_STOPPED) && (binding->state & BINDING_LOCKED)) 01555 IInternetProtocolEx_UnlockRequest(&binding->protocol->IInternetProtocolEx_iface); 01556 01557 hres = binding->stgmed_obj->vtbl->get_result(binding->stgmed_obj, binding->bindf, ppv); 01558 }else if(binding->bindf & BINDF_ASYNCHRONOUS) { 01559 hres = MK_S_ASYNCHRONOUS; 01560 }else { 01561 hres = FAILED(binding->hres) ? binding->hres : S_OK; 01562 } 01563 01564 IBinding_Release(&binding->IBinding_iface); 01565 01566 return hres; 01567 } 01568 01569 HRESULT bind_to_object(IMoniker *mon, IUri *uri, IBindCtx *pbc, REFIID riid, void **ppv) 01570 { 01571 Binding *binding; 01572 HRESULT hres; 01573 01574 *ppv = NULL; 01575 01576 hres = start_binding(mon, NULL, uri, pbc, TRUE, riid, &binding); 01577 if(FAILED(hres)) 01578 return hres; 01579 01580 if(binding->hres != S_OK) { 01581 hres = SUCCEEDED(binding->hres) ? S_OK : binding->hres; 01582 }else if(binding->bindf & BINDF_ASYNCHRONOUS) { 01583 hres = MK_S_ASYNCHRONOUS; 01584 }else { 01585 *ppv = binding->obj; 01586 IUnknown_AddRef(binding->obj); 01587 hres = S_OK; 01588 } 01589 01590 IBinding_Release(&binding->IBinding_iface); 01591 01592 return hres; 01593 } Generated on Fri May 25 2012 04:24:44 for ReactOS by
1.7.6.1
|