extserv.c 10.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * Copyright 2007 Jacek Caban for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "hlink_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(hlink);

typedef struct {
26
    IUnknown           IUnknown_inner;
27 28 29
    IAuthenticate      IAuthenticate_iface;
    IHttpNegotiate     IHttpNegotiate_iface;
    IExtensionServices IExtensionServices_iface;
30

31
    IUnknown *outer_unk;
32 33 34 35 36
    LONG ref;

    HWND hwnd;
    LPWSTR username;
    LPWSTR password;
37
    LPWSTR headers;
38 39
} ExtensionService;

40 41
static inline ExtensionService *impl_from_IUnknown(IUnknown *iface)
{
42
    return CONTAINING_RECORD(iface, ExtensionService, IUnknown_inner);
43
}
44 45 46

static HRESULT WINAPI ExtServUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
47
    ExtensionService *This = impl_from_IUnknown(iface);
48 49 50 51 52

    *ppv = NULL;

    if(IsEqualGUID(&IID_IUnknown, riid)) {
        TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
53
        *ppv = &This->IUnknown_inner;
54 55
    }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
        TRACE("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
56
        *ppv = &This->IAuthenticate_iface;
57 58
    }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
        TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This, ppv);
59
        *ppv = &This->IHttpNegotiate_iface;
60 61
    }else if(IsEqualGUID(&IID_IExtensionServices, riid)) {
        TRACE("(%p)->(IID_IExtensionServices %p)\n", This, ppv);
62
        *ppv = &This->IExtensionServices_iface;
63 64 65
    }

    if(*ppv) {
66
        IUnknown_AddRef((IUnknown*)*ppv);
67 68 69 70 71 72 73 74 75
        return S_OK;
    }

    FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
    return E_NOINTERFACE;
}

static ULONG WINAPI ExtServUnk_AddRef(IUnknown *iface)
{
76
    ExtensionService *This = impl_from_IUnknown(iface);
77 78 79 80 81 82 83 84 85
    LONG ref = InterlockedIncrement(&This->ref);

    TRACE("(%p) ref=%d\n", This, ref);

    return ref;
}

static ULONG WINAPI ExtServUnk_Release(IUnknown *iface)
{
86
    ExtensionService *This = impl_from_IUnknown(iface);
87 88 89 90 91
    LONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p) ref=%d\n", This, ref);

    if(!ref) {
92 93
        heap_free(This->username);
        heap_free(This->password);
94
        heap_free(This->headers);
95
        heap_free(This);
96 97 98 99 100 101 102 103 104 105 106
    }

    return ref;
}

static const IUnknownVtbl ExtServUnkVtbl = {
    ExtServUnk_QueryInterface,
    ExtServUnk_AddRef,
    ExtServUnk_Release
};

107 108 109 110
static inline ExtensionService *impl_from_IAuthenticate(IAuthenticate *iface)
{
    return CONTAINING_RECORD(iface, ExtensionService, IAuthenticate_iface);
}
111 112 113

static HRESULT WINAPI Authenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv)
{
114
    ExtensionService *This = impl_from_IAuthenticate(iface);
115
    return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
116 117 118 119
}

static ULONG WINAPI Authenticate_AddRef(IAuthenticate *iface)
{
120
    ExtensionService *This = impl_from_IAuthenticate(iface);
121
    return IUnknown_AddRef(This->outer_unk);
122 123 124 125
}

static ULONG WINAPI Authenticate_Release(IAuthenticate *iface)
{
126
    ExtensionService *This = impl_from_IAuthenticate(iface);
127
    return IUnknown_Release(This->outer_unk);
128 129 130 131 132
}

static HRESULT WINAPI Authenticate_Authenticate(IAuthenticate *iface,
        HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword)
{
133
    ExtensionService *This = impl_from_IAuthenticate(iface);
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

    TRACE("(%p)->(%p %p %p)\n", This, phwnd, pszUsername, pszPassword);

    if(!phwnd || !pszUsername || !pszPassword)
        return E_INVALIDARG;

    *phwnd = This->hwnd;
    *pszUsername = hlink_co_strdupW(This->username);
    *pszPassword = hlink_co_strdupW(This->password);

    return S_OK;
}

