nsresult nsCollationWin::AllocateRawSortKey(PRInt32 strength, 
                                            const nsAString& stringIn, PRUint8** key, PRUint32* outLen)
{
  int byteLen;
  void *buffer;
  nsresult res = NS_OK;
  DWORD dwMapFlags = LCMAP_SORTKEY;

  if (strength == kCollationCaseInSensitive)
    dwMapFlags |= NORM_IGNORECASE;

  byteLen = LCMapStringW(mLCID, dwMapFlags, 
                         (LPCWSTR) PromiseFlatString(stringIn).get(),
                         -1, NULL, 0);
  buffer = PR_Malloc(byteLen);
  if (!buffer) {
    res = NS_ERROR_OUT_OF_MEMORY;
  } else {
    *key = (PRUint8 *)buffer;
    *outLen = LCMapStringW(mLCID, dwMapFlags, 
                           (LPCWSTR) PromiseFlatString(stringIn).get(),
                           -1, (LPWSTR) buffer, byteLen);
  }
  return res;
}
Example #2
0
QCollatorSortKey QCollator::sortKey(const QString &string) const
{
    if (d->dirty)
        d->init();

#ifndef USE_COMPARESTRINGEX
    int size = LCMapStringW(d->localeID, LCMAP_SORTKEY | d->collator,
                           reinterpret_cast<const wchar_t*>(string.constData()), string.size(),
                           0, 0);
#else
    int size = LCMapStringEx(LPCWSTR(d->localeName.utf16()), LCMAP_SORTKEY | d->collator,
                           reinterpret_cast<LPCWSTR>(string.constData()), string.size(),
                           0, 0, NULL, NULL, 0);
#endif
    QString ret(size, Qt::Uninitialized);
#ifndef USE_COMPARESTRINGEX
    int finalSize = LCMapStringW(d->localeID, LCMAP_SORTKEY | d->collator,
                           reinterpret_cast<const wchar_t*>(string.constData()), string.size(),
                           reinterpret_cast<wchar_t*>(ret.data()), ret.size());
#else
    int finalSize = LCMapStringEx(LPCWSTR(d->localeName.utf16()), LCMAP_SORTKEY | d->collator,
                           reinterpret_cast<LPCWSTR>(string.constData()), string.size(),
                           reinterpret_cast<LPWSTR>(ret.data()), ret.size(),
                           NULL, NULL, 0);
#endif
    if (finalSize == 0) {
        qWarning() << "there were problems when generating the ::sortKey by LCMapStringW with error:" << GetLastError();
    }
    return QCollatorSortKey(new QCollatorSortKeyPrivate(ret));
}
Example #3
0
 inline std::wstring win_map_string_l(unsigned flags,wchar_t const *begin,wchar_t const *end,winlocale const &l)
 {
     std::wstring res;
     int len = LCMapStringW(l.lcid,flags,begin,end-begin,0,0);
     if(len == 0)
         return res;
     std::vector<wchar_t> buf(len+1);
     int l2 = LCMapStringW(l.lcid,flags,begin,end-begin,&buf.front(),buf.size());
     res.assign(&buf.front(),l2);
     return res;
 }
Example #4
0
VOID
WINAPI
SvchostCharLowerW (
    _In_ LPCWSTR lpSrcStr
    )
{
    DWORD cchSrc;

    /* If there's nothing to do, bail out */
    if (lpSrcStr == NULL) return;

    /* Get the length of the input string */
    cchSrc = wcslen(lpSrcStr);

    /* Call the locale API to lower-case it */
    if (LCMapStringW(LANG_USER_DEFAULT,
                     LCMAP_LOWERCASE,
                     lpSrcStr,
                     cchSrc + 1,
                     (LPWSTR)lpSrcStr,
                     cchSrc + 1) == FALSE)
    {
        DBG_ERR("SvchostCharLowerW failed for %ws\n", lpSrcStr);
    }
}
Example #5
0
  wint_t _Locale_wchar_toupper(struct _Locale_ctype* ltype, wint_t c)
  {
    wint_t res;

    LCMapStringW(ltype->lcid, LCMAP_UPPERCASE, &c, 1, &res, 1);
    return res;
  }
