1 /*
2 * WLDAP32 - LDAP support for Wine
3 *
4 * Copyright 2005 Hans Leidekker
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winldap.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
30
31 #ifndef LBER_ERROR
32 # define LBER_ERROR (~0U)
33 #endif
34
35 /***********************************************************************
36 * ber_alloc_t (WLDAP32.@)
37 *
38 * Allocate a berelement structure.
39 *
40 * PARAMS
41 * options [I] Must be LBER_USE_DER.
42 *
43 * RETURNS
44 * Success: Pointer to an allocated berelement structure.
45 * Failure: NULL
46 *
47 * NOTES
48 * Free the berelement structure with ber_free.
49 */
WLDAP32_ber_alloc_t(INT options)50 BerElement * CDECL WLDAP32_ber_alloc_t( INT options )
51 {
52 #ifdef HAVE_LDAP
53 return ber_alloc_t( options );
54 #else
55 return NULL;
56 #endif
57 }
58
59
60 /***********************************************************************
61 * ber_bvdup (WLDAP32.@)
62 *
63 * Copy a berval structure.
64 *
65 * PARAMS
66 * berval [I] Pointer to the berval structure to be copied.
67 *
68 * RETURNS
69 * Success: Pointer to a copy of the berval structure.
70 * Failure: NULL
71 *
72 * NOTES
73 * Free the copy with ber_bvfree.
74 */
WLDAP32_ber_bvdup(BERVAL * berval)75 BERVAL * CDECL WLDAP32_ber_bvdup( BERVAL *berval )
76 {
77 #ifdef HAVE_LDAP
78 return ber_bvdup( berval );
79 #else
80 return NULL;
81 #endif
82 }
83
84
85 /***********************************************************************
86 * ber_bvecfree (WLDAP32.@)
87 *
88 * Free an array of berval structures.
89 *
90 * PARAMS
91 * berval [I] Pointer to an array of berval structures.
92 *
93 * RETURNS
94 * Nothing.
95 *
96 * NOTES
97 * Use this function only to free an array of berval structures
98 * returned by a call to ber_scanf with a 'V' in the format string.
99 */
WLDAP32_ber_bvecfree(PBERVAL * berval)100 void CDECL WLDAP32_ber_bvecfree( PBERVAL *berval )
101 {
102 #ifdef HAVE_LDAP
103 ber_bvecfree( berval );
104 #endif
105 }
106
107
108 /***********************************************************************
109 * ber_bvfree (WLDAP32.@)
110 *
111 * Free a berval structure.
112 *
113 * PARAMS
114 * berval [I] Pointer to a berval structure.
115 *
116 * RETURNS
117 * Nothing.
118 *
119 * NOTES
120 * Use this function only to free berval structures allocated by
121 * an LDAP API.
122 */
WLDAP32_ber_bvfree(BERVAL * berval)123 void CDECL WLDAP32_ber_bvfree( BERVAL *berval )
124 {
125 #ifdef HAVE_LDAP
126 ber_bvfree( berval );
127 #endif
128 }
129
130
131 /***********************************************************************
132 * ber_first_element (WLDAP32.@)
133 *
134 * Return the tag of the first element in a set or sequence.
135 *
136 * PARAMS
137 * berelement [I] Pointer to a berelement structure.
138 * len [O] Receives the length of the first element.
139 * opaque [O] Receives a pointer to a cookie.
140 *
141 * RETURNS
142 * Success: Tag of the first element.
143 * Failure: LBER_DEFAULT (no more data).
144 *
145 * NOTES
146 * len and cookie should be passed to ber_next_element.
147 */
WLDAP32_ber_first_element(BerElement * berelement,ULONG * len,CHAR ** opaque)148 ULONG CDECL WLDAP32_ber_first_element( BerElement *berelement, ULONG *len, CHAR **opaque )
149 {
150 #ifdef HAVE_LDAP
151 return ber_first_element( berelement, len, opaque );
152 #else
153 return LBER_ERROR;
154 #endif
155 }
156
157
158 /***********************************************************************
159 * ber_flatten (WLDAP32.@)
160 *
161 * Flatten a berelement structure into a berval structure.
162 *
163 * PARAMS
164 * berelement [I] Pointer to a berelement structure.
165 * berval [O] Pointer to a berval structure.
166 *
167 * RETURNS
168 * Success: 0
169 * Failure: LBER_ERROR
170 *
171 * NOTES
172 * Free the berval structure with ber_bvfree.
173 */
WLDAP32_ber_flatten(BerElement * berelement,PBERVAL * berval)174 INT CDECL WLDAP32_ber_flatten( BerElement *berelement, PBERVAL *berval )
175 {
176 #ifdef HAVE_LDAP
177 return ber_flatten( berelement, berval );
178 #else
179 return LBER_ERROR;
180 #endif
181 }
182
183
184 /***********************************************************************
185 * ber_free (WLDAP32.@)
186 *
187 * Free a berelement structure.
188 *
189 * PARAMS
190 * berelement [I] Pointer to the berelement structure to be freed.
191 * buf [I] Flag.
192 *
193 * RETURNS
194 * Nothing.
195 *
196 * NOTES
197 * Set buf to 0 if the berelement was allocated with ldap_first_attribute
198 * or ldap_next_attribute, otherwise set it to 1.
199 */
WLDAP32_ber_free(BerElement * berelement,INT buf)200 void CDECL WLDAP32_ber_free( BerElement *berelement, INT buf )
201 {
202 #ifdef HAVE_LDAP
203 ber_free( berelement, buf );
204 #endif
205 }
206
207
208 /***********************************************************************
209 * ber_init (WLDAP32.@)
210 *
211 * Initialise a berelement structure from a berval structure.
212 *
213 * PARAMS
214 * berval [I] Pointer to a berval structure.
215 *
216 * RETURNS
217 * Success: Pointer to a berelement structure.
218 * Failure: NULL
219 *
220 * NOTES
221 * Call ber_free to free the returned berelement structure.
222 */
WLDAP32_ber_init(BERVAL * berval)223 BerElement * CDECL WLDAP32_ber_init( BERVAL *berval )
224 {
225 #ifdef HAVE_LDAP
226 return ber_init( berval );
227 #else
228 return NULL;
229 #endif
230 }
231
232
233 /***********************************************************************
234 * ber_next_element (WLDAP32.@)
235 *
236 * Return the tag of the next element in a set or sequence.
237 *
238 * PARAMS
239 * berelement [I] Pointer to a berelement structure.
240 * len [I/O] Receives the length of the next element.
241 * opaque [I/O] Pointer to a cookie.
242 *
243 * RETURNS
244 * Success: Tag of the next element.
245 * Failure: LBER_DEFAULT (no more data).
246 *
247 * NOTES
248 * len and cookie are initialized by ber_first_element and should
249 * be passed on in subsequent calls to ber_next_element.
250 */
WLDAP32_ber_next_element(BerElement * berelement,ULONG * len,CHAR * opaque)251 ULONG CDECL WLDAP32_ber_next_element( BerElement *berelement, ULONG *len, CHAR *opaque )
252 {
253 #ifdef HAVE_LDAP
254 return ber_next_element( berelement, len, opaque );
255 #else
256 return LBER_ERROR;
257 #endif
258 }
259
260
261 /***********************************************************************
262 * ber_peek_tag (WLDAP32.@)
263 *
264 * Return the tag of the next element.
265 *
266 * PARAMS
267 * berelement [I] Pointer to a berelement structure.
268 * len [O] Receives the length of the next element.
269 *
270 * RETURNS
271 * Success: Tag of the next element.
272 * Failure: LBER_DEFAULT (no more data).
273 */
WLDAP32_ber_peek_tag(BerElement * berelement,ULONG * len)274 ULONG CDECL WLDAP32_ber_peek_tag( BerElement *berelement, ULONG *len )
275 {
276 #ifdef HAVE_LDAP
277 return ber_peek_tag( berelement, len );
278 #else
279 return LBER_ERROR;
280 #endif
281 }
282
283
284 /***********************************************************************
285 * ber_skip_tag (WLDAP32.@)
286 *
287 * Skip the current tag and return the tag of the next element.
288 *
289 * PARAMS
290 * berelement [I] Pointer to a berelement structure.
291 * len [O] Receives the length of the skipped element.
292 *
293 * RETURNS
294 * Success: Tag of the next element.
295 * Failure: LBER_DEFAULT (no more data).
296 */
WLDAP32_ber_skip_tag(BerElement * berelement,ULONG * len)297 ULONG CDECL WLDAP32_ber_skip_tag( BerElement *berelement, ULONG *len )
298 {
299 #ifdef HAVE_LDAP
300 return ber_skip_tag( berelement, len );
301 #else
302 return LBER_ERROR;
303 #endif
304 }
305
306
307 /***********************************************************************
308 * ber_printf (WLDAP32.@)
309 *
310 * Encode a berelement structure.
311 *
312 * PARAMS
313 * berelement [I/O] Pointer to a berelement structure.
314 * fmt [I] Format string.
315 * ... [I] Values to encode.
316 *
317 * RETURNS
318 * Success: Non-negative number.
319 * Failure: LBER_ERROR
320 *
321 * NOTES
322 * berelement must have been allocated with ber_alloc_t. This function
323 * can be called multiple times to append data.
324 */
WLDAP32_ber_printf(BerElement * berelement,PCHAR fmt,...)325 INT WINAPIV WLDAP32_ber_printf( BerElement *berelement, PCHAR fmt, ... )
326 {
327 #ifdef HAVE_LDAP
328 __ms_va_list list;
329 int ret = 0;
330 char new_fmt[2];
331
332 new_fmt[1] = 0;
333 __ms_va_start( list, fmt );
334 while (*fmt)
335 {
336 new_fmt[0] = *fmt++;
337 switch(new_fmt[0])
338 {
339 case 'b':
340 case 'e':
341 case 'i':
342 {
343 int i = va_arg( list, int );
344 ret = ber_printf( berelement, new_fmt, i );
345 break;
346 }
347 case 'o':
348 case 's':
349 {
350 char *str = va_arg( list, char * );
351 ret = ber_printf( berelement, new_fmt, str );
352 break;
353 }
354 case 't':
355 {
356 unsigned int tag = va_arg( list, unsigned int );
357 ret = ber_printf( berelement, new_fmt, tag );
358 break;
359 }
360 case 'v':
361 {
362 char **array = va_arg( list, char ** );
363 ret = ber_printf( berelement, new_fmt, array );
364 break;
365 }
366 case 'V':
367 {
368 struct berval **array = va_arg( list, struct berval ** );
369 ret = ber_printf( berelement, new_fmt, array );
370 break;
371 }
372 case 'X':
373 {
374 char *str = va_arg( list, char * );
375 int len = va_arg( list, int );
376 new_fmt[0] = 'B'; /* 'X' is deprecated */
377 ret = ber_printf( berelement, new_fmt, str, len );
378 break;
379 }
380 case 'n':
381 case '{':
382 case '}':
383 case '[':
384 case ']':
385 ret = ber_printf( berelement, new_fmt );
386 break;
387 default:
388 FIXME( "Unknown format '%c'\n", new_fmt[0] );
389 ret = -1;
390 break;
391 }
392 if (ret == -1) break;
393 }
394 __ms_va_end( list );
395 return ret;
396 #else
397 return LBER_ERROR;
398 #endif
399 }
400
401
402 /***********************************************************************
403 * ber_scanf (WLDAP32.@)
404 *
405 * Decode a berelement structure.
406 *
407 * PARAMS
408 * berelement [I/O] Pointer to a berelement structure.
409 * fmt [I] Format string.
410 * ... [I] Pointers to values to be decoded.
411 *
412 * RETURNS
413 * Success: Non-negative number.
414 * Failure: LBER_ERROR
415 *
416 * NOTES
417 * berelement must have been allocated with ber_init. This function
418 * can be called multiple times to decode data.
419 */
WLDAP32_ber_scanf(BerElement * berelement,PCHAR fmt,...)420 INT WINAPIV WLDAP32_ber_scanf( BerElement *berelement, PCHAR fmt, ... )
421 {
422 #ifdef HAVE_LDAP
423 __ms_va_list list;
424 int ret = 0;
425 char new_fmt[2];
426
427 new_fmt[1] = 0;
428 __ms_va_start( list, fmt );
429 while (*fmt)
430 {
431 new_fmt[0] = *fmt++;
432 switch(new_fmt[0])
433 {
434 case 'a':
435 {
436 char **ptr = va_arg( list, char ** );
437 ret = ber_scanf( berelement, new_fmt, ptr );
438 break;
439 }
440 case 'b':
441 case 'e':
442 case 'i':
443 {
444 int *i = va_arg( list, int * );
445 ret = ber_scanf( berelement, new_fmt, i );
446 break;
447 }
448 case 't':
449 {
450 unsigned int *tag = va_arg( list, unsigned int * );
451 ret = ber_scanf( berelement, new_fmt, tag );
452 break;
453 }
454 case 'v':
455 {
456 char ***array = va_arg( list, char *** );
457 ret = ber_scanf( berelement, new_fmt, array );
458 break;
459 }
460 case 'B':
461 {
462 char **str = va_arg( list, char ** );
463 int *len = va_arg( list, int * );
464 ret = ber_scanf( berelement, new_fmt, str, len );
465 break;
466 }
467 case 'O':
468 {
469 struct berval **ptr = va_arg( list, struct berval ** );
470 ret = ber_scanf( berelement, new_fmt, ptr );
471 break;
472 }
473 case 'V':
474 {
475 struct berval ***array = va_arg( list, struct berval *** );
476 ret = ber_scanf( berelement, new_fmt, array );
477 break;
478 }
479 case 'n':
480 case 'x':
481 case '{':
482 case '}':
483 case '[':
484 case ']':
485 ret = ber_scanf( berelement, new_fmt );
486 break;
487 default:
488 FIXME( "Unknown format '%c'\n", new_fmt[0] );
489 ret = -1;
490 break;
491 }
492 if (ret == -1) break;
493 }
494 __ms_va_end( list );
495 return ret;
496 #else
497 return LBER_ERROR;
498 #endif
499 }
500