comctl32/tests: Make test_combo_WS_VSCROLL() static.
[wine.git] / dlls / wldap32 / init.c
blob6b413f8437db677b5a470dc07b47816cd801156c
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 <stdio.h>
25 #include <stdarg.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 #ifdef HAVE_LDAP
39 /* Should eventually be determined by the algorithm documented on MSDN. */
40 static const WCHAR defaulthost[] = { 'l','o','c','a','l','h','o','s','t',0 };
42 /* Split a space separated string of hostnames into a string array */
43 static char **split_hostnames( const char *hostnames )
45 char **res, *str, *p, *q;
46 unsigned int i = 0;
48 str = strdupU( hostnames );
49 if (!str) return NULL;
51 p = str;
52 while (isspace( *p )) p++;
53 if (*p) i++;
55 while (*p)
57 if (isspace( *p ))
59 while (isspace( *p )) p++;
60 if (*p) i++;
62 p++;
65 res = HeapAlloc( GetProcessHeap(), 0, (i + 1) * sizeof(char *) );
66 if (!res)
68 HeapFree( GetProcessHeap(), 0, str );
69 return NULL;
72 p = str;
73 while (isspace( *p )) p++;
75 q = p;
76 i = 0;
78 while (*p)
80 if (p[1] != '\0')
82 if (isspace( *p ))
84 *p = '\0'; p++;
85 res[i] = strdupU( q );
86 if (!res[i]) goto oom;
87 i++;
89 while (isspace( *p )) p++;
90 q = p;
93 else
95 res[i] = strdupU( q );
96 if (!res[i]) goto oom;
97 i++;
99 p++;
101 res[i] = NULL;
103 HeapFree( GetProcessHeap(), 0, str );
104 return res;
106 oom:
107 while (i > 0) strfreeU( res[--i] );
109 HeapFree( GetProcessHeap(), 0, res );
110 HeapFree( GetProcessHeap(), 0, str );
112 return NULL;
115 /* Determine if a URL starts with a known LDAP scheme */
116 static BOOL has_ldap_scheme( char *url )
118 return !strncasecmp( url, "ldap://", 7 ) ||
119 !strncasecmp( url, "ldaps://", 8 ) ||
120 !strncasecmp( url, "ldapi://", 8 ) ||
121 !strncasecmp( url, "cldap://", 8 );
124 /* Flatten an array of hostnames into a space separated string of URLs.
125 * Prepend a given scheme and append a given port number to each hostname
126 * if necessary.
128 static char *join_hostnames( const char *scheme, char **hostnames, ULONG portnumber )
130 char *res, *p, *q, **v;
131 unsigned int i = 0, size = 0;
132 static const char sep[] = " ", fmt[] = ":%d";
133 char port[7];
135 sprintf( port, fmt, portnumber );
137 for (v = hostnames; *v; v++)
139 if (!has_ldap_scheme( *v ))
141 size += strlen( scheme );
142 q = *v;
144 else
145 /* skip past colon in scheme prefix */
146 q = strchr( *v, '/' );
148 size += strlen( *v );
150 if (!strchr( q, ':' ))
151 size += strlen( port );
153 i++;
156 size += (i - 1) * strlen( sep );
158 res = HeapAlloc( GetProcessHeap(), 0, size + 1 );
159 if (!res) return NULL;
161 p = res;
162 for (v = hostnames; *v; v++)
164 if (v != hostnames)
166 strcpy( p, sep );
167 p += strlen( sep );
170 if (!has_ldap_scheme( *v ))
172 strcpy( p, scheme );
173 p += strlen( scheme );
174 q = *v;
176 else
177 /* skip past colon in scheme prefix */
178 q = strchr( *v, '/' );
180 strcpy( p, *v );
181 p += strlen( *v );
183 if (!strchr( q, ':' ))
185 strcpy( p, port );
186 p += strlen( port );
189 return res;
192 static char *urlify_hostnames( const char *scheme, char *hostnames, ULONG port )
194 char *url = NULL, **strarray;
196 strarray = split_hostnames( hostnames );
197 if (strarray)
198 url = join_hostnames( scheme, strarray, port );
199 else
200 return NULL;
202 strarrayfreeU( strarray );
203 return url;
205 #endif
207 WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
209 #ifdef HAVE_LDAP
210 static LDAP *create_context( const char *url )
212 LDAP *ld;
213 int version = LDAP_VERSION3;
214 if (ldap_initialize( &ld, url ) != LDAP_SUCCESS) return NULL;
215 ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
216 return ld;
218 #endif
220 /***********************************************************************
221 * cldap_openA (WLDAP32.@)
223 * See cldap_openW.
225 WLDAP32_LDAP * CDECL cldap_openA( PCHAR hostname, ULONG portnumber )
227 #ifdef HAVE_LDAP
228 WLDAP32_LDAP *ld = NULL;
229 WCHAR *hostnameW = NULL;
231 TRACE( "(%s, %d)\n", debugstr_a(hostname), portnumber );
233 if (hostname) {
234 hostnameW = strAtoW( hostname );
235 if (!hostnameW) goto exit;
238 ld = cldap_openW( hostnameW, portnumber );
240 exit:
241 strfreeW( hostnameW );
242 return ld;
244 #else
245 return NULL;
246 #endif
249 /***********************************************************************
250 * cldap_openW (WLDAP32.@)
252 * Initialize an LDAP context and create a UDP connection.
254 * PARAMS
255 * hostname [I] Name of the host to connect to.
256 * portnumber [I] Port number to use.
258 * RETURNS
259 * Success: Pointer to an LDAP context.
260 * Failure: NULL
262 * NOTES
263 * The hostname string can be a space separated string of hostnames,
264 * in which case the LDAP runtime will try to connect to the hosts
265 * in order, until a connection can be made. A hostname may have a
266 * trailing port number (separated from the hostname by a ':'), which
267 * will take precedence over the port number supplied as a parameter
268 * to this function.
270 WLDAP32_LDAP * CDECL cldap_openW( PWCHAR hostname, ULONG portnumber )
272 #ifdef HAVE_LDAP
273 LDAP *ld = NULL;
274 char *hostnameU = NULL, *url = NULL;
276 TRACE( "(%s, %d)\n", debugstr_w(hostname), portnumber );
278 if (hostname) {
279 hostnameU = strWtoU( hostname );
280 if (!hostnameU) goto exit;
282 else {
283 hostnameU = strWtoU( defaulthost );
284 if (!hostnameU) goto exit;
287 url = urlify_hostnames( "cldap://", hostnameU, portnumber );
288 if (!url) goto exit;
290 ld = create_context( url );
292 exit:
293 strfreeU( hostnameU );
294 strfreeU( url );
295 return ld;
297 #else
298 return NULL;
299 #endif
302 /***********************************************************************
303 * ldap_connect (WLDAP32.@)
305 * Connect to an LDAP server.
307 * PARAMS
308 * ld [I] Pointer to an LDAP context.
309 * timeout [I] Pointer to an l_timeval structure specifying the
310 * timeout in seconds.
312 * RETURNS
313 * Success: LDAP_SUCCESS
314 * Failure: An LDAP error code.
316 * NOTES
317 * The timeout parameter may be NULL in which case a default timeout
318 * value will be used.
320 ULONG CDECL ldap_connect( WLDAP32_LDAP *ld, struct l_timeval *timeout )
322 TRACE( "(%p, %p)\n", ld, timeout );
324 if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
325 return WLDAP32_LDAP_SUCCESS; /* FIXME: do something, e.g. ping the host */
328 /***********************************************************************
329 * ldap_initA (WLDAP32.@)
331 * See ldap_initW.
333 WLDAP32_LDAP * CDECL ldap_initA( const PCHAR hostname, ULONG portnumber )
335 #ifdef HAVE_LDAP
336 WLDAP32_LDAP *ld = NULL;
337 WCHAR *hostnameW = NULL;
339 TRACE( "(%s, %d)\n", debugstr_a(hostname), portnumber );
341 if (hostname) {
342 hostnameW = strAtoW( hostname );
343 if (!hostnameW) goto exit;
346 ld = ldap_initW( hostnameW, portnumber );
348 exit:
349 strfreeW( hostnameW );
350 return ld;
352 #else
353 return NULL;
354 #endif
357 /***********************************************************************
358 * ldap_initW (WLDAP32.@)
360 * Initialize an LDAP context and create a TCP connection.
362 * PARAMS
363 * hostname [I] Name of the host to connect to.
364 * portnumber [I] Port number to use.
366 * RETURNS
367 * Success: Pointer to an LDAP context.
368 * Failure: NULL
370 * NOTES
371 * The hostname string can be a space separated string of hostnames,
372 * in which case the LDAP runtime will try to connect to the hosts
373 * in order, until a connection can be made. A hostname may have a
374 * trailing port number (separated from the hostname by a ':'), which
375 * will take precedence over the port number supplied as a parameter
376 * to this function. The connection will not be made until the first
377 * LDAP function that needs it is called.
379 WLDAP32_LDAP * CDECL ldap_initW( const PWCHAR hostname, ULONG portnumber )
381 #ifdef HAVE_LDAP
382 LDAP *ld = NULL;
383 char *hostnameU = NULL, *url = NULL;
385 TRACE( "(%s, %d)\n", debugstr_w(hostname), portnumber );
387 if (hostname) {
388 hostnameU = strWtoU( hostname );
389 if (!hostnameU) goto exit;
391 else {
392 hostnameU = strWtoU( defaulthost );
393 if (!hostnameU) goto exit;
396 url = urlify_hostnames( "ldap://", hostnameU, portnumber );
397 if (!url) goto exit;
399 ld = create_context( url );
401 exit:
402 strfreeU( hostnameU );
403 strfreeU( url );
404 return ld;
406 #else
407 return NULL;
408 #endif
411 /***********************************************************************
412 * ldap_openA (WLDAP32.@)
414 * See ldap_openW.
416 WLDAP32_LDAP * CDECL ldap_openA( PCHAR hostname, ULONG portnumber )
418 #ifdef HAVE_LDAP
419 WLDAP32_LDAP *ld = NULL;
420 WCHAR *hostnameW = NULL;
422 TRACE( "(%s, %d)\n", debugstr_a(hostname), portnumber );
424 if (hostname) {
425 hostnameW = strAtoW( hostname );
426 if (!hostnameW) goto exit;
429 ld = ldap_openW( hostnameW, portnumber );
431 exit:
432 strfreeW( hostnameW );
433 return ld;
435 #else
436 return NULL;
437 #endif
440 /***********************************************************************
441 * ldap_openW (WLDAP32.@)
443 * Initialize an LDAP context and create a TCP connection.
445 * PARAMS
446 * hostname [I] Name of the host to connect to.
447 * portnumber [I] Port number to use.
449 * RETURNS
450 * Success: Pointer to an LDAP context.
451 * Failure: NULL
453 * NOTES
454 * The hostname string can be a space separated string of hostnames,
455 * in which case the LDAP runtime will try to connect to the hosts
456 * in order, until a connection can be made. A hostname may have a
457 * trailing port number (separated from the hostname by a ':'), which
458 * will take precedence over the port number supplied as a parameter
459 * to this function.
461 WLDAP32_LDAP * CDECL ldap_openW( PWCHAR hostname, ULONG portnumber )
463 #ifdef HAVE_LDAP
464 LDAP *ld = NULL;
465 char *hostnameU = NULL, *url = NULL;
467 TRACE( "(%s, %d)\n", debugstr_w(hostname), portnumber );
469 if (hostname) {
470 hostnameU = strWtoU( hostname );
471 if (!hostnameU) goto exit;
473 else {
474 hostnameU = strWtoU( defaulthost );
475 if (!hostnameU) goto exit;
478 url = urlify_hostnames( "ldap://", hostnameU, portnumber );
479 if (!url) goto exit;
481 ld = create_context( url );
483 exit:
484 strfreeU( hostnameU );
485 strfreeU( url );
486 return ld;
488 #else
489 return NULL;
490 #endif
493 /***********************************************************************
494 * ldap_sslinitA (WLDAP32.@)
496 * See ldap_sslinitW.
498 WLDAP32_LDAP * CDECL ldap_sslinitA( PCHAR hostname, ULONG portnumber, int secure )
500 #ifdef HAVE_LDAP
501 WLDAP32_LDAP *ld;
502 WCHAR *hostnameW = NULL;
504 TRACE( "(%s, %d, 0x%08x)\n", debugstr_a(hostname), portnumber, secure );
506 if (hostname) {
507 hostnameW = strAtoW( hostname );
508 if (!hostnameW) return NULL;
511 ld = ldap_sslinitW( hostnameW, portnumber, secure );
513 strfreeW( hostnameW );
514 return ld;
516 #else
517 return NULL;
518 #endif
521 /***********************************************************************
522 * ldap_sslinitW (WLDAP32.@)
524 * Initialize an LDAP context and create a secure TCP connection.
526 * PARAMS
527 * hostname [I] Name of the host to connect to.
528 * portnumber [I] Port number to use.
529 * secure [I] Ask the server to create an SSL connection.
531 * RETURNS
532 * Success: Pointer to an LDAP context.
533 * Failure: NULL
535 * NOTES
536 * The hostname string can be a space separated string of hostnames,
537 * in which case the LDAP runtime will try to connect to the hosts
538 * in order, until a connection can be made. A hostname may have a
539 * trailing port number (separated from the hostname by a ':'), which
540 * will take precedence over the port number supplied as a parameter
541 * to this function. The connection will not be made until the first
542 * LDAP function that needs it is called.
544 WLDAP32_LDAP * CDECL ldap_sslinitW( PWCHAR hostname, ULONG portnumber, int secure )
546 #ifdef HAVE_LDAP
547 WLDAP32_LDAP *ld = NULL;
548 char *hostnameU = NULL, *url = NULL;
550 TRACE( "(%s, %d, 0x%08x)\n", debugstr_w(hostname), portnumber, secure );
552 if (hostname) {
553 hostnameU = strWtoU( hostname );
554 if (!hostnameU) goto exit;
556 else {
557 hostnameU = strWtoU( defaulthost );
558 if (!hostnameU) goto exit;
561 if (secure)
562 url = urlify_hostnames( "ldaps://", hostnameU, portnumber );
563 else
564 url = urlify_hostnames( "ldap://", hostnameU, portnumber );
566 if (!url) goto exit;
567 ldap_initialize( &ld, url );
569 exit:
570 strfreeU( hostnameU );
571 strfreeU( url );
572 return ld;
574 #else
575 return NULL;
576 #endif
579 /***********************************************************************
580 * ldap_start_tls_sA (WLDAP32.@)
582 * See ldap_start_tls_sW.
584 ULONG CDECL ldap_start_tls_sA( WLDAP32_LDAP *ld, PULONG retval, WLDAP32_LDAPMessage **result,
585 PLDAPControlA *serverctrls, PLDAPControlA *clientctrls )
587 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
588 #ifdef HAVE_LDAP
589 LDAPControlW **serverctrlsW = NULL, **clientctrlsW = NULL;
591 ret = WLDAP32_LDAP_NO_MEMORY;
593 TRACE( "(%p, %p, %p, %p, %p)\n", ld, retval, result, serverctrls, clientctrls );
595 if (!ld) return ~0u;
597 if (serverctrls) {
598 serverctrlsW = controlarrayAtoW( serverctrls );
599 if (!serverctrlsW) goto exit;
601 if (clientctrls) {
602 clientctrlsW = controlarrayAtoW( clientctrls );
603 if (!clientctrlsW) goto exit;
606 ret = ldap_start_tls_sW( ld, retval, result, serverctrlsW, clientctrlsW );
608 exit:
609 controlarrayfreeW( serverctrlsW );
610 controlarrayfreeW( clientctrlsW );
612 #endif
613 return ret;
616 /***********************************************************************
617 * ldap_start_tls_s (WLDAP32.@)
619 * Start TLS encryption on an LDAP connection.
621 * PARAMS
622 * ld [I] Pointer to an LDAP context.
623 * retval [I] Return value from the server.
624 * result [I] Response message from the server.
625 * serverctrls [I] Array of LDAP server controls.
626 * clientctrls [I] Array of LDAP client controls.
628 * RETURNS
629 * Success: LDAP_SUCCESS
630 * Failure: An LDAP error code.
632 * NOTES
633 * LDAP function that needs it is called.
635 ULONG CDECL ldap_start_tls_sW( WLDAP32_LDAP *ld, PULONG retval, WLDAP32_LDAPMessage **result,
636 PLDAPControlW *serverctrls, PLDAPControlW *clientctrls )
638 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
639 #ifdef HAVE_LDAP
640 LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
642 ret = WLDAP32_LDAP_NO_MEMORY;
644 TRACE( "(%p, %p, %p, %p, %p)\n", ld, retval, result, serverctrls, clientctrls );
646 if (!ld) return ~0u;
648 if (serverctrls) {
649 serverctrlsU = controlarrayWtoU( serverctrls );
650 if (!serverctrlsU) goto exit;
652 if (clientctrls) {
653 clientctrlsU = controlarrayWtoU( clientctrls );
654 if (!clientctrlsU) goto exit;
657 ret = map_error( ldap_start_tls_s( ld, serverctrlsU, clientctrlsU ));
659 exit:
660 controlarrayfreeU( serverctrlsU );
661 controlarrayfreeU( clientctrlsU );
663 #endif
664 return ret;
667 /***********************************************************************
668 * ldap_startup (WLDAP32.@)
670 ULONG CDECL ldap_startup( PLDAP_VERSION_INFO version, HANDLE *instance )
672 TRACE( "(%p, %p)\n", version, instance );
673 return WLDAP32_LDAP_SUCCESS;
676 /***********************************************************************
677 * ldap_stop_tls_s (WLDAP32.@)
679 * Stop TLS encryption on an LDAP connection.
681 * PARAMS
682 * ld [I] Pointer to an LDAP context.
684 * RETURNS
685 * Success: TRUE
686 * Failure: FALSE
688 BOOLEAN CDECL ldap_stop_tls_s( WLDAP32_LDAP *ld )
690 TRACE( "(%p)\n", ld );
691 return TRUE; /* FIXME: find a way to stop tls on a connection */