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