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