search.c 18.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * WLDAP32 - LDAP support for Wine
 *
 * Copyright 2005 Hans Leidekker
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 22 23 24
 */

#include "config.h"
#include "wine/port.h"

#include <stdarg.h>
25 26 27
#ifdef HAVE_LDAP_H
#include <ldap.h>
#endif
28 29 30 31 32 33 34

#include "windef.h"
#include "winbase.h"
#include "winnls.h"

#include "winldap_private.h"
#include "wldap32.h"
35
#include "wine/debug.h"
36 37 38

WINE_DEFAULT_DEBUG_CHANNEL(wldap32);

39 40 41 42 43
/***********************************************************************
 *      ldap_searchA     (WLDAP32.@)
 *
 * See ldap_searchW.
 */
44
ULONG CDECL ldap_searchA( WLDAP32_LDAP *ld, PCHAR base, ULONG scope, PCHAR filter,
45 46
    PCHAR attrs[], ULONG attrsonly )
{
47
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
48
#ifdef HAVE_LDAP
49
    WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
50 51

    ret = WLDAP32_LDAP_NO_MEMORY;
52

53
    TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x)\n", ld, debugstr_a(base),
54 55
           scope, debugstr_a(filter), attrs, attrsonly );

56
    if (!ld) return ~0u;
57

58 59 60 61 62 63 64 65 66 67 68 69
    if (base) {
        baseW = strAtoW( base );
        if (!baseW) goto exit;
    }
    if (filter) {
        filterW = strAtoW( filter );
        if (!filterW) goto exit;
    }
    if (attrs) {
        attrsW = strarrayAtoW( attrs );
        if (!attrsW) goto exit;
    }
70 71 72

    ret = ldap_searchW( ld, baseW, scope, filterW, attrsW, attrsonly );

73
exit:
74 75 76 77 78 79 80 81
    strfreeW( baseW );
    strfreeW( filterW );
    strarrayfreeW( attrsW );

#endif
    return ret;
}

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
/***********************************************************************
 *      ldap_searchW     (WLDAP32.@)
 *
 * Search a directory tree (asynchronous operation).
 *
 * PARAMS
 *  ld        [I] Pointer to an LDAP context.
 *  base      [I] Starting point for the search.
 *  scope     [I] Search scope. One of LDAP_SCOPE_BASE,
 *                LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE.
 *  filter    [I] Search filter.
 *  attrs     [I] Attributes to return.
 *  attrsonly [I] Return no values, only attributes.
 *
 * RETURNS
 *  Success: Message ID of the search operation.
98
 *  Failure: ~0u
99 100 101 102 103 104
 *
 * NOTES
 *  Call ldap_result with the message ID to get the result of
 *  the operation. Cancel the operation by calling ldap_abandon
 *  with the message ID.
 */
105
ULONG CDECL ldap_searchW( WLDAP32_LDAP *ld, PWCHAR base, ULONG scope, PWCHAR filter,
106 107
    PWCHAR attrs[], ULONG attrsonly )
{
108
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
109
#ifdef HAVE_LDAP
110
    char *baseU = NULL, *filterU = NULL, **attrsU = NULL;
111
    int msg;
112 113

    ret = WLDAP32_LDAP_NO_MEMORY;
114

115
    TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x)\n", ld, debugstr_w(base),
116 117
           scope, debugstr_w(filter), attrs, attrsonly );

118
    if (!ld) return ~0u;
119

120 121 122 123 124 125 126 127 128 129 130 131
    if (base) {
        baseU = strWtoU( base );
        if (!baseU) goto exit;
    }
    if (filter) {
        filterU = strWtoU( filter );
        if (!filterU) goto exit;
    }
    if (attrs) {
        attrsU = strarrayWtoU( attrs );
        if (!attrsU) goto exit;
    }
132

133 134 135 136 137 138
    ret = ldap_search_ext( ld, baseU, scope, filterU, attrsU, attrsonly,
                           NULL, NULL, NULL, 0, &msg );

    if (ret == LDAP_SUCCESS)
        ret = msg;
    else
139
        ret = ~0u;
140

141
exit:
142 143 144 145 146 147 148 149
    strfreeU( baseU );
    strfreeU( filterU );
    strarrayfreeU( attrsU );

#endif
    return ret;
}

150 151 152 153 154
/***********************************************************************
 *      ldap_search_extA     (WLDAP32.@)
 *
 * See ldap_search_extW.
 */
