- Merge from trunk up to r45543
[reactos.git] / 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 #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 }