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