Example #6
0
DWORD WINAPI CharLowerBuffW(
    LPWSTR pwsz,
    DWORD cwch)
{
    int cwchT;
    DWORD i;

    if (cwch == 0) {
        return 0;
    }

    cwchT = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
                pwsz, cwch, pwsz, cwch);

    if (cwchT != 0) {
        return cwchT;
    }

    /*
     * LCMapString failed!  The caller is not expecting failure,
     * CharLowerBuffW does not have a failure indicator, so we
     * convert the buffer to lower case as best we can.
     */
    RIPMSG1(RIP_WARNING, "CharLowerBuffW(%ls) failed", pwsz);

    for (i=0; i < cwch; i++) {
        if (IS_UNICODE_BLK1(pwsz[i]) && IsCharUpperA((char)pwsz[i])) {
            pwsz[i] += 'a'-'A';
        }
    }

    return cwch;
}
Example #7
0
static HRESULT lcid_to_rfc1766(LCID lcid, WCHAR *rfc1766, INT len)
{
    WCHAR buffer[6 /* MAX_RFC1766_NAME */];
    INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, ARRAY_SIZE(buffer));
    INT i;

    if (n)
    {
        i = PRIMARYLANGID(lcid);
        if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
            (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
            (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {

            buffer[n - 1] = '-';
            i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, ARRAY_SIZE(buffer) - n);
            if (!i)
                buffer[n - 1] = '\0';
        }
        else
            i = 0;

        LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
        return ((n + i) > len) ? E_INVALIDARG : S_OK;
    }
    return E_FAIL;
}
Example #8
0
bool Cx_TextUtil::ToDBC(std::wstring& text, bool punct)
{
	bool changed = false;
	std::wstring dest('\0', text.size() + 1);

	if (!text.empty() && punct)
	{
		int ret = LCMapStringW(
			MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), 
			LCMAP_HALFWIDTH, 
			text.c_str(), text.size(), 
			&dest[0], dest.size() + 1);

		if (ret > 0 && dest != text)
		{
			text = dest;
			changed = true;
		}
	}
	else if (!text.empty())
	{
		LPCWSTR psrc = text.c_str();
		LPWSTR pdest = &dest[0];
		int i = 0, n = 0;

		for (; psrc[i] != 0; i++)
		{
			if (psrc[i] >= 0xA3B0 && psrc[i] <= 0xA3B9)		// £°..£¹
			{
				pdest[i] = WCHAR('0' + psrc[i] - 0xA3B0);
				n++;
			}
			else if (psrc[i] >= 0xA3C1 && psrc[i] <= 0xA3DA)	// £Á..£Ú
			{
				pdest[i] = WCHAR('A' + psrc[i] - 0xA3C1);
				n++;
			}
			else if (psrc[i] >= 0xA3E1 && psrc[i] <= 0xA3FA)	// £á..£ú
			{
				pdest[i] = WCHAR('a' + psrc[i] - 0xA3E1);
				n++;
			}
			else
			{
				pdest[i] = psrc[i];
			}
		}
		pdest[i] = 0;

		if (n > 0)
		{
			text = dest;
			changed = true;
		}
	}

	return changed;
}
Example #9
0
/*********************************************************************
 *    __crtLCMapStringW (MSVCRT.@)
 */
