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
28 #include "wine/debug.h"
29 #include "winldap_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(wldap32
);
33 static struct WLDAP32_berval null_cookieW
= { 0, NULL
};
35 /***********************************************************************
36 * ldap_create_page_controlA (WLDAP32.@)
38 ULONG CDECL
ldap_create_page_controlA( LDAP
*ld
, ULONG pagesize
, struct WLDAP32_berval
*cookie
, UCHAR critical
,
39 LDAPControlA
**control
)
42 LDAPControlW
*controlW
= NULL
;
44 TRACE( "(%p, %#lx, %p, 0x%02x, %p)\n", ld
, pagesize
, cookie
, critical
, control
);
46 if (!ld
|| !control
|| pagesize
> INT_MAX
) return WLDAP32_LDAP_PARAM_ERROR
;
48 ret
= ldap_create_page_controlW( ld
, pagesize
, cookie
, critical
, &controlW
);
49 if (ret
== WLDAP32_LDAP_SUCCESS
)
51 *control
= controlWtoA( controlW
);
52 ldap_control_freeW( controlW
);
57 /* create a page control by hand */
58 static ULONG
create_page_control( ULONG pagesize
, struct WLDAP32_berval
*cookie
, UCHAR critical
,
59 LDAPControlW
**control
)
62 WLDAP32_BerElement
*ber
;
63 struct WLDAP32_berval
*berval
, *vec
[2];
67 if (!(ber
= WLDAP32_ber_alloc_t( WLDAP32_LBER_USE_DER
))) return WLDAP32_LDAP_NO_MEMORY
;
73 vec
[0] = &null_cookieW
;
74 len
= WLDAP32_ber_printf( ber
, (char *)"{iV}", pagesize
, vec
);
76 ret
= WLDAP32_ber_flatten( ber
, &berval
);
77 WLDAP32_ber_free( ber
, 1 );
79 if (len
== WLDAP32_LBER_ERROR
) return WLDAP32_LDAP_ENCODING_ERROR
;
80 if (ret
== -1) return WLDAP32_LDAP_NO_MEMORY
;
82 /* copy the berval so it can be properly freed by the caller */
83 if (!(val
= malloc( berval
->bv_len
))) return WLDAP32_LDAP_NO_MEMORY
;
86 memcpy( val
, berval
->bv_val
, len
);
87 WLDAP32_ber_bvfree( berval
);
89 if (!(ctrl
= malloc( sizeof(*ctrl
) )))
92 return WLDAP32_LDAP_NO_MEMORY
;
94 if (!(ctrl
->ldctl_oid
= strAtoW( LDAP_PAGED_RESULT_OID_STRING
)))
98 return WLDAP32_LDAP_NO_MEMORY
;
100 ctrl
->ldctl_value
.bv_len
= len
;
101 ctrl
->ldctl_value
.bv_val
= val
;
102 ctrl
->ldctl_iscritical
= critical
;
105 return WLDAP32_LDAP_SUCCESS
;
108 /***********************************************************************
109 * ldap_create_page_controlW (WLDAP32.@)
111 ULONG CDECL
ldap_create_page_controlW( LDAP
*ld
, ULONG pagesize
, struct WLDAP32_berval
*cookie
, UCHAR critical
,
112 LDAPControlW
**control
)
114 TRACE( "(%p, %#lx, %p, 0x%02x, %p)\n", ld
, pagesize
, cookie
, critical
, control
);
116 if (!ld
|| !control
|| pagesize
> INT_MAX
) return WLDAP32_LDAP_PARAM_ERROR
;
117 return create_page_control( pagesize
, cookie
, critical
, control
);
120 ULONG CDECL
ldap_get_next_page( LDAP
*ld
, LDAPSearch
*search
, ULONG pagesize
, ULONG
*message
)
122 FIXME( "(%p, %p, %#lx, %p)\n", ld
, search
, pagesize
, message
);
125 return WLDAP32_LDAP_NOT_SUPPORTED
;
128 ULONG CDECL
ldap_get_next_page_s( LDAP
*ld
, LDAPSearch
*search
, struct l_timeval
*timeout
, ULONG pagesize
,
129 ULONG
*count
, WLDAP32_LDAPMessage
**results
)
133 TRACE( "(%p, %p, %p, %lu, %p, %p)\n", ld
, search
, timeout
, pagesize
, count
, results
);
135 if (!ld
|| !search
|| !count
|| !results
) return ~0u;
137 if (search
->cookie
&& !search
->cookie
->bv_len
)
139 /* end of paged results */
142 return WLDAP32_LDAP_NO_RESULTS_RETURNED
;
145 if (search
->serverctrls
[0])
147 controlfreeW( search
->serverctrls
[0] );
148 search
->serverctrls
[0] = NULL
;
151 TRACE("search->cookie: %s\n", search
->cookie
? debugstr_an(search
->cookie
->bv_val
, search
->cookie
->bv_len
) : "NULL");
152 ret
= ldap_create_page_controlW( ld
, pagesize
, search
->cookie
, 1, &search
->serverctrls
[0] );
153 if (ret
!= WLDAP32_LDAP_SUCCESS
) return ret
;
155 ret
= ldap_search_ext_sW( ld
, search
->dn
, search
->scope
, search
->filter
, search
->attrs
, search
->attrsonly
,
156 search
->serverctrls
, search
->clientctrls
,
157 search
->timeout
.tv_sec
? &search
->timeout
: NULL
, search
->sizelimit
, results
);
158 if (ret
!= WLDAP32_LDAP_SUCCESS
) return ret
;
160 return ldap_get_paged_count( ld
, search
, count
, *results
);
163 ULONG CDECL
ldap_get_paged_count( LDAP
*ld
, LDAPSearch
*search
, ULONG
*count
, WLDAP32_LDAPMessage
*results
)
166 LDAPControlW
**server_ctrls
= NULL
;
168 TRACE( "(%p, %p, %p, %p)\n", ld
, search
, count
, results
);
170 if (!ld
|| !count
|| !results
) return WLDAP32_LDAP_PARAM_ERROR
;
174 ret
= ldap_parse_resultW( ld
, results
, NULL
, NULL
, NULL
, NULL
, &server_ctrls
, 0 );
175 if (ret
!= WLDAP32_LDAP_SUCCESS
) return ret
;
177 if (!server_ctrls
) /* assume end of paged results */
179 search
->cookie
= &null_cookieW
;
180 return WLDAP32_LDAP_SUCCESS
;
183 free( search
->cookie
);
184 search
->cookie
= NULL
;
186 ret
= ldap_parse_page_controlW( ld
, server_ctrls
, count
, &search
->cookie
);
187 if (ret
== WLDAP32_LDAP_SUCCESS
)
188 TRACE( "new search->cookie: %s, count %lu\n",
189 debugstr_an(search
->cookie
->bv_val
, search
->cookie
->bv_len
), *count
);
191 ldap_controls_freeW( server_ctrls
);
195 /***********************************************************************
196 * ldap_parse_page_controlA (WLDAP32.@)
198 ULONG CDECL
ldap_parse_page_controlA( LDAP
*ld
, LDAPControlA
**ctrls
, ULONG
*count
, struct WLDAP32_berval
**cookie
)
201 LDAPControlW
**ctrlsW
= NULL
;
203 TRACE( "(%p, %p, %p, %p)\n", ld
, ctrls
, count
, cookie
);
205 if (!ld
|| !ctrls
|| !count
|| !cookie
) return WLDAP32_LDAP_PARAM_ERROR
;
207 if (!(ctrlsW
= controlarrayAtoW( ctrls
))) return WLDAP32_LDAP_NO_MEMORY
;
208 ret
= ldap_parse_page_controlW( ld
, ctrlsW
, count
, cookie
);
209 controlarrayfreeW( ctrlsW
);
213 /***********************************************************************
214 * ldap_parse_page_controlW (WLDAP32.@)
216 ULONG CDECL
ldap_parse_page_controlW( LDAP
*ld
, LDAPControlW
**ctrls
, ULONG
*ret_count
,
217 struct WLDAP32_berval
**ret_cookie
)
220 LDAPControlW
*control
= NULL
;
221 WLDAP32_BerElement
*ber
;
222 struct WLDAP32_berval
*cookie
= NULL
;
226 TRACE( "(%p, %p, %p, %p)\n", ld
, ctrls
, ret_count
, ret_cookie
);
228 if (!ld
|| !ctrls
|| !ret_count
|| !ret_cookie
) return WLDAP32_LDAP_PARAM_ERROR
;
230 for (i
= 0; ctrls
[i
]; i
++)
232 if (!wcscmp( LDAP_PAGED_RESULT_OID_STRING_W
, ctrls
[i
]->ldctl_oid
))
235 if (!control
) return WLDAP32_LDAP_CONTROL_NOT_FOUND
;
237 if (!(ber
= WLDAP32_ber_init( &control
->ldctl_value
))) return WLDAP32_LDAP_NO_MEMORY
;
239 tag
= WLDAP32_ber_scanf( ber
, (char *)"{iO}", &count
, &cookie
);
240 if (tag
== WLDAP32_LBER_ERROR
) ret
= WLDAP32_LDAP_DECODING_ERROR
;
244 *ret_cookie
= cookie
;
245 ret
= WLDAP32_LDAP_SUCCESS
;
248 WLDAP32_ber_free( ber
, 1 );
252 ULONG CDECL
ldap_search_abandon_page( LDAP
*ld
, LDAPSearch
*search
)
254 LDAPControlW
**ctrls
;
256 TRACE( "(%p, %p)\n", ld
, search
);
258 if (!ld
|| !search
) return ~0u;
261 free( search
->filter
);
262 strarrayfreeW( search
->attrs
);
263 ctrls
= search
->serverctrls
;
264 controlfreeW( ctrls
[0] ); /* page control */
266 while (*ctrls
) controlfreeW( *ctrls
++ );
267 free( search
->serverctrls
);
268 controlarrayfreeW( search
->clientctrls
);
269 if (search
->cookie
&& search
->cookie
!= &null_cookieW
) free( search
->cookie
);
272 return WLDAP32_LDAP_SUCCESS
;
275 LDAPSearch
* CDECL
ldap_search_init_pageA( LDAP
*ld
, char *dn
, ULONG scope
, char *filter
, char **attrs
,
276 ULONG attrsonly
, LDAPControlA
**serverctrls
, LDAPControlA
**clientctrls
,
277 ULONG timelimit
, ULONG sizelimit
, LDAPSortKeyA
**sortkeys
)
279 FIXME( "(%p, %s, %#lx, %s, %p, %#lx, %p, %p, %#lx, %#lx, %p)\n", ld
, debugstr_a(dn
), scope
,
280 debugstr_a(filter
), attrs
, attrsonly
, serverctrls
, clientctrls
, timelimit
, sizelimit
, sortkeys
);
284 LDAPSearch
* CDECL
ldap_search_init_pageW( LDAP
*ld
, WCHAR
*dn
, ULONG scope
, WCHAR
*filter
, WCHAR
**attrs
,
285 ULONG attrsonly
, LDAPControlW
**serverctrls
, LDAPControlW
**clientctrls
,
286 ULONG timelimit
, ULONG sizelimit
, LDAPSortKeyW
**sortkeys
)
291 TRACE( "(%p, %s, %#lx, %s, %p, %#lx, %p, %p, %#lx, %#lx, %p)\n", ld
, debugstr_w(dn
), scope
,
292 debugstr_w(filter
), attrs
, attrsonly
, serverctrls
, clientctrls
, timelimit
, sizelimit
, sortkeys
);
294 if (!(search
= calloc( 1, sizeof(*search
) )))
296 ld
->ld_errno
= WLDAP32_LDAP_NO_MEMORY
;
300 if (dn
&& !(search
->dn
= wcsdup( dn
))) goto fail
;
301 if (filter
&& !(search
->filter
= wcsdup( filter
))) goto fail
;
302 if (attrs
&& !(search
->attrs
= strarraydupW( attrs
))) goto fail
;
304 len
= serverctrls
? controlarraylenW( serverctrls
) : 0;
305 if (!(search
->serverctrls
= malloc( sizeof(LDAPControlW
*) * (len
+ 2) ))) goto fail
;
306 search
->serverctrls
[0] = NULL
; /* reserve 0 for page control */
307 for (i
= 0; i
< len
; i
++)
309 if (!(search
->serverctrls
[i
+ 1] = controldupW( serverctrls
[i
] )))
311 for (; i
> 0; i
--) controlfreeW( search
->serverctrls
[i
] );
315 search
->serverctrls
[len
+ 1] = NULL
;
317 if (clientctrls
&& !(search
->clientctrls
= controlarraydupW( clientctrls
)))
319 for (i
= 0; i
< len
; i
++) controlfreeW( search
->serverctrls
[i
] );
323 search
->scope
= scope
;
324 search
->attrsonly
= attrsonly
;
325 search
->timeout
.tv_sec
= timelimit
;
326 search
->timeout
.tv_usec
= 0;
327 search
->sizelimit
= sizelimit
;
328 search
->cookie
= NULL
;
332 ldap_search_abandon_page( ld
, search
);
333 ld
->ld_errno
= WLDAP32_LDAP_NO_MEMORY
;