static const IAuthenticateVtbl AuthenticateVtbl = {
    Authenticate_QueryInterface,
    Authenticate_AddRef,
    Authenticate_Release,
    Authenticate_Authenticate
};

154 155 156 157
static inline ExtensionService *impl_from_IHttpNegotiate(IHttpNegotiate *iface)
{
    return CONTAINING_RECORD(iface, ExtensionService, IHttpNegotiate_iface);
}
158 159 160

static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate *iface, REFIID riid, void **ppv)
{
161
    ExtensionService *This = impl_from_IHttpNegotiate(iface);
162
    return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
163 164 165 166
}

static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate *iface)
{
167
    ExtensionService *This = impl_from_IHttpNegotiate(iface);
168
    return IUnknown_AddRef(This->outer_unk);
169 170 171 172
}

static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate *iface)
{
173
    ExtensionService *This = impl_from_IHttpNegotiate(iface);
174
    return IUnknown_Release(This->outer_unk);
175 176 177 178 179
}

static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate *iface,
        LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
{
180
    ExtensionService *This = impl_from_IHttpNegotiate(iface);
181 182 183 184 185 186 187 188 189 190 191 192 193 194

    TRACE("(%p)->(%s %s %x %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), dwReserved,
          pszAdditionalHeaders);

    if(!pszAdditionalHeaders)
        return E_INVALIDARG;

    *pszAdditionalHeaders = hlink_co_strdupW(This->headers);
    return S_OK;
}

static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate *iface, DWORD dwResponseCode,
        LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
{
195
    ExtensionService *This = impl_from_IHttpNegotiate(iface);
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211

    TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
          debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);

    *pszAdditionalRequestHeaders = NULL;
    return S_OK;
}

static const IHttpNegotiateVtbl HttpNegotiateVtbl = {
    HttpNegotiate_QueryInterface,
    HttpNegotiate_AddRef,
    HttpNegotiate_Release,
    HttpNegotiate_BeginningTransaction,
    HttpNegotiate_OnResponse
};

212 213 214 215
static inline ExtensionService *impl_from_IExtensionServices(IExtensionServices *iface)
{
    return CONTAINING_RECORD(iface, ExtensionService, IExtensionServices_iface);
}
216 217 218

static HRESULT WINAPI ExtServ_QueryInterface(IExtensionServices *iface, REFIID riid, void **ppv)
{
219
    ExtensionService *This = impl_from_IExtensionServices(iface);
220
    return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
221 222 223 224
}

static ULONG WINAPI ExtServ_AddRef(IExtensionServices *iface)
{
225
    ExtensionService *This = impl_from_IExtensionServices(iface);
226
    return IUnknown_AddRef(This->outer_unk);
227 228 229 230
}

static ULONG WINAPI ExtServ_Release(IExtensionServices *iface)
{
231
    ExtensionService *This = impl_from_IExtensionServices(iface);
232
    return IUnknown_Release(This->outer_unk);
233 234 235 236
}

static HRESULT ExtServ_ImplSetAdditionalHeaders(ExtensionService* This, LPCWSTR pwzAdditionalHeaders)
{
237
    int len;
238 239 240 241 242 243 244

    heap_free(This->headers);
    This->headers = NULL;

    if (!pwzAdditionalHeaders)
        return S_OK;

245
    len = lstrlenW(pwzAdditionalHeaders);
246 247

    if(len && pwzAdditionalHeaders[len-1] != '\n' && pwzAdditionalHeaders[len-1] != '\r') {
248
        This->headers = heap_alloc(len*sizeof(WCHAR) + sizeof(L"\r\n"));
249
        memcpy(This->headers, pwzAdditionalHeaders, len*sizeof(WCHAR));
250
        memcpy(This->headers+len, L"\r\n", sizeof(L"\r\n"));
251 252 253 254 255 256 257 258 259
    }else {
        This->headers = hlink_strdupW(pwzAdditionalHeaders);
    }

    return S_OK;
}