int __crtLCMapStringW(
  LCID lcid, DWORD mapflags, LPCWSTR src, int srclen, LPWSTR dst,
  int dstlen, unsigned int codepage, int xflag
) {
  TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
        lcid,mapflags,src,srclen,dst,dstlen,codepage,xflag);

  return LCMapStringW(lcid,mapflags,src,srclen,dst,dstlen);
}
Example #10
0
int env_strncmp(const wchar_t* a, int na, const wchar_t* b) {
  wchar_t* a_eq;
  wchar_t* b_eq;
  wchar_t* A;
  wchar_t* B;
  int nb;
  int r;

  if (na < 0) {
    a_eq = wcschr(a, L'=');
    assert(a_eq);
    na = (int)(long)(a_eq - a);
  } else {
    na--;
  }
  b_eq = wcschr(b, L'=');
  assert(b_eq);
  nb = b_eq - b;

  A = alloca((na+1) * sizeof(wchar_t));
  B = alloca((nb+1) * sizeof(wchar_t));

  r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, a, na, A, na);
  assert(r==na);
  A[na] = L'\0';
  r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, b, nb, B, nb);
  assert(r==nb);
  B[nb] = L'\0';

  while (1) {
    wchar_t AA = *A++;
    wchar_t BB = *B++;
    if (AA < BB) {
      return -1;
    } else if (AA > BB) {
      return 1;
    } else if (!AA && !BB) {
      return 0;
    }
  }
}
Example #11
0
/*
=======================================
    LCMapStringEx
=======================================
*/
int __stdcall
myLCMapStringEx (
  __CR_IN__ void*           lpLocaleName,
  __CR_IN__ unsigned long   dwMapFlags,
  __CR_IN__ void*           lpSrcStr,
  __CR_IN__ int             cchSrc,
  __CR_IN__ void*           lpDestStr,
  __CR_IN__ int             cchDest,
  __CR_IN__ void*           lpVersionInformation,
  __CR_IN__ void*           lpReserved,
  __CR_IN__ unsigned long   sortHandle
    )
{
    CR_NOUSE(lpVersionInformation);
    CR_NOUSE(lpReserved); CR_NOUSE(sortHandle);
    return (LCMapStringW(myLocaleNameToLCID(lpLocaleName), dwMapFlags,
                         lpSrcStr, cchSrc, lpDestStr, cchDest));
}
Example #12
0
int wcs2mbs( unsigned int codepage, const unsigned short* src, int srclen, char* dst, int dstlen, bool* usedDefChar )
{
	BOOL usedDefaultChar = FALSE;
	int ret = WideCharToMultiByte(codepage, WC_COMPOSITECHECK, (LPCWSTR)src, srclen, dst, dstlen-1, "?", &usedDefaultChar);
	
	if( usedDefaultChar && (codepage == 950 || codepage == 932) )	// BIG5(TW) or SHIFT-JIS(JP)
	{
		if( srclen<0 ) srclen = wcslen((LPCWSTR)src);

		wchar_t* convsrc = new wchar_t[srclen+1];
		int rett = LCMapStringW( 0x804, LCMAP_TRADITIONAL_CHINESE, (LPCWSTR)src, srclen, convsrc, srclen ) ;

		ret = WideCharToMultiByte(codepage, WC_COMPOSITECHECK, convsrc, srclen, dst, dstlen-1, "?", &usedDefaultChar);
		delete[] convsrc;
	}

	dst[ret] = 0;
	if(usedDefChar) *usedDefChar = usedDefaultChar!=FALSE;
	return ret;
}
Example #13
0
LPWSTR WINAPI CharLowerW(
    LPWSTR pwsz)
{
    /*
     * Early out for NULL string or '\0'
     */
    if (pwsz == NULL) {
        return pwsz;
    }

    if (!IS_PTR(pwsz)) {
        if (!LCMapStringW(
                 LOCALE_USER_DEFAULT,
                 LCMAP_LOWERCASE,
                 (LPWSTR)&pwsz,
                 1,
                 (LPWSTR)&pwsz,
                 1
                 )) {
            /*
             * We don't expect LCMapString to fail!  The caller is not expecting
             * failure, CharLowerW does not have a failure indicator, so we do
             * nothing.
             */
            RIPMSG1(RIP_WARNING, "CharLowerW(%#p): LCMapString failed\n", pwsz);
        }

        return pwsz;
    }

    /*
     * pwsz is a null-terminated string
     */
    CharLowerBuffW(pwsz, wcslen(pwsz)+1);
    return pwsz;
}
Example #14
0
int __cdecl __crtLCMapStringA(
        LCID     Locale,
        DWORD    dwMapFlags,
        LPCSTR   lpSrcStr,
        int      cchSrc,
        LPSTR    lpDestStr,
        int      cchDest,
        int      code_page,
        BOOL     bError
        )
{
        static int f_use = 0;

        /*
         * Look for unstubbed 'preferred' flavor. Otherwise use available flavor.
         * Must actually call the function to ensure it's not a stub.
         * (Always try wide version first so WinNT can process codepage correctly.)
         */

        if (0 == f_use) {
            if (0 != LCMapStringW(0, LCMAP_LOWERCASE, L"\0", 1, NULL, 0))
                f_use = USE_W;
            else if (0 != LCMapStringA(0, LCMAP_LOWERCASE, "\0", 1, NULL, 0))
                f_use = USE_A;
            else
                return 0;
        }

        /*
         * LCMapString will map past NULL. Must find NULL if in string
         * before cchSrc characters.
         */
        if (cchSrc > 0)
            cchSrc = strncnt(lpSrcStr, cchSrc);

        /* Use "A" version */

        if (USE_A == f_use) {
            return LCMapStringA( Locale, dwMapFlags, lpSrcStr, cchSrc,
                                 lpDestStr, cchDest );
        }

        /* Use "W" version */

        if (USE_W == f_use)
        {
            int retval;
            int inbuff_size;
            int outbuff_size;
            wchar_t *inwbuffer;
            wchar_t *outwbuffer;

            /*
             * Convert string and return the requested information. Note that
             * we are converting to a wide string so there is not a
             * one-to-one correspondence between number of wide chars in the
             * input string and the number of *bytes* in the buffer. However,
             * there had *better be* a one-to-one correspondence between the
             * number of wide characters and the number of multibyte characters
             * or the resulting mapped string will be worthless to the user.
             */

            /*
             * Use __lc_codepage for conversion if code_page not specified
             */

            if (0 == code_page)
                code_page = __lc_codepage;

            /* find out how big a buffer we need (includes NULL if any) */
            if ( 0 == (inbuff_size =
                       MultiByteToWideChar( code_page,
                                            bError ? MB_PRECOMPOSED |
                                                MB_ERR_INVALID_CHARS :
                                                MB_PRECOMPOSED,
                                            lpSrcStr,
                                            cchSrc,
                                            NULL,
                                            0 )) )
                return 0;

            /* allocate enough space for wide chars */
            __try {
                inwbuffer = (wchar_t *)_alloca( inbuff_size * sizeof(wchar_t) );
            }
            __except(EXCEPTION_EXECUTE_HANDLER) {
                inwbuffer = NULL;
            }

            if ( inwbuffer == NULL )
                return 0;

            /* do the conversion */
            if ( 0 == MultiByteToWideChar( code_page,
                                           MB_PRECOMPOSED,
                                           lpSrcStr,
                                           cchSrc,
                                           inwbuffer,
                                           inbuff_size) )
                return 0;

            /* get size required for string mapping */
            if ( 0 == (retval = LCMapStringW( Locale,
                                              dwMapFlags,
                                              inwbuffer,
                                              inbuff_size,
                                              NULL,
                                              0 )) )
                return 0;

            if (dwMapFlags & LCMAP_SORTKEY) {
                /* retval is size in BYTES */

                if (0 != cchDest) {

                    if (retval > cchDest)
                        return 0;

                    /* do string mapping */
                    if ( 0 == LCMapStringW( Locale,
                                            dwMapFlags,
                                            inwbuffer,
                                            inbuff_size,
                                            (LPWSTR)lpDestStr,
                                            cchDest ) )
                        return 0;
                }
            }
            else {
                /* retval is size in wide chars */

                outbuff_size = retval;

                /* allocate enough space for wide chars (includes NULL if any) */
                __try {
                    outwbuffer = (wchar_t *)_alloca( outbuff_size * sizeof(wchar_t) );
                }
                __except(EXCEPTION_EXECUTE_HANDLER) {
                    outwbuffer = NULL;
                }

                if ( outwbuffer == NULL )
                    return 0;

                /* do string mapping */
                if ( 0 == LCMapStringW( Locale,
                                        dwMapFlags,
                                        inwbuffer,
                                        inbuff_size,
                                        outwbuffer,
                                        outbuff_size ) )
                    return 0;

                if (0 == cchDest) {
                    /* get size required */
                    if ( 0 == (retval =
                               WideCharToMultiByte( code_page,
                                                    WC_COMPOSITECHECK |
                                                        WC_SEPCHARS,
                                                    outwbuffer,
                                                    outbuff_size,
                                                    NULL,
                                                    0,
                                                    NULL,
                                                    NULL )) )
                        return 0;
                }
                else {
                    /* convert mapping */
                    if ( 0 == (retval =
                               WideCharToMultiByte( code_page,
                                                    WC_COMPOSITECHECK |
                                                        WC_SEPCHARS,
                                                    outwbuffer,
                                                    outbuff_size,
                                                    lpDestStr,
                                                    cchDest,
                                                    NULL,
                                                    NULL )) )
                        return 0;
                }
            }

            return retval;
        }
Example #15
0
static int __cdecl __crtLCMapStringW_stat(
    _locale_t plocinfo,
    LCID     Locale,
    DWORD    dwMapFlags,
    LPCWSTR  lpSrcStr,
    int      cchSrc,
    LPWSTR   lpDestStr,
    int      cchDest,
    int      code_page
) {
    static int f_use = 0;

    /*
     * Look for unstubbed 'preferred' flavor. Otherwise use available flavor.
     * Must actually call the function to ensure it's not a stub.
     */

    if (0 == f_use) {
        if (0 != LCMapStringW(0, LCMAP_LOWERCASE, L"\0", 1, NULL, 0)) {
            f_use = USE_W;
        } else if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
            f_use = USE_A;
        }
    }

    /*
     * LCMapString will map past NULL. Must find NULL if in string
     * before cchSrc wide characters.
     */
    if (cchSrc > 0) {
        cchSrc = wcsncnt(lpSrcStr, cchSrc);
    }

    /* Use "W" version */

    if (USE_W == f_use) {
        return LCMapStringW(Locale, dwMapFlags, lpSrcStr, cchSrc,
                            lpDestStr, cchDest);
    }

    /* Use "A" version */

    if (USE_A == f_use || f_use == 0) {
        int retval = 0;
        int inbuff_size;
        int outbuff_size;
        unsigned char* inbuffer = NULL;
        unsigned char* outbuffer = NULL;
        int AnsiCP = 0;

        /*
         * Convert string and return the requested information. Note that
         * we are converting to a multibyte string so there is not a
         * one-to-one correspondence between number of wide chars in the
         * input string and the number of *bytes* in the buffer. However,
         * there had *better be* a one-to-one correspondence between the
         * number of wide characters and the number of multibyte characters
         * (enforced by WC_SEPCHARS) in the buffer or the resulting mapped
         * string will be worthless to the user.
         *
         */

        /*
         * Use __lc_codepage for conversion if code_page not specified
         */

        if (0 == Locale) {
            Locale = plocinfo->locinfo->lc_handle[LC_CTYPE];
        }

        if (0 == code_page) {
            code_page = plocinfo->locinfo->lc_codepage;
        }

        /*
         * Always use Ansi codepage with Ansi WinAPI because they use
         * Ansi codepage
         */
        if (code_page != (AnsiCP = __ansicp(Locale))) {
            if (AnsiCP != -1) {
                code_page = AnsiCP;
            }
        }

        /* find out how big a buffer we need (includes NULL if any) */
        if (0 == (inbuff_size = WideCharToMultiByte(code_page,
                                0,
                                lpSrcStr,
                                cchSrc,
                                NULL,
                                0,
                                NULL,
                                NULL))) {
            return 0;
        }

        /* allocate enough space for chars */
        inbuffer = (unsigned char*)_calloca(inbuff_size, sizeof(char));

        if (inbuffer == NULL) {
            return 0;
        }

        /* do the conversion */
        if (0 ==  WideCharToMultiByte(code_page,
                                      0,
                                      lpSrcStr,
                                      cchSrc,
                                      (char*)inbuffer,
                                      inbuff_size,
                                      NULL,
                                      NULL)) {
            goto error_cleanup;
        }

        /* get size required for string mapping */
        if (0 == (outbuff_size = LCMapStringA(Locale,
                                              dwMapFlags,
                                              (const char*)inbuffer,
                                              inbuff_size,
                                              NULL,
                                              0))) {
            goto error_cleanup;
        }

        /* allocate enough space for chars and NULL */
        outbuffer = (unsigned char*)_calloca(outbuff_size, sizeof(char));

        if (outbuffer == NULL) {
            goto error_cleanup;
        }

        /* do string mapping */
        if (0 == LCMapStringA(Locale,
                              dwMapFlags,
                              (const char*)inbuffer,
                              inbuff_size,
                              (char*)outbuffer,
                              outbuff_size)) {
            goto error_cleanup;
        }

        if (dwMapFlags & LCMAP_SORTKEY) {
            /* outbuff_size > cchDest is allowed */
            retval = outbuff_size;

            if (0 != cchDest)
                /* SORTKEY returns BYTES, just copy */
                _ERRCHECK(strncpy_s((char*)lpDestStr,
                                    cchDest,
                                    (char*)outbuffer,
                                    cchDest <= outbuff_size ? cchDest - 1 : outbuff_size));
        } else {
            if (0 == cchDest) {
                /* get size required */
                if (0 == (retval = MultiByteToWideChar(code_page,
                                                       MB_PRECOMPOSED,
                                                       (const char*)outbuffer,
                                                       outbuff_size,
                                                       NULL,
                                                       0))) {
                    goto error_cleanup;
                }
            } else {
                /* convert mapping */
                if (0 == (retval = MultiByteToWideChar(code_page,
                                                       MB_PRECOMPOSED,
                                                       (const char*)outbuffer,
                                                       outbuff_size,
                                                       lpDestStr,
                                                       cchDest))) {
                    goto error_cleanup;
                }
            }
        }

    error_cleanup:

        if (outbuffer != NULL) {
            _freea(outbuffer);
        }

        _freea(inbuffer);
        return retval;
    } else { /* f_use is neither USE_A nor USE_W */
        return 0;
    }
}
Example #16
0
 size_t _Locale_strwxfrm(struct _Locale_collate* lcol,
                         wchar_t* dst, size_t dst_size,
                         const wchar_t* src, size_t src_size) {
   return LCMapStringW(lcol->lcid, LCMAP_SORTKEY, src, src_size, dst, dst_size);
 }
