wsdapi: Add a trailing '\n' to a WARN() message.
[wine.git] / dlls / wldap32 / misc.c
blob9c421f947077ce89425df686c46e18c1ee5dca14
1 /*
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
25 #include <stdio.h>
26 #ifdef HAVE_LDAP_H
27 #include <ldap.h>
28 #endif
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winnls.h"
34 #include "winldap_private.h"
35 #include "wldap32.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
40 /***********************************************************************
41 * ldap_abandon (WLDAP32.@)
43 * Cancel an asynchronous operation.
45 * PARAMS
46 * ld [I] Pointer to an LDAP context.
47 * msgid [I] ID of the operation to cancel.
49 * RETURNS
50 * Success: LDAP_SUCCESS
51 * Failure: An LDAP error code.
53 ULONG CDECL WLDAP32_ldap_abandon( WLDAP32_LDAP *ld, ULONG msgid )
55 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
56 #ifdef HAVE_LDAP
58 TRACE( "(%p, 0x%08x)\n", ld, msgid );
60 if (!ld) return ~0u;
61 ret = map_error( ldap_abandon_ext( ld, msgid, NULL, NULL ));
63 #endif
64 return ret;
67 /***********************************************************************
68 * ldap_check_filterA (WLDAP32.@)
70 * See ldap_check_filterW.
72 ULONG CDECL ldap_check_filterA( WLDAP32_LDAP *ld, PCHAR filter )
74 ULONG ret;
75 WCHAR *filterW = NULL;
77 TRACE( "(%p, %s)\n", ld, debugstr_a(filter) );
79 if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
81 if (filter) {
82 filterW = strAtoW( filter );
83 if (!filterW) return WLDAP32_LDAP_NO_MEMORY;
86 ret = ldap_check_filterW( ld, filterW );
88 strfreeW( filterW );
89 return ret;
92 /***********************************************************************
93 * ldap_check_filterW (WLDAP32.@)
95 * Check filter syntax.
97 * PARAMS
98 * ld [I] Pointer to an LDAP context.
99 * filter [I] Filter string.
101 * RETURNS
102 * Success: LDAP_SUCCESS
103 * Failure: An LDAP error code.
105 ULONG CDECL ldap_check_filterW( WLDAP32_LDAP *ld, PWCHAR filter )
107 TRACE( "(%p, %s)\n", ld, debugstr_w(filter) );
109 if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
110 return WLDAP32_LDAP_SUCCESS; /* FIXME: do some checks */
113 /***********************************************************************
114 * ldap_cleanup (WLDAP32.@)
116 ULONG CDECL ldap_cleanup( HANDLE instance )
118 TRACE( "(%p)\n", instance );
119 return WLDAP32_LDAP_SUCCESS;
122 /***********************************************************************
123 * ldap_conn_from_msg (WLDAP32.@)
125 * Get the LDAP context for a given message.
127 * PARAMS
128 * ld [I] Pointer to an LDAP context.
129 * res [I] LDAP message.
131 * RETURNS
132 * Success: Pointer to an LDAP context.
133 * Failure: NULL
135 WLDAP32_LDAP * CDECL ldap_conn_from_msg( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *res )
137 TRACE( "(%p, %p)\n", ld, res );
139 if (!ld || !res) return NULL;
140 return ld; /* FIXME: not always correct */
143 /***********************************************************************
144 * ldap_count_entries (WLDAP32.@)
146 * Count the number of entries returned from a search.
148 * PARAMS
149 * ld [I] Pointer to an LDAP context.
150 * res [I] LDAP message.
152 * RETURNS
153 * Success: The number of entries.
154 * Failure: ~0u
156 ULONG CDECL WLDAP32_ldap_count_entries( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *res )
158 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
159 #ifdef HAVE_LDAP
161 TRACE( "(%p, %p)\n", ld, res );
163 if (!ld) return ~0u;
164 ret = ldap_count_entries( ld, res );
166 #endif
167 return ret;
170 /***********************************************************************
171 * ldap_count_references (WLDAP32.@)
173 * Count the number of references returned from a search.
175 * PARAMS
176 * ld [I] Pointer to an LDAP context.
177 * res [I] LDAP message.
179 * RETURNS
180 * Success: The number of references.
181 * Failure: ~0u
183 ULONG CDECL WLDAP32_ldap_count_references( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *res )
185 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
186 #ifdef HAVE_LDAP_COUNT_REFERENCES
188 TRACE( "(%p, %p)\n", ld, res );
190 if (!ld) return 0;
191 ret = ldap_count_references( ld, res );
193 #endif
194 return ret;
197 static ULONG get_escape_size( PCHAR src, ULONG srclen )
199 ULONG i, size = 0;
201 if (src)
203 for (i = 0; i < srclen; i++)
205 if ((src[i] >= '0' && src[i] <= '9') ||
206 (src[i] >= 'A' && src[i] <= 'Z') ||
207 (src[i] >= 'a' && src[i] <= 'z'))
208 size++;
209 else
210 size += 3;
213 return size + 1;
216 static void escape_filter_element( PCHAR src, ULONG srclen, PCHAR dst )
218 ULONG i;
219 static const char fmt[] = "\\%02X";
220 char *d = dst;
222 for (i = 0; i < srclen; i++)
224 if ((src[i] >= '0' && src[i] <= '9') ||
225 (src[i] >= 'A' && src[i] <= 'Z') ||
226 (src[i] >= 'a' && src[i] <= 'z'))
227 *d++ = src[i];
228 else
229 d += sprintf( d, fmt, (unsigned char)src[i] );
231 *++d = 0;
234 /***********************************************************************
235 * ldap_escape_filter_elementA (WLDAP32.@)
237 * See ldap_escape_filter_elementW.
239 ULONG CDECL ldap_escape_filter_elementA( PCHAR src, ULONG srclen, PCHAR dst, ULONG dstlen )
241 ULONG len;
243 TRACE( "(%p, 0x%08x, %p, 0x%08x)\n", src, srclen, dst, dstlen );
245 len = get_escape_size( src, srclen );
246 if (!dst) return len;
248 if (!src || dstlen < len)
249 return WLDAP32_LDAP_PARAM_ERROR;
250 else
252 escape_filter_element( src, srclen, dst );
253 return WLDAP32_LDAP_SUCCESS;
257 /***********************************************************************
258 * ldap_escape_filter_elementW (WLDAP32.@)
260 * Escape binary data for safe passing in filters.
262 * PARAMS
263 * src [I] Filter element to be escaped.
264 * srclen [I] Length in bytes of the filter element.
265 * dst [O] Destination buffer for the escaped filter element.
266 * dstlen [I] Length in bytes of the destination buffer.
268 * RETURNS
269 * Success: LDAP_SUCCESS
270 * Failure: An LDAP error code.
272 ULONG CDECL ldap_escape_filter_elementW( PCHAR src, ULONG srclen, PWCHAR dst, ULONG dstlen )
274 ULONG len;
276 TRACE( "(%p, 0x%08x, %p, 0x%08x)\n", src, srclen, dst, dstlen );
278 len = get_escape_size( src, srclen );
279 if (!dst) return len;
281 /* no matter what you throw at it, this is what native returns */
282 return WLDAP32_LDAP_PARAM_ERROR;
285 /***********************************************************************
286 * ldap_first_attributeA (WLDAP32.@)
288 * See ldap_first_attributeW.
290 PCHAR CDECL ldap_first_attributeA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry,
291 WLDAP32_BerElement** ptr )
293 PCHAR ret = NULL;
294 #ifdef HAVE_LDAP
295 WCHAR *retW;
297 TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
299 if (!ld || !entry) return NULL;
300 retW = ldap_first_attributeW( ld, entry, ptr );
302 ret = strWtoA( retW );
303 ldap_memfreeW( retW );
305 #endif
306 return ret;
309 /***********************************************************************
310 * ldap_first_attributeW (WLDAP32.@)
312 * Get the first attribute for a given entry.
314 * PARAMS
315 * ld [I] Pointer to an LDAP context.
316 * entry [I] Entry to retrieve attribute for.
317 * ptr [O] Position pointer.
319 * RETURNS
320 * Success: Name of the first attribute.
321 * Failure: NULL
323 * NOTES
324 * Use ldap_memfree to free the returned string.
326 PWCHAR CDECL ldap_first_attributeW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry,
327 WLDAP32_BerElement** ptr )
329 PWCHAR ret = NULL;
330 #ifdef HAVE_LDAP
331 char *retU;
333 TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
335 if (!ld || !entry) return NULL;
336 retU = ldap_first_attribute( ld, entry, ptr );
338 ret = strUtoW( retU );
339 ldap_memfree( retU );
341 #endif
342 return ret;
345 /***********************************************************************
346 * ldap_first_entry (WLDAP32.@)
348 * Get the first entry from a result message.
350 * PARAMS
351 * ld [I] Pointer to an LDAP context.
352 * res [I] Search result message.
354 * RETURNS
355 * Success: The first entry.
356 * Failure: NULL
358 * NOTES
359 * The returned entry will be freed when the message is freed.
361 WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_first_entry( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *res )
363 #ifdef HAVE_LDAP
365 TRACE( "(%p, %p)\n", ld, res );
367 if (!ld || !res) return NULL;
368 return ldap_first_entry( ld, res );
370 #else
371 return NULL;
372 #endif
375 /***********************************************************************
376 * ldap_first_reference (WLDAP32.@)
378 * Get the first reference from a result message.
380 * PARAMS
381 * ld [I] Pointer to an LDAP context.
382 * res [I] Search result message.
384 * RETURNS
385 * Success: The first reference.
386 * Failure: NULL
388 WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_first_reference( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *res )
390 #ifdef HAVE_LDAP_FIRST_REFERENCE
392 TRACE( "(%p, %p)\n", ld, res );
394 if (!ld) return NULL;
395 return ldap_first_reference( ld, res );
397 #else
398 return NULL;
399 #endif
402 /***********************************************************************
403 * ldap_memfreeA (WLDAP32.@)
405 * See ldap_memfreeW.
407 void CDECL ldap_memfreeA( PCHAR block )
409 TRACE( "(%p)\n", block );
410 strfreeA( block );
413 /***********************************************************************
414 * ldap_memfreeW (WLDAP32.@)
416 * Free a block of memory.
418 * PARAMS
419 * block [I] Pointer to memory block to be freed.
421 void CDECL ldap_memfreeW( PWCHAR block )
423 TRACE( "(%p)\n", block );
424 strfreeW( block );
427 /***********************************************************************
428 * ldap_msgfree (WLDAP32.@)
430 * Free a message.
432 * PARAMS
433 * res [I] Message to be freed.
435 ULONG CDECL WLDAP32_ldap_msgfree( WLDAP32_LDAPMessage *res )
437 ULONG ret = WLDAP32_LDAP_SUCCESS;
438 #ifdef HAVE_LDAP
440 TRACE( "(%p)\n", res );
441 ldap_msgfree( res );
443 #endif
444 return ret;
447 /***********************************************************************
448 * ldap_next_attributeA (WLDAP32.@)
450 * See ldap_next_attributeW.
452 PCHAR CDECL ldap_next_attributeA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry,
453 WLDAP32_BerElement *ptr )
455 PCHAR ret = NULL;
456 #ifdef HAVE_LDAP
457 WCHAR *retW;
459 TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
461 if (!ld || !entry || !ptr) return NULL;
462 retW = ldap_next_attributeW( ld, entry, ptr );
464 ret = strWtoA( retW );
465 ldap_memfreeW( retW );
467 #endif
468 return ret;
471 /***********************************************************************
472 * ldap_next_attributeW (WLDAP32.@)
474 * Get the next attribute for a given entry.
476 * PARAMS
477 * ld [I] Pointer to an LDAP context.
478 * entry [I] Entry to retrieve attribute for.
479 * ptr [I/O] Position pointer.
481 * RETURNS
482 * Success: The name of the next attribute.
483 * Failure: NULL
485 * NOTES
486 * Free the returned string after each iteration with ldap_memfree.
487 * When done iterating and when ptr != NULL, call ber_free( ptr, 0 ).
489 PWCHAR CDECL ldap_next_attributeW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry,
490 WLDAP32_BerElement *ptr )
492 PWCHAR ret = NULL;
493 #ifdef HAVE_LDAP
494 char *retU;
496 TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
498 if (!ld || !entry || !ptr) return NULL;
499 retU = ldap_next_attribute( ld, entry, ptr );
501 ret = strUtoW( retU );
502 ldap_memfree( retU );
504 #endif
505 return ret;
508 /***********************************************************************
509 * ldap_next_entry (WLDAP32.@)
511 * Get the next entry from a result message.
513 * PARAMS
514 * ld [I] Pointer to an LDAP context.
515 * entry [I] Entry returned by a previous call.
517 * RETURNS
518 * Success: The next entry.
519 * Failure: NULL
521 * NOTES
522 * The returned entry will be freed when the message is freed.
524 WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_next_entry( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry )
526 #ifdef HAVE_LDAP
528 TRACE( "(%p, %p)\n", ld, entry );
530 if (!ld || !entry) return NULL;
531 return ldap_next_entry( ld, entry );
533 #else
534 return NULL;
535 #endif
538 /***********************************************************************
539 * ldap_next_reference (WLDAP32.@)
541 * Get the next reference from a result message.
543 * PARAMS
544 * ld [I] Pointer to an LDAP context.
545 * entry [I] Entry returned by a previous call.
547 * RETURNS
548 * Success: The next reference.
549 * Failure: NULL
551 * NOTES
552 * The returned entry will be freed when the message is freed.
554 WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_next_reference( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry )
556 #ifdef HAVE_LDAP_NEXT_REFERENCE
558 TRACE( "(%p, %p)\n", ld, entry );
560 if (!ld || !entry) return NULL;
561 return ldap_next_reference( ld, entry );
563 #else
564 return NULL;
565 #endif
568 /***********************************************************************
569 * ldap_result (WLDAP32.@)
571 * Get the result of an asynchronous operation.
573 * PARAMS
574 * ld [I] Pointer to an LDAP context.
575 * msgid [I] Message ID of the operation.
576 * all [I] How many results should be returned?
577 * timeout [I] How long to wait for the results?
578 * res [O] Result message for the operation.
580 * RETURNS
581 * Success: One of the following values:
583 * LDAP_RES_ADD
584 * LDAP_RES_BIND
585 * LDAP_RES_COMPARE
586 * LDAP_RES_DELETE
587 * LDAP_RES_EXTENDED
588 * LDAP_RES_MODIFY
589 * LDAP_RES_MODRDN
590 * LDAP_RES_REFERRAL
591 * LDAP_RES_SEARCH_ENTRY
592 * LDAP_RES_SEARCH_RESULT
594 * Failure: ~0u
596 * This function returns 0 when the timeout has expired.
598 * NOTES
599 * A NULL timeout pointer causes the function to block waiting
600 * for results to arrive. A timeout value of 0 causes the function
601 * to immediately return any available results. Free returned results
602 * with ldap_msgfree.
604 ULONG CDECL WLDAP32_ldap_result( WLDAP32_LDAP *ld, ULONG msgid, ULONG all,
605 struct l_timeval *timeout, WLDAP32_LDAPMessage **res )
607 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
608 #ifdef HAVE_LDAP
610 TRACE( "(%p, 0x%08x, 0x%08x, %p, %p)\n", ld, msgid, all, timeout, res );
612 if (!ld || !res || msgid == ~0u) return ~0u;
613 ret = ldap_result( ld, msgid, all, (struct timeval *)timeout, res );
615 #endif
616 return ret;
619 /***********************************************************************
620 * LdapUnicodeToUTF8 (WLDAP32.@)
622 * Convert a wide character string to a UTF8 string.
624 * PARAMS
625 * src [I] Wide character string to convert.
626 * srclen [I] Size of string to convert, in characters.
627 * dst [O] Pointer to a buffer that receives the converted string.
628 * dstlen [I] Size of the destination buffer in characters.
630 * RETURNS
631 * The number of characters written into the destination buffer.
633 * NOTES
634 * Set dstlen to zero to ask for the required buffer size.
636 int CDECL LdapUnicodeToUTF8( LPCWSTR src, int srclen, LPSTR dst, int dstlen )
638 return WideCharToMultiByte( CP_UTF8, 0, src, srclen, dst, dstlen, NULL, NULL );
641 /***********************************************************************
642 * LdapUTF8ToUnicode (WLDAP32.@)
644 * Convert a UTF8 string to a wide character string.
646 * PARAMS
647 * src [I] UTF8 string to convert.
648 * srclen [I] Size of string to convert, in characters.
649 * dst [O] Pointer to a buffer that receives the converted string.
650 * dstlen [I] Size of the destination buffer in characters.
652 * RETURNS
653 * The number of characters written into the destination buffer.
655 * NOTES
656 * Set dstlen to zero to ask for the required buffer size.
658 int CDECL LdapUTF8ToUnicode( LPCSTR src, int srclen, LPWSTR dst, int dstlen )
660 return MultiByteToWideChar( CP_UTF8, 0, src, srclen, dst, dstlen );