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_cookie
= { 0, NULL
};
46 /***********************************************************************
47 * ldap_create_page_controlA (WLDAP32.@)
49 * See ldap_create_page_controlW.
51 ULONG CDECL
ldap_create_page_controlA( WLDAP32_LDAP
*ld
, ULONG pagesize
,
52 struct WLDAP32_berval
*cookie
, UCHAR critical
, PLDAPControlA
*control
)
54 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
56 LDAPControlW
*controlW
= NULL
;
58 TRACE( "(%p, 0x%08x, %p, 0x%02x, %p)\n", ld
, pagesize
, cookie
,
61 if (!ld
|| !control
|| pagesize
> LDAP_MAXINT
)
62 return WLDAP32_LDAP_PARAM_ERROR
;
64 ret
= ldap_create_page_controlW( ld
, pagesize
, cookie
, critical
, &controlW
);
65 if (ret
== LDAP_SUCCESS
)
67 *control
= controlWtoA( controlW
);
68 ldap_control_freeW( controlW
);
77 /* create a page control by hand */
78 static ULONG
create_page_control( ULONG pagesize
, struct WLDAP32_berval
*cookie
,
79 UCHAR critical
, PLDAPControlW
*control
)
84 struct berval
*berval
;
88 ber
= ber_alloc_t( LBER_USE_DER
);
89 if (!ber
) return WLDAP32_LDAP_NO_MEMORY
;
92 tag
= ber_printf( ber
, "{iO}", (ber_int_t
)pagesize
, cookie
);
94 tag
= ber_printf( ber
, "{iO}", (ber_int_t
)pagesize
, &null_cookie
);
96 ret
= ber_flatten( ber
, &berval
);
99 if (tag
== LBER_ERROR
)
100 return WLDAP32_LDAP_ENCODING_ERROR
;
103 return WLDAP32_LDAP_NO_MEMORY
;
105 /* copy the berval so it can be properly freed by the caller */
106 if (!(val
= heap_alloc( berval
->bv_len
))) return WLDAP32_LDAP_NO_MEMORY
;
108 len
= berval
->bv_len
;
109 memcpy( val
, berval
->bv_val
, len
);
110 ber_bvfree( berval
);
112 if (!(ctrl
= heap_alloc( sizeof(LDAPControlW
) )))
115 return WLDAP32_LDAP_NO_MEMORY
;
118 ctrl
->ldctl_oid
= strAtoW( LDAP_PAGED_RESULT_OID_STRING
);
119 ctrl
->ldctl_value
.bv_len
= len
;
120 ctrl
->ldctl_value
.bv_val
= val
;
121 ctrl
->ldctl_iscritical
= critical
;
125 return WLDAP32_LDAP_SUCCESS
;
128 #endif /* HAVE_LDAP */
130 /***********************************************************************
131 * ldap_create_page_controlW (WLDAP32.@)
133 * Create a control for paged search results.
136 * ld [I] Pointer to an LDAP context.
137 * pagesize [I] Number of entries to return per page.
138 * cookie [I] Used by the server to track its location in the
140 * critical [I] Tells the server this control is critical to the
142 * control [O] LDAPControl created.
145 * Success: LDAP_SUCCESS
146 * Failure: An LDAP error code.
148 ULONG CDECL
ldap_create_page_controlW( WLDAP32_LDAP
*ld
, ULONG pagesize
,
149 struct WLDAP32_berval
*cookie
, UCHAR critical
, PLDAPControlW
*control
)
152 TRACE( "(%p, 0x%08x, %p, 0x%02x, %p)\n", ld
, pagesize
, cookie
,
155 if (!ld
|| !control
|| pagesize
> LDAP_MAXINT
)
156 return WLDAP32_LDAP_PARAM_ERROR
;
158 return create_page_control( pagesize
, cookie
, critical
, control
);
161 return WLDAP32_LDAP_NOT_SUPPORTED
;
165 ULONG CDECL
ldap_get_next_page( WLDAP32_LDAP
*ld
, PLDAPSearch search
, ULONG pagesize
,
168 FIXME( "(%p, %p, 0x%08x, %p)\n", ld
, search
, pagesize
, message
);
171 return WLDAP32_LDAP_NOT_SUPPORTED
;
174 ULONG CDECL
ldap_get_next_page_s( WLDAP32_LDAP
*ld
, PLDAPSearch search
,
175 struct l_timeval
*timeout
, ULONG pagesize
, ULONG
*count
,
176 WLDAP32_LDAPMessage
**results
)
181 TRACE( "(%p, %p, %p, %u, %p, %p)\n", ld
, search
, timeout
,
182 pagesize
, count
, results
);
183 if (!ld
|| !search
|| !count
|| !results
) return ~0u;
185 if (search
->cookie
&& search
->cookie
->bv_len
== 0)
187 /* end of paged results */
190 return WLDAP32_LDAP_NO_RESULTS_RETURNED
;
193 if (search
->serverctrls
[0])
195 controlfreeW( search
->serverctrls
[0] );
196 search
->serverctrls
[0] = NULL
;
199 TRACE("search->cookie: %s\n", search
->cookie
? debugstr_an(search
->cookie
->bv_val
, search
->cookie
->bv_len
) : "NULL");
200 ret
= ldap_create_page_controlW( ld
, pagesize
, (struct WLDAP32_berval
*)search
->cookie
, 1, &search
->serverctrls
[0] );
201 if (ret
!= WLDAP32_LDAP_SUCCESS
) return ret
;
203 ret
= ldap_search_ext_sW( ld
, search
->dn
, search
->scope
,
204 search
->filter
, search
->attrs
, search
->attrsonly
,
205 search
->serverctrls
, search
->clientctrls
,
206 search
->timeout
.tv_sec
? &search
->timeout
: NULL
, search
->sizelimit
, results
);
207 if (ret
!= WLDAP32_LDAP_SUCCESS
) return ret
;
209 return ldap_get_paged_count( ld
, search
, count
, *results
);
212 return WLDAP32_LDAP_NOT_SUPPORTED
;
215 ULONG CDECL
ldap_get_paged_count( WLDAP32_LDAP
*ld
, PLDAPSearch search
,
216 ULONG
*count
, WLDAP32_LDAPMessage
*results
)
220 LDAPControlW
**server_ctrls
= NULL
;
222 TRACE( "(%p, %p, %p, %p)\n", ld
, search
, count
, results
);
224 if (!ld
|| !count
|| !results
) return WLDAP32_LDAP_PARAM_ERROR
;
228 ret
= ldap_parse_resultW( ld
, results
, NULL
, NULL
, NULL
, NULL
, &server_ctrls
, 0 );
229 if (ret
!= WLDAP32_LDAP_SUCCESS
) return ret
;
231 if (!server_ctrls
) /* assume end of paged results */
233 search
->cookie
= &null_cookie
;
234 return WLDAP32_LDAP_SUCCESS
;
239 ber_bvfree( search
->cookie
);
240 search
->cookie
= NULL
;
243 ret
= ldap_parse_page_controlW( ld
, server_ctrls
, count
, (struct WLDAP32_berval
**)&search
->cookie
);
244 if (ret
== WLDAP32_LDAP_SUCCESS
)
245 TRACE("new search->cookie: %s, count %u\n", debugstr_an(search
->cookie
->bv_val
, search
->cookie
->bv_len
), *count
);
247 ldap_controls_freeW( server_ctrls
);
252 return WLDAP32_LDAP_NOT_SUPPORTED
;
255 /***********************************************************************
256 * ldap_parse_page_controlA (WLDAP32.@)
258 ULONG CDECL
ldap_parse_page_controlA( WLDAP32_LDAP
*ld
, PLDAPControlA
*ctrls
,
259 ULONG
*count
, struct WLDAP32_berval
**cookie
)
261 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
263 LDAPControlW
**ctrlsW
= NULL
;
265 TRACE( "(%p, %p, %p, %p)\n", ld
, ctrls
, count
, cookie
);
267 if (!ld
|| !ctrls
|| !count
|| !cookie
)
268 return WLDAP32_LDAP_PARAM_ERROR
;
270 ctrlsW
= controlarrayAtoW( ctrls
);
271 if (!ctrlsW
) return WLDAP32_LDAP_NO_MEMORY
;
273 ret
= ldap_parse_page_controlW( ld
, ctrlsW
, count
, cookie
);
274 controlarrayfreeW( ctrlsW
);
280 /***********************************************************************
281 * ldap_parse_page_controlW (WLDAP32.@)
283 ULONG CDECL
ldap_parse_page_controlW( WLDAP32_LDAP
*ld
, PLDAPControlW
*ctrls
,
284 ULONG
*count
, struct WLDAP32_berval
**cookie
)
286 ULONG ret
= WLDAP32_LDAP_NOT_SUPPORTED
;
288 LDAPControlW
*control
= NULL
;
293 TRACE( "(%p, %p, %p, %p)\n", ld
, ctrls
, count
, cookie
);
295 if (!ld
|| !ctrls
|| !count
|| !cookie
)
296 return WLDAP32_LDAP_PARAM_ERROR
;
298 for (i
= 0; ctrls
[i
]; i
++)
300 if (!lstrcmpW( LDAP_PAGED_RESULT_OID_STRING_W
, ctrls
[i
]->ldctl_oid
))
305 return WLDAP32_LDAP_CONTROL_NOT_FOUND
;
307 ber
= ber_init( &((LDAPControl
*)control
)->ldctl_value
);
309 return WLDAP32_LDAP_NO_MEMORY
;
311 tag
= ber_scanf( ber
, "{iO}", count
, cookie
);
312 if ( tag
== LBER_ERROR
)
313 ret
= WLDAP32_LDAP_DECODING_ERROR
;
315 ret
= WLDAP32_LDAP_SUCCESS
;
323 ULONG CDECL
ldap_search_abandon_page( WLDAP32_LDAP
*ld
, PLDAPSearch search
)
326 LDAPControlW
**ctrls
;
328 TRACE( "(%p, %p)\n", ld
, search
);
330 if (!ld
|| !search
) return ~0u;
332 strfreeW( search
->dn
);
333 strfreeW( search
->filter
);
334 strarrayfreeW( search
->attrs
);
335 ctrls
= search
->serverctrls
;
336 controlfreeW( ctrls
[0] ); /* page control */
338 while (*ctrls
) controlfreeW( *ctrls
++ );
339 heap_free( search
->serverctrls
);
340 controlarrayfreeW( search
->clientctrls
);
341 if (search
->cookie
&& search
->cookie
!= &null_cookie
)
342 ber_bvfree( search
->cookie
);
345 return WLDAP32_LDAP_SUCCESS
;
348 return WLDAP32_LDAP_NOT_SUPPORTED
;
352 PLDAPSearch CDECL
ldap_search_init_pageA( WLDAP32_LDAP
*ld
, PCHAR dn
, ULONG scope
,
353 PCHAR filter
, PCHAR attrs
[], ULONG attrsonly
, PLDAPControlA
*serverctrls
,
354 PLDAPControlA
*clientctrls
, ULONG timelimit
, ULONG sizelimit
, PLDAPSortKeyA
*sortkeys
)
356 FIXME( "(%p, %s, 0x%08x, %s, %p, 0x%08x)\n", ld
, debugstr_a(dn
),
357 scope
, debugstr_a(filter
), attrs
, attrsonly
);
361 PLDAPSearch CDECL
ldap_search_init_pageW( WLDAP32_LDAP
*ld
, PWCHAR dn
, ULONG scope
,
362 PWCHAR filter
, PWCHAR attrs
[], ULONG attrsonly
, PLDAPControlW
*serverctrls
,
363 PLDAPControlW
*clientctrls
, ULONG timelimit
, ULONG sizelimit
, PLDAPSortKeyW
*sortkeys
)
369 TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, 0x%08x, 0x%08x, %p)\n",
370 ld
, debugstr_w(dn
), scope
, debugstr_w(filter
), attrs
, attrsonly
,
371 serverctrls
, clientctrls
, timelimit
, sizelimit
, sortkeys
);
373 search
= heap_alloc_zero( sizeof(*search
) );
376 ld
->ld_errno
= WLDAP32_LDAP_NO_MEMORY
;
382 search
->dn
= strdupW( dn
);
383 if (!search
->dn
) goto fail
;
387 search
->filter
= strdupW( filter
);
388 if (!search
->filter
) goto fail
;
392 search
->attrs
= strarraydupW( attrs
);
393 if (!search
->attrs
) goto fail
;
396 len
= serverctrls
? controlarraylenW( serverctrls
) : 0;
397 search
->serverctrls
= heap_alloc( sizeof(LDAPControl
*) * (len
+ 2) );
398 if (!search
->serverctrls
) goto fail
;
399 search
->serverctrls
[0] = NULL
; /* reserve 0 for page control */
400 for (i
= 0; i
< len
; i
++)
402 search
->serverctrls
[i
+ 1] = controldupW( serverctrls
[i
] );
403 if (!search
->serverctrls
[i
+ 1]) goto fail
;
405 search
->serverctrls
[len
+ 1] = NULL
;
409 search
->clientctrls
= controlarraydupW( clientctrls
);
410 if (!search
->clientctrls
) goto fail
;
413 search
->scope
= scope
;
414 search
->attrsonly
= attrsonly
;
415 search
->timeout
.tv_sec
= timelimit
;
416 search
->timeout
.tv_usec
= 0;
417 search
->sizelimit
= sizelimit
;
418 search
->cookie
= NULL
;
423 ldap_search_abandon_page( ld
, search
);
424 ld
->ld_errno
= WLDAP32_LDAP_NO_MEMORY
;