static HRESULT WINAPI ExtServ_SetAdditionalHeaders(IExtensionServices* iface, LPCWSTR pwzAdditionalHeaders)
{
260
    ExtensionService *This = impl_from_IExtensionServices(iface);
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280

    TRACE("(%p)->(%s)\n", This, debugstr_w(pwzAdditionalHeaders));

    return ExtServ_ImplSetAdditionalHeaders(This,pwzAdditionalHeaders);
}

static HRESULT ExtServ_ImplSetAuthenticateData(ExtensionService* This, HWND phwnd, LPCWSTR pwzUsername, LPCWSTR pwzPassword)
{
    heap_free(This->username);
    heap_free(This->password);

    This->hwnd = phwnd;
    This->username = hlink_strdupW(pwzUsername);
    This->password = hlink_strdupW(pwzPassword);

    return S_OK;
}

static HRESULT WINAPI ExtServ_SetAuthenticateData(IExtensionServices* iface, HWND phwnd, LPCWSTR pwzUsername, LPCWSTR pwzPassword)
{
281
    ExtensionService *This = impl_from_IExtensionServices(iface);
282 283 284 285 286 287 288 289 290 291 292 293 294 295

    TRACE("(%p)->(%p %s %s)\n", This, phwnd, debugstr_w(pwzUsername), debugstr_w(pwzPassword));

    return ExtServ_ImplSetAuthenticateData(This, phwnd, pwzUsername, pwzPassword);
}

static const IExtensionServicesVtbl ExtServVtbl = {
    ExtServ_QueryInterface,
    ExtServ_AddRef,
    ExtServ_Release,
    ExtServ_SetAdditionalHeaders,
    ExtServ_SetAuthenticateData
};

296 297 298
/***********************************************************************
 *             HlinkCreateExtensionServices (HLINK.@)
 */
299 300 301 302 303 304 305 306 307 308 309
HRESULT WINAPI HlinkCreateExtensionServices(LPCWSTR pwzAdditionalHeaders,
        HWND phwnd, LPCWSTR pszUsername, LPCWSTR pszPassword,
        IUnknown *punkOuter, REFIID riid, void** ppv)
{
    ExtensionService *ret;
    HRESULT hres = S_OK;

    TRACE("%s %p %s %s %p %s %p\n",debugstr_w(pwzAdditionalHeaders),
            phwnd, debugstr_w(pszUsername), debugstr_w(pszPassword),
            punkOuter, debugstr_guid(riid), ppv);

310
    ret = heap_alloc(sizeof(*ret));
311

312
    ret->IUnknown_inner.lpVtbl = &ExtServUnkVtbl;
313 314 315
    ret->IAuthenticate_iface.lpVtbl = &AuthenticateVtbl;
    ret->IHttpNegotiate_iface.lpVtbl = &HttpNegotiateVtbl;
    ret->IExtensionServices_iface.lpVtbl = &ExtServVtbl;
316
    ret->ref = 1;
317 318 319 320
    ret->headers = NULL;
    ret->hwnd = NULL;
    ret->username = NULL;
    ret->password = NULL;
321

322 323
    ExtServ_ImplSetAuthenticateData(ret, phwnd, pszUsername, pszPassword);
    ExtServ_ImplSetAdditionalHeaders(ret, pwzAdditionalHeaders);
324 325

    if(!punkOuter) {
326 327 328
        ret->outer_unk = &ret->IUnknown_inner;
        hres = IUnknown_QueryInterface(&ret->IUnknown_inner, riid, ppv);
        IUnknown_Release(&ret->IUnknown_inner);
329
    }else if(IsEqualGUID(&IID_IUnknown, riid)) {
330 331
        ret->outer_unk = punkOuter;
        *ppv = &ret->IUnknown_inner;
332
    }else {
333
        IUnknown_Release(&ret->IUnknown_inner);
334 335 336 337 338
        hres = E_INVALIDARG;
    }

    return hres;
}