ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

bindprot.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2007-2009 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 "wine/debug.h"
00021 
00022 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
00023 
00024 typedef void (*task_proc_t)(BindProtocol*,task_header_t*);
00025 
00026 struct _task_header_t {
00027     task_proc_t proc;
00028     task_header_t *next;
00029 };
00030 
00031 #define BUFFER_SIZE     2048
00032 #define MIME_TEST_SIZE  255
00033 
00034 #define WM_MK_CONTINUE   (WM_USER+101)
00035 #define WM_MK_RELEASE    (WM_USER+102)
00036 
00037 static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
00038 {
00039     switch(msg) {
00040     case WM_MK_CONTINUE: {
00041         BindProtocol *This = (BindProtocol*)lParam;
00042         task_header_t *task;
00043 
00044         while(1) {
00045             EnterCriticalSection(&This->section);
00046 
00047             task = This->task_queue_head;
00048             if(task) {
00049                 This->task_queue_head = task->next;
00050                 if(!This->task_queue_head)
00051                     This->task_queue_tail = NULL;
00052             }
00053 
00054             LeaveCriticalSection(&This->section);
00055 
00056             if(!task)
00057                 break;
00058 
00059             This->continue_call++;
00060             task->proc(This, task);
00061             This->continue_call--;
00062         }
00063 
00064         IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
00065         return 0;
00066     }
00067     case WM_MK_RELEASE: {
00068         tls_data_t *data = get_tls_data();
00069 
00070         if(!--data->notif_hwnd_cnt) {
00071             DestroyWindow(hwnd);
00072             data->notif_hwnd = NULL;
00073         }
00074     }
00075     }
00076 
00077     return DefWindowProcW(hwnd, msg, wParam, lParam);
00078 }
00079 
00080 HWND get_notif_hwnd(void)
00081 {
00082     static ATOM wnd_class = 0;
00083     tls_data_t *tls_data;
00084 
00085     static const WCHAR wszURLMonikerNotificationWindow[] =
00086         {'U','R','L',' ','M','o','n','i','k','e','r',' ',
00087          'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
00088 
00089     tls_data = get_tls_data();
00090     if(!tls_data)
00091         return NULL;
00092 
00093     if(tls_data->notif_hwnd_cnt) {
00094         tls_data->notif_hwnd_cnt++;
00095         return tls_data->notif_hwnd;
00096     }
00097 
00098     if(!wnd_class) {
00099         static WNDCLASSEXW wndclass = {
00100             sizeof(wndclass), 0,
00101             notif_wnd_proc, 0, 0,
00102             NULL, NULL, NULL, NULL, NULL,
00103             wszURLMonikerNotificationWindow,
00104             NULL
00105         };
00106 
00107         wndclass.hInstance = hProxyDll;
00108 
00109         wnd_class = RegisterClassExW(&wndclass);
00110         if (!wnd_class && GetLastError() == ERROR_CLASS_ALREADY_EXISTS)
00111             wnd_class = 1;
00112     }
00113 
00114     tls_data->notif_hwnd = CreateWindowExW(0, wszURLMonikerNotificationWindow,
00115             wszURLMonikerNotificationWindow, 0, 0, 0, 0, 0, HWND_MESSAGE,
00116             NULL, hProxyDll, NULL);
00117     if(tls_data->notif_hwnd)
00118         tls_data->notif_hwnd_cnt++;
00119 
00120     TRACE("hwnd = %p\n", tls_data->notif_hwnd);
00121 
00122     return tls_data->notif_hwnd;
00123 }
00124 
00125 void release_notif_hwnd(HWND hwnd)
00126 {
00127     tls_data_t *data = get_tls_data();
00128 
00129     if(!data)
00130         return;
00131 
00132     if(data->notif_hwnd != hwnd) {
00133         PostMessageW(data->notif_hwnd, WM_MK_RELEASE, 0, 0);
00134         return;
00135     }
00136 
00137     if(!--data->notif_hwnd_cnt) {
00138         DestroyWindow(data->notif_hwnd);
00139         data->notif_hwnd = NULL;
00140     }
00141 }
00142 
00143 static void push_task(BindProtocol *This, task_header_t *task, task_proc_t proc)
00144 {
00145     BOOL do_post = FALSE;
00146 
00147     task->proc = proc;
00148     task->next = NULL;
00149 
00150     EnterCriticalSection(&This->section);
00151 
00152     if(This->task_queue_tail) {
00153         This->task_queue_tail->next = task;
00154         This->task_queue_tail = task;
00155     }else {
00156         This->task_queue_tail = This->task_queue_head = task;
00157         do_post = !This->continue_call;
00158     }
00159 
00160     LeaveCriticalSection(&This->section);
00161 
00162     if(do_post) {
00163         IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
00164         PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This);
00165     }
00166 }
00167 
00168 static inline BOOL do_direct_notif(BindProtocol *This)
00169 {
00170     return !(This->pi & PI_APARTMENTTHREADED) || (This->apartment_thread == GetCurrentThreadId() && !This->continue_call);
00171 }
00172 
00173 static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter, LPCWSTR mime)
00174 {
00175     PROTOCOLFILTERDATA filter_data = { sizeof(PROTOCOLFILTERDATA), NULL, NULL, NULL, 0 };
00176     IInternetProtocolSink *protocol_sink, *old_sink;
00177     ProtocolProxy *filter_proxy;
00178     HRESULT hres;
00179 
00180     hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&protocol_sink);
00181     if(FAILED(hres))
00182         return hres;
00183 
00184     hres = create_protocol_proxy(&This->default_protocol_handler.IInternetProtocol_iface, This->protocol_sink, &filter_proxy);
00185     if(FAILED(hres)) {
00186         IInternetProtocolSink_Release(protocol_sink);
00187         return hres;
00188     }
00189 
00190     old_sink = This->protocol_sink;
00191     This->protocol_sink = protocol_sink;
00192     This->filter_proxy = filter_proxy;
00193 
00194     IInternetProtocol_AddRef(mime_filter);
00195     This->protocol_handler = mime_filter;
00196 
00197     filter_data.pProtocol = &filter_proxy->IInternetProtocol_iface;
00198     hres = IInternetProtocol_Start(mime_filter, mime, &filter_proxy->IInternetProtocolSink_iface,
00199             &This->IInternetBindInfo_iface, PI_FILTER_MODE|PI_FORCE_ASYNC,
00200             (HANDLE_PTR)&filter_data);
00201     if(FAILED(hres)) {
00202         IInternetProtocolSink_Release(old_sink);
00203         return hres;
00204     }
00205 
00206     IInternetProtocolSink_ReportProgress(old_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
00207     IInternetProtocolSink_Release(old_sink);
00208 
00209     This->pi &= ~PI_MIMEVERIFICATION; /* FIXME: more tests */
00210     return S_OK;
00211 }
00212 
00213 static void mime_available(BindProtocol *This, LPCWSTR mime, BOOL verified)
00214 {
00215     IInternetProtocol *mime_filter;
00216     HRESULT hres;
00217 
00218     heap_free(This->mime);
00219     This->mime = NULL;
00220 
00221     mime_filter = get_mime_filter(mime);
00222     if(mime_filter) {
00223         TRACE("Got mime filter for %s\n", debugstr_w(mime));
00224 
00225         hres = handle_mime_filter(This, mime_filter, mime);
00226         IInternetProtocol_Release(mime_filter);
00227         if(FAILED(hres))
00228             FIXME("MIME filter failed: %08x\n", hres);
00229     }else {
00230         This->mime = heap_strdupW(mime);
00231 
00232         if(verified || !(This->pi & PI_MIMEVERIFICATION)) {
00233             This->reported_mime = TRUE;
00234 
00235             if(This->protocol_sink)
00236                 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
00237         }
00238     }
00239 }
00240 
00241 static inline BindProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
00242 {
00243     return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolEx_iface);
00244 }
00245 
00246 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
00247 {
00248     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00249 
00250     *ppv = NULL;
00251     if(IsEqualGUID(&IID_IUnknown, riid)) {
00252         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
00253         *ppv = &This->IInternetProtocolEx_iface;
00254     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
00255         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
00256         *ppv = &This->IInternetProtocolEx_iface;
00257     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
00258         TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
00259         *ppv = &This->IInternetProtocolEx_iface;
00260     }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
00261         TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
00262         *ppv = &This->IInternetProtocolEx_iface;
00263     }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
00264         TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
00265         *ppv = &This->IInternetBindInfo_iface;
00266     }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
00267         TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
00268         *ppv = &This->IInternetPriority_iface;
00269     }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
00270         FIXME("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
00271     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
00272         TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
00273         *ppv = &This->IServiceProvider_iface;
00274     }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
00275         TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
00276         *ppv = &This->IInternetProtocolSink_iface;
00277     }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
00278         TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv);
00279 
00280         if(This->protocol) {
00281             IWinInetInfo *inet_info;
00282             HRESULT hres;
00283 
00284             hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetInfo, (void**)&inet_info);
00285             if(SUCCEEDED(hres)) {
00286                 *ppv = &This->IWinInetHttpInfo_iface;
00287                 IWinInetInfo_Release(inet_info);
00288             }
00289         }
00290     }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
00291         TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv);
00292 
00293         if(This->protocol) {
00294             IWinInetHttpInfo *http_info;
00295             HRESULT hres;
00296 
00297             hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
00298             if(SUCCEEDED(hres)) {
00299                 *ppv = &This->IWinInetHttpInfo_iface;
00300                 IWinInetHttpInfo_Release(http_info);
00301             }
00302         }
00303     }else {
00304         WARN("not supported interface %s\n", debugstr_guid(riid));
00305     }
00306 
00307     if(!*ppv)
00308         return E_NOINTERFACE;
00309 
00310     IUnknown_AddRef((IUnknown*)*ppv);
00311     return S_OK;
00312 }
00313 
00314 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface)
00315 {
00316     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00317     LONG ref = InterlockedIncrement(&This->ref);
00318     TRACE("(%p) ref=%d\n", This, ref);
00319     return ref;
00320 }
00321 
00322 static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
00323 {
00324     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00325     LONG ref = InterlockedDecrement(&This->ref);
00326 
00327     TRACE("(%p) ref=%d\n", This, ref);
00328 
00329     if(!ref) {
00330         if(This->wininet_info)
00331             IWinInetInfo_Release(This->wininet_info);
00332         if(This->wininet_http_info)
00333             IWinInetHttpInfo_Release(This->wininet_http_info);
00334         if(This->protocol)
00335             IInternetProtocol_Release(This->protocol);
00336         if(This->bind_info)
00337             IInternetBindInfo_Release(This->bind_info);
00338         if(This->protocol_handler && This->protocol_handler != &This->default_protocol_handler.IInternetProtocol_iface)
00339             IInternetProtocol_Release(This->protocol_handler);
00340         if(This->filter_proxy)
00341             IInternetProtocol_Release(&This->filter_proxy->IInternetProtocol_iface);
00342         if(This->uri)
00343             IUri_Release(This->uri);
00344 
00345         set_binding_sink(This, NULL, NULL);
00346 
00347         if(This->notif_hwnd)
00348             release_notif_hwnd(This->notif_hwnd);
00349         DeleteCriticalSection(&This->section);
00350 
00351         heap_free(This->mime);
00352         heap_free(This);
00353 
00354         URLMON_UnlockModule();
00355     }
00356 
00357     return ref;
00358 }
00359 
00360 static HRESULT WINAPI BindProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
00361         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
00362         DWORD grfPI, HANDLE_PTR dwReserved)
00363 {
00364     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00365     IUri *uri;
00366     HRESULT hres;
00367 
00368     TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
00369             pOIBindInfo, grfPI, dwReserved);
00370 
00371     hres = CreateUri(szUrl, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
00372     if(FAILED(hres))
00373         return hres;
00374 
00375     hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink,
00376             pOIBindInfo, grfPI, (HANDLE*)dwReserved);
00377 
00378     IUri_Release(uri);
00379     return hres;
00380 }
00381 
00382 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
00383 {
00384     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00385 
00386     TRACE("(%p)->(%p)\n", This, pProtocolData);
00387 
00388     return IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
00389 }
00390 
00391 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
00392         DWORD dwOptions)
00393 {
00394     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00395 
00396     TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
00397 
00398     return IInternetProtocol_Abort(This->protocol_handler, hrReason, dwOptions);
00399 }
00400 
00401 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
00402 {
00403     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00404 
00405     TRACE("(%p)->(%08x)\n", This, dwOptions);
00406 
00407     return IInternetProtocol_Terminate(This->protocol_handler, dwOptions);
00408 }
00409 
00410 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocolEx *iface)
00411 {
00412     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00413     FIXME("(%p)\n", This);
00414     return E_NOTIMPL;
00415 }
00416 
00417 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocolEx *iface)
00418 {
00419     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00420     FIXME("(%p)\n", This);
00421     return E_NOTIMPL;
00422 }
00423 
00424 static HRESULT WINAPI BindProtocol_Read(IInternetProtocolEx *iface, void *pv,
00425         ULONG cb, ULONG *pcbRead)
00426 {
00427     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00428 
00429     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
00430 
00431     if(pcbRead)
00432         *pcbRead = 0;
00433     return IInternetProtocol_Read(This->protocol_handler, pv, cb, pcbRead);
00434 }
00435 
00436 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
00437         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
00438 {
00439     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00440     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
00441     return E_NOTIMPL;
00442 }
00443 
00444 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
00445 {
00446     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00447 
00448     TRACE("(%p)->(%08x)\n", This, dwOptions);
00449 
00450     return IInternetProtocol_LockRequest(This->protocol_handler, dwOptions);
00451 }
00452 
00453 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocolEx *iface)
00454 {
00455     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00456 
00457     TRACE("(%p)\n", This);
00458 
00459     return IInternetProtocol_UnlockRequest(This->protocol_handler);
00460 }
00461 
00462 static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
00463         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
00464         DWORD grfPI, HANDLE *dwReserved)
00465 {
00466     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
00467     IInternetProtocol *protocol = NULL;
00468     IInternetProtocolEx *protocolex;
00469     IInternetPriority *priority;
00470     IServiceProvider *service_provider;
00471     BOOL urlmon_protocol = FALSE;
00472     CLSID clsid = IID_NULL;
00473     LPOLESTR clsid_str;
00474     HRESULT hres;
00475 
00476     TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
00477 
00478     if(!pUri || !pOIProtSink || !pOIBindInfo)
00479         return E_INVALIDARG;
00480 
00481     This->pi = grfPI;
00482 
00483     IUri_AddRef(pUri);
00484     This->uri = pUri;
00485 
00486     hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
00487                                                 (void**)&service_provider);
00488     if(SUCCEEDED(hres)) {
00489         /* FIXME: What's protocol CLSID here? */
00490         IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
00491                 &IID_IInternetProtocol, (void**)&protocol);
00492         IServiceProvider_Release(service_provider);
00493     }
00494 
00495     if(!protocol) {
00496         IClassFactory *cf;
00497         IUnknown *unk;
00498 
00499         hres = get_protocol_handler(pUri, &clsid, &urlmon_protocol, &cf);
00500         if(FAILED(hres))
00501             return hres;
00502 
00503         if(This->from_urlmon) {
00504             hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&protocol);
00505             IClassFactory_Release(cf);
00506             if(FAILED(hres))
00507                 return hres;
00508         }else {
00509             hres = IClassFactory_CreateInstance(cf, (IUnknown*)&This->IInternetBindInfo_iface,
00510                     &IID_IUnknown, (void**)&unk);
00511             IClassFactory_Release(cf);
00512             if(FAILED(hres))
00513                 return hres;
00514 
00515             hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
00516             IUnknown_Release(unk);
00517             if(FAILED(hres))
00518                 return hres;
00519         }
00520     }
00521 
00522     StringFromCLSID(&clsid, &clsid_str);
00523     IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
00524     CoTaskMemFree(clsid_str);
00525 
00526     This->protocol = protocol;
00527 
00528     if(urlmon_protocol) {
00529         IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
00530         IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&This->wininet_http_info);
00531     }
00532 
00533     set_binding_sink(This, pOIProtSink, pOIBindInfo);
00534 
00535     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
00536     if(SUCCEEDED(hres)) {
00537         IInternetPriority_SetPriority(priority, This->priority);
00538         IInternetPriority_Release(priority);
00539     }
00540 
00541     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
00542     if(SUCCEEDED(hres)) {
00543         hres = IInternetProtocolEx_StartEx(protocolex, pUri, &This->IInternetProtocolSink_iface,
00544                 &This->IInternetBindInfo_iface, 0, NULL);
00545         IInternetProtocolEx_Release(protocolex);
00546     }else {
00547         BSTR display_uri;
00548 
00549         hres = IUri_GetDisplayUri(pUri, &display_uri);
00550         if(FAILED(hres))
00551             return hres;
00552 
00553         hres = IInternetProtocol_Start(protocol, display_uri, &This->IInternetProtocolSink_iface,
00554                 &This->IInternetBindInfo_iface, 0, 0);
00555         SysFreeString(display_uri);
00556     }
00557 
00558     return hres;
00559 }
00560 
00561 void set_binding_sink(BindProtocol *This, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
00562 {
00563     IInternetProtocolSink *prev_sink;
00564     IServiceProvider *service_provider = NULL;
00565 
00566     if(sink)
00567         IInternetProtocolSink_AddRef(sink);
00568     prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
00569     if(prev_sink)
00570         IInternetProtocolSink_Release(prev_sink);
00571 
00572     if(sink)
00573         IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
00574     service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
00575     if(service_provider)
00576         IServiceProvider_Release(service_provider);
00577 
00578     if(bind_info)
00579         IInternetBindInfo_AddRef(bind_info);
00580     bind_info = InterlockedExchangePointer((void**)&This->bind_info, bind_info);
00581     if(bind_info)
00582         IInternetBindInfo_Release(bind_info);
00583 }
00584 
00585 static const IInternetProtocolExVtbl BindProtocolVtbl = {
00586     BindProtocol_QueryInterface,
00587     BindProtocol_AddRef,
00588     BindProtocol_Release,
00589     BindProtocol_Start,
00590     BindProtocol_Continue,
00591     BindProtocol_Abort,
00592     BindProtocol_Terminate,
00593     BindProtocol_Suspend,
00594     BindProtocol_Resume,
00595     BindProtocol_Read,
00596     BindProtocol_Seek,
00597     BindProtocol_LockRequest,
00598     BindProtocol_UnlockRequest,
00599     BindProtocol_StartEx
00600 };
00601 
00602 static inline BindProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
00603 {
00604     return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocol_iface);
00605 }
00606 
00607 static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
00608 {
00609     ERR("should not be called\n");
00610     return E_NOINTERFACE;
00611 }
00612 
00613 static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocol *iface)
00614 {
00615     BindProtocol *This = impl_from_IInternetProtocol(iface);
00616     return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
00617 }
00618 
00619 static ULONG WINAPI ProtocolHandler_Release(IInternetProtocol *iface)
00620 {
00621     BindProtocol *This = impl_from_IInternetProtocol(iface);
00622     return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
00623 }
00624 
00625 static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR szUrl,
00626         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
00627         DWORD grfPI, HANDLE_PTR dwReserved)
00628 {
00629     ERR("Should not be called\n");
00630     return E_NOTIMPL;
00631 }
00632 
00633 static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
00634 {
00635     BindProtocol *This = impl_from_IInternetProtocol(iface);
00636     HRESULT hres;
00637 
00638     TRACE("(%p)->(%p)\n", This, pProtocolData);
00639 
00640     hres = IInternetProtocol_Continue(This->protocol, pProtocolData);
00641 
00642     heap_free(pProtocolData);
00643     return hres;
00644 }
00645 
00646 static HRESULT WINAPI ProtocolHandler_Abort(IInternetProtocol *iface, HRESULT hrReason,
00647         DWORD dwOptions)
00648 {
00649     BindProtocol *This = impl_from_IInternetProtocol(iface);
00650 
00651     TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
00652 
00653     if(This->protocol && !This->reported_result)
00654         return IInternetProtocol_Abort(This->protocol, hrReason, dwOptions);
00655 
00656     return S_OK;
00657 }
00658 
00659 static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD dwOptions)
00660 {
00661     BindProtocol *This = impl_from_IInternetProtocol(iface);
00662 
00663     TRACE("(%p)->(%08x)\n", This, dwOptions);
00664 
00665     if(!This->reported_result)
00666         return E_FAIL;
00667 
00668     IInternetProtocol_Terminate(This->protocol, 0);
00669 
00670     if(This->filter_proxy) {
00671         IInternetProtocol_Release(&This->filter_proxy->IInternetProtocol_iface);
00672         This->filter_proxy = NULL;
00673     }
00674 
00675     set_binding_sink(This, NULL, NULL);
00676 
00677     if(This->bind_info) {
00678         IInternetBindInfo_Release(This->bind_info);
00679         This->bind_info = NULL;
00680     }
00681 
00682     return S_OK;
00683 }
00684 
00685 static HRESULT WINAPI ProtocolHandler_Suspend(IInternetProtocol *iface)
00686 {
00687     BindProtocol *This = impl_from_IInternetProtocol(iface);
00688     FIXME("(%p)\n", This);
00689     return E_NOTIMPL;
00690 }
00691 
00692 static HRESULT WINAPI ProtocolHandler_Resume(IInternetProtocol *iface)
00693 {
00694     BindProtocol *This = impl_from_IInternetProtocol(iface);
00695     FIXME("(%p)\n", This);
00696     return E_NOTIMPL;
00697 }
00698 
00699 static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocol *iface, void *pv,
00700         ULONG cb, ULONG *pcbRead)
00701 {
00702     BindProtocol *This = impl_from_IInternetProtocol(iface);
00703     ULONG read = 0;
00704     HRESULT hres = S_OK;
00705 
00706     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
00707 
00708     if(This->buf_size) {
00709         read = min(cb, This->buf_size);
00710         memcpy(pv, This->buf, read);
00711 
00712         if(read == This->buf_size) {
00713             heap_free(This->buf);
00714             This->buf = NULL;
00715         }else {
00716             memmove(This->buf, This->buf+cb, This->buf_size-cb);
00717         }
00718 
00719         This->buf_size -= read;
00720     }
00721 
00722     if(read < cb) {
00723         ULONG cread = 0;
00724 
00725         hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb-read, &cread);
00726         read += cread;
00727     }
00728 
00729     *pcbRead = read;
00730     return hres;
00731 }
00732 
00733 static HRESULT WINAPI ProtocolHandler_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
00734         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
00735 {
00736     BindProtocol *This = impl_from_IInternetProtocol(iface);
00737     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
00738     return E_NOTIMPL;
00739 }
00740 
00741 static HRESULT WINAPI ProtocolHandler_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
00742 {
00743     BindProtocol *This = impl_from_IInternetProtocol(iface);
00744 
00745     TRACE("(%p)->(%08x)\n", This, dwOptions);
00746 
00747     return IInternetProtocol_LockRequest(This->protocol, dwOptions);
00748 }
00749 
00750 static HRESULT WINAPI ProtocolHandler_UnlockRequest(IInternetProtocol *iface)
00751 {
00752     BindProtocol *This = impl_from_IInternetProtocol(iface);
00753 
00754     TRACE("(%p)\n", This);
00755 
00756     return IInternetProtocol_UnlockRequest(This->protocol);
00757 }
00758 
00759 static const IInternetProtocolVtbl InternetProtocolHandlerVtbl = {
00760     ProtocolHandler_QueryInterface,
00761     ProtocolHandler_AddRef,
00762     ProtocolHandler_Release,
00763     ProtocolHandler_Start,
00764     ProtocolHandler_Continue,
00765     ProtocolHandler_Abort,
00766     ProtocolHandler_Terminate,
00767     ProtocolHandler_Suspend,
00768     ProtocolHandler_Resume,
00769     ProtocolHandler_Read,
00770     ProtocolHandler_Seek,
00771     ProtocolHandler_LockRequest,
00772     ProtocolHandler_UnlockRequest
00773 };
00774 
00775 static inline BindProtocol *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
00776 {
00777     return CONTAINING_RECORD(iface, BindProtocol, IInternetBindInfo_iface);
00778 }
00779 
00780 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
00781         REFIID riid, void **ppv)
00782 {
00783     BindProtocol *This = impl_from_IInternetBindInfo(iface);
00784     return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
00785 }
00786 
00787 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
00788 {
00789     BindProtocol *This = impl_from_IInternetBindInfo(iface);
00790     return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
00791 }
00792 
00793 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
00794 {
00795     BindProtocol *This = impl_from_IInternetBindInfo(iface);
00796     return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
00797 }
00798 
00799 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
00800         DWORD *grfBINDF, BINDINFO *pbindinfo)
00801 {
00802     BindProtocol *This = impl_from_IInternetBindInfo(iface);
00803     HRESULT hres;
00804 
00805     TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
00806 
00807     hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
00808     if(FAILED(hres)) {
00809         WARN("GetBindInfo failed: %08x\n", hres);
00810         return hres;
00811     }
00812 
00813     *grfBINDF |= BINDF_FROMURLMON;
00814     return hres;
00815 }
00816 
00817 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
00818         ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
00819 {
00820     BindProtocol *This = impl_from_IInternetBindInfo(iface);
00821 
00822     TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
00823 
00824     return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
00825 }
00826 
00827 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
00828     BindInfo_QueryInterface,
00829     BindInfo_AddRef,
00830     BindInfo_Release,
00831     BindInfo_GetBindInfo,
00832     BindInfo_GetBindString
00833 };
00834 
00835 static inline BindProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
00836 {
00837     return CONTAINING_RECORD(iface, BindProtocol, IInternetPriority_iface);
00838 }
00839 
00840 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
00841         REFIID riid, void **ppv)
00842 {
00843     BindProtocol *This = impl_from_IInternetPriority(iface);
00844     return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
00845 }
00846 
00847 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
00848 {
00849     BindProtocol *This = impl_from_IInternetPriority(iface);
00850     return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
00851 }
00852 
00853 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
00854 {
00855     BindProtocol *This = impl_from_IInternetPriority(iface);
00856     return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
00857 }
00858 
00859 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
00860 {
00861     BindProtocol *This = impl_from_IInternetPriority(iface);
00862 
00863     TRACE("(%p)->(%d)\n", This, nPriority);
00864 
00865     This->priority = nPriority;
00866     return S_OK;
00867 }
00868 
00869 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
00870 {
00871     BindProtocol *This = impl_from_IInternetPriority(iface);
00872 
00873     TRACE("(%p)->(%p)\n", This, pnPriority);
00874 
00875     *pnPriority = This->priority;
00876     return S_OK;
00877 }
00878 
00879 static const IInternetPriorityVtbl InternetPriorityVtbl = {
00880     InternetPriority_QueryInterface,
00881     InternetPriority_AddRef,
00882     InternetPriority_Release,
00883     InternetPriority_SetPriority,
00884     InternetPriority_GetPriority
00885 
00886 };
00887 
00888 static inline BindProtocol *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
00889 {
00890     return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolSink_iface);
00891 }
00892 
00893 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
00894         REFIID riid, void **ppv)
00895 {
00896     BindProtocol *This = impl_from_IInternetProtocolSink(iface);
00897     return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
00898 }
00899 
00900 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
00901 {
00902     BindProtocol *This = impl_from_IInternetProtocolSink(iface);
00903     return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
00904 }
00905 
00906 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
00907 {
00908     BindProtocol *This = impl_from_IInternetProtocolSink(iface);
00909     return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
00910 }
00911 
00912 typedef struct {
00913     task_header_t header;
00914     PROTOCOLDATA *data;
00915 } switch_task_t;
00916 
00917 static void switch_proc(BindProtocol *bind, task_header_t *t)
00918 {
00919     switch_task_t *task = (switch_task_t*)t;
00920 
00921     IInternetProtocol_Continue(bind->protocol_handler, task->data);
00922 
00923     heap_free(task);
00924 }
00925 
00926 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
00927         PROTOCOLDATA *pProtocolData)
00928 {
00929     BindProtocol *This = impl_from_IInternetProtocolSink(iface);
00930     PROTOCOLDATA *data;
00931 
00932     TRACE("(%p)->(%p)\n", This, pProtocolData);
00933 
00934     TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
00935           pProtocolData->pData, pProtocolData->cbData);
00936 
00937     data = heap_alloc(sizeof(PROTOCOLDATA));
00938     if(!data)
00939         return E_OUTOFMEMORY;
00940     memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
00941 
00942     if(!do_direct_notif(This)) {
00943         switch_task_t *task;
00944 
00945         task = heap_alloc(sizeof(switch_task_t));
00946         if(!task)
00947             return E_OUTOFMEMORY;
00948 
00949         task->data = data;
00950 
00951         push_task(This, &task->header, switch_proc);
00952         return S_OK;
00953     }
00954 
00955     if(!This->protocol_sink) {
00956         IInternetProtocol_Continue(This->protocol_handler, data);
00957         return S_OK;
00958     }
00959 
00960     return IInternetProtocolSink_Switch(This->protocol_sink, data);
00961 }
00962 
00963 static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR status_text)
00964 {
00965     switch(status_code) {
00966     case BINDSTATUS_FINDINGRESOURCE:
00967     case BINDSTATUS_CONNECTING:
00968     case BINDSTATUS_REDIRECTING:
00969     case BINDSTATUS_SENDINGREQUEST:
00970     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
00971     case BINDSTATUS_DIRECTBIND:
00972     case BINDSTATUS_ACCEPTRANGES:
00973         if(This->protocol_sink)
00974             IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
00975         break;
00976 
00977     case BINDSTATUS_BEGINDOWNLOADDATA:
00978         if(This->protocol_sink)
00979             IInternetProtocolSink_ReportData(This->protocol_sink, This->bscf, This->progress, This->progress_max);
00980         break;
00981 
00982     case BINDSTATUS_MIMETYPEAVAILABLE:
00983         mime_available(This, status_text, FALSE);
00984         break;
00985 
00986     case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
00987         mime_available(This, status_text, TRUE);
00988         break;
00989 
00990     default:
00991         FIXME("unsupported ulStatusCode %u\n", status_code);
00992     }
00993 }
00994 
00995 typedef struct {
00996     task_header_t header;
00997 
00998     ULONG status_code;
00999     LPWSTR status_text;
01000 } on_progress_task_t;
01001 
01002 static void on_progress_proc(BindProtocol *This, task_header_t *t)
01003 {
01004     on_progress_task_t *task = (on_progress_task_t*)t;
01005 
01006     report_progress(This, task->status_code, task->status_text);
01007 
01008     heap_free(task->status_text);
01009     heap_free(task);
01010 }
01011 
01012 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
01013         ULONG ulStatusCode, LPCWSTR szStatusText)
01014 {
01015     BindProtocol *This = impl_from_IInternetProtocolSink(iface);
01016 
01017     TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
01018 
01019     if(do_direct_notif(This)) {
01020         report_progress(This, ulStatusCode, szStatusText);
01021     }else {
01022         on_progress_task_t *task;
01023 
01024         task = heap_alloc(sizeof(on_progress_task_t));
01025 
01026         task->status_code = ulStatusCode;
01027         task->status_text = heap_strdupW(szStatusText);
01028 
01029         push_task(This, &task->header, on_progress_proc);
01030     }
01031 
01032     return S_OK;
01033 }
01034 
01035 static HRESULT report_data(BindProtocol *This, DWORD bscf, ULONG progress, ULONG progress_max)
01036 {
01037     This->bscf = bscf;
01038     This->progress = progress;
01039     This->progress_max = progress_max;
01040 
01041     if(!This->protocol_sink)
01042         return S_OK;
01043 
01044     if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
01045         BYTE buf[BUFFER_SIZE];
01046         DWORD read = 0;
01047         LPWSTR mime;
01048         HRESULT hres;
01049 
01050         do {
01051             read = 0;
01052             hres = IInternetProtocol_Read(This->protocol, buf,
01053                     sizeof(buf)-This->buf_size, &read);
01054             if(FAILED(hres) && hres != E_PENDING)
01055                 return hres;
01056 
01057             if(!This->buf) {
01058                 This->buf = heap_alloc(BUFFER_SIZE);
01059                 if(!This->buf)
01060                     return E_OUTOFMEMORY;
01061             }else if(read + This->buf_size > BUFFER_SIZE) {
01062                 BYTE *tmp;
01063 
01064                 tmp = heap_realloc(This->buf, read+This->buf_size);
01065                 if(!tmp)
01066                     return E_OUTOFMEMORY;
01067                 This->buf = tmp;
01068             }
01069 
01070             memcpy(This->buf+This->buf_size, buf, read);
01071             This->buf_size += read;
01072         }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
01073 
01074         if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
01075             return S_OK;
01076 
01077         bscf = BSCF_FIRSTDATANOTIFICATION;
01078         if(hres == S_FALSE)
01079             bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
01080 
01081         if(!This->reported_mime) {
01082             BSTR raw_uri;
01083 
01084             hres = IUri_GetRawUri(This->uri, &raw_uri);
01085             if(FAILED(hres))
01086                 return hres;
01087 
01088             hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
01089                     This->mime, 0, &mime, 0);
01090             SysFreeString(raw_uri);
01091             if(FAILED(hres))
01092                 return hres;
01093 
01094             mime_available(This, mime, TRUE);
01095             CoTaskMemFree(mime);
01096         }
01097     }
01098 
01099     if(!This->protocol_sink)
01100         return S_OK;
01101 
01102     return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
01103 }
01104 
01105 typedef struct {
01106     task_header_t header;
01107     DWORD bscf;
01108     ULONG progress;
01109     ULONG progress_max;
01110 } report_data_task_t;
01111 
01112 static void report_data_proc(BindProtocol *This, task_header_t *t)
01113 {
01114     report_data_task_t *task = (report_data_task_t*)t;
01115 
01116     report_data(This, task->bscf, task->progress, task->progress_max);
01117     heap_free(task);
01118 }
01119 
01120 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
01121         DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
01122 {
01123     BindProtocol *This = impl_from_IInternetProtocolSink(iface);
01124 
01125     TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
01126 
01127     if(!This->protocol_sink)
01128         return S_OK;
01129 
01130     if(!do_direct_notif(This)) {
01131         report_data_task_t *task;
01132 
01133         task = heap_alloc(sizeof(report_data_task_t));
01134         if(!task)
01135             return E_OUTOFMEMORY;
01136 
01137         task->bscf = grfBSCF;
01138         task->progress = ulProgress;
01139         task->progress_max = ulProgressMax;
01140 
01141         push_task(This, &task->header, report_data_proc);
01142         return S_OK;
01143     }
01144 
01145     return report_data(This, grfBSCF, ulProgress, ulProgressMax);
01146 }
01147 
01148 typedef struct {
01149     task_header_t header;
01150 
01151     HRESULT hres;
01152     DWORD err;
01153     LPWSTR str;
01154 } report_result_task_t;
01155 
01156 static void report_result_proc(BindProtocol *This, task_header_t *t)
01157 {
01158     report_result_task_t *task = (report_result_task_t*)t;
01159 
01160     if(This->protocol_sink)
01161         IInternetProtocolSink_ReportResult(This->protocol_sink, task->hres, task->err, task->str);
01162 
01163     heap_free(task->str);
01164     heap_free(task);
01165 }
01166 
01167 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
01168         HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
01169 {
01170     BindProtocol *This = impl_from_IInternetProtocolSink(iface);
01171 
01172     TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
01173 
01174     if(!This->protocol_sink)
01175         return E_FAIL;
01176 
01177     This->reported_result = TRUE;
01178 
01179     if(!do_direct_notif(This)) {
01180         report_result_task_t *task;
01181 
01182         task = heap_alloc(sizeof(report_result_task_t));
01183         if(!task)
01184             return E_OUTOFMEMORY;
01185 
01186         task->hres = hrResult;
01187         task->err = dwError;
01188         task->str = heap_strdupW(szResult);
01189 
01190         push_task(This, &task->header, report_result_proc);
01191         return S_OK;
01192     }
01193 
01194     return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
01195 }
01196 
01197 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
01198     BPInternetProtocolSink_QueryInterface,
01199     BPInternetProtocolSink_AddRef,
01200     BPInternetProtocolSink_Release,
01201     BPInternetProtocolSink_Switch,
01202     BPInternetProtocolSink_ReportProgress,
01203     BPInternetProtocolSink_ReportData,
01204     BPInternetProtocolSink_ReportResult
01205 };
01206 
01207 static inline BindProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
01208 {
01209     return CONTAINING_RECORD(iface, BindProtocol, IWinInetHttpInfo_iface);
01210 }
01211 
01212 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
01213 {
01214     BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
01215     return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
01216 }
01217 
01218 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
01219 {
01220     BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
01221     return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
01222 }
01223 
01224 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
01225 {
01226     BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
01227     return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
01228 }
01229 
01230 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
01231         void *pBuffer, DWORD *pcbBuffer)
01232 {
01233     BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
01234     FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
01235     return E_NOTIMPL;
01236 }
01237 
01238 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
01239         void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
01240 {
01241     BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
01242     FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
01243     return E_NOTIMPL;
01244 }
01245 
01246 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
01247     WinInetHttpInfo_QueryInterface,
01248     WinInetHttpInfo_AddRef,
01249     WinInetHttpInfo_Release,
01250     WinInetHttpInfo_QueryOption,
01251     WinInetHttpInfo_QueryInfo
01252 };
01253 
01254 static inline BindProtocol *impl_from_IServiceProvider(IServiceProvider *iface)
01255 {
01256     return CONTAINING_RECORD(iface, BindProtocol, IServiceProvider_iface);
01257 }
01258 
01259 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
01260         REFIID riid, void **ppv)
01261 {
01262     BindProtocol *This = impl_from_IServiceProvider(iface);
01263     return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
01264 }
01265 
01266 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
01267 {
01268     BindProtocol *This = impl_from_IServiceProvider(iface);
01269     return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
01270 }
01271 
01272 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
01273 {
01274     BindProtocol *This = impl_from_IServiceProvider(iface);
01275     return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
01276 }
01277 
01278 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
01279         REFGUID guidService, REFIID riid, void **ppv)
01280 {
01281     BindProtocol *This = impl_from_IServiceProvider(iface);
01282 
01283     TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
01284 
01285     if(!This->service_provider)
01286         return E_NOINTERFACE;
01287 
01288     return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
01289 }
01290 
01291 static const IServiceProviderVtbl ServiceProviderVtbl = {
01292     BPServiceProvider_QueryInterface,
01293     BPServiceProvider_AddRef,
01294     BPServiceProvider_Release,
01295     BPServiceProvider_QueryService
01296 };
01297 
01298 HRESULT create_binding_protocol(BOOL from_urlmon, BindProtocol **protocol)
01299 {
01300     BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
01301 
01302     ret->IInternetProtocolEx_iface.lpVtbl   = &BindProtocolVtbl;
01303     ret->IInternetBindInfo_iface.lpVtbl     = &InternetBindInfoVtbl;
01304     ret->IInternetPriority_iface.lpVtbl     = &InternetPriorityVtbl;
01305     ret->IServiceProvider_iface.lpVtbl      = &ServiceProviderVtbl;
01306     ret->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
01307     ret->IWinInetHttpInfo_iface.lpVtbl      = &WinInetHttpInfoVtbl;
01308 
01309     ret->default_protocol_handler.IInternetProtocol_iface.lpVtbl = &InternetProtocolHandlerVtbl;
01310 
01311     ret->ref = 1;
01312     ret->from_urlmon = from_urlmon;
01313     ret->apartment_thread = GetCurrentThreadId();
01314     ret->notif_hwnd = get_notif_hwnd();
01315     ret->protocol_handler = &ret->default_protocol_handler.IInternetProtocol_iface;
01316     InitializeCriticalSection(&ret->section);
01317 
01318     URLMON_LockModule();
01319 
01320     *protocol = ret;
01321     return S_OK;
01322 }

Generated on Fri May 25 2012 04:24:44 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.