155
ULONG CDECL ldap_search_extA( WLDAP32_LDAP *ld, PCHAR base, ULONG scope,
156 157 158
    PCHAR filter, PCHAR attrs[], ULONG attrsonly, PLDAPControlA *serverctrls,
    PLDAPControlA *clientctrls, ULONG timelimit, ULONG sizelimit, ULONG *message )
{
159
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
160
#ifdef HAVE_LDAP
161 162
    WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
    LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
163 164

    ret = WLDAP32_LDAP_NO_MEMORY;
165

166
    TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, 0x%08x, 0x%08x, %p)\n",
167 168 169
           ld, debugstr_a(base), scope, debugstr_a(filter), attrs, attrsonly,
           serverctrls, clientctrls, timelimit, sizelimit, message );

170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
    if (!ld) return WLDAP32_LDAP_PARAM_ERROR;

    if (base) {
        baseW = strAtoW( base );
        if (!baseW) goto exit;
    }
    if (filter)
    {
        filterW = strAtoW( filter );
        if (!filterW) goto exit;
    }
    if (attrs) {
        attrsW = strarrayAtoW( attrs );
        if (!attrsW) goto exit;
    }
    if (serverctrls) {
        serverctrlsW = controlarrayAtoW( serverctrls );
        if (!serverctrlsW) goto exit;
    }
    if (clientctrls) {
        clientctrlsW = controlarrayAtoW( clientctrls );
        if (!clientctrlsW) goto exit;
    }
193 194 195 196

    ret = ldap_search_extW( ld, baseW, scope, filterW, attrsW, attrsonly,
                            serverctrlsW, clientctrlsW, timelimit, sizelimit, message );

197
exit:
198 199 200 201 202 203 204 205 206 207
    strfreeW( baseW );
    strfreeW( filterW );
    strarrayfreeW( attrsW );
    controlarrayfreeW( serverctrlsW );
    controlarrayfreeW( clientctrlsW );

#endif
    return ret;
}

208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
/***********************************************************************
 *      ldap_search_extW     (WLDAP32.@)
 *
 * Search a directory tree (asynchronous operation).
 *
 * PARAMS
 *  ld          [I] Pointer to an LDAP context.
 *  base        [I] Starting point for the search.
 *  scope       [I] Search scope. One of LDAP_SCOPE_BASE,
 *                  LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE.
 *  filter      [I] Search filter.
 *  attrs       [I] Attributes to return.
 *  attrsonly   [I] Return no values, only attributes.
 *  serverctrls [I] Array of LDAP server controls.
 *  clientctrls [I] Array of LDAP client controls.
 *  timelimit   [I] Timeout in seconds.
 *  sizelimit   [I] Maximum number of entries to return. Zero means unlimited.
 *  message     [O] Message ID of the search operation.
 *
 * RETURNS
 *  Success: LDAP_SUCCESS
 *  Failure: An LDAP error code.
 *
 * NOTES
 *  Call ldap_result with the message ID to get the result of
 *  the operation. Cancel the operation by calling ldap_abandon
 *  with the message ID.
 */
236
ULONG CDECL ldap_search_extW( WLDAP32_LDAP *ld, PWCHAR base, ULONG scope,
237 238 239
    PWCHAR filter, PWCHAR attrs[], ULONG attrsonly, PLDAPControlW *serverctrls,
    PLDAPControlW *clientctrls, ULONG timelimit, ULONG sizelimit, ULONG *message )
{
240
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
241
#ifdef HAVE_LDAP
242 243
    char *baseU = NULL, *filterU = NULL, **attrsU = NULL;
    LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
244
    struct timeval tv, *tvp = NULL;
245

246
    ret = WLDAP32_LDAP_NO_MEMORY;
247

248
    TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, 0x%08x, 0x%08x, %p)\n",
249 250 251
           ld, debugstr_w(base), scope, debugstr_w(filter), attrs, attrsonly,
           serverctrls, clientctrls, timelimit, sizelimit, message );

252
    if (!ld) return ~0u;
253

254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
    if (base) {
        baseU = strWtoU( base );
        if (!baseU) goto exit;
    }
    if (filter) {
        filterU = strWtoU( filter );
        if (!filterU) goto exit;
    }
    if (attrs) {
        attrsU = strarrayWtoU( attrs );
        if (!attrsU) goto exit;
    }
    if (serverctrls) {
        serverctrlsU = controlarrayWtoU( serverctrls );
        if (!serverctrlsU) goto exit;
    }
    if (clientctrls) {
        clientctrlsU = controlarrayWtoU( clientctrls );
        if (!clientctrlsU) goto exit;
    }
