xref: /reactos/dll/win32/wldap32/wldap32.h (revision 40462c92)
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 #pragma once
22 
23 #include "wine/heap.h"
24 #include "wine/unicode.h"
25 
26 extern HINSTANCE hwldap32 DECLSPEC_HIDDEN;
27 
28 ULONG map_error( int ) DECLSPEC_HIDDEN;
29 
30 /* A set of helper functions to convert LDAP data structures
31  * to and from ansi (A), wide character (W) and utf8 (U) encodings.
32  */
33 
34 static inline char *strdupU( const char *src )
35 {
36     char *dst;
37     if (!src) return NULL;
38     if ((dst = heap_alloc( (strlen( src ) + 1) * sizeof(char) ))) strcpy( dst, src );
39     return dst;
40 }
41 
42 static inline WCHAR *strdupW( const WCHAR *src )
43 {
44     WCHAR *dst;
45     if (!src) return NULL;
46     if ((dst = heap_alloc( (strlenW( src ) + 1) * sizeof(WCHAR) ))) strcpyW( dst, src );
47     return dst;
48 }
49 
50 static inline LPWSTR strAtoW( LPCSTR str )
51 {
52     LPWSTR ret = NULL;
53     if (str)
54     {
55         DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
56         if ((ret = heap_alloc( len * sizeof(WCHAR) )))
57             MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
58     }
59     return ret;
60 }
61 
62 static inline LPSTR strWtoA( LPCWSTR str )
63 {
64     LPSTR ret = NULL;
65     if (str)
66     {
67         DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
68         if ((ret = heap_alloc( len )))
69             WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
70     }
71     return ret;
72 }
73 
74 static inline char *strWtoU( LPCWSTR str )
75 {
76     LPSTR ret = NULL;
77     if (str)
78     {
79         DWORD len = WideCharToMultiByte( CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL );
80         if ((ret = heap_alloc( len )))
81             WideCharToMultiByte( CP_UTF8, 0, str, -1, ret, len, NULL, NULL );
82     }
83     return ret;
84 }
85 
86 static inline LPWSTR strUtoW( char *str )
87 {
88     LPWSTR ret = NULL;
89     if (str)
90     {
91         DWORD len = MultiByteToWideChar( CP_UTF8, 0, str, -1, NULL, 0 );
92         if ((ret = heap_alloc( len * sizeof(WCHAR) )))
93             MultiByteToWideChar( CP_UTF8, 0, str, -1, ret, len );
94     }
95     return ret;
96 }
97 
98 static inline void strfreeA( LPSTR str )
99 {
100     heap_free( str );
101 }
102 
103 static inline void strfreeW( LPWSTR str )
104 {
105     heap_free( str );
106 }
107 
108 static inline void strfreeU( char *str )
109 {
110     heap_free( str );
111 }
112 
113 static inline DWORD strarraylenA( LPSTR *strarray )
114 {
115     LPSTR *p = strarray;
116     while (*p) p++;
117     return p - strarray;
118 }
119 
120 static inline DWORD strarraylenW( LPWSTR *strarray )
121 {
122     LPWSTR *p = strarray;
123     while (*p) p++;
124     return p - strarray;
125 }
126 
127 static inline DWORD strarraylenU( char **strarray )
128 {
129     char **p = strarray;
130     while (*p) p++;
131     return p - strarray;
132 }
133 
134 static inline LPWSTR *strarrayAtoW( LPSTR *strarray )
135 {
136     LPWSTR *strarrayW = NULL;
137     DWORD size;
138 
139     if (strarray)
140     {
141         size  = sizeof(WCHAR*) * (strarraylenA( strarray ) + 1);
142         if ((strarrayW = heap_alloc( size )))
143         {
144             LPSTR *p = strarray;
145             LPWSTR *q = strarrayW;
146 
147             while (*p) *q++ = strAtoW( *p++ );
148             *q = NULL;
149         }
150     }
151     return strarrayW;
152 }
153 
154 static inline LPSTR *strarrayWtoA( LPWSTR *strarray )
155 {
156     LPSTR *strarrayA = NULL;
157     DWORD size;
158 
159     if (strarray)
160     {
161         size = sizeof(LPSTR) * (strarraylenW( strarray ) + 1);
162         if ((strarrayA = heap_alloc( size )))
163         {
164             LPWSTR *p = strarray;
165             LPSTR *q = strarrayA;
166 
167             while (*p) *q++ = strWtoA( *p++ );
168             *q = NULL;
169         }
170     }
171     return strarrayA;
172 }
173 
174 static inline char **strarrayWtoU( LPWSTR *strarray )
175 {
176     char **strarrayU = NULL;
177     DWORD size;
178 
179     if (strarray)
180     {
181         size = sizeof(char*) * (strarraylenW( strarray ) + 1);
182         if ((strarrayU = heap_alloc( size )))
183         {
184             LPWSTR *p = strarray;
185             char **q = strarrayU;
186 
187             while (*p) *q++ = strWtoU( *p++ );
188             *q = NULL;
189         }
190     }
191     return strarrayU;
192 }
193 
194 static inline LPWSTR *strarrayUtoW( char **strarray )
195 {
196     LPWSTR *strarrayW = NULL;
197     DWORD size;
198 
199     if (strarray)
200     {
201         size = sizeof(WCHAR*) * (strarraylenU( strarray ) + 1);
202         if ((strarrayW = heap_alloc( size )))
203         {
204             char **p = strarray;
205             LPWSTR *q = strarrayW;
206 
207             while (*p) *q++ = strUtoW( *p++ );
208             *q = NULL;
209         }
210     }
211     return strarrayW;
212 }
213 
214 static inline void strarrayfreeA( LPSTR *strarray )
215 {
216     if (strarray)
217     {
218         LPSTR *p = strarray;
219         while (*p) strfreeA( *p++ );
220         heap_free( strarray );
221     }
222 }
223 
224 static inline void strarrayfreeW( LPWSTR *strarray )
225 {
226     if (strarray)
227     {
228         LPWSTR *p = strarray;
229         while (*p) strfreeW( *p++ );
230         heap_free( strarray );
231     }
232 }
233 
234 static inline void strarrayfreeU( char **strarray )
235 {
236     if (strarray)
237     {
238         char **p = strarray;
239         while (*p) strfreeU( *p++ );
240         heap_free( strarray );
241     }
242 }
243 
244 #ifdef HAVE_LDAP
245 
246 static inline struct berval *bvdup( struct berval *bv )
247 {
248     struct berval *berval;
249     DWORD size = sizeof(struct berval) + bv->bv_len;
250 
251     if ((berval = heap_alloc( size )))
252     {
253         char *val = (char *)berval + sizeof(struct berval);
254 
255         berval->bv_len = bv->bv_len;
256         berval->bv_val = val;
257         memcpy( val, bv->bv_val, bv->bv_len );
258     }
259     return berval;
260 }
261 
262 static inline DWORD bvarraylen( struct berval **bv )
263 {
264     struct berval **p = bv;
265     while (*p) p++;
266     return p - bv;
267 }
268 
269 static inline struct berval **bvarraydup( struct berval **bv )
270 {
271     struct berval **berval = NULL;
272     DWORD size;
273 
274     if (bv)
275     {
276         size = sizeof(struct berval *) * (bvarraylen( bv ) + 1);
277         if ((berval = heap_alloc( size )))
278         {
279             struct berval **p = bv;
280             struct berval **q = berval;
281 
282             while (*p) *q++ = bvdup( *p++ );
283             *q = NULL;
284         }
285     }
286     return berval;
287 }
288 
289 static inline void bvarrayfree( struct berval **bv )
290 {
291     struct berval **p = bv;
292     while (*p) heap_free( *p++ );
293     heap_free( bv );
294 }
295 
296 static inline LDAPModW *modAtoW( LDAPModA *mod )
297 {
298     LDAPModW *modW;
299 
300     if ((modW = heap_alloc( sizeof(LDAPModW) )))
301     {
302         modW->mod_op = mod->mod_op;
303         modW->mod_type = strAtoW( mod->mod_type );
304 
305         if (mod->mod_op & LDAP_MOD_BVALUES)
306             modW->mod_vals.modv_bvals = bvarraydup( mod->mod_vals.modv_bvals );
307         else
308             modW->mod_vals.modv_strvals = strarrayAtoW( mod->mod_vals.modv_strvals );
309     }
310     return modW;
311 }
312 
313 static inline LDAPMod *modWtoU( LDAPModW *mod )
314 {
315     LDAPMod *modU;
316 
317     if ((modU = heap_alloc( sizeof(LDAPMod) )))
318     {
319         modU->mod_op = mod->mod_op;
320         modU->mod_type = strWtoU( mod->mod_type );
321 
322         if (mod->mod_op & LDAP_MOD_BVALUES)
323             modU->mod_vals.modv_bvals = bvarraydup( mod->mod_vals.modv_bvals );
324         else
325             modU->mod_vals.modv_strvals = strarrayWtoU( mod->mod_vals.modv_strvals );
326     }
327     return modU;
328 }
329 
330 static inline void modfreeW( LDAPModW *mod )
331 {
332     if (mod->mod_op & LDAP_MOD_BVALUES)
333         bvarrayfree( mod->mod_vals.modv_bvals );
334     else
335         strarrayfreeW( mod->mod_vals.modv_strvals );
336     heap_free( mod );
337 }
338 
339 static inline void modfreeU( LDAPMod *mod )
340 {
341     if (mod->mod_op & LDAP_MOD_BVALUES)
342         bvarrayfree( mod->mod_vals.modv_bvals );
343     else
344         strarrayfreeU( mod->mod_vals.modv_strvals );
345     heap_free( mod );
346 }
347 
348 static inline DWORD modarraylenA( LDAPModA **modarray )
349 {
350     LDAPModA **p = modarray;
351     while (*p) p++;
352     return p - modarray;
353 }
354 
355 static inline DWORD modarraylenW( LDAPModW **modarray )
356 {
357     LDAPModW **p = modarray;
358     while (*p) p++;
359     return p - modarray;
360 }
361 
362 static inline LDAPModW **modarrayAtoW( LDAPModA **modarray )
363 {
364     LDAPModW **modarrayW = NULL;
365     DWORD size;
366 
367     if (modarray)
368     {
369         size = sizeof(LDAPModW*) * (modarraylenA( modarray ) + 1);
370         if ((modarrayW = heap_alloc( size )))
371         {
372             LDAPModA **p = modarray;
373             LDAPModW **q = modarrayW;
374 
375             while (*p) *q++ = modAtoW( *p++ );
376             *q = NULL;
377         }
378     }
379     return modarrayW;
380 }
381 
382 static inline LDAPMod **modarrayWtoU( LDAPModW **modarray )
383 {
384     LDAPMod **modarrayU = NULL;
385     DWORD size;
386 
387     if (modarray)
388     {
389         size = sizeof(LDAPMod*) * (modarraylenW( modarray ) + 1);
390         if ((modarrayU = heap_alloc( size )))
391         {
392             LDAPModW **p = modarray;
393             LDAPMod **q = modarrayU;
394 
395             while (*p) *q++ = modWtoU( *p++ );
396             *q = NULL;
397         }
398     }
399     return modarrayU;
400 }
401 
402 static inline void modarrayfreeW( LDAPModW **modarray )
403 {
404     if (modarray)
405     {
406         LDAPModW **p = modarray;
407         while (*p) modfreeW( *p++ );
408         heap_free( modarray );
409     }
410 }
411 
412 static inline void modarrayfreeU( LDAPMod **modarray )
413 {
414     if (modarray)
415     {
416         LDAPMod **p = modarray;
417         while (*p) modfreeU( *p++ );
418         heap_free( modarray );
419     }
420 }
421 
422 static inline LDAPControlW *controlAtoW( LDAPControlA *control )
423 {
424     LDAPControlW *controlW;
425     DWORD len = control->ldctl_value.bv_len;
426     char *val = NULL;
427 
428     if (control->ldctl_value.bv_val)
429     {
430         if (!(val = heap_alloc( len ))) return NULL;
431         memcpy( val, control->ldctl_value.bv_val, len );
432     }
433 
434     if (!(controlW = heap_alloc( sizeof(LDAPControlW) )))
435     {
436         heap_free( val );
437         return NULL;
438     }
439 
440     controlW->ldctl_oid = strAtoW( control->ldctl_oid );
441     controlW->ldctl_value.bv_len = len;
442     controlW->ldctl_value.bv_val = val;
443     controlW->ldctl_iscritical = control->ldctl_iscritical;
444 
445     return controlW;
446 }
447 
448 static inline LDAPControlA *controlWtoA( LDAPControlW *control )
449 {
450     LDAPControlA *controlA;
451     DWORD len = control->ldctl_value.bv_len;
452     char *val = NULL;
453 
454     if (control->ldctl_value.bv_val)
455     {
456         if (!(val = heap_alloc( len ))) return NULL;
457         memcpy( val, control->ldctl_value.bv_val, len );
458     }
459 
460     if (!(controlA = heap_alloc( sizeof(LDAPControlA) )))
461     {
462         heap_free( val );
463         return NULL;
464     }
465 
466     controlA->ldctl_oid = strWtoA( control->ldctl_oid );
467     controlA->ldctl_value.bv_len = len;
468     controlA->ldctl_value.bv_val = val;
469     controlA->ldctl_iscritical = control->ldctl_iscritical;
470 
471     return controlA;
472 }
473 
474 static inline LDAPControl *controlWtoU( LDAPControlW *control )
475 {
476     LDAPControl *controlU;
477     DWORD len = control->ldctl_value.bv_len;
478     char *val = NULL;
479 
480     if (control->ldctl_value.bv_val)
481     {
482         if (!(val = heap_alloc( len ))) return NULL;
483         memcpy( val, control->ldctl_value.bv_val, len );
484     }
485 
486     if (!(controlU = heap_alloc( sizeof(LDAPControl) )))
487     {
488         heap_free( val );
489         return NULL;
490     }
491 
492     controlU->ldctl_oid = strWtoU( control->ldctl_oid );
493     controlU->ldctl_value.bv_len = len;
494     controlU->ldctl_value.bv_val = val;
495     controlU->ldctl_iscritical = control->ldctl_iscritical;
496 
497     return controlU;
498 }
499 
500 static inline LDAPControlW *controlUtoW( LDAPControl *control )
501 {
502     LDAPControlW *controlW;
503     DWORD len = control->ldctl_value.bv_len;
504     char *val = NULL;
505 
506     if (control->ldctl_value.bv_val)
507     {
508         if (!(val = heap_alloc( len ))) return NULL;
509         memcpy( val, control->ldctl_value.bv_val, len );
510     }
511 
512     if (!(controlW = heap_alloc( sizeof(LDAPControlW) )))
513     {
514         heap_free( val );
515         return NULL;
516     }
517 
518     controlW->ldctl_oid = strUtoW( control->ldctl_oid );
519     controlW->ldctl_value.bv_len = len;
520     controlW->ldctl_value.bv_val = val;
521     controlW->ldctl_iscritical = control->ldctl_iscritical;
522 
523     return controlW;
524 }
525 
526 static inline void controlfreeA( LDAPControlA *control )
527 {
528     if (control)
529     {
530         strfreeA( control->ldctl_oid );
531         heap_free( control->ldctl_value.bv_val );
532         heap_free( control );
533     }
534 }
535 
536 static inline void controlfreeW( LDAPControlW *control )
537 {
538     if (control)
539     {
540         strfreeW( control->ldctl_oid );
541         heap_free( control->ldctl_value.bv_val );
542         heap_free( control );
543     }
544 }
545 
546 static inline void controlfreeU( LDAPControl *control )
547 {
548     if (control)
549     {
550         strfreeU( control->ldctl_oid );
551         heap_free( control->ldctl_value.bv_val );
552         heap_free( control );
553     }
554 }
555 
556 static inline DWORD controlarraylenA( LDAPControlA **controlarray )
557 {
558     LDAPControlA **p = controlarray;
559     while (*p) p++;
560     return p - controlarray;
561 }
562 
563 static inline DWORD controlarraylenW( LDAPControlW **controlarray )
564 {
565     LDAPControlW **p = controlarray;
566     while (*p) p++;
567     return p - controlarray;
568 }
569 
570 static inline DWORD controlarraylenU( LDAPControl **controlarray )
571 {
572     LDAPControl **p = controlarray;
573     while (*p) p++;
574     return p - controlarray;
575 }
576 
577 static inline LDAPControlW **controlarrayAtoW( LDAPControlA **controlarray )
578 {
579     LDAPControlW **controlarrayW = NULL;
580     DWORD size;
581 
582     if (controlarray)
583     {
584         size = sizeof(LDAPControlW*) * (controlarraylenA( controlarray ) + 1);
585         if ((controlarrayW = heap_alloc( size )))
586         {
587             LDAPControlA **p = controlarray;
588             LDAPControlW **q = controlarrayW;
589 
590             while (*p) *q++ = controlAtoW( *p++ );
591             *q = NULL;
592         }
593     }
594     return controlarrayW;
595 }
596 
597 static inline LDAPControlA **controlarrayWtoA( LDAPControlW **controlarray )
598 {
599     LDAPControlA **controlarrayA = NULL;
600     DWORD size;
601 
602     if (controlarray)
603     {
604         size = sizeof(LDAPControl*) * (controlarraylenW( controlarray ) + 1);
605         if ((controlarrayA = heap_alloc( size )))
606         {
607             LDAPControlW **p = controlarray;
608             LDAPControlA **q = controlarrayA;
609 
610             while (*p) *q++ = controlWtoA( *p++ );
611             *q = NULL;
612         }
613     }
614     return controlarrayA;
615 }
616 
617 static inline LDAPControl **controlarrayWtoU( LDAPControlW **controlarray )
618 {
619     LDAPControl **controlarrayU = NULL;
620     DWORD size;
621 
622     if (controlarray)
623     {
624         size = sizeof(LDAPControl*) * (controlarraylenW( controlarray ) + 1);
625         if ((controlarrayU = heap_alloc( size )))
626         {
627             LDAPControlW **p = controlarray;
628             LDAPControl **q = controlarrayU;
629 
630             while (*p) *q++ = controlWtoU( *p++ );
631             *q = NULL;
632         }
633     }
634     return controlarrayU;
635 }
636 
637 static inline LDAPControlW **controlarrayUtoW( LDAPControl **controlarray )
638 {
639     LDAPControlW **controlarrayW = NULL;
640     DWORD size;
641 
642     if (controlarray)
643     {
644         size = sizeof(LDAPControlW*) * (controlarraylenU( controlarray ) + 1);
645         if ((controlarrayW = heap_alloc( size )))
646         {
647             LDAPControl **p = controlarray;
648             LDAPControlW **q = controlarrayW;
649 
650             while (*p) *q++ = controlUtoW( *p++ );
651             *q = NULL;
652         }
653     }
654     return controlarrayW;
655 }
656 
657 static inline void controlarrayfreeA( LDAPControlA **controlarray )
658 {
659     if (controlarray)
660     {
661         LDAPControlA **p = controlarray;
662         while (*p) controlfreeA( *p++ );
663         heap_free( controlarray );
664     }
665 }
666 
667 static inline void controlarrayfreeW( LDAPControlW **controlarray )
668 {
669     if (controlarray)
670     {
671         LDAPControlW **p = controlarray;
672         while (*p) controlfreeW( *p++ );
673         heap_free( controlarray );
674     }
675 }
676 
677 static inline void controlarrayfreeU( LDAPControl **controlarray )
678 {
679     if (controlarray)
680     {
681         LDAPControl **p = controlarray;
682         while (*p) controlfreeU( *p++ );
683         heap_free( controlarray );
684     }
685 }
686 
687 static inline LDAPSortKeyW *sortkeyAtoW( LDAPSortKeyA *sortkey )
688 {
689     LDAPSortKeyW *sortkeyW;
690 
691     if ((sortkeyW = heap_alloc( sizeof(LDAPSortKeyW) )))
692     {
693         sortkeyW->sk_attrtype = strAtoW( sortkey->sk_attrtype );
694         sortkeyW->sk_matchruleoid = strAtoW( sortkey->sk_matchruleoid );
695         sortkeyW->sk_reverseorder = sortkey->sk_reverseorder;
696     }
697     return sortkeyW;
698 }
699 
700 static inline LDAPSortKeyA *sortkeyWtoA( LDAPSortKeyW *sortkey )
701 {
702     LDAPSortKeyA *sortkeyA;
703 
704     if ((sortkeyA = heap_alloc( sizeof(LDAPSortKeyA) )))
705     {
706         sortkeyA->sk_attrtype = strWtoA( sortkey->sk_attrtype );
707         sortkeyA->sk_matchruleoid = strWtoA( sortkey->sk_matchruleoid );
708         sortkeyA->sk_reverseorder = sortkey->sk_reverseorder;
709     }
710     return sortkeyA;
711 }
712 
713 static inline LDAPSortKey *sortkeyWtoU( LDAPSortKeyW *sortkey )
714 {
715     LDAPSortKey *sortkeyU;
716 
717     if ((sortkeyU = heap_alloc( sizeof(LDAPSortKey) )))
718     {
719         sortkeyU->attributeType = strWtoU( sortkey->sk_attrtype );
720         sortkeyU->orderingRule = strWtoU( sortkey->sk_matchruleoid );
721         sortkeyU->reverseOrder = sortkey->sk_reverseorder;
722     }
723     return sortkeyU;
724 }
725 
726 static inline void sortkeyfreeA( LDAPSortKeyA *sortkey )
727 {
728     if (sortkey)
729     {
730         strfreeA( sortkey->sk_attrtype );
731         strfreeA( sortkey->sk_matchruleoid );
732         heap_free( sortkey );
733     }
734 }
735 
736 static inline void sortkeyfreeW( LDAPSortKeyW *sortkey )
737 {
738     if (sortkey)
739     {
740         strfreeW( sortkey->sk_attrtype );
741         strfreeW( sortkey->sk_matchruleoid );
742         heap_free( sortkey );
743     }
744 }
745 
746 static inline void sortkeyfreeU( LDAPSortKey *sortkey )
747 {
748     if (sortkey)
749     {
750         strfreeU( sortkey->attributeType );
751         strfreeU( sortkey->orderingRule );
752         heap_free( sortkey );
753     }
754 }
755 
756 static inline DWORD sortkeyarraylenA( LDAPSortKeyA **sortkeyarray )
757 {
758     LDAPSortKeyA **p = sortkeyarray;
759     while (*p) p++;
760     return p - sortkeyarray;
761 }
762 
763 static inline DWORD sortkeyarraylenW( LDAPSortKeyW **sortkeyarray )
764 {
765     LDAPSortKeyW **p = sortkeyarray;
766     while (*p) p++;
767     return p - sortkeyarray;
768 }
769 
770 static inline LDAPSortKeyW **sortkeyarrayAtoW( LDAPSortKeyA **sortkeyarray )
771 {
772     LDAPSortKeyW **sortkeyarrayW = NULL;
773     DWORD size;
774 
775     if (sortkeyarray)
776     {
777         size = sizeof(LDAPSortKeyW*) * (sortkeyarraylenA( sortkeyarray ) + 1);
778         if ((sortkeyarrayW = heap_alloc( size )))
779         {
780             LDAPSortKeyA **p = sortkeyarray;
781             LDAPSortKeyW **q = sortkeyarrayW;
782 
783             while (*p) *q++ = sortkeyAtoW( *p++ );
784             *q = NULL;
785         }
786     }
787     return sortkeyarrayW;
788 }
789 
790 static inline LDAPSortKey **sortkeyarrayWtoU( LDAPSortKeyW **sortkeyarray )
791 {
792     LDAPSortKey **sortkeyarrayU = NULL;
793     DWORD size;
794 
795     if (sortkeyarray)
796     {
797         size = sizeof(LDAPSortKey*) * (sortkeyarraylenW( sortkeyarray ) + 1);
798         if ((sortkeyarrayU = heap_alloc( size )))
799         {
800             LDAPSortKeyW **p = sortkeyarray;
801             LDAPSortKey **q = sortkeyarrayU;
802 
803             while (*p) *q++ = sortkeyWtoU( *p++ );
804             *q = NULL;
805         }
806     }
807     return sortkeyarrayU;
808 }
809 
810 static inline void sortkeyarrayfreeW( LDAPSortKeyW **sortkeyarray )
811 {
812     if (sortkeyarray)
813     {
814         LDAPSortKeyW **p = sortkeyarray;
815         while (*p) sortkeyfreeW( *p++ );
816         heap_free( sortkeyarray );
817     }
818 }
819 
820 static inline void sortkeyarrayfreeU( LDAPSortKey **sortkeyarray )
821 {
822     if (sortkeyarray)
823     {
824         LDAPSortKey **p = sortkeyarray;
825         while (*p) sortkeyfreeU( *p++ );
826         heap_free( sortkeyarray );
827     }
828 }
829 #endif /* HAVE_LDAP */
830