1 /* 2 * Copyright 2007 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 "hlink_private.h" 20 21 #include "wine/debug.h" 22 #include "wine/unicode.h" 23 24 WINE_DEFAULT_DEBUG_CHANNEL(hlink); 25 26 typedef struct { 27 IUnknown IUnknown_inner; 28 IAuthenticate IAuthenticate_iface; 29 IHttpNegotiate IHttpNegotiate_iface; 30 IExtensionServices IExtensionServices_iface; 31 32 IUnknown *outer_unk; 33 LONG ref; 34 35 HWND hwnd; 36 LPWSTR username; 37 LPWSTR password; 38 LPWSTR headers; 39 } ExtensionService; 40 41 static inline ExtensionService *impl_from_IUnknown(IUnknown *iface) 42 { 43 return CONTAINING_RECORD(iface, ExtensionService, IUnknown_inner); 44 } 45 46 static HRESULT WINAPI ExtServUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 47 { 48 ExtensionService *This = impl_from_IUnknown(iface); 49 50 *ppv = NULL; 51 52 if(IsEqualGUID(&IID_IUnknown, riid)) { 53 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 54 *ppv = &This->IUnknown_inner; 55 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) { 56 TRACE("(%p)->(IID_IAuthenticate %p)\n", This, ppv); 57 *ppv = &This->IAuthenticate_iface; 58 }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) { 59 TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This, ppv); 60 *ppv = &This->IHttpNegotiate_iface; 61 }else if(IsEqualGUID(&IID_IExtensionServices, riid)) { 62 TRACE("(%p)->(IID_IExtensionServices %p)\n", This, ppv); 63 *ppv = &This->IExtensionServices_iface; 64 } 65 66 if(*ppv) { 67 IUnknown_AddRef((IUnknown*)*ppv); 68 return S_OK; 69 } 70 71 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 72 return E_NOINTERFACE; 73 } 74 75 static ULONG WINAPI ExtServUnk_AddRef(IUnknown *iface) 76 { 77 ExtensionService *This = impl_from_IUnknown(iface); 78 LONG ref = InterlockedIncrement(&This->ref); 79 80 TRACE("(%p) ref=%d\n", This, ref); 81 82 return ref; 83 } 84 85 static ULONG WINAPI ExtServUnk_Release(IUnknown *iface) 86 { 87 ExtensionService *This = impl_from_IUnknown(iface); 88 LONG ref = InterlockedDecrement(&This->ref); 89 90 TRACE("(%p) ref=%d\n", This, ref); 91 92 if(!ref) { 93 heap_free(This->username); 94 heap_free(This->password); 95 heap_free(This->headers); 96 heap_free(This); 97 } 98 99 return ref; 100 } 101 102 static const IUnknownVtbl ExtServUnkVtbl = { 103 ExtServUnk_QueryInterface, 104 ExtServUnk_AddRef, 105 ExtServUnk_Release 106 }; 107 108 static inline ExtensionService *impl_from_IAuthenticate(IAuthenticate *iface) 109 { 110 return CONTAINING_RECORD(iface, ExtensionService, IAuthenticate_iface); 111 } 112 113 static HRESULT WINAPI Authenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv) 114 { 115 ExtensionService *This = impl_from_IAuthenticate(iface); 116 return IUnknown_QueryInterface(This->outer_unk, riid, ppv); 117 } 118 119 static ULONG WINAPI Authenticate_AddRef(IAuthenticate *iface) 120 { 121 ExtensionService *This = impl_from_IAuthenticate(iface); 122 return IUnknown_AddRef(This->outer_unk); 123 } 124 125 static ULONG WINAPI Authenticate_Release(IAuthenticate *iface) 126 { 127 ExtensionService *This = impl_from_IAuthenticate(iface); 128 return IUnknown_Release(This->outer_unk); 129 } 130 131 static HRESULT WINAPI Authenticate_Authenticate(IAuthenticate *iface, 132 HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword) 133 { 134 ExtensionService *This = impl_from_IAuthenticate(iface); 135 136 TRACE("(%p)->(%p %p %p)\n", This, phwnd, pszUsername, pszPassword); 137 138 if(!phwnd || !pszUsername || !pszPassword) 139 return E_INVALIDARG; 140 141 *phwnd = This->hwnd; 142 *pszUsername = hlink_co_strdupW(This->username); 143 *pszPassword = hlink_co_strdupW(This->password); 144 145 return S_OK; 146 } 147 148 static const IAuthenticateVtbl AuthenticateVtbl = { 149 Authenticate_QueryInterface, 150 Authenticate_AddRef, 151 Authenticate_Release, 152 Authenticate_Authenticate 153 }; 154 155 static inline ExtensionService *impl_from_IHttpNegotiate(IHttpNegotiate *iface) 156 { 157 return CONTAINING_RECORD(iface, ExtensionService, IHttpNegotiate_iface); 158 } 159 160 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate *iface, REFIID riid, void **ppv) 161 { 162 ExtensionService *This = impl_from_IHttpNegotiate(iface); 163 return IUnknown_QueryInterface(This->outer_unk, riid, ppv); 164 } 165 166 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate *iface) 167 { 168 ExtensionService *This = impl_from_IHttpNegotiate(iface); 169 return IUnknown_AddRef(This->outer_unk); 170 } 171 172 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate *iface) 173 { 174 ExtensionService *This = impl_from_IHttpNegotiate(iface); 175 return IUnknown_Release(This->outer_unk); 176 } 177 178 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate *iface, 179 LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders) 180 { 181 ExtensionService *This = impl_from_IHttpNegotiate(iface); 182 183 TRACE("(%p)->(%s %s %x %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), dwReserved, 184 pszAdditionalHeaders); 185 186 if(!pszAdditionalHeaders) 187 return E_INVALIDARG; 188 189 *pszAdditionalHeaders = hlink_co_strdupW(This->headers); 190 return S_OK; 191 } 192 193 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate *iface, DWORD dwResponseCode, 194 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders) 195 { 196 ExtensionService *This = impl_from_IHttpNegotiate(iface); 197 198 TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders), 199 debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders); 200 201 *pszAdditionalRequestHeaders = NULL; 202 return S_OK; 203 } 204 205 static const IHttpNegotiateVtbl HttpNegotiateVtbl = { 206 HttpNegotiate_QueryInterface, 207 HttpNegotiate_AddRef, 208 HttpNegotiate_Release, 209 HttpNegotiate_BeginningTransaction, 210 HttpNegotiate_OnResponse 211 }; 212 213 static inline ExtensionService *impl_from_IExtensionServices(IExtensionServices *iface) 214 { 215 return CONTAINING_RECORD(iface, ExtensionService, IExtensionServices_iface); 216 } 217 218 static HRESULT WINAPI ExtServ_QueryInterface(IExtensionServices *iface, REFIID riid, void **ppv) 219 { 220 ExtensionService *This = impl_from_IExtensionServices(iface); 221 return IUnknown_QueryInterface(This->outer_unk, riid, ppv); 222 } 223 224 static ULONG WINAPI ExtServ_AddRef(IExtensionServices *iface) 225 { 226 ExtensionService *This = impl_from_IExtensionServices(iface); 227 return IUnknown_AddRef(This->outer_unk); 228 } 229 230 static ULONG WINAPI ExtServ_Release(IExtensionServices *iface) 231 { 232 ExtensionService *This = impl_from_IExtensionServices(iface); 233 return IUnknown_Release(This->outer_unk); 234 } 235 236 static HRESULT ExtServ_ImplSetAdditionalHeaders(ExtensionService* This, LPCWSTR pwzAdditionalHeaders) 237 { 238 int len; 239 240 heap_free(This->headers); 241 This->headers = NULL; 242 243 if (!pwzAdditionalHeaders) 244 return S_OK; 245 246 len = strlenW(pwzAdditionalHeaders); 247 248 if(len && pwzAdditionalHeaders[len-1] != '\n' && pwzAdditionalHeaders[len-1] != '\r') { 249 static const WCHAR endlW[] = {'\r','\n',0}; 250 This->headers = heap_alloc(len*sizeof(WCHAR) + sizeof(endlW)); 251 memcpy(This->headers, pwzAdditionalHeaders, len*sizeof(WCHAR)); 252 memcpy(This->headers+len, endlW, sizeof(endlW)); 253 }else { 254 This->headers = hlink_strdupW(pwzAdditionalHeaders); 255 } 256 257 return S_OK; 258 } 259 260 static HRESULT WINAPI ExtServ_SetAdditionalHeaders(IExtensionServices* iface, LPCWSTR pwzAdditionalHeaders) 261 { 262 ExtensionService *This = impl_from_IExtensionServices(iface); 263 264 TRACE("(%p)->(%s)\n", This, debugstr_w(pwzAdditionalHeaders)); 265 266 return ExtServ_ImplSetAdditionalHeaders(This,pwzAdditionalHeaders); 267 } 268 269 static HRESULT ExtServ_ImplSetAuthenticateData(ExtensionService* This, HWND phwnd, LPCWSTR pwzUsername, LPCWSTR pwzPassword) 270 { 271 heap_free(This->username); 272 heap_free(This->password); 273 274 This->hwnd = phwnd; 275 This->username = hlink_strdupW(pwzUsername); 276 This->password = hlink_strdupW(pwzPassword); 277 278 return S_OK; 279 } 280 281 static HRESULT WINAPI ExtServ_SetAuthenticateData(IExtensionServices* iface, HWND phwnd, LPCWSTR pwzUsername, LPCWSTR pwzPassword) 282 { 283 ExtensionService *This = impl_from_IExtensionServices(iface); 284 285 TRACE("(%p)->(%p %s %s)\n", This, phwnd, debugstr_w(pwzUsername), debugstr_w(pwzPassword)); 286 287 return ExtServ_ImplSetAuthenticateData(This, phwnd, pwzUsername, pwzPassword); 288 } 289 290 static const IExtensionServicesVtbl ExtServVtbl = { 291 ExtServ_QueryInterface, 292 ExtServ_AddRef, 293 ExtServ_Release, 294 ExtServ_SetAdditionalHeaders, 295 ExtServ_SetAuthenticateData 296 }; 297 298 /*********************************************************************** 299 * HlinkCreateExtensionServices (HLINK.@) 300 */ 301 HRESULT WINAPI HlinkCreateExtensionServices(LPCWSTR pwzAdditionalHeaders, 302 HWND phwnd, LPCWSTR pszUsername, LPCWSTR pszPassword, 303 IUnknown *punkOuter, REFIID riid, void** ppv) 304 { 305 ExtensionService *ret; 306 HRESULT hres = S_OK; 307 308 TRACE("%s %p %s %s %p %s %p\n",debugstr_w(pwzAdditionalHeaders), 309 phwnd, debugstr_w(pszUsername), debugstr_w(pszPassword), 310 punkOuter, debugstr_guid(riid), ppv); 311 312 ret = heap_alloc(sizeof(*ret)); 313 314 ret->IUnknown_inner.lpVtbl = &ExtServUnkVtbl; 315 ret->IAuthenticate_iface.lpVtbl = &AuthenticateVtbl; 316 ret->IHttpNegotiate_iface.lpVtbl = &HttpNegotiateVtbl; 317 ret->IExtensionServices_iface.lpVtbl = &ExtServVtbl; 318 ret->ref = 1; 319 ret->headers = NULL; 320 ret->hwnd = NULL; 321 ret->username = NULL; 322 ret->password = NULL; 323 324 ExtServ_ImplSetAuthenticateData(ret, phwnd, pszUsername, pszPassword); 325 ExtServ_ImplSetAdditionalHeaders(ret, pwzAdditionalHeaders); 326 327 if(!punkOuter) { 328 ret->outer_unk = &ret->IUnknown_inner; 329 hres = IUnknown_QueryInterface(&ret->IUnknown_inner, riid, ppv); 330 IUnknown_Release(&ret->IUnknown_inner); 331 }else if(IsEqualGUID(&IID_IUnknown, riid)) { 332 ret->outer_unk = punkOuter; 333 *ppv = &ret->IUnknown_inner; 334 }else { 335 IUnknown_Release(&ret->IUnknown_inner); 336 hres = E_INVALIDARG; 337 } 338 339 return hres; 340 } 341