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
)))
100 return LDAP_NO_MEMORY
;
102 ctrl
->ldctl_value
.bv_len
= len
;
103 ctrl
->ldctl_value
.bv_val
= val
;
104 ctrl
->ldctl_iscritical
= critical
;
110 /***********************************************************************
111 * ldap_create_page_controlW (WLDAP32.@)
113 * Create a control for paged search results.
116 * ld [I] Pointer to an LDAP context.
117 * pagesize [I] Number of entries to return per page.
118 * cookie [I] Used by the server to track its location in the
120 * critical [I] Tells the server this control is critical to the
122 * control [O] LDAPControl created.
125 * Success: LDAP_SUCCESS
126 * Failure: An LDAP error code.
128 ULONG CDECL
ldap_create_page_controlW( LDAP
*ld
, ULONG pagesize
, struct berval
*cookie
, UCHAR critical
,
129 LDAPControlW
**control
)
131 TRACE( "(%p, 0x%08x, %p, 0x%02x, %p)\n", ld
, pagesize
, cookie
, critical
, control
);
133 if (!ld
|| !control
|| pagesize
> INT_MAX
) return LDAP_PARAM_ERROR
;
134 return create_page_control( pagesize
, cookie
, critical
, control
);
137 ULONG CDECL
ldap_get_next_page( LDAP
*ld
, LDAPSearch
*search
, ULONG pagesize
, ULONG
*message
)
139 FIXME( "(%p, %p, 0x%08x, %p)\n", ld
, search
, pagesize
, message
);
142 return LDAP_NOT_SUPPORTED
;
145 ULONG CDECL
ldap_get_next_page_s( LDAP
*ld
, LDAPSearch
*search
, struct l_timeval
*timeout
, ULONG pagesize
,
146 ULONG
*count
, LDAPMessage
**results
)
150 TRACE( "(%p, %p, %p, %u, %p, %p)\n", ld
, search
, timeout
, pagesize
, count
, results
);
152 if (!ld
|| !search
|| !count
|| !results
) return ~0u;
154 if (search
->cookie
&& !search
->cookie
->bv_len
)
156 /* end of paged results */
159 return LDAP_NO_RESULTS_RETURNED
;
162 if (search
->serverctrls
[0])
164 controlfreeW( search
->serverctrls
[0] );
165 search
->serverctrls
[0] = NULL
;
168 TRACE("search->cookie: %s\n", search
->cookie
? debugstr_an(search
->cookie
->bv_val
, search
->cookie
->bv_len
) : "NULL");
169 ret
= ldap_create_page_controlW( ld
, pagesize
, search
->cookie
, 1, &search
->serverctrls
[0] );
170 if (ret
!= LDAP_SUCCESS
) return ret
;
172 ret
= ldap_search_ext_sW( ld
, search
->dn
, search
->scope
, search
->filter
, search
->attrs
, search
->attrsonly
,
173 search
->serverctrls
, search
->clientctrls
,
174 search
->timeout
.tv_sec
? &search
->timeout
: NULL
, search
->sizelimit
, results
);
175 if (ret
!= LDAP_SUCCESS
) return ret
;
177 return ldap_get_paged_count( ld
, search
, count
, *results
);
180 ULONG CDECL
ldap_get_paged_count( LDAP
*ld
, LDAPSearch
*search
, ULONG
*count
, LDAPMessage
*results
)
183 LDAPControlW
**server_ctrls
= NULL
;
185 TRACE( "(%p, %p, %p, %p)\n", ld
, search
, count
, results
);
187 if (!ld
|| !count
|| !results
) return LDAP_PARAM_ERROR
;
191 ret
= ldap_parse_resultW( ld
, results
, NULL
, NULL
, NULL
, NULL
, &server_ctrls
, 0 );
192 if (ret
!= LDAP_SUCCESS
) return ret
;
194 if (!server_ctrls
) /* assume end of paged results */
196 search
->cookie
= &null_cookieW
;
200 free( search
->cookie
);
201 search
->cookie
= NULL
;
203 ret
= ldap_parse_page_controlW( ld
, server_ctrls
, count
, &search
->cookie
);
204 if (ret
== LDAP_SUCCESS
)
205 TRACE("new search->cookie: %s, count %u\n", debugstr_an(search
->cookie
->bv_val
, search
->cookie
->bv_len
), *count
);
207 ldap_controls_freeW( server_ctrls
);
211 /***********************************************************************
212 * ldap_parse_page_controlA (WLDAP32.@)
214 ULONG CDECL
ldap_parse_page_controlA( LDAP
*ld
, LDAPControlA
**ctrls
, ULONG
*count
, struct berval
**cookie
)
217 LDAPControlW
**ctrlsW
= NULL
;
219 TRACE( "(%p, %p, %p, %p)\n", ld
, ctrls
, count
, cookie
);
221 if (!ld
|| !ctrls
|| !count
|| !cookie
) return LDAP_PARAM_ERROR
;
223 if (!(ctrlsW
= controlarrayAtoW( ctrls
))) return LDAP_NO_MEMORY
;
224 ret
= ldap_parse_page_controlW( ld
, ctrlsW
, count
, cookie
);
225 controlarrayfreeW( ctrlsW
);
229 /***********************************************************************
230 * ldap_parse_page_controlW (WLDAP32.@)
232 ULONG CDECL
ldap_parse_page_controlW( LDAP
*ld
, LDAPControlW
**ctrls
, ULONG
*ret_count
, struct berval
**ret_cookie
)
235 LDAPControlW
*control
= NULL
;
237 struct berval
*cookie
= NULL
;
241 TRACE( "(%p, %p, %p, %p)\n", ld
, ctrls
, ret_count
, ret_cookie
);
243 if (!ld
|| !ctrls
|| !ret_count
|| !ret_cookie
) return LDAP_PARAM_ERROR
;
245 for (i
= 0; ctrls
[i
]; i
++)
247 if (!wcscmp( LDAP_PAGED_RESULT_OID_STRING_W
, ctrls
[i
]->ldctl_oid
))
250 if (!control
) return LDAP_CONTROL_NOT_FOUND
;
252 if (!(ber
= ber_init( &control
->ldctl_value
))) return LDAP_NO_MEMORY
;
254 tag
= ber_scanf( ber
, (char *)"{iO}", &count
, &cookie
);
255 if (tag
== LBER_ERROR
) ret
= LDAP_DECODING_ERROR
;
259 *ret_cookie
= cookie
;
267 ULONG CDECL
ldap_search_abandon_page( LDAP
*ld
, LDAPSearch
*search
)
269 LDAPControlW
**ctrls
;
271 TRACE( "(%p, %p)\n", ld
, search
);
273 if (!ld
|| !search
) return ~0u;
276 free( search
->filter
);
277 strarrayfreeW( search
->attrs
);
278 ctrls
= search
->serverctrls
;
279 controlfreeW( ctrls
[0] ); /* page control */
281 while (*ctrls
) controlfreeW( *ctrls
++ );
282 free( search
->serverctrls
);
283 controlarrayfreeW( search
->clientctrls
);
284 if (search
->cookie
&& search
->cookie
!= &null_cookieW
) free( search
->cookie
);
290 LDAPSearch
* CDECL
ldap_search_init_pageA( LDAP
*ld
, char *dn
, ULONG scope
, char *filter
, char **attrs
,
291 ULONG attrsonly
, LDAPControlA
**serverctrls
, LDAPControlA
**clientctrls
, ULONG timelimit
, ULONG sizelimit
,
292 LDAPSortKeyA
**sortkeys
)
294 FIXME( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, 0x%08x, 0x%08x, %p)\n", ld
, debugstr_a(dn
), scope
,
295 debugstr_a(filter
), attrs
, attrsonly
, serverctrls
, clientctrls
, timelimit
, sizelimit
, sortkeys
);
299 LDAPSearch
* CDECL
ldap_search_init_pageW( LDAP
*ld
, WCHAR
*dn
, ULONG scope
, WCHAR
*filter
, WCHAR
**attrs
,
300 ULONG attrsonly
, LDAPControlW
**serverctrls
, LDAPControlW
**clientctrls
, ULONG timelimit
, ULONG sizelimit
,
301 LDAPSortKeyW
**sortkeys
)
306 TRACE( "(%p, %s, 0x%08x, %s, %p, 0x%08x, %p, %p, 0x%08x, 0x%08x, %p)\n", ld
, debugstr_w(dn
), scope
,
307 debugstr_w(filter
), attrs
, attrsonly
, serverctrls
, clientctrls
, timelimit
, sizelimit
, sortkeys
);
309 if (!(search
= calloc( 1, sizeof(*search
) )))
311 ld
->ld_errno
= LDAP_NO_MEMORY
;
315 if (dn
&& !(search
->dn
= strdupW( dn
))) goto fail
;
316 if (filter
&& !(search
->filter
= strdupW( filter
))) goto fail
;
317 if (attrs
&& !(search
->attrs
= strarraydupW( attrs
))) goto fail
;
319 len
= serverctrls
? controlarraylenW( serverctrls
) : 0;
320 if (!(search
->serverctrls
= malloc( sizeof(LDAPControlW
*) * (len
+ 2) ))) goto fail
;
321 search
->serverctrls
[0] = NULL
; /* reserve 0 for page control */
322 for (i
= 0; i
< len
; i
++)
324 if (!(search
->serverctrls
[i
+ 1] = controldupW( serverctrls
[i
] )))
326 for (; i
> 0; i
--) controlfreeW( search
->serverctrls
[i
] );
330 search
->serverctrls
[len
+ 1] = NULL
;
332 if (clientctrls
&& !(search
->clientctrls
= controlarraydupW( clientctrls
)))
334 for (i
= 0; i
< len
; i
++) controlfreeW( search
->serverctrls
[i
] );
338 search
->scope
= scope
;
339 search
->attrsonly
= attrsonly
;
340 search
->timeout
.tv_sec
= timelimit
;
341 search
->timeout
.tv_usec
= 0;
342 search
->sizelimit
= sizelimit
;
343 search
->cookie
= NULL
;
347 ldap_search_abandon_page( ld
, search
);
348 ld
->ld_errno
= LDAP_NO_MEMORY
;