wininet/tests: Improve error reporting in a couple of tests.
[wine] / dlls / wldap32 / parse.c
1 /*
2  * WLDAP32 - LDAP support for Wine
3  *
4  * Copyright 2005 Hans Leidekker
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdarg.h>
25 #ifdef HAVE_LDAP_H
26 #include <ldap.h>
27 #endif
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winnls.h"
32
33 #include "winldap_private.h"
34 #include "wldap32.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
38
39 /***********************************************************************
40  *      ldap_parse_extended_resultA     (WLDAP32.@)
41  *
42  * See ldap_parse_extended_resultW.
43  */
44 ULONG CDECL ldap_parse_extended_resultA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result,
45     PCHAR *oid, struct WLDAP32_berval **data, BOOLEAN free )
46 {
47     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
48 #ifdef HAVE_LDAP
49     WCHAR *oidW = NULL;
50
51     TRACE( "(%p, %p, %p, %p, 0x%02x)\n", ld, result, oid, data, free );
52
53     if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
54     if (!result) return WLDAP32_LDAP_NO_RESULTS_RETURNED;
55
56     ret = ldap_parse_extended_resultW( ld, result, &oidW, data, free );
57
58     if (oid) {
59         *oid = strWtoA( oidW );
60         if (!*oid) ret = WLDAP32_LDAP_NO_MEMORY;
61         ldap_memfreeW( oidW );
62     }
63
64 #endif
65     return ret;
66 }
67
68 /***********************************************************************
69  *      ldap_parse_extended_resultW     (WLDAP32.@)
70  *
71  * Parse the result of an extended operation. 
72  *
73  * PARAMS
74  *  ld      [I] Pointer to an LDAP context.
75  *  result  [I] Result message from an extended operation.
76  *  oid     [O] OID of the extended operation.
77  *  data    [O] Result data.
78  *  free    [I] Free the result message?
79  *
80  * RETURNS
81  *  Success: LDAP_SUCCESS
82  *  Failure: An LDAP error code.
83  *
84  * NOTES
85  *  Free the OID and result data with ldap_memfree. Pass a nonzero
86  *  value for 'free' or call ldap_msgfree to free the result message.
87  */
88 ULONG CDECL ldap_parse_extended_resultW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result,
89     PWCHAR *oid, struct WLDAP32_berval **data, BOOLEAN free )
90 {
91     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
92 #ifdef HAVE_LDAP
93     char *oidU = NULL;
94
95     TRACE( "(%p, %p, %p, %p, 0x%02x)\n", ld, result, oid, data, free );
96
97     if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
98     if (!result) return WLDAP32_LDAP_NO_RESULTS_RETURNED;
99
100     ret = map_error( ldap_parse_extended_result( ld, result, &oidU, (struct berval **)data, free ) );
101
102     if (oid) {
103         *oid = strUtoW( oidU );
104         if (!*oid) ret = WLDAP32_LDAP_NO_MEMORY;
105         ldap_memfree( oidU );
106     }
107
108 #endif
109     return ret;
110 }
111
112 /***********************************************************************
113  *      ldap_parse_referenceA     (WLDAP32.@)
114  *
115  * See ldap_parse_referenceW.
116  */
117 ULONG CDECL ldap_parse_referenceA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *message,
118     PCHAR **referrals )
119 {
120     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
121 #ifdef HAVE_LDAP
122     WCHAR **referralsW = NULL;
123
124     TRACE( "(%p, %p, %p)\n", ld, message, referrals );
125
126     if (!ld) return ~0u;
127
128     ret = ldap_parse_referenceW( ld, message, &referralsW );
129
130     *referrals = strarrayWtoA( referralsW );
131     ldap_value_freeW( referralsW );
132
133 #endif 
134     return ret;
135 }
136
137 /***********************************************************************
138  *      ldap_parse_referenceW     (WLDAP32.@)
139  *
140  * Return any referrals from a result message.
141  *
142  * PARAMS
143  *  ld         [I] Pointer to an LDAP context.
144  *  result     [I] Result message.
145  *  referrals  [O] Array of referral URLs.
146  *
147  * RETURNS
148  *  Success: LDAP_SUCCESS
149  *  Failure: An LDAP error code.
150  *
151  * NOTES
152  *  Free the referrals with ldap_value_free.
153  */
154 ULONG CDECL ldap_parse_referenceW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *message,
155     PWCHAR **referrals )
156 {
157     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
158 #ifdef HAVE_LDAP_PARSE_REFERENCE
159     char **referralsU = NULL;
160
161     TRACE( "(%p, %p, %p)\n", ld, message, referrals );
162
163     if (!ld) return ~0u;
164     
165     ret = map_error( ldap_parse_reference( ld, message, &referralsU, NULL, 0 ));
166
167     *referrals = strarrayUtoW( referralsU );
168     ldap_memfree( referralsU );
169
170 #endif
171     return ret;
172 }
173
174 /***********************************************************************
175  *      ldap_parse_resultA     (WLDAP32.@)
176  *
177  * See ldap_parse_resultW.
178  */
179 ULONG CDECL ldap_parse_resultA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result,
180     ULONG *retcode, PCHAR *matched, PCHAR *error, PCHAR **referrals,
181     PLDAPControlA **serverctrls, BOOLEAN free )
182 {
183     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
184 #ifdef HAVE_LDAP
185     WCHAR *matchedW = NULL, *errorW = NULL, **referralsW = NULL;
186     LDAPControlW **serverctrlsW = NULL;
187
188     TRACE( "(%p, %p, %p, %p, %p, %p, %p, 0x%02x)\n", ld, result, retcode,
189            matched, error, referrals, serverctrls, free );
190
191     if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
192
193     ret = ldap_parse_resultW( ld, result, retcode, &matchedW, &errorW,
194                               &referralsW, &serverctrlsW, free );
195
196     if (matched) *matched = strWtoA( matchedW );
197     if (error) *error = strWtoA( errorW );
198
199     if (referrals) *referrals = strarrayWtoA( referralsW );
200     if (serverctrls) *serverctrls = controlarrayWtoA( serverctrlsW );
201
202     ldap_memfreeW( matchedW );
203     ldap_memfreeW( errorW );
204     ldap_value_freeW( referralsW );
205     ldap_controls_freeW( serverctrlsW );
206
207 #endif
208     return ret;
209 }
210
211 /***********************************************************************
212  *      ldap_parse_resultW     (WLDAP32.@)
213  *
214  * Parse a result message. 
215  *
216  * PARAMS
217  *  ld           [I] Pointer to an LDAP context.
218  *  result       [I] Result message.
219  *  retcode      [O] Return code for the server operation.
220  *  matched      [O] DNs matched in the operation.
221  *  error        [O] Error message for the operation.
222  *  referrals    [O] Referrals found in the result message.
223  *  serverctrls  [O] Controls used in the operation.
224  *  free         [I] Free the result message?
225  *
226  * RETURNS
227  *  Success: LDAP_SUCCESS
228  *  Failure: An LDAP error code.
229  *
230  * NOTES
231  *  Free the DNs and error message with ldap_memfree. Free
232  *  the referrals with ldap_value_free and the controls with
233  *  ldap_controls_free. Pass a nonzero value for 'free' or call
234  *  ldap_msgfree to free the result message.
235  */
236 ULONG CDECL ldap_parse_resultW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result,
237     ULONG *retcode, PWCHAR *matched, PWCHAR *error, PWCHAR **referrals,
238     PLDAPControlW **serverctrls, BOOLEAN free )
239 {
240     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
241 #ifdef HAVE_LDAP
242     char *matchedU = NULL, *errorU = NULL, **referralsU = NULL;
243     LDAPControl **serverctrlsU = NULL;
244
245     TRACE( "(%p, %p, %p, %p, %p, %p, %p, 0x%02x)\n", ld, result, retcode,
246            matched, error, referrals, serverctrls, free );
247
248     if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
249
250     ret = map_error( ldap_parse_result( ld, result, (int *)retcode, &matchedU, &errorU,
251                                         &referralsU, &serverctrlsU, free ));
252
253     if (matched) *matched = strUtoW( matchedU );
254     if (error) *error = strUtoW( errorU );
255
256     if (referrals) *referrals = strarrayUtoW( referralsU );
257     if (serverctrls) *serverctrls = controlarrayUtoW( serverctrlsU );
258
259     ldap_memfree( matchedU );
260     ldap_memfree( errorU );
261     strarrayfreeU( referralsU );
262     ldap_controls_free( serverctrlsU );
263
264 #endif
265     return ret;
266 }
267
268 /***********************************************************************
269  *      ldap_parse_sort_controlA     (WLDAP32.@)
270  *
271  * See ldap_parse_sort_controlW.
272  */
273 ULONG CDECL ldap_parse_sort_controlA( WLDAP32_LDAP *ld, PLDAPControlA *control,
274     ULONG *result, PCHAR *attr )
275 {
276     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
277 #ifdef HAVE_LDAP
278     WCHAR *attrW = NULL;
279     LDAPControlW **controlW = NULL;
280
281     TRACE( "(%p, %p, %p, %p)\n", ld, control, result, attr );
282
283     if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
284     if (!control) return WLDAP32_LDAP_CONTROL_NOT_FOUND;
285
286     controlW = controlarrayAtoW( control );
287     if (!controlW) return WLDAP32_LDAP_NO_MEMORY;
288
289     ret = ldap_parse_sort_controlW( ld, controlW, result, &attrW );
290
291     *attr = strWtoA( attrW );
292     controlarrayfreeW( controlW );
293
294 #endif
295     return ret;
296 }
297
298 /***********************************************************************
299  *      ldap_parse_sort_controlW     (WLDAP32.@)
300  *
301  * Parse a sort control.
302  *
303  * PARAMS
304  *  ld       [I] Pointer to an LDAP context.
305  *  control  [I] Control obtained from a result message.
306  *  result   [O] Result code.
307  *  attr     [O] Failing attribute.
308  *
309  * RETURNS
310  *  Success: LDAP_SUCCESS
311  *  Failure: An LDAP error code.
312  *
313  * NOTES
314  *  If the function fails, free the failing attribute with ldap_memfree.
315  */
316 ULONG CDECL ldap_parse_sort_controlW( WLDAP32_LDAP *ld, PLDAPControlW *control,
317     ULONG *result, PWCHAR *attr )
318 {
319     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
320 #ifdef HAVE_LDAP
321     char *attrU = NULL;
322     LDAPControl **controlU = NULL;
323 #ifdef HAVE_LDAP_PARSE_SORT_CONTROL
324     unsigned long res;
325 #elif defined(HAVE_LDAP_PARSE_SORTRESPONSE_CONTROL)
326     ber_int_t res;
327     LDAPControl *sortcontrol = NULL;
328     unsigned int i;
329 #endif
330
331     TRACE( "(%p, %p, %p, %p)\n", ld, control, result, attr );
332
333     if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
334     if (!control) return WLDAP32_LDAP_CONTROL_NOT_FOUND;
335
336     controlU = controlarrayWtoU( control );
337     if (!controlU) return WLDAP32_LDAP_NO_MEMORY;
338
339 #ifdef HAVE_LDAP_PARSE_SORT_CONTROL
340     if (!(ret = ldap_parse_sort_control( ld, controlU, &res, &attrU )))
341     {
342         *result = res;
343         *attr = strUtoW( attrU );
344     }
345 #elif defined(HAVE_LDAP_PARSE_SORTRESPONSE_CONTROL)
346     for (i = 0; controlU[i]; i++)
347     {
348         if (!strcmp( LDAP_SERVER_RESP_SORT_OID, controlU[i]->ldctl_oid ))
349             sortcontrol = controlU[i];
350     }
351     if (!sortcontrol)
352     {
353         controlarrayfreeU( controlU );
354         return WLDAP32_LDAP_CONTROL_NOT_FOUND;
355     }
356     if (!(ret = ldap_parse_sortresponse_control( ld, sortcontrol, &res, &attrU )))
357     {
358         *result = res;
359         *attr = strUtoW( attrU );
360     }
361 #endif
362     controlarrayfreeU( controlU );
363
364 #endif
365     return map_error( ret );
366 }
367
368 /***********************************************************************
369  *      ldap_parse_vlv_controlA     (WLDAP32.@)
370  *
371  * See ldap_parse_vlv_controlW.
372  */
373 INT CDECL ldap_parse_vlv_controlA( WLDAP32_LDAP *ld, PLDAPControlA *control,
374     PULONG targetpos, PULONG listcount,
375     struct WLDAP32_berval **context, PINT errcode )
376 {
377     int ret = WLDAP32_LDAP_NOT_SUPPORTED;
378 #ifdef HAVE_LDAP
379     LDAPControlW **controlW = NULL;
380
381     TRACE( "(%p, %p, %p, %p, %p, %p)\n", ld, control, targetpos,
382            listcount, context, errcode );
383
384     if (!ld) return ~0u;
385
386     if (control) {
387         controlW = controlarrayAtoW( control );
388         if (!controlW) return WLDAP32_LDAP_NO_MEMORY;
389     }
390
391     ret = ldap_parse_vlv_controlW( ld, controlW, targetpos, listcount,
392                                    context, errcode );
393
394     controlarrayfreeW( controlW );
395
396 #endif
397     return ret;
398 }
399
400 /***********************************************************************
401  *      ldap_parse_vlv_controlW     (WLDAP32.@)
402  *
403  * Parse a virtual list view control.
404  *
405  * PARAMS
406  *  ld         [I] Pointer to an LDAP context.
407  *  control    [I] Controls obtained from a result message.
408  *  targetpos  [O] Position of the target in the result list.
409  *  listcount  [O] Estimate of the number of results in the list.
410  *  context    [O] Server side context.
411  *  errcode    [O] Error code from the listview operation.
412  *
413  * RETURNS
414  *  Success: LDAP_SUCCESS
415  *  Failure: An LDAP error code.
416  *
417  * NOTES
418  *  Free the server context with ber_bvfree.
419  */
420 INT CDECL ldap_parse_vlv_controlW( WLDAP32_LDAP *ld, PLDAPControlW *control,
421     PULONG targetpos, PULONG listcount,
422     struct WLDAP32_berval **context, PINT errcode )
423 {
424     int ret = WLDAP32_LDAP_NOT_SUPPORTED;
425 #ifdef HAVE_LDAP
426     LDAPControl **controlU = NULL;
427 #ifdef HAVE_LDAP_PARSE_VLV_CONTROL
428     unsigned long pos, count;
429 #elif defined(HAVE_LDAP_PARSE_VLVRESPONSE_CONTROL)
430     ber_int_t pos, count;
431     LDAPControl *vlvcontrol = NULL;
432     unsigned int i;
433 #endif
434
435     TRACE( "(%p, %p, %p, %p, %p, %p)\n", ld, control, targetpos,
436            listcount, context, errcode );
437
438     if (!ld || !control) return ~0u;
439
440     controlU = controlarrayWtoU( control );
441     if (!controlU) return WLDAP32_LDAP_NO_MEMORY;
442
443 #ifdef HAVE_LDAP_PARSE_VLV_CONTROL
444     if (!(ret = ldap_parse_vlv_control( ld, controlU, &pos, &count,
445                                         (struct berval **)context, errcode )))
446     {
447         *targetpos = pos;
448         *listcount = count;
449     }
450 #elif defined(HAVE_LDAP_PARSE_VLVRESPONSE_CONTROL)
451     for (i = 0; controlU[i]; i++)
452     {
453         if (!strcmp( LDAP_CONTROL_VLVRESPONSE, controlU[i]->ldctl_oid ))
454             vlvcontrol = controlU[i];
455     }
456     if (!vlvcontrol)
457     {
458         controlarrayfreeU( controlU );
459         return WLDAP32_LDAP_CONTROL_NOT_FOUND;
460     }
461     if (!(ret = ldap_parse_vlvresponse_control( ld, vlvcontrol, &pos, &count,
462                                                 (struct berval **)context, errcode )))
463     {
464         *targetpos = pos;
465         *listcount = count;
466     }
467 #endif
468     controlarrayfreeU( controlU );
469
470 #endif
471     return map_error( ret );
472 }