예제 #1
0
파일: chartran.c 프로젝트: conioh/os-design
int
WCSToMBEx(
    WORD wCodePage,
    LPCWSTR pUnicodeString,
    int cchUnicodeString,
    LPSTR *ppAnsiString,
    int nAnsiChar,
    BOOL bAllocateMem)
{
    ULONG nCharsInAnsiString;
#ifdef _USERK_
    INT iCharsInAnsiString;
#endif // _USERK_

    if (nAnsiChar == 0 || cchUnicodeString == 0 || pUnicodeString == NULL) {
        return 0;      // nothing to translate or nowhere to put it
    }

    /*
     * Adjust the cchUnicodeString value.  If cchUnicodeString == -1 then the
     * string pointed to by pUnicodeString is NUL terminated so we
     * count the number of bytes.  If cchUnicodeString < -1 this is an
     * illegal value so we return FALSE.  Otherwise, cchUnicodeString is
     * set and requires no adjustment.
     */
    if (cchUnicodeString == -1) {
        cchUnicodeString = (wcslen(pUnicodeString) + 1);
    } else if (cchUnicodeString < -1) {
        return 0;     // illegal value
    }

    /*
     * Adjust the nAnsiChar value.  If nAnsiChar == -1 then we pick a
     * value based on cchUnicodeString to hold the converted string.  If
     * nAnsiChar < -1 this is an illegal value so we return FALSE.
     * Otherwise, nAnsiChar is set and requires no adjustment.
     */
    if (nAnsiChar == -1) {
        if (bAllocateMem == FALSE) {
            return 0;  // no destination
        }
        nAnsiChar = cchUnicodeString * DBCS_CHARSIZE;
    } else if (nAnsiChar < -1) {
        return 0;     // illegal value
    }

    if (bAllocateMem) {
        /*
         * We need to allocate memory to hold the translated string.
         */
        *ppAnsiString = (LPSTR)UserRtlAllocMem(nAnsiChar);
        if (*ppAnsiString == NULL) {
            return 0;
        }
    }

    /*
     * translate Unicode string pointed to by pUnicodeString into
     * ANSI and store in location pointed to by pAnsiString.  We
     * stop translating when we fill up the ANSI buffer or reach
     * the end of the Unicode string.
     */

    /*
     * if the target multibyte codepage is eqaul to ACP, Call faster Rtl function.
     */
    if (IS_ACP(wCodePage)) {

        NTSTATUS Status;

        Status = RtlUnicodeToMultiByteN(
                        (PCH)*ppAnsiString,
                        nAnsiChar,
                        &nCharsInAnsiString,
                        (PWCH)pUnicodeString,
                        cchUnicodeString * sizeof(WCHAR));
        /*
         * If the ansi buffer is too small, RtlUnicodeToMultiByteN()
         * returns STATUS_BUFFER_OVERFLOW. In this case, the function
         * put as many ansi characters as specified in the buffer and
         *  returns the number by chacacters(in bytes) written. We would
         * like to return the actual byte  count written in the ansi
         * buffer rather than returnning 0 since callers of this function
         * don't expect to be returned 0 in most case.
         */

        if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
            if (bAllocateMem) {
                UserRtlFreeMem(*ppAnsiString);
            }
            return 0;   // translation failed
        }

        return (int)nCharsInAnsiString;

    } else {

#ifdef _USERK_
        /*
         * Call GRE to convert string to Unicode. (Kernel mode)
         */

        iCharsInAnsiString = EngWideCharToMultiByte(
                                 (UINT)wCodePage,
                                 (LPWSTR)pUnicodeString,
                                 cchUnicodeString * sizeof(WCHAR),
                                 (LPSTR)*ppAnsiString,
                                 nAnsiChar);

        nCharsInAnsiString = (iCharsInAnsiString == -1) ? 0 :
                                                          (ULONG) iCharsInAnsiString;

#else
        /*
         * Call NLS API (Kernel32) to convert string to Unicode. (User mode)
         */
        nCharsInAnsiString = WideCharToMultiByte(
                                 (UINT)wCodePage, 0,
                                 (LPCWSTR)pUnicodeString,
                                 cchUnicodeString,
                                 (LPSTR)*ppAnsiString,
                                 nAnsiChar,
                                 NULL, NULL);
#endif // _USERK_

        if (nCharsInAnsiString == 0) {
            if (bAllocateMem) {
                UserRtlFreeMem(*ppAnsiString);
            }
        }

        return (int)nCharsInAnsiString;
    }
}
예제 #2
0
int wvsprintfA(
    LPSTR lpOut,
    LPCSTR lpFmt,
    va_list arglist)
{
    BOOL fAllocateMem;
    char prefix, fillch;
    int left, width, prec, size, sign, radix, upper, hprefix;
    int cchLimit = WSPRINTF_LIMIT, cch;
    LPSTR lpT, lpTMB;
    LPWSTR pwsz;
    va_list varglist = arglist;
    union {
        long l;
        unsigned long ul;
        char sz[2];
        WCHAR wsz[2];
    } val;

    while (*lpFmt != 0) {
        if (*lpFmt == '%') {

            /*
             * read the flags.  These can be in any order
             */
            left = 0;
            prefix = 0;
            while (*++lpFmt) {
                if (*lpFmt == '-')
                    left++;
                else if (*lpFmt == '#')
                    prefix++;
                else
                    break;
            }

            /*
             * find fill character
             */
            if (*lpFmt == '0') {
                fillch = '0';
                lpFmt++;
            } else
                fillch = ' ';

            /*
             * read the width specification
             */
            lpFmt = SP_GetFmtValue((LPCSTR)lpFmt, &cch);
            width = cch;

            /*
             * read the precision
             */
            if (*lpFmt == '.') {
                lpFmt = SP_GetFmtValue((LPCSTR)++lpFmt, &cch);
                prec = cch;
            } else
                prec = -1;

            /*
             * get the operand size
             * default size: size == 0
             * long number:  size == 1
             * wide chars:   size == 2
             * It may be a good idea to check the value of size when it
             * is tested for non-zero below (IanJa)
             */
            hprefix = 0;
            if (*lpFmt == 'w') {
                size = 2;
                lpFmt++;
            } else if (*lpFmt == 'l') {
                size = 1;
                lpFmt++;
            } else if (*lpFmt == 't') {
                size = 0;
                lpFmt++;
            } else {
                size = 0;
                if (*lpFmt == 'h') {
                    lpFmt++;
                    hprefix = 1;
                }
            }

            upper = 0;
            sign = 0;
            radix = 10;

            switch (*lpFmt) {
            case 0:
                goto errorout;

            case 'i':
            case 'd':
                size=1;
                sign++;

                /*** FALL THROUGH to case 'u' ***/

            case 'u':
                /* turn off prefix if decimal */
                prefix = 0;
donumeric:
                /* special cases to act like MSC v5.10 */
                if (left || prec >= 0)
                    fillch = ' ';

                /*
                 * if size == 1, "%lu" was specified (good);
                 * if size == 2, "%wu" was specified (bad)
                 */
                if (size) {
                    val.l = va_arg(varglist, long);
                } else if (sign) {
                    val.l = (long)va_arg(varglist, short);
                } else {
                    val.ul = va_arg(varglist, unsigned);
                }

                if (sign && val.l < 0L)
                    val.l = -val.l;
                else
                    sign = 0;

                lpT = lpOut;

                /*
                 * blast the number backwards into the user buffer
                 */
                cch = SP_PutNumber(lpOut, val.l, cchLimit, radix, upper);
                if (!(cchLimit -= cch))
                    goto errorout;

                lpOut += cch;
                width -= cch;
                prec -= cch;
                if (prec > 0)
                    width -= prec;

                /*
                 * fill to the field precision
                 */
                while (prec-- > 0)
                    out('0');

                if (width > 0 && !left) {
                    /*
                     * if we're filling with spaces, put sign first
                     */
                    if (fillch != '0') {
                        if (sign) {
                            sign = 0;
                            out('-');
                            width--;
                        }

                        if (prefix) {
                            out(prefix);
                            out('0');
                            prefix = 0;
                        }
                    }

                    if (sign)
                        width--;

                    /*
                     * fill to the field width
                     */
                    while (width-- > 0)
                        out(fillch);

                    /*
                     * still have a sign?
                     */
                    if (sign)
                        out('-');

                    if (prefix) {
                        out(prefix);
                        out('0');
                    }

                    /*
                     * now reverse the string in place
                     */
                    SP_Reverse(lpT, lpOut - 1);
                } else {
                    /*
                     * add the sign character
                     */
                    if (sign) {
                        out('-');
                        width--;
                    }

                    if (prefix) {
                        out(prefix);
                        out('0');
                    }

                    /*
                     * reverse the string in place
                     */
                    SP_Reverse(lpT, lpOut - 1);

                    /*
                     * pad to the right of the string in case left aligned
                     */
                    while (width-- > 0)
                        out(fillch);
                }
                break;

            case 'X':
                upper++;

                /*** FALL THROUGH to case 'x' ***/

            case 'x':
                radix = 16;
                if (prefix)
                    if (upper)
                        prefix = 'X';
                    else
                        prefix = 'x';
                goto donumeric;

            case 'C':
                /*
                 * explicit size specifier overrides case
                 */
                if (!size && !hprefix) {
                    size = 1;           // force WCHAR
                }

                /*** FALL THROUGH to case 'c' ***/

            case 'c':
                /*
                 * if size == 0, "%c" or "%hc" or "%tc" was specified (CHAR)
                 * if size == 1, "%C" or "%lc" was specified (WCHAR);
                 * if size == 2, "%wc" was specified (WCHAR)
                 */
                cch = 1; /* One character must be copied to the output buffer */
                if (size) {
                    val.wsz[0] = va_arg(varglist, WCHAR);
                    val.wsz[1] = 0x0000;
                    pwsz = val.wsz;
                    goto putwstring;
                } else {
                    val.sz[0] = va_arg(varglist, CHAR);
                    val.sz[1] = 0;
                    lpT = val.sz;
                    goto putstring;
                }

            case 'S':
                /*
                 * explicit size specifier overrides case
                 */
                if (!size && !hprefix) {
                    size = 1;           // force LPWSTR
                }

                /*** FALL THROUGH to case 's' ***/

            case 's':
                /*
                 * if size == 0, "%s" or "%hs" or "%ts" was specified (LPSTR);
                 * if size == 1, "%S" or "%ls" was specified (LPWSTR);
                 * if size == 2, "%ws" was specified (LPWSTR)
                 */
                if (size) {
                    pwsz = va_arg(varglist, LPWSTR);
                    cch = wcslen(pwsz);
putwstring:
                    cch = WCSToMB(pwsz, cch, &lpTMB, -1, TRUE);
                    fAllocateMem = (BOOL) cch;
                    lpT = lpTMB;
                } else {
                    lpT = va_arg(varglist, LPSTR);
                    cch = strlen(lpT);
putstring:
                    fAllocateMem = FALSE;
                }

                if (prec >= 0 && cch > prec)
                    cch = prec;
                width -= cch;

                if (fAllocateMem) {
                    if (cch + (width < 0 ? 0 : width) >= cchLimit) {
                        UserRtlFreeMem(lpTMB);
                        goto errorout;
                    }
                }

                if (left) {
                    while (cch--)
                        out(*lpT++);
                    while (width-- > 0)
                        out(fillch);
                } else {
                    while (width-- > 0)
                        out(fillch);
                    while (cch--)
                        out(*lpT++);
                }

                if (fAllocateMem) {
                     UserRtlFreeMem(lpTMB);
                }
                break;

            default:
normalch:
                out(*lpFmt);
                break;
            }  /* END OF SWITCH(*lpFmt) */
예제 #3
0
파일: chartran.c 프로젝트: conioh/os-design
int MBToWCSEx(
    WORD wCodePage,
    LPCSTR pAnsiString,
    int nAnsiChar,
    LPWSTR *ppUnicodeString,
    int cchUnicodeString,
    BOOL bAllocateMem)
{
    ULONG nBytesInUnicodeString;

    if (nAnsiChar == 0 || cchUnicodeString == 0 || pAnsiString == NULL) {
        return 0;      // nothing to translate or nowhere to put it
    }

    /*
     * Adjust the nAnsiChar value.  If nAnsiChar == -1 then the
     * string pointed to by pAnsiString is NUL terminated so we
     * count the number of bytes.  If nAnsiChar < -1 this is an
     * illegal value so we return FALSE.  Otherwise, nAnsiChar is
     * set and requires no adjustment.
     */

#ifdef _USERK_
    UserAssert(nAnsiChar >= USER_AWCONV_COUNTSTRINGSZ);
#endif
    if (nAnsiChar < 0) {

        /*
         *  Bug 268035 - joejo
         *  Need to fail if the count is a negative number less than -2!
         */
        if (nAnsiChar < USER_AWCONV_COUNTSTRINGSZ) {
            return 0;
        }

#if (USER_AWCONV_COUNTSTRING != -1 || USER_AWCONV_COUNTSTRINGSZ != -2)
#error USER_AWCONV_COUNTSTRING or USER_AWCONV_COUNTSTRINGSZ has unexpected value.
#endif
        /* HACK HACK HACK
         * If nAnsiChar is -1 (USER_AWCONV_COUNTSTRING), nAnsiChar length will be strlen() + 1,
         * to allocate the memory including trailing \0: this is compatible to the original code.
         * If nAnsiCahr is -2 (USER_AWCONV_COUNTSTRINGSZ), memory for trailing \0 will not be needed,
         * so memory allocation is optimized and the return value would be same as strlen().
         */
        nAnsiChar = strlen(pAnsiString) + 2 + nAnsiChar;   // don't forget the NUL if nAnsiChar == -1

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

    /*
     * Adjust the cchUnicodeString value.  If cchUnicodeString == -1 then we
     * pick a value based on nAnsiChar to hold the converted string.  If
     * cchUnicodeString < -1 this is an illegal value so we return FALSE.
     * Otherwise, cchUnicodeString is set and requires no adjustment.
     */
    if (cchUnicodeString == -1) {
        if (bAllocateMem == FALSE) {
            return 0;    // no destination
        }
        cchUnicodeString = nAnsiChar;
    } else if (cchUnicodeString < -1) {
        return 0;     // illegal value
    }

    if (bAllocateMem) {
        *ppUnicodeString = (LPWSTR)UserRtlAllocMem(cchUnicodeString*sizeof(WCHAR));
        if (*ppUnicodeString == NULL) {
            return 0;    // allocation failed
        }
    }

    /*
     * if codepage is CP_ACP, We will call faster RtlXXX function.
     */
    if (IS_ACP(wCodePage)) {
        /*
         * translate ANSI string pointed to by pAnsiString into Unicode
         * and store in location pointed to by pUnicodeString.  We
         * stop translating when we fill up the Unicode buffer or reach
         * the end of the ANSI string.
         */
        if (!NT_SUCCESS(RtlMultiByteToUnicodeN(
                            (PWCH)*ppUnicodeString,
                            cchUnicodeString * sizeof(WCHAR),
                            &nBytesInUnicodeString,
                            (PCH)pAnsiString,
                            nAnsiChar
                            ))) {
            if (bAllocateMem) {
                UserRtlFreeMem(*ppUnicodeString);
            }
            return 0;   // translation failed
        }

        return (int)(nBytesInUnicodeString / sizeof(WCHAR));

    } else {
        /*
         * if wCodePage is not ACP, Call NLS API.
         */
        ULONG nCharsInUnicodeString;

#ifdef _USERK_

        /*
         * I believe we will never hit this code which is why I am
         * adding this assert.  [gerritv] 5-21-96
         */
#define SHOULD_NOT_REACH_HERE   0
        UserAssert(SHOULD_NOT_REACH_HERE);
#undef  SHOULD_NOT_REACH_HERE
        return 0;

#if 0   // FYI: old code
        INT   iCharsInUnicodeString;

        /*
         * Call GRE to convert string to Unicode. (Kernel mode)
         * I believe we will never hit this code which is why I am
         * adding this assert.  [gerritv] 5-21-96
         */

        UserAssert(0);

        iCharsInUnicodeString = EngMultiByteToWideChar(
                                    (UINT)wCodePage,
                                    (LPWSTR)*ppUnicodeString,
                                    (int)cchUnicodeString * sizeof(WCHAR),
                                    (LPSTR)pAnsiString,
                                    (int)nAnsiChar);

        nCharsInUnicodeString = (iCharsInUnicodeString == -1) ? 0 :
                                                          (ULONG) iCharsInUnicodeString;
#endif

#else
        /*
         * Call NLS API (Kernel32) to convert string to Unicode. (User mode)
         */
        nCharsInUnicodeString = MultiByteToWideChar(
                                    (UINT)wCodePage, 0,
                                    (LPCSTR)pAnsiString,
                                    (int)nAnsiChar,
                                    (LPWSTR)*ppUnicodeString,
                                    (int)cchUnicodeString);
#endif // _USERK_

        if (nCharsInUnicodeString == 0) {
            if (bAllocateMem) {
                UserRtlFreeMem(*ppUnicodeString);
            }
        }

        return (int)nCharsInUnicodeString;
    }

}