winspool/tests: Add tests for GetFormA().
[wine.git] / dlls / wldap32 / misc.c
blobdbda4609ff2f2e94bee59bbefd0cc755b69921ee
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 <stdarg.h>
22 #include <stdlib.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winnls.h"
26 #include "winldap.h"
28 #include "wine/debug.h"
29 #include "winldap_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
33 /***********************************************************************
34 * ldap_abandon (WLDAP32.@)
36 * Cancel an asynchronous operation.
38 * PARAMS
39 * ld [I] Pointer to an LDAP context.
40 * msgid [I] ID of the operation to cancel.
42 * RETURNS
43 * Success: LDAP_SUCCESS
44 * Failure: An LDAP error code.
46 ULONG CDECL ldap_abandon( LDAP *ld, ULONG msgid )
48 TRACE( "(%p, 0x%08x)\n", ld, msgid );
50 if (!ld) return ~0u;
51 return map_error( ldap_funcs->fn_ldap_abandon_ext( CTX(ld), msgid, NULL, NULL ) );
54 /***********************************************************************
55 * ldap_check_filterA (WLDAP32.@)
57 * See ldap_check_filterW.
59 ULONG CDECL ldap_check_filterA( LDAP *ld, char *filter )
61 ULONG ret;
62 WCHAR *filterW = NULL;
64 TRACE( "(%p, %s)\n", ld, debugstr_a(filter) );
66 if (!ld) return LDAP_PARAM_ERROR;
67 if (filter && !(filterW = strAtoW( filter ))) return LDAP_NO_MEMORY;
69 ret = ldap_check_filterW( ld, filterW );
71 free( filterW );
72 return ret;
75 /***********************************************************************
76 * ldap_check_filterW (WLDAP32.@)
78 * Check filter syntax.
80 * PARAMS
81 * ld [I] Pointer to an LDAP context.
82 * filter [I] Filter string.
84 * RETURNS
85 * Success: LDAP_SUCCESS
86 * Failure: An LDAP error code.
88 ULONG CDECL ldap_check_filterW( LDAP *ld, WCHAR *filter )
90 TRACE( "(%p, %s)\n", ld, debugstr_w(filter) );
92 if (!ld) return LDAP_PARAM_ERROR;
93 return LDAP_SUCCESS; /* FIXME: do some checks */
96 /***********************************************************************
97 * ldap_cleanup (WLDAP32.@)
99 ULONG CDECL ldap_cleanup( HANDLE instance )
101 TRACE( "(%p)\n", instance );
102 return LDAP_SUCCESS;
105 /***********************************************************************
106 * ldap_conn_from_msg (WLDAP32.@)
108 * Get the LDAP context for a given message.
110 * PARAMS
111 * ld [I] Pointer to an LDAP context.
112 * res [I] LDAP message.
114 * RETURNS
115 * Success: Pointer to an LDAP context.
116 * Failure: NULL
118 LDAP * CDECL ldap_conn_from_msg( LDAP *ld, LDAPMessage *res )
120 TRACE( "(%p, %p)\n", ld, res );
122 if (!ld || !res) return NULL;
123 return ld; /* FIXME: not always correct */
126 /***********************************************************************
127 * ldap_count_entries (WLDAP32.@)
129 * Count the number of entries returned from a search.
131 * PARAMS
132 * ld [I] Pointer to an LDAP context.
133 * res [I] LDAP message.
135 * RETURNS
136 * Success: The number of entries.
137 * Failure: ~0u
139 ULONG CDECL ldap_count_entries( LDAP *ld, LDAPMessage *res )
141 TRACE( "(%p, %p)\n", ld, res );
143 if (!ld) return ~0u;
144 return ldap_funcs->fn_ldap_count_entries( CTX(ld), MSG(res) );
147 /***********************************************************************
148 * ldap_count_references (WLDAP32.@)
150 * Count the number of references returned from a search.
152 * PARAMS
153 * ld [I] Pointer to an LDAP context.
154 * res [I] LDAP message.
156 * RETURNS
157 * Success: The number of references.
158 * Failure: ~0u
160 ULONG CDECL ldap_count_references( LDAP *ld, LDAPMessage *res )
162 TRACE( "(%p, %p)\n", ld, res );
164 if (!ld) return 0;
165 return ldap_funcs->fn_ldap_count_references( CTX(ld), MSG(res) );
168 static ULONG get_escape_size( PCHAR src, ULONG srclen )
170 ULONG i, size = 0;
172 if (src)
174 for (i = 0; i < srclen; i++)
176 if ((src[i] >= '0' && src[i] <= '9') ||
177 (src[i] >= 'A' && src[i] <= 'Z') ||
178 (src[i] >= 'a' && src[i] <= 'z'))
179 size++;
180 else
181 size += 3;
184 return size + 1;
187 static void escape_filter_element( char *src, ULONG srclen, char *dst )
189 ULONG i;
190 static const char fmt[] = "\\%02X";
191 char *d = dst;
193 for (i = 0; i < srclen; i++)
195 if ((src[i] >= '0' && src[i] <= '9') ||
196 (src[i] >= 'A' && src[i] <= 'Z') ||
197 (src[i] >= 'a' && src[i] <= 'z'))
198 *d++ = src[i];
199 else
200 d += sprintf( d, fmt, (unsigned char)src[i] );
202 *++d = 0;
205 /***********************************************************************
206 * ldap_escape_filter_elementA (WLDAP32.@)
208 * See ldap_escape_filter_elementW.
210 ULONG CDECL ldap_escape_filter_elementA( char *src, ULONG srclen, char *dst, ULONG dstlen )
212 ULONG len = get_escape_size( src, srclen );
214 TRACE( "(%p, 0x%08x, %p, 0x%08x)\n", src, srclen, dst, dstlen );
216 if (!dst) return len;
217 if (!src || dstlen < len) return LDAP_PARAM_ERROR;
219 escape_filter_element( src, srclen, dst );
220 return LDAP_SUCCESS;
223 /***********************************************************************
224 * ldap_escape_filter_elementW (WLDAP32.@)
226 * Escape binary data for safe passing in filters.
228 * PARAMS
229 * src [I] Filter element to be escaped.
230 * srclen [I] Length in bytes of the filter element.
231 * dst [O] Destination buffer for the escaped filter element.
232 * dstlen [I] Length in bytes of the destination buffer.
234 * RETURNS
235 * Success: LDAP_SUCCESS
236 * Failure: An LDAP error code.
238 ULONG CDECL ldap_escape_filter_elementW( char *src, ULONG srclen, WCHAR *dst, ULONG dstlen )
240 ULONG len = get_escape_size( src, srclen );
242 TRACE( "(%p, 0x%08x, %p, 0x%08x)\n", src, srclen, dst, dstlen );
244 if (!dst) return len;
246 /* no matter what you throw at it, this is what native returns */
247 return LDAP_PARAM_ERROR;
250 /***********************************************************************
251 * ldap_first_attributeA (WLDAP32.@)
253 * See ldap_first_attributeW.
255 char * CDECL ldap_first_attributeA( LDAP *ld, LDAPMessage *entry, BerElement **ber )
257 char *ret = NULL;
258 WCHAR *retW;
260 TRACE( "(%p, %p, %p)\n", ld, entry, ber );
262 if (!ld || !entry) return NULL;
264 retW = ldap_first_attributeW( ld, entry, ber );
265 if (retW)
267 ret = strWtoA( retW );
268 ldap_memfreeW( retW );
271 return ret;
274 /***********************************************************************
275 * ldap_first_attributeW (WLDAP32.@)
277 * Get the first attribute for a given entry.
279 * PARAMS
280 * ld [I] Pointer to an LDAP context.
281 * entry [I] Entry to retrieve attribute for.
282 * ptr [O] Position pointer.
284 * RETURNS
285 * Success: Name of the first attribute.
286 * Failure: NULL
288 * NOTES
289 * Use ldap_memfree to free the returned string.
291 WCHAR * CDECL ldap_first_attributeW( LDAP *ld, LDAPMessage *entry, BerElement **ptr )
293 WCHAR *ret = NULL;
294 BerElement *ber;
295 char *retU;
296 void *berU;
298 TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
300 if (!ld || !entry) return NULL;
302 retU = ldap_funcs->fn_ldap_first_attribute( CTX(ld), MSG(entry), &berU );
303 if (retU && (ber = malloc( sizeof(*ber) )))
305 BER(ber) = (char *)berU;
306 *ptr = ber;
307 ret = strUtoW( retU );
310 ldap_funcs->fn_ldap_memfree( retU );
311 return ret;
314 /***********************************************************************
315 * ldap_first_entry (WLDAP32.@)
317 * Get the first entry from a result message.
319 * PARAMS
320 * ld [I] Pointer to an LDAP context.
321 * res [I] Search result message.
323 * RETURNS
324 * Success: The first entry.
325 * Failure: NULL
327 * NOTES
328 * The returned entry will be freed when the message is freed.
330 LDAPMessage * CDECL ldap_first_entry( LDAP *ld, LDAPMessage *res )
332 void *msgU;
334 TRACE( "(%p, %p)\n", ld, res );
336 if (!ld || !res) return NULL;
338 msgU = ldap_funcs->fn_ldap_first_entry( CTX(ld), MSG(res) );
339 if (msgU)
341 assert( msgU == MSG(res) );
342 return res;
345 return NULL;
348 /***********************************************************************
349 * ldap_first_reference (WLDAP32.@)
351 * Get the first reference from a result message.
353 * PARAMS
354 * ld [I] Pointer to an LDAP context.
355 * res [I] Search result message.
357 * RETURNS
358 * Success: The first reference.
359 * Failure: NULL
361 LDAPMessage * CDECL ldap_first_reference( LDAP *ld, LDAPMessage *res )
363 void *msgU;
365 TRACE( "(%p, %p)\n", ld, res );
367 if (!ld) return NULL;
369 msgU = ldap_funcs->fn_ldap_first_reference( CTX(ld), MSG(res) );
370 if (msgU)
372 assert( msgU == MSG(res) );
373 return res;
376 return NULL;
379 /***********************************************************************
380 * ldap_memfreeA (WLDAP32.@)
382 * See ldap_memfreeW.
384 void CDECL ldap_memfreeA( char *block )
386 TRACE( "(%p)\n", block );
387 free( block );
390 /***********************************************************************
391 * ldap_memfreeW (WLDAP32.@)
393 * Free a block of memory.
395 * PARAMS
396 * block [I] Pointer to memory block to be freed.
398 void CDECL ldap_memfreeW( WCHAR *block )
400 TRACE( "(%p)\n", block );
401 free( block );
404 /***********************************************************************
405 * ldap_msgfree (WLDAP32.@)
407 * Free a message.
409 * PARAMS
410 * res [I] Message to be freed.
412 ULONG CDECL ldap_msgfree( LDAPMessage *res )
414 LDAPMessage *entry, *list = res;
416 TRACE( "(%p)\n", res );
418 if (!res) return LDAP_SUCCESS;
420 ldap_funcs->fn_ldap_msgfree( MSG(res) );
421 while (list)
423 entry = list;
424 list = entry->lm_next;
425 free( entry );
428 return LDAP_SUCCESS;
431 /***********************************************************************
432 * ldap_next_attributeA (WLDAP32.@)
434 * See ldap_next_attributeW.
436 char * CDECL ldap_next_attributeA( LDAP *ld, LDAPMessage *entry, BerElement *ptr )
438 char *ret = NULL;
439 WCHAR *retW;
441 TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
443 if (!ld || !entry || !ptr) return NULL;
445 retW = ldap_next_attributeW( ld, entry, ptr );
446 if (retW)
448 ret = strWtoA( retW );
449 ldap_memfreeW( retW );
452 return ret;
455 /***********************************************************************
456 * ldap_next_attributeW (WLDAP32.@)
458 * Get the next attribute for a given entry.
460 * PARAMS
461 * ld [I] Pointer to an LDAP context.
462 * entry [I] Entry to retrieve attribute for.
463 * ptr [I/O] Position pointer.
465 * RETURNS
466 * Success: The name of the next attribute.
467 * Failure: NULL
469 * NOTES
470 * Free the returned string after each iteration with ldap_memfree.
471 * When done iterating and when ptr != NULL, call ber_free( ptr, 0 ).
473 WCHAR * CDECL ldap_next_attributeW( LDAP *ld, LDAPMessage *entry, BerElement *ptr )
475 WCHAR *ret = NULL;
476 char *retU;
478 TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
480 if (!ld || !entry || !ptr) return NULL;
482 retU = ldap_funcs->fn_ldap_next_attribute( CTX(ld), MSG(entry), BER(ptr) );
483 if (retU)
485 ret = strUtoW( retU );
486 ldap_funcs->fn_ldap_memfree( retU );
489 return ret;
492 /***********************************************************************
493 * ldap_next_entry (WLDAP32.@)
495 * Get the next entry from a result message.
497 * PARAMS
498 * ld [I] Pointer to an LDAP context.
499 * entry [I] Entry returned by a previous call.
501 * RETURNS
502 * Success: The next entry.
503 * Failure: NULL
505 * NOTES
506 * The returned entry will be freed when the message is freed.
508 LDAPMessage * CDECL ldap_next_entry( LDAP *ld, LDAPMessage *entry )
510 LDAPMessage *msg = NULL;
511 void *msgU;
513 TRACE( "(%p, %p)\n", ld, entry );
515 if (!ld || !entry) return NULL;
517 if (entry->lm_next) return entry->lm_next;
519 msgU = ldap_funcs->fn_ldap_next_entry( CTX(ld), MSG(entry) );
520 if (msgU && (msg = calloc( 1, sizeof(*msg) )))
522 MSG(msg) = msgU;
523 entry->lm_next = msg;
526 return msg;
529 /***********************************************************************
530 * ldap_next_reference (WLDAP32.@)
532 * Get the next reference from a result message.
534 * PARAMS
535 * ld [I] Pointer to an LDAP context.
536 * entry [I] Entry returned by a previous call.
538 * RETURNS
539 * Success: The next reference.
540 * Failure: NULL
542 * NOTES
543 * The returned entry will be freed when the message is freed.
545 LDAPMessage * CDECL ldap_next_reference( LDAP *ld, LDAPMessage *entry )
547 LDAPMessage *msg = NULL;
548 void *msgU;
550 TRACE( "(%p, %p)\n", ld, entry );
552 if (!ld || !entry) return NULL;
554 if (entry->lm_next) return entry->lm_next;
556 msgU = ldap_funcs->fn_ldap_next_reference( CTX(ld), MSG(entry) );
557 if (msgU && (msg = calloc( 1, sizeof(*msg) )))
559 MSG(msg) = msgU;
560 entry->lm_next = msg;
563 return msg;
566 /***********************************************************************
567 * ldap_result (WLDAP32.@)
569 * Get the result of an asynchronous operation.
571 * PARAMS
572 * ld [I] Pointer to an LDAP context.
573 * msgid [I] Message ID of the operation.
574 * all [I] How many results should be returned?
575 * timeout [I] How long to wait for the results?
576 * res [O] Result message for the operation.
578 * RETURNS
579 * Success: One of the following values:
581 * LDAP_RES_ADD
582 * LDAP_RES_BIND
583 * LDAP_RES_COMPARE
584 * LDAP_RES_DELETE
585 * LDAP_RES_EXTENDED
586 * LDAP_RES_MODIFY
587 * LDAP_RES_MODRDN
588 * LDAP_RES_REFERRAL
589 * LDAP_RES_SEARCH_ENTRY
590 * LDAP_RES_SEARCH_RESULT
592 * Failure: ~0u
594 * This function returns 0 when the timeout has expired.
596 * NOTES
597 * A NULL timeout pointer causes the function to block waiting
598 * for results to arrive. A timeout value of 0 causes the function
599 * to immediately return any available results. Free returned results
600 * with ldap_msgfree.
602 ULONG CDECL ldap_result( LDAP *ld, ULONG msgid, ULONG all, struct l_timeval *timeout, LDAPMessage **res )
604 LDAPMessage *msg;
605 struct timevalU timeval;
606 void *msgU = NULL;
607 ULONG ret;
609 TRACE( "(%p, 0x%08x, 0x%08x, %p, %p)\n", ld, msgid, all, timeout, res );
611 if (!ld || !res || msgid == ~0u) return ~0u;
613 if (timeout)
615 timeval.tv_sec = timeout->tv_sec;
616 timeval.tv_usec = timeout->tv_usec;
619 ret = ldap_funcs->fn_ldap_result( CTX(ld), msgid, all, timeout ? &timeval : NULL, &msgU );
620 if (msgU && (msg = calloc( 1, sizeof(*msg) )))
622 MSG(msg) = msgU;
623 *res = msg;
626 return ret;
629 /***********************************************************************
630 * LdapUnicodeToUTF8 (WLDAP32.@)
632 * Convert a wide character string to a UTF8 string.
634 * PARAMS
635 * src [I] Wide character string to convert.
636 * srclen [I] Size of string to convert, in characters.
637 * dst [O] Pointer to a buffer that receives the converted string.
638 * dstlen [I] Size of the destination buffer in characters.
640 * RETURNS
641 * The number of characters written into the destination buffer.
643 * NOTES
644 * Set dstlen to zero to ask for the required buffer size.
646 int CDECL LdapUnicodeToUTF8( const WCHAR *src, int srclen, char *dst, int dstlen )
648 return WideCharToMultiByte( CP_UTF8, 0, src, srclen, dst, dstlen, NULL, NULL );
651 /***********************************************************************
652 * LdapUTF8ToUnicode (WLDAP32.@)
654 * Convert a UTF8 string to a wide character string.
656 * PARAMS
657 * src [I] UTF8 string to convert.
658 * srclen [I] Size of string to convert, in characters.
659 * dst [O] Pointer to a buffer that receives the converted string.
660 * dstlen [I] Size of the destination buffer in characters.
662 * RETURNS
663 * The number of characters written into the destination buffer.
665 * NOTES
666 * Set dstlen to zero to ask for the required buffer size.
668 int CDECL LdapUTF8ToUnicode( const char *src, int srclen, WCHAR *dst, int dstlen )
670 return MultiByteToWideChar( CP_UTF8, 0, src, srclen, dst, dstlen );