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