int __cdecl __crtLCMapStringW(
        LCID     Locale,
        DWORD    dwMapFlags,
        LPCWSTR  lpSrcStr,
        int      cchSrc,
        LPWSTR   lpDestStr,
        int      cchDest,
        int      code_page
        )
{
        static int f_use = 0;

        /*
         * Look for unstubbed 'preferred' flavor. Otherwise use available flavor.
         * Must actually call the function to ensure it's not a stub.
         */

        if (0 == f_use) {
            if (0 != LCMapStringW(0, LCMAP_LOWERCASE, L"\0", 1, NULL, 0))
                f_use = USE_W;
            else if (0 != LCMapStringA(0, LCMAP_LOWERCASE, "\0", 1, NULL, 0))
                f_use = USE_A;
            else
                return 0;
        }

        /*
         * LCMapString will map past NULL. Must find NULL if in string
         * before cchSrc wide characters.
         */
        if (cchSrc > 0)
            cchSrc = wcsncnt(lpSrcStr, cchSrc);

        /* Use "W" version */

        if (USE_W == f_use) {
            return LCMapStringW( Locale, dwMapFlags, lpSrcStr, cchSrc,
                                 lpDestStr, cchDest );
        }

        /* Use "A" version */

        if (USE_A == f_use) {

            int retval;
            int inbuff_size;
            int outbuff_size;
            unsigned char *inbuffer;
            unsigned char *outbuffer;

            /*
             * Convert string and return the requested information. Note that
             * we are converting to a multibyte string so there is not a
             * one-to-one correspondence between number of wide chars in the
             * input string and the number of *bytes* in the buffer. However,
             * there had *better be* a one-to-one correspondence between the
             * number of wide characters and the number of multibyte characters
             * (enforced by WC_SEPCHARS) in the buffer or the resulting mapped
             * string will be worthless to the user.
             *
             */

            /*
             * Use __lc_codepage for conversion if code_page not specified
             */

            if (0 == code_page)
                code_page = __lc_codepage;

            /* find out how big a buffer we need (includes NULL if any) */
            if ( 0 == (inbuff_size = WideCharToMultiByte( code_page,
                                                          WC_COMPOSITECHECK |
                                                            WC_SEPCHARS,
                                                          lpSrcStr,
                                                          cchSrc,
                                                          NULL,
                                                          0,
                                                          NULL,
                                                          NULL )) )
                return 0;

            /* allocate enough space for chars */
            __try {
                inbuffer = (unsigned char *)_alloca( inbuff_size * sizeof(char) );
            }
            __except(EXCEPTION_EXECUTE_HANDLER) {
                inbuffer = NULL;
            }

            if ( inbuffer == NULL )
                return 0;

            /* do the conversion */
            if ( 0 ==  WideCharToMultiByte( code_page,
                                            WC_COMPOSITECHECK | WC_SEPCHARS,
                                            lpSrcStr,
                                            cchSrc,
                                            inbuffer,
                                            inbuff_size,
                                            NULL,
                                            NULL ) )
                return 0;

            /* get size required for string mapping */
            if ( 0 == (outbuff_size = LCMapStringA( Locale,
                                                    dwMapFlags,
                                                    inbuffer,
                                                    inbuff_size,
                                                    NULL,
                                                    0 )) )
                return 0;

            /* allocate enough space for chars and NULL */
            __try {
                outbuffer = (unsigned char *)_alloca( outbuff_size * sizeof(char) );
            }
            __except(EXCEPTION_EXECUTE_HANDLER) {
                outbuffer = NULL;
            }

            if ( outbuffer == NULL )
                return 0;

            /* do string mapping */
            if ( 0 == LCMapStringA( Locale,
                                    dwMapFlags,
                                    inbuffer,
                                    inbuff_size,
                                    outbuffer,
                                    outbuff_size ) )
                return 0;

            if (dwMapFlags & LCMAP_SORTKEY) {

                /* outbuff_size > cchDest is allowed */
                retval = outbuff_size;

                if (0 != cchDest)
                    /* SORTKEY returns BYTES, just copy */
                    strncpy( (char *)lpDestStr,
                             (char *)outbuffer,
                             cchDest < outbuff_size ? cchDest : outbuff_size );
            }
            else {
                if (0 == cchDest) {
                    /* get size required */
                    if ( 0 == (retval = MultiByteToWideChar( code_page,
                                                             MB_PRECOMPOSED,
                                                             outbuffer,
                                                             outbuff_size,
                                                             NULL,
                                                             0 )) )
                        return 0;
                }
                else {
                    /* convert mapping */
                    if ( 0 == (retval = MultiByteToWideChar( code_page,
                                                             MB_PRECOMPOSED,
                                                             outbuffer,
                                                             outbuff_size,
                                                             lpDestStr,
                                                             cchDest )) )
                        return 0;
                }
            }

            return retval;
        }