274

275 276 277 278 279 280
    if (timelimit)
    {
        tv.tv_sec = timelimit;
        tv.tv_usec = 0;
        tvp = &tv;
    }
281

282
    ret = map_error( ldap_search_ext( ld, baseU, scope, filterU, attrsU, attrsonly,
283
                                      serverctrlsU, clientctrlsU, tvp, sizelimit, (int *)message ));
284

285
exit:
286 287 288 289 290 291 292 293 294 295
    strfreeU( baseU );
    strfreeU( filterU );
    strarrayfreeU( attrsU );
    controlarrayfreeU( serverctrlsU );
    controlarrayfreeU( clientctrlsU );

#endif
    return ret;
}

296 297 298 299 300
/***********************************************************************
 *      ldap_search_ext_sA     (WLDAP32.@)
 *
 * See ldap_search_ext_sW.
 */
301
ULONG CDECL ldap_search_ext_sA( WLDAP32_LDAP *ld, PCHAR base, ULONG scope,
302
    PCHAR filter, PCHAR attrs[], ULONG attrsonly, PLDAPControlA *serverctrls,
303
    PLDAPControlA *clientctrls, struct l_timeval* timeout, ULONG sizelimit, WLDAP32_LDAPMessage **res )
304
{
305
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
306
#ifdef HAVE_LDAP
307 308
    WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
    LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
309 310

    ret = WLDAP32_LDAP_NO_MEMORY;
311

312
    TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, %p, 0x%08x, %p)\n",
313
           ld, debugstr_a(base), scope, debugstr_a(filter), attrs, attrsonly,
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
           serverctrls, clientctrls, timeout, sizelimit, res );

    if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;

    if (base) {
        baseW = strAtoW( base );
        if (!baseW) goto exit;
    }
    if (filter) {
        filterW = strAtoW( filter );
        if (!filterW) goto exit;
    }
    if (attrs) {
        attrsW = strarrayAtoW( attrs );
        if (!attrsW) goto exit;
    }
    if (serverctrls) {
        serverctrlsW = controlarrayAtoW( serverctrls );
        if (!serverctrlsW) goto exit;
    }
    if (clientctrls) {
        clientctrlsW = controlarrayAtoW( clientctrls );
        if (!clientctrlsW) goto exit;
    }
338 339

    ret = ldap_search_ext_sW( ld, baseW, scope, filterW, attrsW, attrsonly,
340
                              serverctrlsW, clientctrlsW, timeout, sizelimit, res );
341

342
exit:
343 344 345 346 347 348 349 350 351 352
    strfreeW( baseW );
    strfreeW( filterW );
    strarrayfreeW( attrsW );
    controlarrayfreeW( serverctrlsW );
    controlarrayfreeW( clientctrlsW );

#endif
    return ret;
}

353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
/***********************************************************************
 *      ldap_search_ext_sW     (WLDAP32.@)
 *
 * Search a directory tree (synchronous operation).
 *
 * PARAMS
 *  ld          [I] Pointer to an LDAP context.
 *  base        [I] Starting point for the search.
 *  scope       [I] Search scope. One of LDAP_SCOPE_BASE,
 *                  LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE.
 *  filter      [I] Search filter.
 *  attrs       [I] Attributes to return.
 *  attrsonly   [I] Return no values, only attributes.
 *  serverctrls [I] Array of LDAP server controls.
 *  clientctrls [I] Array of LDAP client controls.
 *  timeout     [I] Timeout in seconds.
 *  sizelimit   [I] Maximum number of entries to return. Zero means unlimited.
 *  res         [O] Results of the search operation.
 *
 * RETURNS
 *  Success: LDAP_SUCCESS
 *  Failure: An LDAP error code.
 *
 * NOTES
 *  Call ldap_msgfree to free the results.
 */
379
ULONG CDECL ldap_search_ext_sW( WLDAP32_LDAP *ld, PWCHAR base, ULONG scope,
380
    PWCHAR filter, PWCHAR attrs[], ULONG attrsonly, PLDAPControlW *serverctrls,
381
    PLDAPControlW *clientctrls, struct l_timeval* timeout, ULONG sizelimit, WLDAP32_LDAPMessage **res )
382
{
383
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
384
#ifdef HAVE_LDAP
385 386
    char *baseU = NULL, *filterU = NULL, **attrsU = NULL;
    LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
387 388

    ret = WLDAP32_LDAP_NO_MEMORY;
389

390
    TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, %p, 0x%08x, %p)\n",
