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