| /* | |
| * 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 | |
| } |