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
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.
39 * ld [I] Pointer to an LDAP context.
40 * msgid [I] ID of the operation to cancel.
43 * Success: LDAP_SUCCESS
44 * Failure: An LDAP error code.
46 ULONG CDECL
ldap_abandon( LDAP
*ld
, ULONG msgid
)
48 TRACE( "(%p, %#lx)\n", ld
, msgid
);
53 struct ldap_abandon_ext_params params
= { CTX(ld
), msgid
};
54 return map_error( LDAP_CALL( ldap_abandon_ext
, ¶ms
));
58 /***********************************************************************
59 * ldap_check_filterA (WLDAP32.@)
61 * See ldap_check_filterW.
63 ULONG CDECL
ldap_check_filterA( LDAP
*ld
, char *filter
)
66 WCHAR
*filterW
= NULL
;
68 TRACE( "(%p, %s)\n", ld
, debugstr_a(filter
) );
70 if (!ld
) return LDAP_PARAM_ERROR
;
71 if (filter
&& !(filterW
= strAtoW( filter
))) return LDAP_NO_MEMORY
;
73 ret
= ldap_check_filterW( ld
, filterW
);
79 /***********************************************************************
80 * ldap_check_filterW (WLDAP32.@)
82 * Check filter syntax.
85 * ld [I] Pointer to an LDAP context.
86 * filter [I] Filter string.
89 * Success: LDAP_SUCCESS
90 * Failure: An LDAP error code.
92 ULONG CDECL
ldap_check_filterW( LDAP
*ld
, WCHAR
*filter
)
94 TRACE( "(%p, %s)\n", ld
, debugstr_w(filter
) );
96 if (!ld
) return LDAP_PARAM_ERROR
;
97 return LDAP_SUCCESS
; /* FIXME: do some checks */
100 /***********************************************************************
101 * ldap_cleanup (WLDAP32.@)
103 ULONG CDECL
ldap_cleanup( HANDLE instance
)
105 TRACE( "(%p)\n", instance
);
109 /***********************************************************************
110 * ldap_conn_from_msg (WLDAP32.@)
112 * Get the LDAP context for a given message.
115 * ld [I] Pointer to an LDAP context.
116 * res [I] LDAP message.
119 * Success: Pointer to an LDAP context.
122 LDAP
* CDECL
ldap_conn_from_msg( LDAP
*ld
, LDAPMessage
*res
)
124 TRACE( "(%p, %p)\n", ld
, res
);
126 if (!ld
|| !res
) return NULL
;
127 return ld
; /* FIXME: not always correct */
130 /***********************************************************************
131 * ldap_count_entries (WLDAP32.@)
133 * Count the number of entries returned from a search.
136 * ld [I] Pointer to an LDAP context.
137 * res [I] LDAP message.
140 * Success: The number of entries.
143 ULONG CDECL
ldap_count_entries( LDAP
*ld
, LDAPMessage
*res
)
145 TRACE( "(%p, %p)\n", ld
, res
);
150 struct ldap_count_entries_params params
= { CTX(ld
), MSG(res
) };
151 return LDAP_CALL( ldap_count_entries
, ¶ms
);
155 /***********************************************************************
156 * ldap_count_references (WLDAP32.@)
158 * Count the number of references returned from a search.
161 * ld [I] Pointer to an LDAP context.
162 * res [I] LDAP message.
165 * Success: The number of references.
168 ULONG CDECL
ldap_count_references( LDAP
*ld
, LDAPMessage
*res
)
170 TRACE( "(%p, %p)\n", ld
, res
);
175 struct ldap_count_references_params params
= { CTX(ld
), MSG(res
) };
176 return LDAP_CALL( ldap_count_references
, ¶ms
);
180 static ULONG
get_escape_size( PCHAR src
, ULONG srclen
)
186 for (i
= 0; i
< srclen
; i
++)
188 if ((src
[i
] >= '0' && src
[i
] <= '9') ||
189 (src
[i
] >= 'A' && src
[i
] <= 'Z') ||
190 (src
[i
] >= 'a' && src
[i
] <= 'z'))
199 static void escape_filter_element( char *src
, ULONG srclen
, char *dst
)
202 static const char fmt
[] = "\\%02X";
205 for (i
= 0; i
< srclen
; i
++)
207 if ((src
[i
] >= '0' && src
[i
] <= '9') ||
208 (src
[i
] >= 'A' && src
[i
] <= 'Z') ||
209 (src
[i
] >= 'a' && src
[i
] <= 'z'))
212 d
+= sprintf( d
, fmt
, (unsigned char)src
[i
] );
217 /***********************************************************************
218 * ldap_escape_filter_elementA (WLDAP32.@)
220 * See ldap_escape_filter_elementW.
222 ULONG CDECL
ldap_escape_filter_elementA( char *src
, ULONG srclen
, char *dst
, ULONG dstlen
)
224 ULONG len
= get_escape_size( src
, srclen
);
226 TRACE( "(%p, %#lx, %p, %#lx)\n", src
, srclen
, dst
, dstlen
);
228 if (!dst
) return len
;
229 if (!src
|| dstlen
< len
) return LDAP_PARAM_ERROR
;
231 escape_filter_element( src
, srclen
, dst
);
235 /***********************************************************************
236 * ldap_escape_filter_elementW (WLDAP32.@)
238 * Escape binary data for safe passing in filters.
241 * src [I] Filter element to be escaped.
242 * srclen [I] Length in bytes of the filter element.
243 * dst [O] Destination buffer for the escaped filter element.
244 * dstlen [I] Length in bytes of the destination buffer.
247 * Success: LDAP_SUCCESS
248 * Failure: An LDAP error code.
250 ULONG CDECL
ldap_escape_filter_elementW( char *src
, ULONG srclen
, WCHAR
*dst
, ULONG dstlen
)
252 ULONG len
= get_escape_size( src
, srclen
);
254 TRACE( "(%p, %#lx, %p, %#lx)\n", src
, srclen
, dst
, dstlen
);
256 if (!dst
) return len
;
258 /* no matter what you throw at it, this is what native returns */
259 return LDAP_PARAM_ERROR
;
262 /***********************************************************************
263 * ldap_first_attributeA (WLDAP32.@)
265 * See ldap_first_attributeW.
267 char * CDECL
ldap_first_attributeA( LDAP
*ld
, LDAPMessage
*entry
, BerElement
**ber
)
272 TRACE( "(%p, %p, %p)\n", ld
, entry
, ber
);
274 if (!ld
|| !entry
) return NULL
;
276 retW
= ldap_first_attributeW( ld
, entry
, ber
);
279 ret
= strWtoA( retW
);
280 ldap_memfreeW( retW
);
286 /***********************************************************************
287 * ldap_first_attributeW (WLDAP32.@)
289 * Get the first attribute for a given entry.
292 * ld [I] Pointer to an LDAP context.
293 * entry [I] Entry to retrieve attribute for.
294 * ptr [O] Position pointer.
297 * Success: Name of the first attribute.
301 * Use ldap_memfree to free the returned string.
303 WCHAR
* CDECL
ldap_first_attributeW( LDAP
*ld
, LDAPMessage
*entry
, BerElement
**ptr
)
310 TRACE( "(%p, %p, %p)\n", ld
, entry
, ptr
);
314 struct ldap_first_attribute_params params
= { CTX(ld
), MSG(entry
), &berU
, &retU
};
315 LDAP_CALL( ldap_first_attribute
, ¶ms
);
319 if (retU
&& (ber
= malloc( sizeof(*ber
) )))
321 BER(ber
) = (char *)berU
;
323 ret
= strUtoW( retU
);
326 LDAP_CALL( ldap_memfree
, retU
);
330 /***********************************************************************
331 * ldap_first_entry (WLDAP32.@)
333 * Get the first entry from a result message.
336 * ld [I] Pointer to an LDAP context.
337 * res [I] Search result message.
340 * Success: The first entry.
344 * The returned entry will be freed when the message is freed.
346 LDAPMessage
* CDECL
ldap_first_entry( LDAP
*ld
, LDAPMessage
*res
)
350 TRACE( "(%p, %p)\n", ld
, res
);
354 struct ldap_first_entry_params params
= { CTX(ld
), MSG(res
), &msgU
};
355 if (!LDAP_CALL( ldap_first_entry
, ¶ms
))
357 assert( msgU
== MSG(res
) );
364 /***********************************************************************
365 * ldap_first_reference (WLDAP32.@)
367 * Get the first reference from a result message.
370 * ld [I] Pointer to an LDAP context.
371 * res [I] Search result message.
374 * Success: The first reference.
377 LDAPMessage
* CDECL
ldap_first_reference( LDAP
*ld
, LDAPMessage
*res
)
381 TRACE( "(%p, %p)\n", ld
, res
);
385 struct ldap_first_reference_params params
= { CTX(ld
), MSG(res
), &msgU
};
386 if (!LDAP_CALL( ldap_first_reference
, ¶ms
))
388 assert( msgU
== MSG(res
) );
395 /***********************************************************************
396 * ldap_memfreeA (WLDAP32.@)
400 void CDECL
ldap_memfreeA( char *block
)
402 TRACE( "(%p)\n", block
);
406 /***********************************************************************
407 * ldap_memfreeW (WLDAP32.@)
409 * Free a block of memory.
412 * block [I] Pointer to memory block to be freed.
414 void CDECL
ldap_memfreeW( WCHAR
*block
)
416 TRACE( "(%p)\n", block
);
420 /***********************************************************************
421 * ldap_msgfree (WLDAP32.@)
426 * res [I] Message to be freed.
428 ULONG CDECL
ldap_msgfree( LDAPMessage
*res
)
430 LDAPMessage
*entry
, *list
= res
;
432 TRACE( "(%p)\n", res
);
434 if (!res
) return LDAP_SUCCESS
;
436 LDAP_CALL( ldap_msgfree
, MSG(res
) );
440 list
= entry
->lm_next
;
447 /***********************************************************************
448 * ldap_next_attributeA (WLDAP32.@)
450 * See ldap_next_attributeW.
452 char * CDECL
ldap_next_attributeA( LDAP
*ld
, LDAPMessage
*entry
, BerElement
*ptr
)
457 TRACE( "(%p, %p, %p)\n", ld
, entry
, ptr
);
459 if (!ld
|| !entry
|| !ptr
) return NULL
;
461 retW
= ldap_next_attributeW( ld
, entry
, ptr
);
464 ret
= strWtoA( retW
);
465 ldap_memfreeW( retW
);
471 /***********************************************************************
472 * ldap_next_attributeW (WLDAP32.@)
474 * Get the next attribute for a given entry.
477 * ld [I] Pointer to an LDAP context.
478 * entry [I] Entry to retrieve attribute for.
479 * ptr [I/O] Position pointer.
482 * Success: The name of the next attribute.
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 WCHAR
* CDECL
ldap_next_attributeW( LDAP
*ld
, LDAPMessage
*entry
, BerElement
*ptr
)
494 TRACE( "(%p, %p, %p)\n", ld
, entry
, ptr
);
496 if (ld
&& entry
&& ptr
)
498 struct ldap_next_attribute_params params
= { CTX(ld
), MSG(entry
), BER(ptr
), &retU
};
499 if (!LDAP_CALL( ldap_next_attribute
, ¶ms
))
501 ret
= strUtoW( retU
);
502 LDAP_CALL( ldap_memfree
, retU
);
508 /***********************************************************************
509 * ldap_next_entry (WLDAP32.@)
511 * Get the next entry from a result message.
514 * ld [I] Pointer to an LDAP context.
515 * entry [I] Entry returned by a previous call.
518 * Success: The next entry.
522 * The returned entry will be freed when the message is freed.
524 LDAPMessage
* CDECL
ldap_next_entry( LDAP
*ld
, LDAPMessage
*entry
)
526 LDAPMessage
*msg
= NULL
;
529 TRACE( "(%p, %p)\n", ld
, entry
);
531 if (!ld
|| !entry
) return NULL
;
533 if (entry
->lm_next
) return entry
->lm_next
;
536 struct ldap_next_entry_params params
= { CTX(ld
), MSG(entry
), &msgU
};
537 LDAP_CALL( ldap_next_entry
, ¶ms
);
540 if (msgU
&& (msg
= calloc( 1, sizeof(*msg
) )))
543 entry
->lm_next
= msg
;
549 /***********************************************************************
550 * ldap_next_reference (WLDAP32.@)
552 * Get the next reference from a result message.
555 * ld [I] Pointer to an LDAP context.
556 * entry [I] Entry returned by a previous call.
559 * Success: The next reference.
563 * The returned entry will be freed when the message is freed.
565 LDAPMessage
* CDECL
ldap_next_reference( LDAP
*ld
, LDAPMessage
*entry
)
567 LDAPMessage
*msg
= NULL
;
570 TRACE( "(%p, %p)\n", ld
, entry
);
572 if (!ld
|| !entry
) return NULL
;
574 if (entry
->lm_next
) return entry
->lm_next
;
577 struct ldap_next_reference_params params
= { CTX(ld
), MSG(entry
), &msgU
};
578 LDAP_CALL( ldap_next_reference
, ¶ms
);
580 if (msgU
&& (msg
= calloc( 1, sizeof(*msg
) )))
583 entry
->lm_next
= msg
;
589 /***********************************************************************
590 * ldap_result (WLDAP32.@)
592 * Get the result of an asynchronous operation.
595 * ld [I] Pointer to an LDAP context.
596 * msgid [I] Message ID of the operation.
597 * all [I] How many results should be returned?
598 * timeout [I] How long to wait for the results?
599 * res [O] Result message for the operation.
602 * Success: One of the following values:
612 * LDAP_RES_SEARCH_ENTRY
613 * LDAP_RES_SEARCH_RESULT
617 * This function returns 0 when the timeout has expired.
620 * A NULL timeout pointer causes the function to block waiting
621 * for results to arrive. A timeout value of 0 causes the function
622 * to immediately return any available results. Free returned results
625 ULONG CDECL
ldap_result( LDAP
*ld
, ULONG msgid
, ULONG all
, struct l_timeval
*timeout
, LDAPMessage
**res
)
628 struct timevalU timeval
;
632 TRACE( "(%p, %#lx, %#lx, %p, %p)\n", ld
, msgid
, all
, timeout
, res
);
634 if (ld
&& res
&& msgid
!= ~0u)
636 struct ldap_result_params params
= { CTX(ld
), msgid
, all
, timeout
? &timeval
: NULL
, &msgU
};
640 timeval
.tv_sec
= timeout
->tv_sec
;
641 timeval
.tv_usec
= timeout
->tv_usec
;
644 ret
= LDAP_CALL( ldap_result
, ¶ms
);
646 if (msgU
&& (msg
= calloc( 1, sizeof(*msg
) )))
655 /***********************************************************************
656 * LdapUnicodeToUTF8 (WLDAP32.@)
658 * Convert a wide character string to a UTF8 string.
661 * src [I] Wide character string to convert.
662 * srclen [I] Size of string to convert, in characters.
663 * dst [O] Pointer to a buffer that receives the converted string.
664 * dstlen [I] Size of the destination buffer in characters.
667 * The number of characters written into the destination buffer.
670 * Set dstlen to zero to ask for the required buffer size.
672 int CDECL
LdapUnicodeToUTF8( const WCHAR
*src
, int srclen
, char *dst
, int dstlen
)
674 return WideCharToMultiByte( CP_UTF8
, 0, src
, srclen
, dst
, dstlen
, NULL
, NULL
);
677 /***********************************************************************
678 * LdapUTF8ToUnicode (WLDAP32.@)
680 * Convert a UTF8 string to a wide character string.
683 * src [I] UTF8 string to convert.
684 * srclen [I] Size of string to convert, in characters.
685 * dst [O] Pointer to a buffer that receives the converted string.
686 * dstlen [I] Size of the destination buffer in characters.
689 * The number of characters written into the destination buffer.
692 * Set dstlen to zero to ask for the required buffer size.
694 int CDECL
LdapUTF8ToUnicode( const char *src
, int srclen
, WCHAR
*dst
, int dstlen
)
696 return MultiByteToWideChar( CP_UTF8
, 0, src
, srclen
, dst
, dstlen
);