wldap32: Fix handling of zero timeout value in ldap_search_extW.
[wine] / dlls / wldap32 / search.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
23 #include "wine/port.h"
24 #include "wine/debug.h"
25
26 #include <stdarg.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winnls.h"
31
32 #ifdef HAVE_LDAP_H
33 #include <ldap.h>
34 #endif
35
36 #include "winldap_private.h"
37 #include "wldap32.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
40
41 /***********************************************************************
42  *      ldap_searchA     (WLDAP32.@)
43  *
44  * See ldap_searchW.
45  */
46 ULONG CDECL ldap_searchA( WLDAP32_LDAP *ld, PCHAR base, ULONG scope, PCHAR filter,
47     PCHAR attrs[], ULONG attrsonly )
48 {
49     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
50 #ifdef HAVE_LDAP
51     WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
52
53     ret = WLDAP32_LDAP_NO_MEMORY;
54
55     TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x)\n", ld, debugstr_a(base),
56            scope, debugstr_a(filter), attrs, attrsonly );
57
58     if (!ld) return ~0u;
59
60     if (base) {
61         baseW = strAtoW( base );
62         if (!baseW) goto exit;
63     }
64     if (filter) {
65         filterW = strAtoW( filter );
66         if (!filterW) goto exit;
67     }
68     if (attrs) {
69         attrsW = strarrayAtoW( attrs );
70         if (!attrsW) goto exit;
71     }
72
73     ret = ldap_searchW( ld, baseW, scope, filterW, attrsW, attrsonly );
74
75 exit:
76     strfreeW( baseW );
77     strfreeW( filterW );
78     strarrayfreeW( attrsW );
79
80 #endif
81     return ret;
82 }
83
84 /***********************************************************************
85  *      ldap_searchW     (WLDAP32.@)
86  *
87  * Search a directory tree (asynchronous operation).
88  *
89  * PARAMS
90  *  ld        [I] Pointer to an LDAP context.
91  *  base      [I] Starting point for the search.
92  *  scope     [I] Search scope. One of LDAP_SCOPE_BASE,
93  *                LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE.
94  *  filter    [I] Search filter.
95  *  attrs     [I] Attributes to return.
96  *  attrsonly [I] Return no values, only attributes.
97  *
98  * RETURNS
99  *  Success: Message ID of the search operation.
100  *  Failure: ~0u
101  *
102  * NOTES
103  *  Call ldap_result with the message ID to get the result of
104  *  the operation. Cancel the operation by calling ldap_abandon
105  *  with the message ID.
106  */
107 ULONG CDECL ldap_searchW( WLDAP32_LDAP *ld, PWCHAR base, ULONG scope, PWCHAR filter,
108     PWCHAR attrs[], ULONG attrsonly )
109 {
110     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
111 #ifdef HAVE_LDAP
112     char *baseU = NULL, *filterU = NULL, **attrsU = NULL;
113     int msg;
114
115     ret = WLDAP32_LDAP_NO_MEMORY;
116
117     TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x)\n", ld, debugstr_w(base),
118            scope, debugstr_w(filter), attrs, attrsonly );
119
120     if (!ld) return ~0u;
121
122     if (base) {
123         baseU = strWtoU( base );
124         if (!baseU) goto exit;
125     }
126     if (filter) {
127         filterU = strWtoU( filter );
128         if (!filterU) goto exit;
129     }
130     if (attrs) {
131         attrsU = strarrayWtoU( attrs );
132         if (!attrsU) goto exit;
133     }
134
135     ret = ldap_search_ext( ld, baseU, scope, filterU, attrsU, attrsonly,
136                            NULL, NULL, NULL, 0, &msg );
137
138     if (ret == LDAP_SUCCESS)
139         ret = msg;
140     else
141         ret = ~0u;
142
143 exit:
144     strfreeU( baseU );
145     strfreeU( filterU );
146     strarrayfreeU( attrsU );
147
148 #endif
149     return ret;
150 }
151
152 /***********************************************************************
153  *      ldap_search_extA     (WLDAP32.@)
154  *
155  * See ldap_search_extW.
156  */
157 ULONG CDECL ldap_search_extA( WLDAP32_LDAP *ld, PCHAR base, ULONG scope,
158     PCHAR filter, PCHAR attrs[], ULONG attrsonly, PLDAPControlA *serverctrls,
159     PLDAPControlA *clientctrls, ULONG timelimit, ULONG sizelimit, ULONG *message )
160 {
161     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
162 #ifdef HAVE_LDAP
163     WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
164     LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
165
166     ret = WLDAP32_LDAP_NO_MEMORY;
167
168     TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, 0x%08x, 0x%08x, %p)\n",
169            ld, debugstr_a(base), scope, debugstr_a(filter), attrs, attrsonly,
170            serverctrls, clientctrls, timelimit, sizelimit, message );
171
172     if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
173
174     if (base) {
175         baseW = strAtoW( base );
176         if (!baseW) goto exit;
177     }
178     if (filter)
179     {
180         filterW = strAtoW( filter );
181         if (!filterW) goto exit;
182     }
183     if (attrs) {
184         attrsW = strarrayAtoW( attrs );
185         if (!attrsW) goto exit;
186     }
187     if (serverctrls) {
188         serverctrlsW = controlarrayAtoW( serverctrls );
189         if (!serverctrlsW) goto exit;
190     }
191     if (clientctrls) {
192         clientctrlsW = controlarrayAtoW( clientctrls );
193         if (!clientctrlsW) goto exit;
194     }
195
196     ret = ldap_search_extW( ld, baseW, scope, filterW, attrsW, attrsonly,
197                             serverctrlsW, clientctrlsW, timelimit, sizelimit, message );
198
199 exit:
200     strfreeW( baseW );
201     strfreeW( filterW );
202     strarrayfreeW( attrsW );
203     controlarrayfreeW( serverctrlsW );
204     controlarrayfreeW( clientctrlsW );
205
206 #endif
207     return ret;
208 }
209
210 /***********************************************************************
211  *      ldap_search_extW     (WLDAP32.@)
212  *
213  * Search a directory tree (asynchronous operation).
214  *
215  * PARAMS
216  *  ld          [I] Pointer to an LDAP context.
217  *  base        [I] Starting point for the search.
218  *  scope       [I] Search scope. One of LDAP_SCOPE_BASE,
219  *                  LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE.
220  *  filter      [I] Search filter.
221  *  attrs       [I] Attributes to return.
222  *  attrsonly   [I] Return no values, only attributes.
223  *  serverctrls [I] Array of LDAP server controls.
224  *  clientctrls [I] Array of LDAP client controls.
225  *  timelimit   [I] Timeout in seconds.
226  *  sizelimit   [I] Maximum number of entries to return. Zero means unlimited.
227  *  message     [O] Message ID of the search operation.
228  *
229  * RETURNS
230  *  Success: LDAP_SUCCESS
231  *  Failure: An LDAP error code.
232  *
233  * NOTES
234  *  Call ldap_result with the message ID to get the result of
235  *  the operation. Cancel the operation by calling ldap_abandon
236  *  with the message ID.
237  */
238 ULONG CDECL ldap_search_extW( WLDAP32_LDAP *ld, PWCHAR base, ULONG scope,
239     PWCHAR filter, PWCHAR attrs[], ULONG attrsonly, PLDAPControlW *serverctrls,
240     PLDAPControlW *clientctrls, ULONG timelimit, ULONG sizelimit, ULONG *message )
241 {
242     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
243 #ifdef HAVE_LDAP
244     char *baseU = NULL, *filterU = NULL, **attrsU = NULL;
245     LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
246     struct timeval tv, *tvp = NULL;
247
248     ret = WLDAP32_LDAP_NO_MEMORY;
249
250     TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, 0x%08x, 0x%08x, %p)\n",
251            ld, debugstr_w(base), scope, debugstr_w(filter), attrs, attrsonly,
252            serverctrls, clientctrls, timelimit, sizelimit, message );
253
254     if (!ld) return ~0u;
255
256     if (base) {
257         baseU = strWtoU( base );
258         if (!baseU) goto exit;
259     }
260     if (filter) {
261         filterU = strWtoU( filter );
262         if (!filterU) goto exit;
263     }
264     if (attrs) {
265         attrsU = strarrayWtoU( attrs );
266         if (!attrsU) goto exit;
267     }
268     if (serverctrls) {
269         serverctrlsU = controlarrayWtoU( serverctrls );
270         if (!serverctrlsU) goto exit;
271     }
272     if (clientctrls) {
273         clientctrlsU = controlarrayWtoU( clientctrls );
274         if (!clientctrlsU) goto exit;
275     }
276
277     if (timelimit)
278     {
279         tv.tv_sec = timelimit;
280         tv.tv_usec = 0;
281         tvp = &tv;
282     }
283
284     ret = map_error( ldap_search_ext( ld, baseU, scope, filterU, attrsU, attrsonly,
285                                       serverctrlsU, clientctrlsU, tvp, sizelimit, (int *)message ));
286
287 exit:
288     strfreeU( baseU );
289     strfreeU( filterU );
290     strarrayfreeU( attrsU );
291     controlarrayfreeU( serverctrlsU );
292     controlarrayfreeU( clientctrlsU );
293
294 #endif
295     return ret;
296 }
297
298 /***********************************************************************
299  *      ldap_search_ext_sA     (WLDAP32.@)
300  *
301  * See ldap_search_ext_sW.
302  */
303 ULONG CDECL ldap_search_ext_sA( WLDAP32_LDAP *ld, PCHAR base, ULONG scope,
304     PCHAR filter, PCHAR attrs[], ULONG attrsonly, PLDAPControlA *serverctrls,
305     PLDAPControlA *clientctrls, struct l_timeval* timeout, ULONG sizelimit, WLDAP32_LDAPMessage **res )
306 {
307     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
308 #ifdef HAVE_LDAP
309     WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
310     LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
311
312     ret = WLDAP32_LDAP_NO_MEMORY;
313
314     TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, %p, 0x%08x, %p)\n",
315            ld, debugstr_a(base), scope, debugstr_a(filter), attrs, attrsonly,
316            serverctrls, clientctrls, timeout, sizelimit, res );
317
318     if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;
319
320     if (base) {
321         baseW = strAtoW( base );
322         if (!baseW) goto exit;
323     }
324     if (filter) {
325         filterW = strAtoW( filter );
326         if (!filterW) goto exit;
327     }
328     if (attrs) {
329         attrsW = strarrayAtoW( attrs );
330         if (!attrsW) goto exit;
331     }
332     if (serverctrls) {
333         serverctrlsW = controlarrayAtoW( serverctrls );
334         if (!serverctrlsW) goto exit;
335     }
336     if (clientctrls) {
337         clientctrlsW = controlarrayAtoW( clientctrls );
338         if (!clientctrlsW) goto exit;
339     }
340
341     ret = ldap_search_ext_sW( ld, baseW, scope, filterW, attrsW, attrsonly,
342                               serverctrlsW, clientctrlsW, timeout, sizelimit, res );
343
344 exit:
345     strfreeW( baseW );
346     strfreeW( filterW );
347     strarrayfreeW( attrsW );
348     controlarrayfreeW( serverctrlsW );
349     controlarrayfreeW( clientctrlsW );
350
351 #endif
352     return ret;
353 }
354
355 /***********************************************************************
356  *      ldap_search_ext_sW     (WLDAP32.@)
357  *
358  * Search a directory tree (synchronous operation).
359  *
360  * PARAMS
361  *  ld          [I] Pointer to an LDAP context.
362  *  base        [I] Starting point for the search.
363  *  scope       [I] Search scope. One of LDAP_SCOPE_BASE,
364  *                  LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE.
365  *  filter      [I] Search filter.
366  *  attrs       [I] Attributes to return.
367  *  attrsonly   [I] Return no values, only attributes.
368  *  serverctrls [I] Array of LDAP server controls.
369  *  clientctrls [I] Array of LDAP client controls.
370  *  timeout     [I] Timeout in seconds.
371  *  sizelimit   [I] Maximum number of entries to return. Zero means unlimited.
372  *  res         [O] Results of the search operation.
373  *
374  * RETURNS
375  *  Success: LDAP_SUCCESS
376  *  Failure: An LDAP error code.
377  *
378  * NOTES
379  *  Call ldap_msgfree to free the results.
380  */
381 ULONG CDECL ldap_search_ext_sW( WLDAP32_LDAP *ld, PWCHAR base, ULONG scope,
382     PWCHAR filter, PWCHAR attrs[], ULONG attrsonly, PLDAPControlW *serverctrls,
383     PLDAPControlW *clientctrls, struct l_timeval* timeout, ULONG sizelimit, WLDAP32_LDAPMessage **res )
384 {
385     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
386 #ifdef HAVE_LDAP
387     char *baseU = NULL, *filterU = NULL, **attrsU = NULL;
388     LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
389
390     ret = WLDAP32_LDAP_NO_MEMORY;
391
392     TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, %p, 0x%08x, %p)\n",
393            ld, debugstr_w(base), scope, debugstr_w(filter), attrs, attrsonly,
394            serverctrls, clientctrls, timeout, sizelimit, res );
395
396     if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;
397
398     if (base) {
399         baseU = strWtoU( base );
400         if (!baseU) goto exit;
401     }
402     if (filter) {
403         filterU = strWtoU( filter );
404         if (!filterU) goto exit;
405     }
406     if (attrs) {
407         attrsU = strarrayWtoU( attrs );
408         if (!attrsU) goto exit;
409     }
410     if (serverctrls) {
411         serverctrlsU = controlarrayWtoU( serverctrls );
412         if (!serverctrlsU) goto exit;
413     }
414     if (clientctrls) {
415         clientctrlsU = controlarrayWtoU( clientctrls );
416         if (!clientctrlsU) goto exit;
417     }
418
419     ret = map_error( ldap_search_ext_s( ld, baseU, scope, filterU, attrsU, attrsonly,
420                                         serverctrlsU, clientctrlsU, (struct timeval *)timeout,
421                                         sizelimit, res ));
422
423 exit:
424     strfreeU( baseU );
425     strfreeU( filterU );
426     strarrayfreeU( attrsU );
427     controlarrayfreeU( serverctrlsU );
428     controlarrayfreeU( clientctrlsU );
429
430 #endif
431     return ret;
432 }
433
434 /***********************************************************************
435  *      ldap_search_sA     (WLDAP32.@)
436  *
437  * See ldap_search_sW.
438  */
439 ULONG CDECL ldap_search_sA( WLDAP32_LDAP *ld, PCHAR base, ULONG scope, PCHAR filter,
440     PCHAR attrs[], ULONG attrsonly, WLDAP32_LDAPMessage **res )
441 {
442     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
443 #ifdef HAVE_LDAP
444     WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
445
446     ret = WLDAP32_LDAP_NO_MEMORY;
447
448     TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p)\n", ld, debugstr_a(base),
449            scope, debugstr_a(filter), attrs, attrsonly, res );
450
451     if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;
452
453     if (base) {
454         baseW = strAtoW( base );
455         if (!baseW) goto exit;
456     }
457     if (filter) {
458         filterW = strAtoW( filter );
459         if (!filterW) goto exit;
460     }
461     if (attrs) {
462         attrsW = strarrayAtoW( attrs );
463         if (!attrsW) goto exit;
464     }
465
466     ret = ldap_search_sW( ld, baseW, scope, filterW, attrsW, attrsonly, res );
467
468 exit:
469     strfreeW( baseW );
470     strfreeW( filterW );
471     strarrayfreeW( attrsW );
472
473 #endif
474     return ret;
475 }
476
477 /***********************************************************************
478  *      ldap_search_sW     (WLDAP32.@)
479  *
480  * Search a directory tree (synchronous operation).
481  *
482  * PARAMS
483  *  ld        [I] Pointer to an LDAP context.
484  *  base      [I] Starting point for the search.
485  *  scope     [I] Search scope. One of LDAP_SCOPE_BASE,
486  *                LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE.
487  *  filter    [I] Search filter.
488  *  attrs     [I] Attributes to return.
489  *  attrsonly [I] Return no values, only attributes.
490  *  res       [O] Results of the search operation.
491  *
492  * RETURNS
493  *  Success: LDAP_SUCCESS
494  *  Failure: An LDAP error code.
495  *
496  * NOTES
497  *  Call ldap_msgfree to free the results.
498  */
499 ULONG CDECL ldap_search_sW( WLDAP32_LDAP *ld, PWCHAR base, ULONG scope, PWCHAR filter,
500     PWCHAR attrs[], ULONG attrsonly, WLDAP32_LDAPMessage **res )
501 {
502     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
503 #ifdef HAVE_LDAP
504     char *baseU = NULL, *filterU = NULL, **attrsU = NULL;
505
506     ret = WLDAP32_LDAP_NO_MEMORY;
507
508     TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p)\n", ld, debugstr_w(base),
509            scope, debugstr_w(filter), attrs, attrsonly, res );
510
511     if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;
512
513     if (base) {
514         baseU = strWtoU( base );
515         if (!baseU) goto exit;
516     }
517     if (filter) {
518         filterU = strWtoU( filter );
519         if (!filterU) goto exit;
520     }
521     if (attrs) {
522         attrsU = strarrayWtoU( attrs );
523         if (!attrsU) goto exit;
524     }
525
526     ret = map_error( ldap_search_ext_s( ld, baseU, scope, filterU, attrsU, attrsonly,
527                                         NULL, NULL, NULL, 0, res ));
528
529 exit:
530     strfreeU( baseU );
531     strfreeU( filterU );
532     strarrayfreeU( attrsU );
533
534 #endif
535     return ret;
536 }
537
538 /***********************************************************************
539  *      ldap_search_stA     (WLDAP32.@)
540  *
541  * See ldap_search_stW.
542  */
543 ULONG CDECL ldap_search_stA( WLDAP32_LDAP *ld, const PCHAR base, ULONG scope,
544     const PCHAR filter, PCHAR attrs[], ULONG attrsonly,
545     struct l_timeval *timeout, WLDAP32_LDAPMessage **res )
546 {
547     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
548 #ifdef HAVE_LDAP
549     WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
550
551     ret = WLDAP32_LDAP_NO_MEMORY;
552
553     TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p)\n", ld,
554            debugstr_a(base), scope, debugstr_a(filter), attrs,
555            attrsonly, timeout, res );
556
557     if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;
558
559     if (base) {
560         baseW = strAtoW( base );
561         if (!baseW) goto exit;
562     }
563     if (filter) {
564         filterW = strAtoW( filter );
565         if (!filterW) goto exit;
566     }
567     if (attrs) {
568         attrsW = strarrayAtoW( attrs );
569         if (!attrsW) goto exit;
570     }
571
572     ret = ldap_search_stW( ld, baseW, scope, filterW, attrsW, attrsonly,
573                            timeout, res );
574
575 exit:
576     strfreeW( baseW );
577     strfreeW( filterW );
578     strarrayfreeW( attrsW );
579
580 #endif
581     return ret;
582 }
583
584 /***********************************************************************
585  *      ldap_search_stW     (WLDAP32.@)
586  *
587  * Search a directory tree (synchronous operation).
588  *
589  * PARAMS
590  *  ld        [I] Pointer to an LDAP context.
591  *  base      [I] Starting point for the search.
592  *  scope     [I] Search scope. One of LDAP_SCOPE_BASE,
593  *                LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE.
594  *  filter    [I] Search filter.
595  *  attrs     [I] Attributes to return.
596  *  attrsonly [I] Return no values, only attributes.
597  *  timeout   [I] Timeout in seconds.
598  *  res       [O] Results of the search operation.
599  *
600  * RETURNS
601  *  Success: LDAP_SUCCESS
602  *  Failure: An LDAP error code.
603  *
604  * NOTES
605  *  Call ldap_msgfree to free the results.
606  */
607 ULONG CDECL ldap_search_stW( WLDAP32_LDAP *ld, const PWCHAR base, ULONG scope,
608     const PWCHAR filter, PWCHAR attrs[], ULONG attrsonly,
609     struct l_timeval *timeout, WLDAP32_LDAPMessage **res )
610 {
611     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
612 #ifdef HAVE_LDAP
613     char *baseU = NULL, *filterU = NULL, **attrsU = NULL;
614
615     ret = WLDAP32_LDAP_NO_MEMORY;
616
617     TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p)\n", ld,
618            debugstr_w(base), scope, debugstr_w(filter), attrs,
619            attrsonly, timeout, res );
620
621     if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;
622
623     if (base) {
624         baseU = strWtoU( base );
625         if (!baseU) goto exit;
626     }
627     if (filter) {
628         filterU = strWtoU( filter );
629         if (!filterU) goto exit;
630     }
631     if (attrs) {
632         attrsU = strarrayWtoU( attrs );
633         if (!attrsU) goto exit;
634     }
635
636     ret = map_error( ldap_search_ext_s( ld, baseU, scope, filterU, attrsU, attrsonly,
637                                         NULL, NULL, (struct timeval *)timeout, 0, res ));
638
639 exit:
640     strfreeU( baseU );
641     strfreeU( filterU );
642     strarrayfreeU( attrsU );
643
644 #endif
645     return ret;
646 }