1 /* 2 * Copyright 2009 Jacek Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "urlmon_main.h" 20 #include "wine/debug.h" 21 22 WINE_DEFAULT_DEBUG_CHANNEL(urlmon); 23 24 typedef struct { 25 Protocol base; 26 27 IInternetProtocol IInternetProtocol_iface; 28 IInternetPriority IInternetPriority_iface; 29 30 LONG ref; 31 } GopherProtocol; 32 33 static inline GopherProtocol *impl_from_Protocol(Protocol *prot) 34 { 35 return CONTAINING_RECORD(prot, GopherProtocol, base); 36 } 37 38 static HRESULT GopherProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags, 39 HINTERNET internet_session, IInternetBindInfo *bind_info) 40 { 41 GopherProtocol *This = impl_from_Protocol(prot); 42 BSTR url; 43 HRESULT hres; 44 45 hres = IUri_GetAbsoluteUri(uri, &url); 46 if(FAILED(hres)) 47 return hres; 48 49 This->base.request = InternetOpenUrlW(internet_session, url, NULL, 0, 50 request_flags, (DWORD_PTR)&This->base); 51 SysFreeString(url); 52 if (!This->base.request && GetLastError() != ERROR_IO_PENDING) { 53 WARN("InternetOpenUrl failed: %d\n", GetLastError()); 54 return INET_E_RESOURCE_NOT_FOUND; 55 } 56 57 return S_OK; 58 } 59 60 static HRESULT GopherProtocol_end_request(Protocol *prot) 61 { 62 return E_NOTIMPL; 63 } 64 65 static HRESULT GopherProtocol_start_downloading(Protocol *prot) 66 { 67 return S_OK; 68 } 69 70 static void GopherProtocol_close_connection(Protocol *prot) 71 { 72 } 73 74 static void GopherProtocol_on_error(Protocol *prot, DWORD error) 75 { 76 FIXME("(%p) %d - stub\n", prot, error); 77 } 78 79 static const ProtocolVtbl AsyncProtocolVtbl = { 80 GopherProtocol_open_request, 81 GopherProtocol_end_request, 82 GopherProtocol_start_downloading, 83 GopherProtocol_close_connection, 84 GopherProtocol_on_error 85 }; 86 87 static inline GopherProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface) 88 { 89 return CONTAINING_RECORD(iface, GopherProtocol, IInternetProtocol_iface); 90 } 91 92 static HRESULT WINAPI GopherProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv) 93 { 94 GopherProtocol *This = impl_from_IInternetProtocol(iface); 95 96 *ppv = NULL; 97 if(IsEqualGUID(&IID_IUnknown, riid)) { 98 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 99 *ppv = &This->IInternetProtocol_iface; 100 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { 101 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv); 102 *ppv = &This->IInternetProtocol_iface; 103 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) { 104 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv); 105 *ppv = &This->IInternetProtocol_iface; 106 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) { 107 TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv); 108 *ppv = &This->IInternetPriority_iface; 109 } 110 111 if(*ppv) { 112 IInternetProtocol_AddRef(iface); 113 return S_OK; 114 } 115 116 WARN("not supported interface %s\n", debugstr_guid(riid)); 117 return E_NOINTERFACE; 118 } 119 120 static ULONG WINAPI GopherProtocol_AddRef(IInternetProtocol *iface) 121 { 122 GopherProtocol *This = impl_from_IInternetProtocol(iface); 123 LONG ref = InterlockedIncrement(&This->ref); 124 TRACE("(%p) ref=%d\n", This, ref); 125 return ref; 126 } 127 128 static ULONG WINAPI GopherProtocol_Release(IInternetProtocol *iface) 129 { 130 GopherProtocol *This = impl_from_IInternetProtocol(iface); 131 LONG ref = InterlockedDecrement(&This->ref); 132 133 TRACE("(%p) ref=%d\n", This, ref); 134 135 if(!ref) { 136 heap_free(This); 137 138 URLMON_UnlockModule(); 139 } 140 141 return ref; 142 } 143 144 static HRESULT WINAPI GopherProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, 145 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, 146 DWORD grfPI, HANDLE_PTR dwReserved) 147 { 148 GopherProtocol *This = impl_from_IInternetProtocol(iface); 149 IUri *uri; 150 HRESULT hres; 151 152 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, 153 pOIBindInfo, grfPI, dwReserved); 154 155 hres = CreateUri(szUrl, 0, 0, &uri); 156 if(FAILED(hres)) 157 return hres; 158 159 hres = protocol_start(&This->base, &This->IInternetProtocol_iface, uri, pOIProtSink, 160 pOIBindInfo); 161 162 IUri_Release(uri); 163 return hres; 164 } 165 166 static HRESULT WINAPI GopherProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData) 167 { 168 GopherProtocol *This = impl_from_IInternetProtocol(iface); 169 170 TRACE("(%p)->(%p)\n", This, pProtocolData); 171 172 return protocol_continue(&This->base, pProtocolData); 173 } 174 175 static HRESULT WINAPI GopherProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason, 176 DWORD dwOptions) 177 { 178 GopherProtocol *This = impl_from_IInternetProtocol(iface); 179 180 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); 181 182 return protocol_abort(&This->base, hrReason); 183 } 184 185 static HRESULT WINAPI GopherProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions) 186 { 187 GopherProtocol *This = impl_from_IInternetProtocol(iface); 188 189 TRACE("(%p)->(%08x)\n", This, dwOptions); 190 191 protocol_close_connection(&This->base); 192 return S_OK; 193 } 194 195 static HRESULT WINAPI GopherProtocol_Suspend(IInternetProtocol *iface) 196 { 197 GopherProtocol *This = impl_from_IInternetProtocol(iface); 198 FIXME("(%p)\n", This); 199 return E_NOTIMPL; 200 } 201 202 static HRESULT WINAPI GopherProtocol_Resume(IInternetProtocol *iface) 203 { 204 GopherProtocol *This = impl_from_IInternetProtocol(iface); 205 FIXME("(%p)\n", This); 206 return E_NOTIMPL; 207 } 208 209 static HRESULT WINAPI GopherProtocol_Read(IInternetProtocol *iface, void *pv, 210 ULONG cb, ULONG *pcbRead) 211 { 212 GopherProtocol *This = impl_from_IInternetProtocol(iface); 213 214 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead); 215 216 return protocol_read(&This->base, pv, cb, pcbRead); 217 } 218 219 static HRESULT WINAPI GopherProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove, 220 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) 221 { 222 GopherProtocol *This = impl_from_IInternetProtocol(iface); 223 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition); 224 return E_NOTIMPL; 225 } 226 227 static HRESULT WINAPI GopherProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions) 228 { 229 GopherProtocol *This = impl_from_IInternetProtocol(iface); 230 231 TRACE("(%p)->(%08x)\n", This, dwOptions); 232 233 return protocol_lock_request(&This->base); 234 } 235 236 static HRESULT WINAPI GopherProtocol_UnlockRequest(IInternetProtocol *iface) 237 { 238 GopherProtocol *This = impl_from_IInternetProtocol(iface); 239 240 TRACE("(%p)\n", This); 241 242 return protocol_unlock_request(&This->base); 243 } 244 245 static const IInternetProtocolVtbl GopherProtocolVtbl = { 246 GopherProtocol_QueryInterface, 247 GopherProtocol_AddRef, 248 GopherProtocol_Release, 249 GopherProtocol_Start, 250 GopherProtocol_Continue, 251 GopherProtocol_Abort, 252 GopherProtocol_Terminate, 253 GopherProtocol_Suspend, 254 GopherProtocol_Resume, 255 GopherProtocol_Read, 256 GopherProtocol_Seek, 257 GopherProtocol_LockRequest, 258 GopherProtocol_UnlockRequest 259 }; 260 261 static inline GopherProtocol *impl_from_IInternetPriority(IInternetPriority *iface) 262 { 263 return CONTAINING_RECORD(iface, GopherProtocol, IInternetPriority_iface); 264 } 265 266 static HRESULT WINAPI GopherPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv) 267 { 268 GopherProtocol *This = impl_from_IInternetPriority(iface); 269 return IInternetProtocol_QueryInterface(&This->IInternetProtocol_iface, riid, ppv); 270 } 271 272 static ULONG WINAPI GopherPriority_AddRef(IInternetPriority *iface) 273 { 274 GopherProtocol *This = impl_from_IInternetPriority(iface); 275 return IInternetProtocol_AddRef(&This->IInternetProtocol_iface); 276 } 277 278 static ULONG WINAPI GopherPriority_Release(IInternetPriority *iface) 279 { 280 GopherProtocol *This = impl_from_IInternetPriority(iface); 281 return IInternetProtocol_Release(&This->IInternetProtocol_iface); 282 } 283 284 static HRESULT WINAPI GopherPriority_SetPriority(IInternetPriority *iface, LONG nPriority) 285 { 286 GopherProtocol *This = impl_from_IInternetPriority(iface); 287 288 TRACE("(%p)->(%d)\n", This, nPriority); 289 290 This->base.priority = nPriority; 291 return S_OK; 292 } 293 294 static HRESULT WINAPI GopherPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority) 295 { 296 GopherProtocol *This = impl_from_IInternetPriority(iface); 297 298 TRACE("(%p)->(%p)\n", This, pnPriority); 299 300 *pnPriority = This->base.priority; 301 return S_OK; 302 } 303 304 static const IInternetPriorityVtbl GopherPriorityVtbl = { 305 GopherPriority_QueryInterface, 306 GopherPriority_AddRef, 307 GopherPriority_Release, 308 GopherPriority_SetPriority, 309 GopherPriority_GetPriority 310 }; 311 312 HRESULT GopherProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) 313 { 314 GopherProtocol *ret; 315 316 TRACE("(%p %p)\n", pUnkOuter, ppobj); 317 318 URLMON_LockModule(); 319 320 ret = heap_alloc_zero(sizeof(GopherProtocol)); 321 322 ret->base.vtbl = &AsyncProtocolVtbl; 323 ret->IInternetProtocol_iface.lpVtbl = &GopherProtocolVtbl; 324 ret->IInternetPriority_iface.lpVtbl = &GopherPriorityVtbl; 325 ret->ref = 1; 326 327 *ppobj = &ret->IInternetProtocol_iface; 328 329 return S_OK; 330 } 331