2 * WLDAP32 - LDAP support for Wine
4 * Copyright 2005 Hans Leidekker
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.
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.
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
22 #include "wine/port.h"
29 #define LDAP_MAXINT 2147483647
36 #include "winldap_private.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(wldap32
);
43 static struct berval null_cookieU
= { 0, NULL
};
44 static struct WLDAP32_berval null_cookieW
= { 0, NULL
};
47 /***********************************************************************
48 * ldap_create_page_controlA (WLDAP32.@)
50 * See ldap_create_page_controlW.
52 ULONG CDECL
ldap_create_page_controlA( WLDAP32_LDAP
*ld
, ULONG pagesize
,
53 struct WLDAP32_berval
*cookie
, UCHAR critical
, PLDAPControlA
*control
)
55 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
57 LDAPControlW
*controlW
= NULL
;
59 TRACE( "(%p, 0x%08x, %p, 0x%02x, %p)\n", ld
, pagesize
, cookie
,
62 if (!ld
|| !control
|| pagesize
> LDAP_MAXINT
)
63 return WLDAP32_LDAP_PARAM_ERROR
;
65 ret
= ldap_create_page_controlW( ld
, pagesize
, cookie
, critical
, &controlW
);
66 if (ret
== LDAP_SUCCESS
)
68 *control
= controlWtoA( controlW
);
69 ldap_control_freeW( controlW
);
78 /* create a page control by hand */
79 static ULONG
create_page_control( ULONG pagesize
, struct berval
*cookie
,
80 UCHAR critical
, PLDAPControlW
*control
)
85 struct berval
*berval
;
89 ber
= ber_alloc_t( LBER_USE_DER
);
90 if (!ber
) return WLDAP32_LDAP_NO_MEMORY
;
93 tag
= ber_printf( ber
, "{iO}", (ber_int_t
)pagesize
, cookie
);
95 tag
= ber_printf( ber
, "{iO}", (ber_int_t
)pagesize
, &null_cookieU
);
97 ret
= ber_flatten( ber
, &berval
);
100 if (tag
== LBER_ERROR
)
101 return WLDAP32_LDAP_ENCODING_ERROR
;
104 return WLDAP32_LDAP_NO_MEMORY
;
106 /* copy the berval so it can be properly freed by the caller */
107 if (!(val
= heap_alloc( berval
->bv_len
))) return WLDAP32_LDAP_NO_MEMORY
;
109 len
= berval
->bv_len
;
110 memcpy( val
, berval
->bv_val
, len
);
111 ber_bvfree( berval
);
113 if (!(ctrl
= heap_alloc( sizeof(LDAPControlW
) )))
116 return WLDAP32_LDAP_NO_MEMORY
;
119 ctrl
->ldctl_oid
= strAtoW( LDAP_PAGED_RESULT_OID_STRING
);
120 ctrl
->ldctl_value
.bv_len
= len
;
121 ctrl
->ldctl_value
.bv_val
= val
;
122 ctrl
->ldctl_iscritical
= critical
;
126 return WLDAP32_LDAP_SUCCESS
;
129 #endif /* HAVE_LDAP */
131 /***********************************************************************
132 * ldap_create_page_controlW (WLDAP32.@)
134 * Create a control for paged search results.
137 * ld [I] Pointer to an LDAP context.
138 * pagesize [I] Number of entries to return per page.
139 * cookie [I] Used by the server to track its location in the
141 * critical [I] Tells the server this control is critical to the
143 * control [O] LDAPControl created.
146 * Success: LDAP_SUCCESS
147 * Failure: An LDAP error code.
149 ULONG CDECL
ldap_create_page_controlW( WLDAP32_LDAP
*ld
, ULONG pagesize
,
150 struct WLDAP32_berval
*cookie
, UCHAR critical
, PLDAPControlW
*control
)
153 struct berval
*cookieU
= NULL
;
156 TRACE( "(%p, 0x%08x, %p, 0x%02x, %p)\n", ld
, pagesize
, cookie
,
159 if (!ld
|| !control
|| pagesize
> LDAP_MAXINT
)
160 return WLDAP32_LDAP_PARAM_ERROR
;
162 if (cookie
&& !(cookieU
= bervalWtoU( cookie
))) return WLDAP32_LDAP_NO_MEMORY
;
163 ret
= create_page_control( pagesize
, cookieU
, critical
, control
);
164 heap_free( cookieU
);
168 return WLDAP32_LDAP_NOT_SUPPORTED
;
172 ULONG CDECL
ldap_get_next_page( WLDAP32_LDAP
*ld
, PLDAPSearch search
, ULONG pagesize
,
175 FIXME( "(%p, %p, 0x%08x, %p)\n", ld
, search
, pagesize
, message
);
178 return WLDAP32_LDAP_NOT_SUPPORTED
;
181 ULONG CDECL
ldap_get_next_page_s( WLDAP32_LDAP
*ld
, PLDAPSearch search
,
182 struct l_timeval
*timeout
, ULONG pagesize
, ULONG
*count
,
183 WLDAP32_LDAPMessage
**results
)
188 TRACE( "(%p, %p, %p, %u, %p, %p)\n", ld
, search
, timeout
,
189 pagesize
, count
, results
);
190 if (!ld
|| !search
|| !count
|| !results
) return ~0u;
192 if (search
->cookie
&& search
->cookie
->bv_len
== 0)
194 /* end of paged results */
197 return WLDAP32_LDAP_NO_RESULTS_RETURNED
;
200 if (search
->serverctrls
[0])
202 controlfreeW( search
->serverctrls
[0] );
203 search
->serverctrls
[0] = NULL
;
206 TRACE("search->cookie: %s\n", search
->cookie
? debugstr_an(search
->cookie
->bv_val
, search
->cookie
->bv_len
) : "NULL");
207 ret
= ldap_create_page_controlW( ld
, pagesize
, search
->cookie
, 1, &search
->serverctrls
[0] );
208 if (ret
!= WLDAP32_LDAP_SUCCESS
) return ret
;
210 ret
= ldap_search_ext_sW( ld
, search
->dn
, search
->scope
,
211 search
->filter
, search
->attrs
, search
->attrsonly
,
212 search
->serverctrls
, search
->clientctrls
,
213 search
->timeout
.tv_sec
? &search
->timeout
: NULL
, search
->sizelimit
, results
);
214 if (ret
!= WLDAP32_LDAP_SUCCESS
) return ret
;
216 return ldap_get_paged_count( ld
, search
, count
, *results
);
219 return WLDAP32_LDAP_NOT_SUPPORTED
;
222 ULONG CDECL
ldap_get_paged_count( WLDAP32_LDAP
*ld
, PLDAPSearch search
,
223 ULONG
*count
, WLDAP32_LDAPMessage
*results
)
227 LDAPControlW
**server_ctrls
= NULL
;
229 TRACE( "(%p, %p, %p, %p)\n", ld
, search
, count
, results
);
231 if (!ld
|| !count
|| !results
) return WLDAP32_LDAP_PARAM_ERROR
;
235 ret
= ldap_parse_resultW( ld
, results
, NULL
, NULL
, NULL
, NULL
, &server_ctrls
, 0 );
236 if (ret
!= WLDAP32_LDAP_SUCCESS
) return ret
;
238 if (!server_ctrls
) /* assume end of paged results */
240 search
->cookie
= &null_cookieW
;
241 return WLDAP32_LDAP_SUCCESS
;
244 heap_free( search
->cookie
);
245 search
->cookie
= NULL
;
247 ret
= ldap_parse_page_controlW( ld
, server_ctrls
, count
, &search
->cookie
);
248 if (ret
== WLDAP32_LDAP_SUCCESS
)
249 TRACE("new search->cookie: %s, count %u\n", debugstr_an(search
->cookie
->bv_val
, search
->cookie
->bv_len
), *count
);
251 ldap_controls_freeW( server_ctrls
);
256 return WLDAP32_LDAP_NOT_SUPPORTED
;
259 /***********************************************************************
260 * ldap_parse_page_controlA (WLDAP32.@)
262 ULONG CDECL
ldap_parse_page_controlA( WLDAP32_LDAP
*ld
, PLDAPControlA
*ctrls
,
263 ULONG
*count
, struct WLDAP32_berval
**cookie
)
265 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
267 LDAPControlW
**ctrlsW
= NULL
;
269 TRACE( "(%p, %p, %p, %p)\n", ld
, ctrls
, count
, cookie
);
271 if (!ld
|| !ctrls
|| !count
|| !cookie
)
272 return WLDAP32_LDAP_PARAM_ERROR
;
274 ctrlsW
= controlarrayAtoW( ctrls
);
275 if (!ctrlsW
) return WLDAP32_LDAP_NO_MEMORY
;
277 ret
= ldap_parse_page_controlW( ld
, ctrlsW
, count
, cookie
);
278 controlarrayfreeW( ctrlsW
);
284 /***********************************************************************
285 * ldap_parse_page_controlW (WLDAP32.@)
287 ULONG CDECL
ldap_parse_page_controlW( WLDAP32_LDAP
*ld
, PLDAPControlW
*ctrls
,
288 ULONG
*count
, struct WLDAP32_berval
**cookie
)
290 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
292 LDAPControlW
*control
= NULL
;
293 struct berval
*cookieU
= NULL
, *valueU
;
298 TRACE( "(%p, %p, %p, %p)\n", ld
, ctrls
, count
, cookie
);
300 if (!ld
|| !ctrls
|| !count
|| !cookie
)
301 return WLDAP32_LDAP_PARAM_ERROR
;
303 for (i
= 0; ctrls
[i
]; i
++)
305 if (!lstrcmpW( LDAP_PAGED_RESULT_OID_STRING_W
, ctrls
[i
]->ldctl_oid
))
310 return WLDAP32_LDAP_CONTROL_NOT_FOUND
;
312 if (cookie
&& !(cookieU
= bervalWtoU( *cookie
)))
313 return WLDAP32_LDAP_NO_MEMORY
;
315 if (!(valueU
= bervalWtoU( &control
->ldctl_value
)))
317 heap_free( cookieU
);
318 return WLDAP32_LDAP_NO_MEMORY
;
321 ber
= ber_init( valueU
);
325 heap_free( cookieU
);
326 return WLDAP32_LDAP_NO_MEMORY
;
329 tag
= ber_scanf( ber
, "{iO}", count
, &cookieU
);
330 if (tag
== LBER_ERROR
)
331 ret
= WLDAP32_LDAP_DECODING_ERROR
;
333 ret
= WLDAP32_LDAP_SUCCESS
;
335 heap_free( cookieU
);
342 ULONG CDECL
ldap_search_abandon_page( WLDAP32_LDAP
*ld
, PLDAPSearch search
)
345 LDAPControlW
**ctrls
;
347 TRACE( "(%p, %p)\n", ld
, search
);
349 if (!ld
|| !search
) return ~0u;
351 strfreeW( search
->dn
);
352 strfreeW( search
->filter
);
353 strarrayfreeW( search
->attrs
);
354 ctrls
= search
->serverctrls
;
355 controlfreeW( ctrls
[0] ); /* page control */
357 while (*ctrls
) controlfreeW( *ctrls
++ );
358 heap_free( search
->serverctrls
);
359 controlarrayfreeW( search
->clientctrls
);
360 if (search
->cookie
&& search
->cookie
!= &null_cookieW
)
361 heap_free( search
->cookie
);
364 return WLDAP32_LDAP_SUCCESS
;
367 return WLDAP32_LDAP_NOT_SUPPORTED
;
371 PLDAPSearch CDECL
ldap_search_init_pageA( WLDAP32_LDAP
*ld
, PCHAR dn
, ULONG scope
,
372 PCHAR filter
, PCHAR attrs
[], ULONG attrsonly
, PLDAPControlA
*serverctrls
,
373 PLDAPControlA
*clientctrls
, ULONG timelimit
, ULONG sizelimit
, PLDAPSortKeyA
*sortkeys
)
375 FIXME( "(%p, %s, 0x%08x, %s, %p, 0x%08x)\n", ld
, debugstr_a(dn
),
376 scope
, debugstr_a(filter
), attrs
, attrsonly
);
380 PLDAPSearch CDECL
ldap_search_init_pageW( WLDAP32_LDAP
*ld
, PWCHAR dn
, ULONG scope
,
381 PWCHAR filter
, PWCHAR attrs
[], ULONG attrsonly
, PLDAPControlW
*serverctrls
,
382 PLDAPControlW
*clientctrls
, ULONG timelimit
, ULONG sizelimit
, PLDAPSortKeyW
*sortkeys
)
388 TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, 0x%08x, 0x%08x, %p)\n",
389 ld
, debugstr_w(dn
), scope
, debugstr_w(filter
), attrs
, attrsonly
,
390 serverctrls
, clientctrls
, timelimit
, sizelimit
, sortkeys
);
392 search
= heap_alloc_zero( sizeof(*search
) );
395 ld
->ld_errno
= WLDAP32_LDAP_NO_MEMORY
;
401 search
->dn
= strdupW( dn
);
402 if (!search
->dn
) goto fail
;
406 search
->filter
= strdupW( filter
);
407 if (!search
->filter
) goto fail
;
411 search
->attrs
= strarraydupW( attrs
);
412 if (!search
->attrs
) goto fail
;
415 len
= serverctrls
? controlarraylenW( serverctrls
) : 0;
416 search
->serverctrls
= heap_alloc( sizeof(LDAPControl
*) * (len
+ 2) );
417 if (!search
->serverctrls
) goto fail
;
418 search
->serverctrls
[0] = NULL
; /* reserve 0 for page control */
419 for (i
= 0; i
< len
; i
++)
421 search
->serverctrls
[i
+ 1] = controldupW( serverctrls
[i
] );
422 if (!search
->serverctrls
[i
+ 1]) goto fail
;
424 search
->serverctrls
[len
+ 1] = NULL
;
428 search
->clientctrls
= controlarraydupW( clientctrls
);
429 if (!search
->clientctrls
) goto fail
;
432 search
->scope
= scope
;
433 search
->attrsonly
= attrsonly
;
434 search
->timeout
.tv_sec
= timelimit
;
435 search
->timeout
.tv_usec
= 0;
436 search
->sizelimit
= sizelimit
;
437 search
->cookie
= NULL
;
442 ldap_search_abandon_page( ld
, search
);
443 ld
->ld_errno
= WLDAP32_LDAP_NO_MEMORY
;