2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afs/param.h>
17 #define EWOULDBLOCK WSAEWOULDBLOCK
18 #define EINPROGRESS WSAEINPROGRESS
19 #define EALREADY WSAEALREADY
20 #define ENOTSOCK WSAENOTSOCK
21 #define EDESTADDRREQ WSAEDESTADDRREQ
22 #define EMSGSIZE WSAEMSGSIZE
23 #define EPROTOTYPE WSAEPROTOTYPE
24 #define ENOPROTOOPT WSAENOPROTOOPT
25 #define EPROTONOSUPPORT WSAEPROTONOSUPPORT
26 #define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
27 #define EOPNOTSUPP WSAEOPNOTSUPP
28 #define EPFNOSUPPORT WSAEPFNOSUPPORT
29 #define EAFNOSUPPORT WSAEAFNOSUPPORT
30 #define EADDRINUSE WSAEADDRINUSE
31 #define EADDRNOTAVAIL WSAEADDRNOTAVAIL
32 #define ENETDOWN WSAENETDOWN
33 #define ENETUNREACH WSAENETUNREACH
34 #define ENETRESET WSAENETRESET
35 #define ECONNABORTED WSAECONNABORTED
36 #define ECONNRESET WSAECONNRESET
37 #define ENOBUFS WSAENOBUFS
38 #define EISCONN WSAEISCONN
39 #define ENOTCONN WSAENOTCONN
40 #define ESHUTDOWN WSAESHUTDOWN
41 #define ETOOMANYREFS WSAETOOMANYREFS
42 #define ETIMEDOUT WSAETIMEDOUT
43 #define ECONNREFUSED WSAECONNREFUSED
47 #define ELOOP WSAELOOP
51 #define ENAMETOOLONG WSAENAMETOOLONG
52 #define EHOSTDOWN WSAEHOSTDOWN
53 #define EHOSTUNREACH WSAEHOSTUNREACH
57 #define ENOTEMPTY WSAENOTEMPTY
58 #define EPROCLIM WSAEPROCLIM
59 #define EUSERS WSAEUSERS
60 #define EDQUOT WSAEDQUOT
61 #define ESTALE WSAESTALE
62 #define EREMOTE WSAEREMOTE
63 #endif /* EWOULDBLOCK */
64 #include <afs/unified_afs.h>
72 #define STRSAFE_NO_DEPRECATE
76 static osi_once_t cm_utilsOnce;
78 osi_rwlock_t cm_utilsLock;
80 cm_space_t *cm_spaceListp;
82 static int et2sys[512];
85 init_et_to_sys_error(void)
87 memset(&et2sys, 0, sizeof(et2sys));
88 et2sys[(UAEPERM - ERROR_TABLE_BASE_uae)] = EPERM;
89 et2sys[(UAENOENT - ERROR_TABLE_BASE_uae)] = ENOENT;
90 et2sys[(UAESRCH - ERROR_TABLE_BASE_uae)] = ESRCH;
91 et2sys[(UAEINTR - ERROR_TABLE_BASE_uae)] = EINTR;
92 et2sys[(UAEIO - ERROR_TABLE_BASE_uae)] = EIO;
93 et2sys[(UAENXIO - ERROR_TABLE_BASE_uae)] = ENXIO;
94 et2sys[(UAE2BIG - ERROR_TABLE_BASE_uae)] = E2BIG;
95 et2sys[(UAENOEXEC - ERROR_TABLE_BASE_uae)] = ENOEXEC;
96 et2sys[(UAEBADF - ERROR_TABLE_BASE_uae)] = EBADF;
97 et2sys[(UAECHILD - ERROR_TABLE_BASE_uae)] = ECHILD;
98 et2sys[(UAEAGAIN - ERROR_TABLE_BASE_uae)] = EAGAIN;
99 et2sys[(UAENOMEM - ERROR_TABLE_BASE_uae)] = ENOMEM;
100 et2sys[(UAEACCES - ERROR_TABLE_BASE_uae)] = EACCES;
101 et2sys[(UAEFAULT - ERROR_TABLE_BASE_uae)] = EFAULT;
102 et2sys[(UAENOTBLK - ERROR_TABLE_BASE_uae)] = ENOTBLK;
103 et2sys[(UAEBUSY - ERROR_TABLE_BASE_uae)] = EBUSY;
104 et2sys[(UAEEXIST - ERROR_TABLE_BASE_uae)] = EEXIST;
105 et2sys[(UAEXDEV - ERROR_TABLE_BASE_uae)] = EXDEV;
106 et2sys[(UAENODEV - ERROR_TABLE_BASE_uae)] = ENODEV;
107 et2sys[(UAENOTDIR - ERROR_TABLE_BASE_uae)] = ENOTDIR;
108 et2sys[(UAEISDIR - ERROR_TABLE_BASE_uae)] = EISDIR;
109 et2sys[(UAEINVAL - ERROR_TABLE_BASE_uae)] = EINVAL;
110 et2sys[(UAENFILE - ERROR_TABLE_BASE_uae)] = ENFILE;
111 et2sys[(UAEMFILE - ERROR_TABLE_BASE_uae)] = EMFILE;
112 et2sys[(UAENOTTY - ERROR_TABLE_BASE_uae)] = ENOTTY;
113 et2sys[(UAETXTBSY - ERROR_TABLE_BASE_uae)] = ETXTBSY;
114 et2sys[(UAEFBIG - ERROR_TABLE_BASE_uae)] = EFBIG;
115 et2sys[(UAENOSPC - ERROR_TABLE_BASE_uae)] = ENOSPC;
116 et2sys[(UAESPIPE - ERROR_TABLE_BASE_uae)] = ESPIPE;
117 et2sys[(UAEROFS - ERROR_TABLE_BASE_uae)] = EROFS;
118 et2sys[(UAEMLINK - ERROR_TABLE_BASE_uae)] = EMLINK;
119 et2sys[(UAEPIPE - ERROR_TABLE_BASE_uae)] = EPIPE;
120 et2sys[(UAEDOM - ERROR_TABLE_BASE_uae)] = EDOM;
121 et2sys[(UAERANGE - ERROR_TABLE_BASE_uae)] = ERANGE;
122 et2sys[(UAEDEADLK - ERROR_TABLE_BASE_uae)] = EDEADLK;
123 et2sys[(UAENAMETOOLONG - ERROR_TABLE_BASE_uae)] = ENAMETOOLONG;
124 et2sys[(UAENOLCK - ERROR_TABLE_BASE_uae)] = ENOLCK;
125 et2sys[(UAENOSYS - ERROR_TABLE_BASE_uae)] = ENOSYS;
126 et2sys[(UAENOTEMPTY - ERROR_TABLE_BASE_uae)] = ENOTEMPTY;
127 et2sys[(UAELOOP - ERROR_TABLE_BASE_uae)] = ELOOP;
128 et2sys[(UAEWOULDBLOCK - ERROR_TABLE_BASE_uae)] = EWOULDBLOCK;
129 et2sys[(UAENOMSG - ERROR_TABLE_BASE_uae)] = ENOMSG;
130 et2sys[(UAEIDRM - ERROR_TABLE_BASE_uae)] = EIDRM;
131 et2sys[(UAECHRNG - ERROR_TABLE_BASE_uae)] = ECHRNG;
132 et2sys[(UAEL2NSYNC - ERROR_TABLE_BASE_uae)] = EL2NSYNC;
133 et2sys[(UAEL3HLT - ERROR_TABLE_BASE_uae)] = EL3HLT;
134 et2sys[(UAEL3RST - ERROR_TABLE_BASE_uae)] = EL3RST;
135 et2sys[(UAELNRNG - ERROR_TABLE_BASE_uae)] = ELNRNG;
136 et2sys[(UAEUNATCH - ERROR_TABLE_BASE_uae)] = EUNATCH;
137 et2sys[(UAENOCSI - ERROR_TABLE_BASE_uae)] = ENOCSI;
138 et2sys[(UAEL2HLT - ERROR_TABLE_BASE_uae)] = EL2HLT;
139 et2sys[(UAEBADE - ERROR_TABLE_BASE_uae)] = EBADE;
140 et2sys[(UAEBADR - ERROR_TABLE_BASE_uae)] = EBADR;
141 et2sys[(UAEXFULL - ERROR_TABLE_BASE_uae)] = EXFULL;
142 et2sys[(UAENOANO - ERROR_TABLE_BASE_uae)] = ENOANO;
143 et2sys[(UAEBADRQC - ERROR_TABLE_BASE_uae)] = EBADRQC;
144 et2sys[(UAEBADSLT - ERROR_TABLE_BASE_uae)] = EBADSLT;
145 et2sys[(UAEBFONT - ERROR_TABLE_BASE_uae)] = EBFONT;
146 et2sys[(UAENOSTR - ERROR_TABLE_BASE_uae)] = ENOSTR;
147 et2sys[(UAENODATA - ERROR_TABLE_BASE_uae)] = ENODATA;
148 et2sys[(UAETIME - ERROR_TABLE_BASE_uae)] = ETIME;
149 et2sys[(UAENOSR - ERROR_TABLE_BASE_uae)] = ENOSR;
150 et2sys[(UAENONET - ERROR_TABLE_BASE_uae)] = ENONET;
151 et2sys[(UAENOPKG - ERROR_TABLE_BASE_uae)] = ENOPKG;
152 et2sys[(UAEREMOTE - ERROR_TABLE_BASE_uae)] = EREMOTE;
153 et2sys[(UAENOLINK - ERROR_TABLE_BASE_uae)] = ENOLINK;
154 et2sys[(UAEADV - ERROR_TABLE_BASE_uae)] = EADV;
155 et2sys[(UAESRMNT - ERROR_TABLE_BASE_uae)] = ESRMNT;
156 et2sys[(UAECOMM - ERROR_TABLE_BASE_uae)] = ECOMM;
157 et2sys[(UAEPROTO - ERROR_TABLE_BASE_uae)] = EPROTO;
158 et2sys[(UAEMULTIHOP - ERROR_TABLE_BASE_uae)] = EMULTIHOP;
159 et2sys[(UAEDOTDOT - ERROR_TABLE_BASE_uae)] = EDOTDOT;
160 et2sys[(UAEBADMSG - ERROR_TABLE_BASE_uae)] = EBADMSG;
161 et2sys[(UAEOVERFLOW - ERROR_TABLE_BASE_uae)] = EOVERFLOW;
162 et2sys[(UAENOTUNIQ - ERROR_TABLE_BASE_uae)] = ENOTUNIQ;
163 et2sys[(UAEBADFD - ERROR_TABLE_BASE_uae)] = EBADFD;
164 et2sys[(UAEREMCHG - ERROR_TABLE_BASE_uae)] = EREMCHG;
165 et2sys[(UAELIBACC - ERROR_TABLE_BASE_uae)] = ELIBACC;
166 et2sys[(UAELIBBAD - ERROR_TABLE_BASE_uae)] = ELIBBAD;
167 et2sys[(UAELIBSCN - ERROR_TABLE_BASE_uae)] = ELIBSCN;
168 et2sys[(UAELIBMAX - ERROR_TABLE_BASE_uae)] = ELIBMAX;
169 et2sys[(UAELIBEXEC - ERROR_TABLE_BASE_uae)] = ELIBEXEC;
170 et2sys[(UAEILSEQ - ERROR_TABLE_BASE_uae)] = EILSEQ;
171 et2sys[(UAERESTART - ERROR_TABLE_BASE_uae)] = ERESTART;
172 et2sys[(UAESTRPIPE - ERROR_TABLE_BASE_uae)] = ESTRPIPE;
173 et2sys[(UAEUSERS - ERROR_TABLE_BASE_uae)] = EUSERS;
174 et2sys[(UAENOTSOCK - ERROR_TABLE_BASE_uae)] = ENOTSOCK;
175 et2sys[(UAEDESTADDRREQ - ERROR_TABLE_BASE_uae)] = EDESTADDRREQ;
176 et2sys[(UAEMSGSIZE - ERROR_TABLE_BASE_uae)] = EMSGSIZE;
177 et2sys[(UAEPROTOTYPE - ERROR_TABLE_BASE_uae)] = EPROTOTYPE;
178 et2sys[(UAENOPROTOOPT - ERROR_TABLE_BASE_uae)] = ENOPROTOOPT;
179 et2sys[(UAEPROTONOSUPPORT - ERROR_TABLE_BASE_uae)] = EPROTONOSUPPORT;
180 et2sys[(UAESOCKTNOSUPPORT - ERROR_TABLE_BASE_uae)] = ESOCKTNOSUPPORT;
181 et2sys[(UAEOPNOTSUPP - ERROR_TABLE_BASE_uae)] = EOPNOTSUPP;
182 et2sys[(UAEPFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EPFNOSUPPORT;
183 et2sys[(UAEAFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EAFNOSUPPORT;
184 et2sys[(UAEADDRINUSE - ERROR_TABLE_BASE_uae)] = EADDRINUSE;
185 et2sys[(UAEADDRNOTAVAIL - ERROR_TABLE_BASE_uae)] = EADDRNOTAVAIL;
186 et2sys[(UAENETDOWN - ERROR_TABLE_BASE_uae)] = ENETDOWN;
187 et2sys[(UAENETUNREACH - ERROR_TABLE_BASE_uae)] = ENETUNREACH;
188 et2sys[(UAENETRESET - ERROR_TABLE_BASE_uae)] = ENETRESET;
189 et2sys[(UAECONNABORTED - ERROR_TABLE_BASE_uae)] = ECONNABORTED;
190 et2sys[(UAECONNRESET - ERROR_TABLE_BASE_uae)] = ECONNRESET;
191 et2sys[(UAENOBUFS - ERROR_TABLE_BASE_uae)] = ENOBUFS;
192 et2sys[(UAEISCONN - ERROR_TABLE_BASE_uae)] = EISCONN;
193 et2sys[(UAENOTCONN - ERROR_TABLE_BASE_uae)] = ENOTCONN;
194 et2sys[(UAESHUTDOWN - ERROR_TABLE_BASE_uae)] = ESHUTDOWN;
195 et2sys[(UAETOOMANYREFS - ERROR_TABLE_BASE_uae)] = ETOOMANYREFS;
196 et2sys[(UAETIMEDOUT - ERROR_TABLE_BASE_uae)] = ETIMEDOUT;
197 et2sys[(UAECONNREFUSED - ERROR_TABLE_BASE_uae)] = ECONNREFUSED;
198 et2sys[(UAEHOSTDOWN - ERROR_TABLE_BASE_uae)] = EHOSTDOWN;
199 et2sys[(UAEHOSTUNREACH - ERROR_TABLE_BASE_uae)] = EHOSTUNREACH;
200 et2sys[(UAEALREADY - ERROR_TABLE_BASE_uae)] = EALREADY;
201 et2sys[(UAEINPROGRESS - ERROR_TABLE_BASE_uae)] = EINPROGRESS;
202 et2sys[(UAESTALE - ERROR_TABLE_BASE_uae)] = ESTALE;
203 et2sys[(UAEUCLEAN - ERROR_TABLE_BASE_uae)] = EUCLEAN;
204 et2sys[(UAENOTNAM - ERROR_TABLE_BASE_uae)] = ENOTNAM;
205 et2sys[(UAENAVAIL - ERROR_TABLE_BASE_uae)] = ENAVAIL;
206 et2sys[(UAEISNAM - ERROR_TABLE_BASE_uae)] = EISNAM;
207 et2sys[(UAEREMOTEIO - ERROR_TABLE_BASE_uae)] = EREMOTEIO;
208 et2sys[(UAEDQUOT - ERROR_TABLE_BASE_uae)] = EDQUOT;
209 et2sys[(UAENOMEDIUM - ERROR_TABLE_BASE_uae)] = ENOMEDIUM;
210 et2sys[(UAEMEDIUMTYPE - ERROR_TABLE_BASE_uae)] = EMEDIUMTYPE;
214 et_to_sys_error(afs_int32 in)
216 if (in < ERROR_TABLE_BASE_uae || in >= ERROR_TABLE_BASE_uae + 512)
218 if (et2sys[in - ERROR_TABLE_BASE_uae] != 0)
219 return et2sys[in - ERROR_TABLE_BASE_uae];
223 long cm_MapRPCError(long error, cm_req_t *reqp)
228 /* If we had to stop retrying, report our saved error code. */
229 if (reqp && error == CM_ERROR_TIMEDOUT) {
230 if (reqp->accessError)
231 return reqp->accessError;
232 if (reqp->volumeError)
233 return reqp->volumeError;
235 return reqp->rpcError;
239 error = et_to_sys_error(error);
242 error = CM_ERROR_TIMEDOUT;
243 else if (error == EROFS)
244 error = CM_ERROR_READONLY;
245 else if (error == EACCES)
246 error = CM_ERROR_NOACCESS;
247 else if (error == EXDEV)
248 error = CM_ERROR_CROSSDEVLINK;
249 else if (error == EEXIST)
250 error = CM_ERROR_EXISTS;
251 else if (error == ENOTDIR)
252 error = CM_ERROR_NOTDIR;
253 else if (error == ENOENT)
254 error = CM_ERROR_NOSUCHFILE;
255 else if (error == EAGAIN
256 || error == 35 /* EAGAIN, Digital UNIX */
257 || error == WSAEWOULDBLOCK)
258 error = CM_ERROR_WOULDBLOCK;
259 else if (error == VDISKFULL
261 error = CM_ERROR_SPACE;
262 else if (error == VOVERQUOTA
264 || error == 49 /* EDQUOT on Solaris */
265 || error == 88 /* EDQUOT on AIX */
266 || error == 69 /* EDQUOT on Digital UNIX and HPUX */
267 || error == 122 /* EDQUOT on Linux */
268 || error == 1133) /* EDQUOT on Irix */
269 error = CM_ERROR_QUOTA;
270 else if (error == VNOVNODE)
271 error = CM_ERROR_BADFD;
272 else if (error == EISDIR)
273 return CM_ERROR_ISDIR;
277 long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
282 /* If we had to stop retrying, report our saved error code. */
283 if (reqp && error == CM_ERROR_TIMEDOUT) {
284 if (reqp->accessError)
285 return reqp->accessError;
286 if (reqp->volumeError)
287 return reqp->volumeError;
289 return reqp->rpcError;
293 error = et_to_sys_error(error);
296 error = CM_ERROR_TIMEDOUT;
297 else if (error == EROFS)
298 error = CM_ERROR_READONLY;
299 else if (error == ENOTDIR)
300 error = CM_ERROR_NOTDIR;
301 else if (error == EACCES)
302 error = CM_ERROR_NOACCESS;
303 else if (error == ENOENT)
304 error = CM_ERROR_NOSUCHFILE;
305 else if (error == ENOTEMPTY
306 || error == 17 /* AIX */
307 || error == 66 /* SunOS 4, Digital UNIX */
308 || error == 93 /* Solaris 2, IRIX */
309 || error == 247) /* HP/UX */
310 error = CM_ERROR_NOTEMPTY;
314 long cm_MapVLRPCError(long error, cm_req_t *reqp)
316 if (error == 0) return 0;
318 /* If we had to stop retrying, report our saved error code. */
319 if (reqp && error == CM_ERROR_TIMEDOUT) {
320 if (reqp->accessError)
321 return reqp->accessError;
322 if (reqp->volumeError)
323 return reqp->volumeError;
325 return reqp->rpcError;
329 error = et_to_sys_error(error);
332 error = CM_ERROR_TIMEDOUT;
333 else if (error == VL_NOENT)
334 error = CM_ERROR_NOSUCHVOLUME;
338 cm_space_t *cm_GetSpace(void)
342 if (osi_Once(&cm_utilsOnce)) {
343 lock_InitializeRWLock(&cm_utilsLock, "cm_utilsLock");
344 osi_EndOnce(&cm_utilsOnce);
347 lock_ObtainWrite(&cm_utilsLock);
348 if (tsp = cm_spaceListp) {
349 cm_spaceListp = tsp->nextp;
351 else tsp = (cm_space_t *) malloc(sizeof(cm_space_t));
352 (void) memset(tsp, 0, sizeof(cm_space_t));
353 lock_ReleaseWrite(&cm_utilsLock);
358 void cm_FreeSpace(cm_space_t *tsp)
360 lock_ObtainWrite(&cm_utilsLock);
361 tsp->nextp = cm_spaceListp;
363 lock_ReleaseWrite(&cm_utilsLock);
366 /* This is part of the Microsoft Internationalized Domain Name
368 #include <normalization.h>
371 (WINAPI *pNormalizeString)( __in NORM_FORM NormForm,
372 __in_ecount(cwSrcLength) LPCWSTR lpSrcString,
373 __in int cwSrcLength,
374 __out_ecount(cwDstLength) LPWSTR lpDstString,
375 __in int cwDstLength ) = NULL;
378 (WINAPI *pIsNormalizedString)( __in NORM_FORM NormForm,
379 __in_ecount(cwLength) LPCWSTR lpString,
380 __in int cwLength ) = NULL;
383 #define NLSDLLNAME "Normaliz.dll"
384 #define NLSMAXCCH 1024
387 #define AFS_NORM_FORM NormalizationC
389 long cm_InitNormalization(void)
393 if (pNormalizeString != NULL)
396 h_Nls = LoadLibrary(NLSDLLNAME);
397 if (h_Nls == INVALID_HANDLE_VALUE) {
398 afsi_log("Can't load " NLSDLLNAME ": LastError=%d", GetLastError());
402 pNormalizeString = GetProcAddress(h_Nls, "NormalizeString");
403 pIsNormalizedString = GetProcAddress(h_Nls, "IsNormalizedString");
405 return (pNormalizeString && pIsNormalizedString);
408 /* \brief Normalize a UTF-16 string.
410 If the supplied destination buffer is
411 insufficient or NULL, then a new buffer will be allocated to hold
412 the normalized string.
414 \param[in] src : Source UTF-16 string. Length is specified in
417 \param[in] cch_src : The character count in cch_src is assumed to
418 be tight and include the terminating NULL character if there is
419 one. If the NULL is absent, the resulting string will not be
422 \param[out] ext_dest : The destination buffer. Can be NULL, in
423 which case *pcch_dest MUST be NULL.
425 \param[in,out] pcch_dest : On entry *pcch_dest contains a count of
426 characters in the destination buffer. On exit, it will contain
427 a count of characters that were copied to the destination
430 Returns a pointer to the buffer containing the normalized string or
431 NULL if the call was unsuccessful. If the returned destination
432 buffer is different fron the supplied buffer and non-NULL, it
433 should be freed using free().
436 NormalizeUtf16String(const wchar_t * src, int cch_src, wchar_t * ext_dest, int *pcch_dest)
438 if ((pIsNormalizedString && (*pIsNormalizedString)(AFS_NORM_FORM, src, cch_src)) ||
439 (!pNormalizeString)) {
445 int cch_dest = *pcch_dest;
449 while (tries-- > 0) {
451 rv = (*pNormalizeString)(AFS_NORM_FORM, src, cch_src, dest, cch_dest);
453 if (rv <= 0 && (gle = GetLastError()) != ERROR_SUCCESS) {
455 osi_Log1(afsd_logp, "NormalizeUtf16String error = %d", gle);
457 if (gle == ERROR_INSUFFICIENT_BUFFER) {
459 /* The buffer wasn't big enough. We are going to
460 try allocating one. */
462 cch_dest = (-rv) + NLSERRCCH;
466 /* Something else is wrong */
470 } else if (rv < 0) { /* rv < 0 && gle == ERROR_SUCCESS */
472 /* Technically not one of the expected outcomes */
475 } else { /* rv > 0 || (rv == 0 && gle == ERROR_SUCCESS) */
477 /* Possibly succeeded */
479 if (rv == 0) { /* Succeeded and the return string is empty */
485 /* Nope. We only calculated the required size of the buffer */
487 cch_dest = rv + NLSERRCCH;
498 if (dest != ext_dest && dest)
500 dest = malloc(cch_dest * sizeof(wchar_t));
505 if (dest != ext_dest && dest)
512 /* No need to or unable to normalize. Just copy the string */
513 if (SUCCEEDED(StringCchCopyNW(ext_dest, *pcch_dest, src, cch_src))) {
514 *pcch_dest = cch_src;
523 /* \brief Normalize a UTF-16 string into a UTF-8 string.
525 \param[in] src : Source string.
527 \param[in] cch_src : Count of characters in src. If the count includes the
528 NULL terminator, then the resulting string will be NULL
529 terminated. If it is -1, then src is assumed to be NULL
532 \param[out] adest : Destination buffer.
534 \param[in] cch_adest : Number of characters in the destination buffer.
536 Returns the number of characters stored into cch_adest. This will
537 include the terminating NULL if cch_src included the terminating
538 NULL or was -1. If this is 0, then the operation was unsuccessful.
540 long cm_NormalizeUtf16StringToUtf8(const wchar_t * src, int cch_src,
541 char * adest, int cch_adest)
546 if (FAILED(StringCchLengthW(src, NLSMAXCCH, &cch)))
547 return CM_ERROR_TOOBIG;
553 wchar_t nbuf[NLSMAXCCH];
554 wchar_t * normalized;
555 int cch_norm = NLSMAXCCH;
557 normalized = NormalizeUtf16String(src, cch_src, nbuf, &cch_norm);
559 cch_adest = WideCharToMultiByte(CP_UTF8, 0, normalized, cch_norm,
560 adest, cch_adest, NULL, 0);
562 if (normalized != nbuf && normalized)
576 /* \brief Normalize a UTF-8 string.
578 \param[in] src String to normalize.
580 \param[in] cch_src : Count of characters in src. If this value is
581 -1, then src is assumed to be NULL terminated. The translated
582 string will be NULL terminated only if this is -1 or the count
583 includes the terminating NULL.
585 \param[out] adest : Destination string.
587 \param[in] cch_adest : Number of characters in the destination
590 Returns the number of characters stored into adest or 0 if the call
593 long cm_NormalizeUtf8String(const char * src, int cch_src,
594 char * adest, int cch_adest)
596 wchar_t wsrcbuf[NLSMAXCCH];
601 /* Get some edge cases out first, so we don't have to worry about
602 cch_src being 0 etc. */
605 } else if (*src == '\0') {
610 cch = MultiByteToWideChar(CP_UTF8, 0, src, cch_src * sizeof(char),
621 wnorm = NormalizeUtf16String(wsrcbuf, cch, NULL, &cch_norm);
629 cch = WideCharToMultiByte(CP_UTF8, 0, wnorm, cch_norm,
630 adest, cch_adest * sizeof(char),