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
30 #include "wine/debug.h"
31 #include "winldap_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wldap32
);
35 static struct berval null_cookieW
= { 0, NULL
};
37 /***********************************************************************
38 * ldap_create_page_controlA (WLDAP32.@)
40 * See ldap_create_page_controlW.
42 ULONG CDECL
ldap_create_page_controlA( LDAP
*ld
, ULONG pagesize
, struct berval
*cookie
, UCHAR critical
,
43 LDAPControlA
**control
)
46 LDAPControlW
*controlW
= NULL
;
48 TRACE( "(%p, 0x%08x, %p, 0x%02x, %p)\n", ld
, pagesize
, cookie
, critical
, control
);
50 if (!ld
|| !control
|| pagesize
> INT_MAX
) return LDAP_PARAM_ERROR
;
52 ret
= ldap_create_page_controlW( ld
, pagesize
, cookie
, critical
, &controlW
);
53 if (ret
== LDAP_SUCCESS
)
55 *control
= controlWtoA( controlW
);
56 ldap_control_freeW( controlW
);
61 /* create a page control by hand */
62 static ULONG
create_page_control( ULONG pagesize
, struct berval
*cookie
, UCHAR critical
, LDAPControlW
**control
)
66 struct berval
*berval
, *vec
[2];
70 if (!(ber
= ber_alloc_t( LBER_USE_DER
))) return LDAP_NO_MEMORY
;
76 vec
[0] = &null_cookieW
;
77 len
= ber_printf( ber
, (char *)"{iV}", pagesize
, vec
);
79 ret
= ber_flatten( ber
, &berval
);
82 if (len
== LBER_ERROR
) return LDAP_ENCODING_ERROR
;
83 if (ret
== -1) return LDAP_NO_MEMORY
;
85 /* copy the berval so it can be properly freed by the caller */
86 if (!(val
= malloc( berval
->bv_len
))) return LDAP_NO_MEMORY
;
89 memcpy( val
, berval
->bv_val
, len
);
92 if (!(ctrl
= malloc( sizeof(*ctrl
) )))
95 return LDAP_NO_MEMORY
;
97 if (!(ctrl
->ldctl_oid
= strAtoW( LDAP_PAGED_RESULT_OID_STRING
)))
101 return LDAP_NO_MEMORY
;
103 ctrl
->ldctl_value
.bv_len
= len
;
104 ctrl
->ldctl_value
.bv_val
= val
;
105 ctrl
->ldctl_iscritical
= critical
;
111 /***********************************************************************
112 * ldap_create_page_controlW (WLDAP32.@)
114 * Create a control for paged search results.
117 * ld [I] Pointer to an LDAP context.
118 * pagesize [I] Number of entries to return per page.
119 * cookie [I] Used by the server to track its location in the
121 * critical [I] Tells the server this control is critical to the
123 * control [O] LDAPControl created.
126 * Success: LDAP_SUCCESS
127 * Failure: An LDAP error code.
129 ULONG CDECL
ldap_create_page_controlW( LDAP
*ld
, ULONG pagesize
, struct berval
*cookie
, UCHAR critical
,
130 LDAPControlW
**control
)
132 TRACE( "(%p, 0x%08x, %p, 0x%02x, %p)\n", ld
, pagesize
, cookie
, critical
, control
);
134 if (!ld
|| !control
|| pagesize
> INT_MAX
) return LDAP_PARAM_ERROR
;
135 return create_page_control( pagesize
, cookie
, critical
, control
);
138 ULONG CDECL
ldap_get_next_page( LDAP
*ld
, LDAPSearch
*search
, ULONG pagesize
, ULONG
*message
)
140 FIXME( "(%p, %p, 0x%08x, %p)\n", ld
, search
, pagesize
, message
);
143 return LDAP_NOT_SUPPORTED
;
146 ULONG CDECL
ldap_get_next_page_s( LDAP
*ld
, LDAPSearch
*search
, struct l_timeval
*timeout
, ULONG pagesize
,
147 ULONG
*count
, LDAPMessage
**results
)
151 TRACE( "(%p, %p, %p, %u, %p, %p)\n", ld
, search
, timeout
, pagesize
, count
, results
);
153 if (!ld
|| !search
|| !count
|| !results
) return ~0u;
155 if (search
->cookie
&& !search
->cookie
->bv_len
)
157 /* end of paged results */
160 return LDAP_NO_RESULTS_RETURNED
;
163 if (search
->serverctrls
[0])
165 controlfreeW( search
->serverctrls
[0] );
166 search
->serverctrls
[0] = NULL
;
169 TRACE("search->cookie: %s\n", search
->cookie
? debugstr_an(search
->cookie
->bv_val
, search
->cookie
->bv_len
) : "NULL");
170 ret
= ldap_create_page_controlW( ld
, pagesize
, search
->cookie
, 1, &search
->serverctrls
[0] );
171 if (ret
!= LDAP_SUCCESS
) return ret
;
173 ret
= ldap_search_ext_sW( ld
, search
->dn
, search
->scope
, search
->filter
, search
->attrs
, search
->attrsonly
,
174 search
->serverctrls
, search
->clientctrls
,
175 search
->timeout
.tv_sec
? &search
->timeout
: NULL
, search
->sizelimit
, results
);
176 if (ret
!= LDAP_SUCCESS
) return ret
;
178 return ldap_get_paged_count( ld
, search
, count
, *results
);
181 ULONG CDECL
ldap_get_paged_count( LDAP
*ld
, LDAPSearch
*search
, ULONG
*count
, LDAPMessage
*results
)
184 LDAPControlW
**server_ctrls
= NULL
;
186 TRACE( "(%p, %p, %p, %p)\n", ld
, search
, count
, results
);
188 if (!ld
|| !count
|| !results
) return LDAP_PARAM_ERROR
;
192 ret
= ldap_parse_resultW( ld
, results
, NULL
, NULL
, NULL
, NULL
, &server_ctrls
, 0 );
193 if (ret
!= LDAP_SUCCESS
) return ret
;
195 if (!server_ctrls
) /* assume end of paged results */
197 search
->cookie
= &null_cookieW
;
201 free( search
->cookie
);
202 search
->cookie
= NULL
;
204 ret
= ldap_parse_page_controlW( ld
, server_ctrls
, count
, &search
->cookie
);
205 if (ret
== LDAP_SUCCESS
)
206 TRACE("new search->cookie: %s, count %u\n", debugstr_an(search
->cookie
->bv_val
, search
->cookie
->bv_len
), *count
);
208 ldap_controls_freeW( server_ctrls
);
212 /***********************************************************************
213 * ldap_parse_page_controlA (WLDAP32.@)
215 ULONG CDECL
ldap_parse_page_controlA( LDAP
*ld
, LDAPControlA
**ctrls
, ULONG
*count
, struct berval
**cookie
)
218 LDAPControlW
**ctrlsW
= NULL
;
220 TRACE( "(%p, %p, %p, %p)\n", ld
, ctrls
, count
, cookie
);
222 if (!ld
|| !ctrls
|| !count
|| !cookie
) return LDAP_PARAM_ERROR
;
224 if (!(ctrlsW
= controlarrayAtoW( ctrls
))) return LDAP_NO_MEMORY
;
225 ret
= ldap_parse_page_controlW( ld
, ctrlsW
, count
, cookie
);
226 controlarrayfreeW( ctrlsW
);
230 /***********************************************************************
231 * ldap_parse_page_controlW (WLDAP32.@)
233 ULONG CDECL
ldap_parse_page_controlW( LDAP
*ld
, LDAPControlW
**ctrls
, ULONG
*ret_count
, struct berval
**ret_cookie
)
236 LDAPControlW
*control
= NULL
;
238 struct berval
*cookie
= NULL
;
242 TRACE( "(%p, %p, %p, %p)\n", ld
, ctrls
, ret_count
, ret_cookie
);
244 if (!ld
|| !ctrls
|| !ret_count
|| !ret_cookie
) return LDAP_PARAM_ERROR
;
246 for (i
= 0; ctrls
[i
]; i
++)
248 if (!wcscmp( LDAP_PAGED_RESULT_OID_STRING_W
, ctrls
[i
]->ldctl_oid
))
251 if (!control
) return LDAP_CONTROL_NOT_FOUND
;
253 if (!(ber
= ber_init( &control
->ldctl_value
))) return LDAP_NO_MEMORY
;
255 tag
= ber_scanf( ber
, (char *)"{iO}", &count
, &cookie
);
256 if (tag
== LBER_ERROR
) ret
= LDAP_DECODING_ERROR
;
260 *ret_cookie
= cookie
;
268 ULONG CDECL
ldap_search_abandon_page( LDAP
*ld
, LDAPSearch
*search
)
270 LDAPControlW
**ctrls
;
272 TRACE( "(%p, %p)\n", ld
, search
);
274 if (!ld
|| !search
) return ~0u;
277 free( search
->filter
);
278 strarrayfreeW( search
->attrs
);
279 ctrls
= search
->serverctrls
;
280 controlfreeW( ctrls
[0] ); /* page control */
282 while (*ctrls
) controlfreeW( *ctrls
++ );
283 free( search
->serverctrls
);
284 controlarrayfreeW( search
->clientctrls
);
285 if (search
->cookie
&& search
->cookie
!= &null_cookieW
) free( search
->cookie
);
291 LDAPSearch
* CDECL
ldap_search_init_pageA( LDAP
*ld
, char *dn
, ULONG scope
, char *filter
, char **attrs
,
292 ULONG attrsonly
, LDAPControlA
**serverctrls
, LDAPControlA
**clientctrls
, ULONG timelimit
, ULONG sizelimit
,
293 LDAPSortKeyA
**sortkeys
)
295 FIXME( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, 0x%08x, 0x%08x, %p)\n", ld
, debugstr_a(dn
), scope
,
296 debugstr_a(filter
), attrs
, attrsonly
, serverctrls
, clientctrls
, timelimit
, sizelimit
, sortkeys
);
300 LDAPSearch
* CDECL
ldap_search_init_pageW( LDAP
*ld
, WCHAR
*dn
, ULONG scope
, WCHAR
*filter
, WCHAR
**attrs
,
301 ULONG attrsonly
, LDAPControlW
**serverctrls
, LDAPControlW
**clientctrls
, ULONG timelimit
, ULONG sizelimit
,
302 LDAPSortKeyW
**sortkeys
)
307 TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, 0x%08x, 0x%08x, %p)\n", ld
, debugstr_w(dn
), scope
,
308 debugstr_w(filter
), attrs
, attrsonly
, serverctrls
, clientctrls
, timelimit
, sizelimit
, sortkeys
);
310 if (!(search
= calloc( 1, sizeof(*search
) )))
312 ld
->ld_errno
= LDAP_NO_MEMORY
;
316 if (dn
&& !(search
->dn
= strdupW( dn
))) goto fail
;
317 if (filter
&& !(search
->filter
= strdupW( filter
))) goto fail
;
318 if (attrs
&& !(search
->attrs
= strarraydupW( attrs
))) goto fail
;
320 len
= serverctrls
? controlarraylenW( serverctrls
) : 0;
321 if (!(search
->serverctrls
= malloc( sizeof(LDAPControlW
*) * (len
+ 2) ))) goto fail
;
322 search
->serverctrls
[0] = NULL
; /* reserve 0 for page control */
323 for (i
= 0; i
< len
; i
++)
325 if (!(search
->serverctrls
[i
+ 1] = controldupW( serverctrls
[i
] )))
327 for (; i
> 0; i
--) controlfreeW( search
->serverctrls
[i
] );
331 search
->serverctrls
[len
+ 1] = NULL
;
333 if (clientctrls
&& !(search
->clientctrls
= controlarraydupW( clientctrls
)))
335 for (i
= 0; i
< len
; i
++) controlfreeW( search
->serverctrls
[i
] );
339 search
->scope
= scope
;
340 search
->attrsonly
= attrsonly
;
341 search
->timeout
.tv_sec
= timelimit
;
342 search
->timeout
.tv_usec
= 0;
343 search
->sizelimit
= sizelimit
;
344 search
->cookie
= NULL
;
348 ldap_search_abandon_page( ld
, search
);
349 ld
->ld_errno
= LDAP_NO_MEMORY
;