|  | /* | 
|  | * WLDAP32 - LDAP support for Wine | 
|  | * | 
|  | * Copyright 2005 Hans Leidekker | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  |  | 
|  | #include <stdarg.h> | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "winldap.h" | 
|  | #include "wine/debug.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(wldap32); | 
|  |  | 
|  | #ifndef LBER_ERROR | 
|  | # define LBER_ERROR (~0U) | 
|  | #endif | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_alloc_t     (WLDAP32.@) | 
|  | * | 
|  | * Allocate a berelement structure. | 
|  | * | 
|  | * PARAMS | 
|  | *  options [I] Must be LBER_USE_DER. | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: Pointer to an allocated berelement structure. | 
|  | *  Failure: NULL | 
|  | * | 
|  | * NOTES | 
|  | *  Free the berelement structure with ber_free. | 
|  | */ | 
|  | BerElement * CDECL WLDAP32_ber_alloc_t( INT options ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | return ber_alloc_t( options ); | 
|  | #else | 
|  | return NULL; | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_bvdup     (WLDAP32.@) | 
|  | * | 
|  | * Copy a berval structure. | 
|  | * | 
|  | * PARAMS | 
|  | *  berval [I] Pointer to the berval structure to be copied. | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: Pointer to a copy of the berval structure. | 
|  | *  Failure: NULL | 
|  | * | 
|  | * NOTES | 
|  | *  Free the copy with ber_bvfree. | 
|  | */ | 
|  | BERVAL * CDECL WLDAP32_ber_bvdup( BERVAL *berval ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | return ber_bvdup( berval ); | 
|  | #else | 
|  | return NULL; | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_bvecfree     (WLDAP32.@) | 
|  | * | 
|  | * Free an array of berval structures. | 
|  | * | 
|  | * PARAMS | 
|  | *  berval [I] Pointer to an array of berval structures. | 
|  | * | 
|  | * RETURNS | 
|  | *  Nothing. | 
|  | * | 
|  | * NOTES | 
|  | *  Use this function only to free an array of berval structures | 
|  | *  returned by a call to ber_scanf with a 'V' in the format string. | 
|  | */ | 
|  | void CDECL WLDAP32_ber_bvecfree( PBERVAL *berval ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | ber_bvecfree( berval ); | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_bvfree     (WLDAP32.@) | 
|  | * | 
|  | * Free a berval structure. | 
|  | * | 
|  | * PARAMS | 
|  | *  berval [I] Pointer to a berval structure. | 
|  | * | 
|  | * RETURNS | 
|  | *  Nothing. | 
|  | * | 
|  | * NOTES | 
|  | *  Use this function only to free berval structures allocated by | 
|  | *  an LDAP API. | 
|  | */ | 
|  | void CDECL WLDAP32_ber_bvfree( BERVAL *berval ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | ber_bvfree( berval ); | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_first_element     (WLDAP32.@) | 
|  | * | 
|  | * Return the tag of the first element in a set or sequence. | 
|  | * | 
|  | * PARAMS | 
|  | *  berelement [I] Pointer to a berelement structure. | 
|  | *  len        [O] Receives the length of the first element. | 
|  | *  opaque     [O] Receives a pointer to a cookie. | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: Tag of the first element. | 
|  | *  Failure: LBER_DEFAULT (no more data). | 
|  | * | 
|  | * NOTES | 
|  | *  len and cookie should be passed to ber_next_element. | 
|  | */ | 
|  | ULONG CDECL WLDAP32_ber_first_element( BerElement *berelement, ULONG *len, CHAR **opaque ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | return ber_first_element( berelement, len, opaque ); | 
|  | #else | 
|  | return LBER_ERROR; | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_flatten     (WLDAP32.@) | 
|  | * | 
|  | * Flatten a berelement structure into a berval structure. | 
|  | * | 
|  | * PARAMS | 
|  | *  berelement [I] Pointer to a berelement structure. | 
|  | *  berval    [O] Pointer to a berval structure. | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: 0 | 
|  | *  Failure: LBER_ERROR | 
|  | * | 
|  | * NOTES | 
|  | *  Free the berval structure with ber_bvfree. | 
|  | */ | 
|  | INT CDECL WLDAP32_ber_flatten( BerElement *berelement, PBERVAL *berval ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | return ber_flatten( berelement, berval ); | 
|  | #else | 
|  | return LBER_ERROR; | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_free     (WLDAP32.@) | 
|  | * | 
|  | * Free a berelement structure. | 
|  | * | 
|  | * PARAMS | 
|  | *  berelement [I] Pointer to the berelement structure to be freed. | 
|  | *  buf       [I] Flag. | 
|  | * | 
|  | * RETURNS | 
|  | *  Nothing. | 
|  | * | 
|  | * NOTES | 
|  | *  Set buf to 0 if the berelement was allocated with ldap_first_attribute | 
|  | *  or ldap_next_attribute, otherwise set it to 1. | 
|  | */ | 
|  | void CDECL WLDAP32_ber_free( BerElement *berelement, INT buf ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | ber_free( berelement, buf ); | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_init     (WLDAP32.@) | 
|  | * | 
|  | * Initialise a berelement structure from a berval structure. | 
|  | * | 
|  | * PARAMS | 
|  | *  berval [I] Pointer to a berval structure. | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: Pointer to a berelement structure. | 
|  | *  Failure: NULL | 
|  | * | 
|  | * NOTES | 
|  | *  Call ber_free to free the returned berelement structure. | 
|  | */ | 
|  | BerElement * CDECL WLDAP32_ber_init( BERVAL *berval ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | return ber_init( berval ); | 
|  | #else | 
|  | return NULL; | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_next_element     (WLDAP32.@) | 
|  | * | 
|  | * Return the tag of the next element in a set or sequence. | 
|  | * | 
|  | * PARAMS | 
|  | *  berelement [I]   Pointer to a berelement structure. | 
|  | *  len        [I/O] Receives the length of the next element. | 
|  | *  opaque     [I/O] Pointer to a cookie. | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: Tag of the next element. | 
|  | *  Failure: LBER_DEFAULT (no more data). | 
|  | * | 
|  | * NOTES | 
|  | *  len and cookie are initialized by ber_first_element and should | 
|  | *  be passed on in subsequent calls to ber_next_element. | 
|  | */ | 
|  | ULONG CDECL WLDAP32_ber_next_element( BerElement *berelement, ULONG *len, CHAR *opaque ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | return ber_next_element( berelement, len, opaque ); | 
|  | #else | 
|  | return LBER_ERROR; | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_peek_tag     (WLDAP32.@) | 
|  | * | 
|  | * Return the tag of the next element. | 
|  | * | 
|  | * PARAMS | 
|  | *  berelement [I] Pointer to a berelement structure. | 
|  | *  len        [O] Receives the length of the next element. | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: Tag of the next element. | 
|  | *  Failure: LBER_DEFAULT (no more data). | 
|  | */ | 
|  | ULONG CDECL WLDAP32_ber_peek_tag( BerElement *berelement, ULONG *len ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | return ber_peek_tag( berelement, len ); | 
|  | #else | 
|  | return LBER_ERROR; | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_skip_tag     (WLDAP32.@) | 
|  | * | 
|  | * Skip the current tag and return the tag of the next element. | 
|  | * | 
|  | * PARAMS | 
|  | *  berelement [I] Pointer to a berelement structure. | 
|  | *  len        [O] Receives the length of the skipped element. | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: Tag of the next element. | 
|  | *  Failure: LBER_DEFAULT (no more data). | 
|  | */ | 
|  | ULONG CDECL WLDAP32_ber_skip_tag( BerElement *berelement, ULONG *len ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | return ber_skip_tag( berelement, len ); | 
|  | #else | 
|  | return LBER_ERROR; | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_printf     (WLDAP32.@) | 
|  | * | 
|  | * Encode a berelement structure. | 
|  | * | 
|  | * PARAMS | 
|  | *  berelement [I/O] Pointer to a berelement structure. | 
|  | *  fmt        [I]   Format string. | 
|  | *  ...        [I]   Values to encode. | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: Non-negative number. | 
|  | *  Failure: LBER_ERROR | 
|  | * | 
|  | * NOTES | 
|  | *  berelement must have been allocated with ber_alloc_t. This function | 
|  | *  can be called multiple times to append data. | 
|  | */ | 
|  | INT CDECL WLDAP32_ber_printf( BerElement *berelement, PCHAR fmt, ... ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | __ms_va_list list; | 
|  | int ret = 0; | 
|  | char new_fmt[2]; | 
|  |  | 
|  | new_fmt[1] = 0; | 
|  | __ms_va_start( list, fmt ); | 
|  | while (*fmt) | 
|  | { | 
|  | new_fmt[0] = *fmt++; | 
|  | switch(new_fmt[0]) | 
|  | { | 
|  | case 'b': | 
|  | case 'e': | 
|  | case 'i': | 
|  | { | 
|  | int i = va_arg( list, int ); | 
|  | ret = ber_printf( berelement, new_fmt, i ); | 
|  | break; | 
|  | } | 
|  | case 'o': | 
|  | case 's': | 
|  | { | 
|  | char *str = va_arg( list, char * ); | 
|  | ret = ber_printf( berelement, new_fmt, str ); | 
|  | break; | 
|  | } | 
|  | case 't': | 
|  | { | 
|  | unsigned int tag = va_arg( list, unsigned int ); | 
|  | ret = ber_printf( berelement, new_fmt, tag ); | 
|  | break; | 
|  | } | 
|  | case 'v': | 
|  | { | 
|  | char **array = va_arg( list, char ** ); | 
|  | ret = ber_printf( berelement, new_fmt, array ); | 
|  | break; | 
|  | } | 
|  | case 'V': | 
|  | { | 
|  | struct berval **array = va_arg( list, struct berval ** ); | 
|  | ret = ber_printf( berelement, new_fmt, array ); | 
|  | break; | 
|  | } | 
|  | case 'X': | 
|  | { | 
|  | char *str = va_arg( list, char * ); | 
|  | int len = va_arg( list, int ); | 
|  | new_fmt[0] = 'B';  /* 'X' is deprecated */ | 
|  | ret = ber_printf( berelement, new_fmt, str, len ); | 
|  | break; | 
|  | } | 
|  | case 'n': | 
|  | case '{': | 
|  | case '}': | 
|  | case '[': | 
|  | case ']': | 
|  | ret = ber_printf( berelement, new_fmt ); | 
|  | break; | 
|  | default: | 
|  | FIXME( "Unknown format '%c'\n", new_fmt[0] ); | 
|  | ret = -1; | 
|  | break; | 
|  | } | 
|  | if (ret == -1) break; | 
|  | } | 
|  | __ms_va_end( list ); | 
|  | return ret; | 
|  | #else | 
|  | return LBER_ERROR; | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *      ber_scanf     (WLDAP32.@) | 
|  | * | 
|  | * Decode a berelement structure. | 
|  | * | 
|  | * PARAMS | 
|  | *  berelement [I/O] Pointer to a berelement structure. | 
|  | *  fmt        [I]   Format string. | 
|  | *  ...        [I]   Pointers to values to be decoded. | 
|  | * | 
|  | * RETURNS | 
|  | *  Success: Non-negative number. | 
|  | *  Failure: LBER_ERROR | 
|  | * | 
|  | * NOTES | 
|  | *  berelement must have been allocated with ber_init. This function | 
|  | *  can be called multiple times to decode data. | 
|  | */ | 
|  | INT CDECL WLDAP32_ber_scanf( BerElement *berelement, PCHAR fmt, ... ) | 
|  | { | 
|  | #ifdef HAVE_LDAP | 
|  | __ms_va_list list; | 
|  | int ret = 0; | 
|  | char new_fmt[2]; | 
|  |  | 
|  | new_fmt[1] = 0; | 
|  | __ms_va_start( list, fmt ); | 
|  | while (*fmt) | 
|  | { | 
|  | new_fmt[0] = *fmt++; | 
|  | switch(new_fmt[0]) | 
|  | { | 
|  | case 'a': | 
|  | { | 
|  | char **ptr = va_arg( list, char ** ); | 
|  | ret = ber_scanf( berelement, new_fmt, ptr ); | 
|  | break; | 
|  | } | 
|  | case 'b': | 
|  | case 'e': | 
|  | case 'i': | 
|  | { | 
|  | int *i = va_arg( list, int * ); | 
|  | ret = ber_scanf( berelement, new_fmt, i ); | 
|  | break; | 
|  | } | 
|  | case 't': | 
|  | { | 
|  | unsigned int *tag = va_arg( list, unsigned int * ); | 
|  | ret = ber_scanf( berelement, new_fmt, tag ); | 
|  | break; | 
|  | } | 
|  | case 'v': | 
|  | { | 
|  | char ***array = va_arg( list, char *** ); | 
|  | ret = ber_scanf( berelement, new_fmt, array ); | 
|  | break; | 
|  | } | 
|  | case 'B': | 
|  | { | 
|  | char **str = va_arg( list, char ** ); | 
|  | int *len = va_arg( list, int * ); | 
|  | ret = ber_scanf( berelement, new_fmt, str, len ); | 
|  | break; | 
|  | } | 
|  | case 'O': | 
|  | { | 
|  | struct berval **ptr = va_arg( list, struct berval ** ); | 
|  | ret = ber_scanf( berelement, new_fmt, ptr ); | 
|  | break; | 
|  | } | 
|  | case 'V': | 
|  | { | 
|  | struct berval ***array = va_arg( list, struct berval *** ); | 
|  | ret = ber_scanf( berelement, new_fmt, array ); | 
|  | break; | 
|  | } | 
|  | case 'n': | 
|  | case 'x': | 
|  | case '{': | 
|  | case '}': | 
|  | case '[': | 
|  | case ']': | 
|  | ret = ber_scanf( berelement, new_fmt ); | 
|  | break; | 
|  | default: | 
|  | FIXME( "Unknown format '%c'\n", new_fmt[0] ); | 
|  | ret = -1; | 
|  | break; | 
|  | } | 
|  | if (ret == -1) break; | 
|  | } | 
|  | __ms_va_end( list ); | 
|  | return ret; | 
|  | #else | 
|  | return LBER_ERROR; | 
|  | #endif | 
|  | } |