Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / dll / win32 / wldap32 / misc.c
1 /*
2 * WLDAP32 - LDAP support for Wine
3 *
4 * Copyright 2005 Hans Leidekker
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "winldap_private.h"
22
23 #include <stdio.h>
24
25 /***********************************************************************
26 * ldap_abandon (WLDAP32.@)
27 *
28 * Cancel an asynchronous operation.
29 *
30 * PARAMS
31 * ld [I] Pointer to an LDAP context.
32 * msgid [I] ID of the operation to cancel.
33 *
34 * RETURNS
35 * Success: LDAP_SUCCESS
36 * Failure: An LDAP error code.
37 */
38 ULONG CDECL WLDAP32_ldap_abandon( WLDAP32_LDAP *ld, ULONG msgid )
39 {
40 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
41 #ifdef HAVE_LDAP
42
43 TRACE( "(%p, 0x%08x)\n", ld, msgid );
44
45 if (!ld) return ~0u;
46 ret = map_error( ldap_abandon_ext( ld, msgid, NULL, NULL ));
47
48 #endif
49 return ret;
50 }
51
52 /***********************************************************************
53 * ldap_check_filterA (WLDAP32.@)
54 *
55 * See ldap_check_filterW.
56 */
57 ULONG CDECL ldap_check_filterA( WLDAP32_LDAP *ld, PCHAR filter )
58 {
59 ULONG ret;
60 WCHAR *filterW = NULL;
61
62 TRACE( "(%p, %s)\n", ld, debugstr_a(filter) );
63
64 if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
65
66 if (filter) {
67 filterW = strAtoW( filter );
68 if (!filterW) return WLDAP32_LDAP_NO_MEMORY;
69 }
70
71 ret = ldap_check_filterW( ld, filterW );
72
73 strfreeW( filterW );
74 return ret;
75 }
76
77 /***********************************************************************
78 * ldap_check_filterW (WLDAP32.@)
79 *
80 * Check filter syntax.
81 *
82 * PARAMS
83 * ld [I] Pointer to an LDAP context.
84 * filter [I] Filter string.
85 *
86 * RETURNS
87 * Success: LDAP_SUCCESS
88 * Failure: An LDAP error code.
89 */
90 ULONG CDECL ldap_check_filterW( WLDAP32_LDAP *ld, PWCHAR filter )
91 {
92 TRACE( "(%p, %s)\n", ld, debugstr_w(filter) );
93
94 if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
95 return WLDAP32_LDAP_SUCCESS; /* FIXME: do some checks */
96 }
97
98 /***********************************************************************
99 * ldap_cleanup (WLDAP32.@)
100 */
101 ULONG CDECL ldap_cleanup( HANDLE instance )
102 {
103 TRACE( "(%p)\n", instance );
104 return WLDAP32_LDAP_SUCCESS;
105 }
106
107 /***********************************************************************
108 * ldap_conn_from_msg (WLDAP32.@)
109 *
110 * Get the LDAP context for a given message.
111 *
112 * PARAMS
113 * ld [I] Pointer to an LDAP context.
114 * res [I] LDAP message.
115 *
116 * RETURNS
117 * Success: Pointer to an LDAP context.
118 * Failure: NULL
119 */
120 WLDAP32_LDAP * CDECL ldap_conn_from_msg( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *res )
121 {
122 TRACE( "(%p, %p)\n", ld, res );
123
124 if (!ld || !res) return NULL;
125 return ld; /* FIXME: not always correct */
126 }
127
128 /***********************************************************************
129 * ldap_count_entries (WLDAP32.@)
130 *
131 * Count the number of entries returned from a search.
132 *
133 * PARAMS
134 * ld [I] Pointer to an LDAP context.
135 * res [I] LDAP message.
136 *
137 * RETURNS
138 * Success: The number of entries.
139 * Failure: ~0u
140 */
141 ULONG CDECL WLDAP32_ldap_count_entries( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *res )
142 {
143 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
144 #ifdef HAVE_LDAP
145
146 TRACE( "(%p, %p)\n", ld, res );
147
148 if (!ld) return ~0u;
149 ret = ldap_count_entries( ld, res );
150
151 #endif
152 return ret;
153 }
154
155 /***********************************************************************
156 * ldap_count_references (WLDAP32.@)
157 *
158 * Count the number of references returned from a search.
159 *
160 * PARAMS
161 * ld [I] Pointer to an LDAP context.
162 * res [I] LDAP message.
163 *
164 * RETURNS
165 * Success: The number of references.
166 * Failure: ~0u
167 */
168 ULONG CDECL WLDAP32_ldap_count_references( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *res )
169 {
170 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
171 #ifdef HAVE_LDAP_COUNT_REFERENCES
172
173 TRACE( "(%p, %p)\n", ld, res );
174
175 if (!ld) return 0;
176 ret = ldap_count_references( ld, res );
177
178 #endif
179 return ret;
180 }
181
182 static ULONG get_escape_size( PCHAR src, ULONG srclen )
183 {
184 ULONG i, size = 0;
185
186 if (src)
187 {
188 for (i = 0; i < srclen; i++)
189 {
190 if ((src[i] >= '0' && src[i] <= '9') ||
191 (src[i] >= 'A' && src[i] <= 'Z') ||
192 (src[i] >= 'a' && src[i] <= 'z'))
193 size++;
194 else
195 size += 3;
196 }
197 }
198 return size + 1;
199 }
200
201 static void escape_filter_element( PCHAR src, ULONG srclen, PCHAR dst )
202 {
203 ULONG i;
204 static const char fmt[] = "\\%02X";
205 char *d = dst;
206
207 for (i = 0; i < srclen; i++)
208 {
209 if ((src[i] >= '0' && src[i] <= '9') ||
210 (src[i] >= 'A' && src[i] <= 'Z') ||
211 (src[i] >= 'a' && src[i] <= 'z'))
212 *d++ = src[i];
213 else
214 d += sprintf( d, fmt, (unsigned char)src[i] );
215 }
216 *++d = 0;
217 }
218
219 /***********************************************************************
220 * ldap_escape_filter_elementA (WLDAP32.@)
221 *
222 * See ldap_escape_filter_elementW.
223 */
224 ULONG CDECL ldap_escape_filter_elementA( PCHAR src, ULONG srclen, PCHAR dst, ULONG dstlen )
225 {
226 ULONG len;
227
228 TRACE( "(%p, 0x%08x, %p, 0x%08x)\n", src, srclen, dst, dstlen );
229
230 len = get_escape_size( src, srclen );
231 if (!dst) return len;
232
233 if (!src || dstlen < len)
234 return WLDAP32_LDAP_PARAM_ERROR;
235 else
236 {
237 escape_filter_element( src, srclen, dst );
238 return WLDAP32_LDAP_SUCCESS;
239 }
240 }
241
242 /***********************************************************************
243 * ldap_escape_filter_elementW (WLDAP32.@)
244 *
245 * Escape binary data for safe passing in filters.
246 *
247 * PARAMS
248 * src [I] Filter element to be escaped.
249 * srclen [I] Length in bytes of the filter element.
250 * dst [O] Destination buffer for the escaped filter element.
251 * dstlen [I] Length in bytes of the destination buffer.
252 *
253 * RETURNS
254 * Success: LDAP_SUCCESS
255 * Failure: An LDAP error code.
256 */
257 ULONG CDECL ldap_escape_filter_elementW( PCHAR src, ULONG srclen, PWCHAR dst, ULONG dstlen )
258 {
259 ULONG len;
260
261 TRACE( "(%p, 0x%08x, %p, 0x%08x)\n", src, srclen, dst, dstlen );
262
263 len = get_escape_size( src, srclen );
264 if (!dst) return len;
265
266 /* no matter what you throw at it, this is what native returns */
267 return WLDAP32_LDAP_PARAM_ERROR;
268 }
269
270 /***********************************************************************
271 * ldap_first_attributeA (WLDAP32.@)
272 *
273 * See ldap_first_attributeW.
274 */
275 PCHAR CDECL ldap_first_attributeA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry,
276 WLDAP32_BerElement** ptr )
277 {
278 PCHAR ret = NULL;
279 #ifdef HAVE_LDAP
280 WCHAR *retW;
281
282 TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
283
284 if (!ld || !entry) return NULL;
285 retW = ldap_first_attributeW( ld, entry, ptr );
286
287 ret = strWtoA( retW );
288 ldap_memfreeW( retW );
289
290 #endif
291 return ret;
292 }
293
294 /***********************************************************************
295 * ldap_first_attributeW (WLDAP32.@)
296 *
297 * Get the first attribute for a given entry.
298 *
299 * PARAMS
300 * ld [I] Pointer to an LDAP context.
301 * entry [I] Entry to retrieve attribute for.
302 * ptr [O] Position pointer.
303 *
304 * RETURNS
305 * Success: Name of the first attribute.
306 * Failure: NULL
307 *
308 * NOTES
309 * Use ldap_memfree to free the returned string.
310 */
311 PWCHAR CDECL ldap_first_attributeW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry,
312 WLDAP32_BerElement** ptr )
313 {
314 PWCHAR ret = NULL;
315 #ifdef HAVE_LDAP
316 char *retU;
317
318 TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
319
320 if (!ld || !entry) return NULL;
321 retU = ldap_first_attribute( ld, entry, ptr );
322
323 ret = strUtoW( retU );
324 ldap_memfree( retU );
325
326 #endif
327 return ret;
328 }
329
330 /***********************************************************************
331 * ldap_first_entry (WLDAP32.@)
332 *
333 * Get the first entry from a result message.
334 *
335 * PARAMS
336 * ld [I] Pointer to an LDAP context.
337 * res [I] Search result message.
338 *
339 * RETURNS
340 * Success: The first entry.
341 * Failure: NULL
342 *
343 * NOTES
344 * The returned entry will be freed when the message is freed.
345 */
346 WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_first_entry( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *res )
347 {
348 #ifdef HAVE_LDAP
349
350 TRACE( "(%p, %p)\n", ld, res );
351
352 if (!ld || !res) return NULL;
353 return ldap_first_entry( ld, res );
354
355 #else
356 return NULL;
357 #endif
358 }
359
360 /***********************************************************************
361 * ldap_first_reference (WLDAP32.@)
362 *
363 * Get the first reference from a result message.
364 *
365 * PARAMS
366 * ld [I] Pointer to an LDAP context.
367 * res [I] Search result message.
368 *
369 * RETURNS
370 * Success: The first reference.
371 * Failure: NULL
372 */
373 WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_first_reference( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *res )
374 {
375 #ifdef HAVE_LDAP_FIRST_REFERENCE
376
377 TRACE( "(%p, %p)\n", ld, res );
378
379 if (!ld) return NULL;
380 return ldap_first_reference( ld, res );
381
382 #else
383 return NULL;
384 #endif
385 }
386
387 /***********************************************************************
388 * ldap_memfreeA (WLDAP32.@)
389 *
390 * See ldap_memfreeW.
391 */
392 void CDECL ldap_memfreeA( PCHAR block )
393 {
394 TRACE( "(%p)\n", block );
395 strfreeA( block );
396 }
397
398 /***********************************************************************
399 * ldap_memfreeW (WLDAP32.@)
400 *
401 * Free a block of memory.
402 *
403 * PARAMS
404 * block [I] Pointer to memory block to be freed.
405 */
406 void CDECL ldap_memfreeW( PWCHAR block )
407 {
408 TRACE( "(%p)\n", block );
409 strfreeW( block );
410 }
411
412 /***********************************************************************
413 * ldap_msgfree (WLDAP32.@)
414 *
415 * Free a message.
416 *
417 * PARAMS
418 * res [I] Message to be freed.
419 */
420 ULONG CDECL WLDAP32_ldap_msgfree( WLDAP32_LDAPMessage *res )
421 {
422 ULONG ret = WLDAP32_LDAP_SUCCESS;
423 #ifdef HAVE_LDAP
424
425 TRACE( "(%p)\n", res );
426 ldap_msgfree( res );
427
428 #endif
429 return ret;
430 }
431
432 /***********************************************************************
433 * ldap_next_attributeA (WLDAP32.@)
434 *
435 * See ldap_next_attributeW.
436 */
437 PCHAR CDECL ldap_next_attributeA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry,
438 WLDAP32_BerElement *ptr )
439 {
440 PCHAR ret = NULL;
441 #ifdef HAVE_LDAP
442 WCHAR *retW;
443
444 TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
445
446 if (!ld || !entry || !ptr) return NULL;
447 retW = ldap_next_attributeW( ld, entry, ptr );
448
449 ret = strWtoA( retW );
450 ldap_memfreeW( retW );
451
452 #endif
453 return ret;
454 }
455
456 /***********************************************************************
457 * ldap_next_attributeW (WLDAP32.@)
458 *
459 * Get the next attribute for a given entry.
460 *
461 * PARAMS
462 * ld [I] Pointer to an LDAP context.
463 * entry [I] Entry to retrieve attribute for.
464 * ptr [I/O] Position pointer.
465 *
466 * RETURNS
467 * Success: The name of the next attribute.
468 * Failure: NULL
469 *
470 * NOTES
471 * Free the returned string after each iteration with ldap_memfree.
472 * When done iterating and when ptr != NULL, call ber_free( ptr, 0 ).
473 */
474 PWCHAR CDECL ldap_next_attributeW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry,
475 WLDAP32_BerElement *ptr )
476 {
477 PWCHAR ret = NULL;
478 #ifdef HAVE_LDAP
479 char *retU;
480
481 TRACE( "(%p, %p, %p)\n", ld, entry, ptr );
482
483 if (!ld || !entry || !ptr) return NULL;
484 retU = ldap_next_attribute( ld, entry, ptr );
485
486 ret = strUtoW( retU );
487 ldap_memfree( retU );
488
489 #endif
490 return ret;
491 }
492
493 /***********************************************************************
494 * ldap_next_entry (WLDAP32.@)
495 *
496 * Get the next entry from a result message.
497 *
498 * PARAMS
499 * ld [I] Pointer to an LDAP context.
500 * entry [I] Entry returned by a previous call.
501 *
502 * RETURNS
503 * Success: The next entry.
504 * Failure: NULL
505 *
506 * NOTES
507 * The returned entry will be freed when the message is freed.
508 */
509 WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_next_entry( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry )
510 {
511 #ifdef HAVE_LDAP
512
513 TRACE( "(%p, %p)\n", ld, entry );
514
515 if (!ld || !entry) return NULL;
516 return ldap_next_entry( ld, entry );
517
518 #else
519 return NULL;
520 #endif
521 }
522
523 /***********************************************************************
524 * ldap_next_reference (WLDAP32.@)
525 *
526 * Get the next reference from a result message.
527 *
528 * PARAMS
529 * ld [I] Pointer to an LDAP context.
530 * entry [I] Entry returned by a previous call.
531 *
532 * RETURNS
533 * Success: The next reference.
534 * Failure: NULL
535 *
536 * NOTES
537 * The returned entry will be freed when the message is freed.
538 */
539 WLDAP32_LDAPMessage * CDECL WLDAP32_ldap_next_reference( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *entry )
540 {
541 #ifdef HAVE_LDAP_NEXT_REFERENCE
542
543 TRACE( "(%p, %p)\n", ld, entry );
544
545 if (!ld || !entry) return NULL;
546 return ldap_next_reference( ld, entry );
547
548 #else
549 return NULL;
550 #endif
551 }
552
553 /***********************************************************************
554 * ldap_result (WLDAP32.@)
555 *
556 * Get the result of an asynchronous operation.
557 *
558 * PARAMS
559 * ld [I] Pointer to an LDAP context.
560 * msgid [I] Message ID of the operation.
561 * all [I] How many results should be returned?
562 * timeout [I] How long to wait for the results?
563 * res [O] Result message for the operation.
564 *
565 * RETURNS
566 * Success: One of the following values:
567 *
568 * LDAP_RES_ADD
569 * LDAP_RES_BIND
570 * LDAP_RES_COMPARE
571 * LDAP_RES_DELETE
572 * LDAP_RES_EXTENDED
573 * LDAP_RES_MODIFY
574 * LDAP_RES_MODRDN
575 * LDAP_RES_REFERRAL
576 * LDAP_RES_SEARCH_ENTRY
577 * LDAP_RES_SEARCH_RESULT
578 *
579 * Failure: ~0u
580 *
581 * This function returns 0 when the timeout has expired.
582 *
583 * NOTES
584 * A NULL timeout pointer causes the function to block waiting
585 * for results to arrive. A timeout value of 0 causes the function
586 * to immediately return any available results. Free returned results
587 * with ldap_msgfree.
588 */
589 ULONG CDECL WLDAP32_ldap_result( WLDAP32_LDAP *ld, ULONG msgid, ULONG all,
590 struct l_timeval *timeout, WLDAP32_LDAPMessage **res )
591 {
592 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
593 #ifdef HAVE_LDAP
594
595 TRACE( "(%p, 0x%08x, 0x%08x, %p, %p)\n", ld, msgid, all, timeout, res );
596
597 if (!ld || !res || msgid == ~0u) return ~0u;
598 ret = ldap_result( ld, msgid, all, (struct timeval *)timeout, res );
599
600 #endif
601 return ret;
602 }
603
604 /***********************************************************************
605 * LdapUnicodeToUTF8 (WLDAP32.@)
606 *
607 * Convert a wide character string to a UTF8 string.
608 *
609 * PARAMS
610 * src [I] Wide character string to convert.
611 * srclen [I] Size of string to convert, in characters.
612 * dst [O] Pointer to a buffer that receives the converted string.
613 * dstlen [I] Size of the destination buffer in characters.
614 *
615 * RETURNS
616 * The number of characters written into the destination buffer.
617 *
618 * NOTES
619 * Set dstlen to zero to ask for the required buffer size.
620 */
621 int CDECL LdapUnicodeToUTF8( LPCWSTR src, int srclen, LPSTR dst, int dstlen )
622 {
623 return WideCharToMultiByte( CP_UTF8, 0, src, srclen, dst, dstlen, NULL, NULL );
624 }
625
626 /***********************************************************************
627 * LdapUTF8ToUnicode (WLDAP32.@)
628 *
629 * Convert a UTF8 string to a wide character string.
630 *
631 * PARAMS
632 * src [I] UTF8 string to convert.
633 * srclen [I] Size of string to convert, in characters.
634 * dst [O] Pointer to a buffer that receives the converted string.
635 * dstlen [I] Size of the destination buffer in characters.
636 *
637 * RETURNS
638 * The number of characters written into the destination buffer.
639 *
640 * NOTES
641 * Set dstlen to zero to ask for the required buffer size.
642 */
643 int CDECL LdapUTF8ToUnicode( LPCSTR src, int srclen, LPWSTR dst, int dstlen )
644 {
645 return MultiByteToWideChar( CP_UTF8, 0, src, srclen, dst, dstlen );
646 }