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