391
           ld, debugstr_w(base), scope, debugstr_w(filter), attrs, attrsonly,
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
           serverctrls, clientctrls, timeout, sizelimit, res );

    if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;

    if (base) {
        baseU = strWtoU( base );
        if (!baseU) goto exit;
    }
    if (filter) {
        filterU = strWtoU( filter );
        if (!filterU) goto exit;
    }
    if (attrs) {
        attrsU = strarrayWtoU( attrs );
        if (!attrsU) goto exit;
    }
    if (serverctrls) {
        serverctrlsU = controlarrayWtoU( serverctrls );
        if (!serverctrlsU) goto exit;
    }
    if (clientctrls) {
        clientctrlsU = controlarrayWtoU( clientctrls );
        if (!clientctrlsU) goto exit;
    }
416

417 418 419
    ret = map_error( ldap_search_ext_s( ld, baseU, scope, filterU, attrsU, attrsonly,
                                        serverctrlsU, clientctrlsU, (struct timeval *)timeout,
                                        sizelimit, res ));
420

421
exit:
422 423 424 425 426 427 428 429 430 431
    strfreeU( baseU );
    strfreeU( filterU );
    strarrayfreeU( attrsU );
    controlarrayfreeU( serverctrlsU );
    controlarrayfreeU( clientctrlsU );

#endif
    return ret;
}

432 433 434 435 436
/***********************************************************************
 *      ldap_search_sA     (WLDAP32.@)
 *
 * See ldap_search_sW.
 */
437
ULONG CDECL ldap_search_sA( WLDAP32_LDAP *ld, PCHAR base, ULONG scope, PCHAR filter,
438 439
    PCHAR attrs[], ULONG attrsonly, WLDAP32_LDAPMessage **res )
{
440
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
441
#ifdef HAVE_LDAP
442
    WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
443 444

    ret = WLDAP32_LDAP_NO_MEMORY;
445

446
    TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p)\n", ld, debugstr_a(base),
447 448
           scope, debugstr_a(filter), attrs, attrsonly, res );

449 450 451 452 453 454 455 456 457 458 459 460 461 462
    if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;

    if (base) {
        baseW = strAtoW( base );
        if (!baseW) goto exit;
    }
    if (filter) {
        filterW = strAtoW( filter );
        if (!filterW) goto exit;
    }
    if (attrs) {
        attrsW = strarrayAtoW( attrs );
        if (!attrsW) goto exit;
    }
463 464 465

    ret = ldap_search_sW( ld, baseW, scope, filterW, attrsW, attrsonly, res );

466
exit:
467 468 469 470 471 472 473 474
    strfreeW( baseW );
    strfreeW( filterW );
    strarrayfreeW( attrsW );

#endif
    return ret;
}

475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
/***********************************************************************
 *      ldap_search_sW     (WLDAP32.@)
 *
 * Search a directory tree (synchronous operation).
 *
 * PARAMS
 *  ld        [I] Pointer to an LDAP context.
 *  base      [I] Starting point for the search.
 *  scope     [I] Search scope. One of LDAP_SCOPE_BASE,
 *                LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE.
 *  filter    [I] Search filter.
 *  attrs     [I] Attributes to return.
 *  attrsonly [I] Return no values, only attributes.
 *  res       [O] Results of the search operation.
 *
 * RETURNS
 *  Success: LDAP_SUCCESS
 *  Failure: An LDAP error code.
 *
 * NOTES
 *  Call ldap_msgfree to free the results.
 */
497
ULONG CDECL ldap_search_sW( WLDAP32_LDAP *ld, PWCHAR base, ULONG scope, PWCHAR filter,
498 499
    PWCHAR attrs[], ULONG attrsonly, WLDAP32_LDAPMessage **res )
{
500
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
501
#ifdef HAVE_LDAP
502
    char *baseU = NULL, *filterU = NULL, **attrsU = NULL;
503 504

    ret = WLDAP32_LDAP_NO_MEMORY;
505

506
    TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p)\n", ld, debugstr_w(base),
507 508
           scope, debugstr_w(filter), attrs, attrsonly, res );

509 510 511 512 513 514 515 516 517 518 519 520 521 522
    if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;

    if (base) {
        baseU = strWtoU( base );
        if (!baseU) goto exit;
    }
    if (filter) {
        filterU = strWtoU( filter );
        if (!filterU) goto exit;
    }
    if (attrs) {
        attrsU = strarrayWtoU( attrs );
        if (!attrsU) goto exit;
    }
