xref: /reactos/dll/win32/hlink/extserv.c (revision 1734f297)
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