523

524 525
    ret = map_error( ldap_search_ext_s( ld, baseU, scope, filterU, attrsU, attrsonly,
                                        NULL, NULL, NULL, 0, res ));
526

527
exit:
528 529 530 531 532 533 534 535
    strfreeU( baseU );
    strfreeU( filterU );
    strarrayfreeU( attrsU );

#endif
    return ret;
}

536 537 538 539 540
/***********************************************************************
 *      ldap_search_stA     (WLDAP32.@)
 *
 * See ldap_search_stW.
 */
541
ULONG CDECL ldap_search_stA( WLDAP32_LDAP *ld, const PCHAR base, ULONG scope,
542 543 544
    const PCHAR filter, PCHAR attrs[], ULONG attrsonly,
    struct l_timeval *timeout, WLDAP32_LDAPMessage **res )
{
545
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
546
#ifdef HAVE_LDAP
547
    WCHAR *baseW = NULL, *filterW = NULL, **attrsW = NULL;
548 549

    ret = WLDAP32_LDAP_NO_MEMORY;
550

551
    TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p)\n", ld,
552 553 554
           debugstr_a(base), scope, debugstr_a(filter), attrs,
           attrsonly, timeout, res );

555 556 557 558 559 560 561 562 563 564 565 566 567 568
    if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;

    if (base) {
        baseW = strAtoW( base );
        if (!baseW) goto exit;
    }
    if (filter) {
        filterW = strAtoW( filter );
        if (!filterW) goto exit;
    }
    if (attrs) {
        attrsW = strarrayAtoW( attrs );
        if (!attrsW) goto exit;
    }
569 570 571 572

    ret = ldap_search_stW( ld, baseW, scope, filterW, attrsW, attrsonly,
                           timeout, res );

573
exit:
574 575 576 577 578 579 580 581
    strfreeW( baseW );
    strfreeW( filterW );
    strarrayfreeW( attrsW );

#endif
    return ret;
}

582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
/***********************************************************************
 *      ldap_search_stW     (WLDAP32.@)
 *
 * Search a directory tree (synchronous operation).
 *
 * PARAMS
 *  ld        [I] Pointer to an LDAP context.
 *  base      [I] Starting point for the search.
 *  scope     [I] Search scope. One of LDAP_SCOPE_BASE,
 *                LDAP_SCOPE_ONELEVEL and LDAP_SCOPE_SUBTREE.
 *  filter    [I] Search filter.
 *  attrs     [I] Attributes to return.
 *  attrsonly [I] Return no values, only attributes.
 *  timeout   [I] Timeout in seconds.
 *  res       [O] Results of the search operation.
 *
 * RETURNS
 *  Success: LDAP_SUCCESS
 *  Failure: An LDAP error code.
 *
 * NOTES
 *  Call ldap_msgfree to free the results.
 */
605
ULONG CDECL ldap_search_stW( WLDAP32_LDAP *ld, const PWCHAR base, ULONG scope,
606 607 608
    const PWCHAR filter, PWCHAR attrs[], ULONG attrsonly,
    struct l_timeval *timeout, WLDAP32_LDAPMessage **res )
{
609
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
610
#ifdef HAVE_LDAP
611
    char *baseU = NULL, *filterU = NULL, **attrsU = NULL;
612 613

    ret = WLDAP32_LDAP_NO_MEMORY;
614

615
    TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p)\n", ld,
616 617 618
           debugstr_w(base), scope, debugstr_w(filter), attrs,
           attrsonly, timeout, res );

619 620 621 622 623 624 625 626 627 628 629 630 631 632
    if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR;

    if (base) {
        baseU = strWtoU( base );
        if (!baseU) goto exit;
    }
    if (filter) {
        filterU = strWtoU( filter );
        if (!filterU) goto exit;
    }
    if (attrs) {
        attrsU = strarrayWtoU( attrs );
        if (!attrsU) goto exit;
    }
633

634 635
    ret = map_error( ldap_search_ext_s( ld, baseU, scope, filterU, attrsU, attrsonly,
                                        NULL, NULL, (struct timeval *)timeout, 0, res ));
636

637
exit:
638 639 640 641 642 643 644
    strfreeU( baseU );
    strfreeU( filterU );
    strarrayfreeU( attrsU );

#endif
    return ret;
}