Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

852 lines
32 KiB

/*++
Copyright (c) 1991-1999, Microsoft Corporation All rights reserved.
Module Name:
c_gb18030.c
Abstract:
This file contains functions to convert GB18030-2000 (code page 54936) into Unicode, and vice versa.
The target module is c_g18030.dll. This will be the external DLL used by WideCharToMultiByte()
and MultiByteToWideChar() to perform the conversion for GB18030 codepage.
External Routines in this file:
DllEntry
NlsDllCodePageTranslation
Notes:
GB18030-2000 (aka GBK2K) is designed to be mostly compatible with GBK (codepage 936),
while supports the full range of Unicode code points (BMP + 16 supplementary planes).
The structure for GB18030 is:
* Single byte:
0x00 ~ 0x7f
* Two-byte:
0x81 ~ 0xfe, 0x40 ~ 0x7e (leading byte, trailing byte)
0x81 ~ 0xfe, 0x80 ~ 0xfe (leading byte, trailing byte)
* Four-byte:
0x81 ~ 0xfe, 0x30 ~ 0x39, 0x81 ~ 0xfe, 0x30 ~ 0x39.
The surrogare pair will be encoded from 0x90, 0x30, 0x81, 0x30
The BMP range is fully supported in GB18030 using 1-byte, 2-byte and 4-byte sequences.
In valid 4-byte GB18030, there are two gaps that can not be mapped to Unicode characters.
0x84, 0x31, 0xa5, 0x30 (just after the GB18030 bytes for U+FFFF(*)) ~ 0x8f, 0x39, 0xfe, 0x39 (just before the first GB18030 bytes for U+D800,U+DC00)
0xe3, 0x32, 0x9a, 0x36 (just after the GB18030 bytes for U+DBFF U+DFFF(**)) ~ 0xfe, 0x39, 0xfe, 0x39
Note1: U+FFFF = 0x84, 0x31, 0xa4, 0x39
Note2: U+DBFF U+DFFF = 0xe3, 0x32, 0x9a, 0x35
Tables used in c_g18030.dll:
* From Unicode to bytes:
* g_wUnicodeToGB:
Used to convert Unicode character to 2-byte GBK, 2-byte GB18030, or 4-byte GB18030.
The index is 0x0000 ~ 0xffff, for Unicode BMP range.
When the valures are:
Value Meaning
====== =======
0xffff 2-byte GB18030, which is compatible with GBK. Call WC2MB(936,...) to convert.
0xfffe ~ [0xfffe - (ARRAYSIZE(g_wUnicodeToGBTwoBytes))+1]
2-byte GB18030, which is NOT compatible with GBK. (0xfffe - Value) will be indexed into
a second table g_wUnicodeToGBTwoBytes, which contains the two-byte GB18030 values.
E.g. if the value is 0xfffe, the index into g_wUnicodeToGBTwoBytes is 0, so the two-byte
GB18030 will be 0xa8, 0xbf (which are stored g_wUnicodeToGBTwoBytes[0],g_wUnicodeToGBTwoBytes[1])
0x0000 ~ 0x99fb
An offset value that can be used to convert to 4-byte GB18030
If the value is 0x000, the 4-byte GB18030 is 0x81, 0x30, 0x81, 0x30.
* From bytes to Unicode
* Two-byte GB18030 to Unicode:
* g_wGBLeadByteOffset
The index into this table is lead byte 0x80 ~ 0xff (converted to index 0x00 ~ 0x7f).
If the value is 0x0000, it means that this lead byte is compatible with GBK.
Otherwise, the value can be:
0x0100 This is used to indexed into g_wUnicodeFromGBTwoBytes[0x0000 ~ 0x00ff].
The value of g_wUnicodeFromGBTwoBytesis the Unicode value for this lead byte with the next valid trailing byte.
0x0200 This is used to indexed into g_wUnicodeFromGBTwoBytes[0x0100 ~ 0x01ff].
0x0300 This is used to indexed into g_wUnicodeFromGBTwoBytes[0x0200 ~ 0x02ff].
0x0400 This is used to indexed into g_wUnicodeFromGBTwoBytes[0x0300 ~ 0x03ff].
E.g. g_wGBLeadByteOffset[0x07] = 0x0000. It means that GB18030 two-byte lead byte 0x87 is compatible with GBK.
g_wGBLeadByteOffset[0x28] = 0x0200. It means that GB18030 two-byte lead byte 0xa8 (0x28+0x80 = 0xa8) is NOT compatible with GBK.
The Unicode value for 0xa8, <trail byte> will be stored in g_wUnicodeFromGBTwoBytes[0x0100+<trail byte>]
* Four-byte GB18030 to Unicode:
* g_wGBFourBytesToUnicode
The table is used to convert 4-byte GB18030 into a Unicode.
The index value is the offset of the 4-byte GB18030.
4-byte GB18030 Index value
============== ===========
81,30,81,30 0
81,30,81,31 1
81,30,81,32 2
... ...
The value of g_wGBFourBytesToUnicode cotains the Unicode codepoint for the offset of the
corresponding 4-byte GB18030.
E.g. g_wGBFourBytesToUnicode[0] = 0x0080. This means that GB18030 0x81, 0x30, 0x81, 0x30 will be converted to Unicode U+0800.
Revision History:
02-20-2001 YSLin Created.
--*/
//
// Include Files.
//
#include <share.h>
#include "c_gb18030.h"
//
// Constant Declarations.
//
//
// Structure used in GetCPInfo().
//
CPINFO g_CPInfo =
{
//UINT MaxCharSize;
4,
//BYTE DefaultChar[MAX_DEFAULTCHAR];
{0x3f, 0x00},
//BYTE LeadByte[MAX_LEADBYTES];
// Since GBK2K can have up to 4 bytes, we don't return
// 0x81-0xfe as lead bytes here.
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
};
// This is the offset for the start of surrogate U+D800, U+DC00
#define SURROGATE_OFFSET GET_FOUR_BYTES_OFFSET_FROM_BYTES(0x90, 0x30, 0x81, 0x30)
// This is the offset for the end of surrogate U+DBFF, U+DFFF
#define SURROGATE_MAX_OFFSET GET_FOUR_BYTES_OFFSET_FROM_BYTES(0xe3, 0x32, 0x9a, 0x35)
//-------------------------------------------------------------------------//
// EXTERNAL ROUTINES //
//-------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////
//
// NlsDllCodePageTranslation
//
// This routine is the main exported procedure for the functionality in
// this DLL. All calls to this DLL must go through this function.
//
// 02-20-2001 YSLin Created.
////////////////////////////////////////////////////////////////////////////
STDAPI_(DWORD) NlsDllCodePageTranslation(
DWORD CodePage,
DWORD dwFlags,
LPSTR lpMultiByteStr,
int cchMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar,
LPCPINFO lpCPInfo)
{
//
// Error out if internally needed c_*.nls file is not installed.
//
if (!IsValidCodePage(CODEPAGE_GBK))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
switch (dwFlags)
{
case ( NLS_CP_CPINFO ) :
{
memcpy(lpCPInfo, &g_CPInfo, sizeof(CPINFO));
return (TRUE);
}
case ( NLS_CP_MBTOWC ) :
{
return (BytesToUnicode((BYTE*)lpMultiByteStr, cchMultiByte, NULL, lpWideCharStr, cchWideChar));
}
case ( NLS_CP_WCTOMB ) :
{
return (UnicodeToBytes(lpWideCharStr, cchWideChar, lpMultiByteStr, cchMultiByte));
}
}
//
// This shouldn't happen since this gets called by the NLS APIs.
//
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
//-------------------------------------------------------------------------//
// INTERNAL ROUTINES //
//-------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////
//
// GetBytesToUnicodeCount
//
// Return the Unicode character count needed to convert the specified
// GB18030 multi-byte string.
//
// Parameters:
// lpMultiByteStr The multi-byte string to be converted.
// cchMultiByte The byte size of the multi-byte string to be converted
// bSupportEncoder If TRUE and we have a lead byte at the end of string,
// we will not convert that lead byte. Otherwise,
// convert it to the default character.
//
// 02-21-2001 YSLin Created.
////////////////////////////////////////////////////////////////////////////
DWORD GetBytesToUnicodeCount(BYTE* lpMultiByteStr, int cchMultiByte, BOOL bSupportEncoder)
{
int i = 0;
BYTE ch;
DWORD cchWCCount = 0;
WORD wOffset;
BYTE offset1, offset2, offset3, offset4;
DWORD dwFourBytesOffset;
if (cchMultiByte == -1)
{
cchMultiByte = strlen((LPSTR)lpMultiByteStr);
}
while (i < cchMultiByte)
{
ch = lpMultiByteStr[i];
if (ch <= 0x7f)
{
cchWCCount++;
i++;
} else if (IS_GB_LEAD_BYTE(ch))
{
offset1 = (ch - GBK2K_BYTE1_MIN);
//
// If this is a lead byte, look ahead to see if this is
// a two-byte GB18030 or four-byte GB18030.
//
if (i+1 < cchMultiByte)
{
if (IS_GB_TWO_BYTES_TRAILING(lpMultiByteStr[i+1]))
{
//
// The trailing byte is a GB18030 two-byte.
//
cchWCCount++;
i += 2;
} else if (i+3 < cchMultiByte)
{
//
// Check if this is a four-byte GB18030.
//
if (IS_GB_FOUR_BYTES_TRAILING(lpMultiByteStr[i+1]) &&
IS_GB_LEAD_BYTE(lpMultiByteStr[i+2]) &&
IS_GB_FOUR_BYTES_TRAILING(lpMultiByteStr[i+3]))
{
offset2 = lpMultiByteStr[i+1] - GBK2K_BYTE2_MIN;
offset3 = lpMultiByteStr[i+2] - GBK2K_BYTE3_MIN;
offset4 = lpMultiByteStr[i+3] - GBK2K_BYTE4_MIN;
//
// Four-byte GB18030
//
dwFourBytesOffset = GET_FOUR_BYTES_OFFSET(offset1, offset2, offset3, offset4);
if (dwFourBytesOffset <= g_wMax4BytesOffset)
{
//
// The Unicode will be in the BMP range.
//
cchWCCount++;
} else if (dwFourBytesOffset >= SURROGATE_OFFSET && dwFourBytesOffset <= SURROGATE_MAX_OFFSET)
{
//
// This will be converted to a surrogate pair.
//
cchWCCount+=2;
} else {
//
// Valid GBK2K code point, but can not be mapped to Unicode.
//
cchWCCount++;
}
i += 4;
} else
{
if (bSupportEncoder)
{
// Set i to cchMultiByte so that we will bail out the while loop.
i = cchMultiByte;
} else
{
//
// We have a lead byte, but do have have a valid trailing byte.
//
// Use default Unicode char.
i++;
cchWCCount++;
}
}
}else
{
if (bSupportEncoder)
{
// Set i to cchMultiByte so that we will bail out the while loop.
i = cchMultiByte;
} else
{
//
// We have a lead byte, but do have have a valid trailing byte.
//
// Use default Unicode char.
i++;
cchWCCount++;
}
}
} else
{
//
// We have a lead byte at the end of the string.
//
if (bSupportEncoder)
{
i++;
} else
{
// Use default Unicode char.
i++;
cchWCCount++;
}
}
}else
{
//
// This byte is NOT between 0x00 ~ 0x7f, and not a lead byte.
// Use the default character.
//
i++;
cchWCCount++;
}
}
return (cchWCCount);
}
BOOL __forceinline PutDefaultCharacter(UINT* pCchWCCount, UINT cchWideChar, LPWSTR lpWideCharStr)
{
//
// This byte is NOT between 0x00 ~ 0x7f, not a lead byte.
//
if (*pCchWCCount >= cchWideChar)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (FALSE);
}
lpWideCharStr[(*pCchWCCount)++] = GB18030_DEFAULT_UNICODE_CHAR;
return (TRUE);
}
STDAPI_(DWORD) BytesToUnicode(
BYTE* lpMultiByteStr,
UINT cchMultiByte,
UINT* pcchLeftOverBytes,
LPWSTR lpWideCharStr,
UINT cchWideChar)
{
UINT i = 0;
BYTE ch;
UINT cchWCCount = 0;
BYTE offset1, offset2, offset3, offset4;
WORD wOffset;
DWORD dwOffset;
int nResult;
if ((lpWideCharStr == NULL) || (cchWideChar == 0))
{
return (GetBytesToUnicodeCount(lpMultiByteStr, cchMultiByte, (pcchLeftOverBytes != NULL)));
}
if (cchMultiByte == -1)
{
cchMultiByte = strlen((LPSTR)lpMultiByteStr);
}
if (pcchLeftOverBytes != NULL)
{
*pcchLeftOverBytes = 0;
}
//
// NOTENOTE YSLin:
// If you make fix in the following code, remember to make the appropriate fix
// in GetBytesToUnicodeCount() as well.
//
while (i < cchMultiByte)
{
ch = lpMultiByteStr[i];
if (ch <= 0x7f)
{
//
// This byte is from 0x00 ~ 0x7f.
//
if (cchWCCount >= cchWideChar)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
lpWideCharStr[cchWCCount++] = ch;
i++;
} else if (IS_GB_LEAD_BYTE(ch))
{
offset1 = ch - GBK2K_BYTE1_MIN;
//
// If this is a lead byte, just look ahead to see if this is
// a two-byte GB18030 or four-byte GB18030.
//
if (i+1 < cchMultiByte)
{
if (IS_GB_TWO_BYTES_TRAILING(lpMultiByteStr[i+1]))
{
//
// The trailing byte is a GB18030 two-byte.
//
//
// Look up the table to see if we have the table for
// the mapping Unicode character.
//
wOffset = g_wGBLeadByteOffset[ch - 0x80];
if (wOffset == 0x0000)
{
if (cchWCCount == cchWideChar)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
//
// We don't have the table, because this is a GBK compatible two-byte GB18030.
//
//
// Two-byte GB18030
//
nResult = MultiByteToWideChar(CODEPAGE_GBK, 0, (LPCSTR)(lpMultiByteStr+i), 2, lpWideCharStr+cchWCCount, 1);
if (nResult == 0)
{
return (0);
}
cchWCCount++;
i += 2;
} else
{
if (cchWCCount == cchWideChar)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
wOffset -= 0x0100;
lpWideCharStr[cchWCCount++] = g_wUnicodeFromGBTwoBytes[wOffset + lpMultiByteStr[i+1]];
i+= 2;
}
} else if (i+3 < cchMultiByte)
{
if (IS_GB_FOUR_BYTES_TRAILING(lpMultiByteStr[i+1]) &&
IS_GB_LEAD_BYTE(lpMultiByteStr[i+2]) &&
IS_GB_FOUR_BYTES_TRAILING(lpMultiByteStr[i+3]))
{
offset2 = lpMultiByteStr[i+1] - GBK2K_BYTE2_MIN;
offset3 = lpMultiByteStr[i+2] - GBK2K_BYTE3_MIN;
offset4 = lpMultiByteStr[i+3] - GBK2K_BYTE4_MIN;
//
// Four-byte GB18030
//
dwOffset = GET_FOUR_BYTES_OFFSET(offset1, offset2, offset3, offset4);
if (dwOffset <= g_wMax4BytesOffset)
{
if (cchWCCount == cchWideChar)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
//
// The Unicode will be in the BMP range.
//
lpWideCharStr[cchWCCount++] = g_wGBFourBytesToUnicode[dwOffset];
} else if (dwOffset >= SURROGATE_OFFSET && dwOffset <= SURROGATE_MAX_OFFSET)
{
if (cchWCCount + 2 > cchWideChar)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
//
// This will be converted to a surrogate pair.
//
dwOffset -= SURROGATE_OFFSET;
lpWideCharStr[cchWCCount++] = 0xd800 + (WORD)(dwOffset / 0x400);
lpWideCharStr[cchWCCount++] = 0xdc00 + (WORD)(dwOffset % 0x400);
} else
{
//
// Valid GBK2K code point, but can not be mapped to Unicode.
//
if (!PutDefaultCharacter(&cchWCCount, cchWideChar, lpWideCharStr))
{
return (0);
}
}
i += 4;
}else
{
if (!PutDefaultCharacter(&cchWCCount, cchWideChar, lpWideCharStr))
{
return (0);
}
i++;
}
}else
{
if (pcchLeftOverBytes != NULL)
{
*pcchLeftOverBytes = cchMultiByte - i;
// Set i to cchMultiByte so that we will bail out the while loop.
i = cchMultiByte;
} else
{
//
// We have a lead byte, but do have have a valid trailing byte.
//
// Use default Unicode char.
if (!PutDefaultCharacter(&cchWCCount, cchWideChar, lpWideCharStr))
{
return (0);
}
i++;
}
}
} else
{
if (pcchLeftOverBytes != NULL)
{
*pcchLeftOverBytes = 1;
i++;
} else
{
// We have a lead byte, but do have have a trailing byte.
// Use default Unicode char.
if (!PutDefaultCharacter(&cchWCCount, cchWideChar, lpWideCharStr))
{
return (0);
}
i++;
}
}
} else
{
if (!PutDefaultCharacter(&cchWCCount, cchWideChar, lpWideCharStr))
{
return (0);
}
i++;
}
}
return (cchWCCount);
}
DWORD GetUnicodeToBytesCount(LPWSTR lpWideCharStr, int cchWideChar)
{
int i;
WORD wch;
int cchMBCount = 0;
DWORD wOffset;
if (cchWideChar == -1)
{
cchWideChar = wcslen(lpWideCharStr);
}
for (i = 0; i < cchWideChar; i++)
{
wch = lpWideCharStr[i];
if (wch <= 0x7f)
{
// One-byte GB18030.
cchMBCount++;
} else if (IS_HIGH_SURROGATE(wch))
{
//
// Look ahead one character to see if the next char is a low surrogate.
//
if (i + 1 < cchWideChar)
{
if (IS_LOW_SURROGATE(lpWideCharStr[ i+1 ]))
{
//
// Found a surrogate pair. This will be a four-byte GB18030.
//
cchMBCount += 4;
i++;
} else
{
//
// A High surrogate character without a trailing low surrogate character.
// In this case, we will convert this character to a default character.
//
cchMBCount++;
}
} else
{
//
// A High surrogate character without a valid trailing low surrogate character.
// In this case, we will convert this character to a default character.
//
cchMBCount++;
}
} else if (IS_LOW_SURROGATE(wch))
{
//
// Only a low surrogate character without a leading high surrogate.
// In this case, we will convert this character to a default character.
//
cchMBCount++;
} else
{
//
// Not a surrogate character. Look up the table to see this BMP Unicode character
// will be converted to a two-byte GB18030 or four-byte GB18030.
//
wOffset = g_wUnicodeToGB[wch];
if (wOffset == 0xFFFF)
{
//
// This Unicode character will be converted to GBK compatible two-byte code.
//
cchMBCount += 2;
} else if (wOffset <= g_wMax4BytesOffset)
{
//
// This Unicode character will be converted to four-byte GB18030.
//
cchMBCount += 4;
} else
{
//
// This Unicode character will be converted to two-byte GB18030, which is not compatible
// with GBK.
//
cchMBCount += 2;
}
}
}
return (cchMBCount);
}
STDAPI_(DWORD) UnicodeToBytes(
LPWSTR lpWideCharStr,
UINT cchWideChar,
LPSTR lpMultiByteStr,
UINT cchMultiByte)
{
UINT i;
WORD wch;
UINT cchMBCount = 0;
CHAR MBTwoBytes[2];
BYTE MBFourBytes[4];
WORD wOffset;
DWORD dwSurrogateOffset;
int nResult;
if ((lpMultiByteStr == NULL) || (cchMultiByte == 0))
{
return (GetUnicodeToBytesCount(lpWideCharStr, cchWideChar));
}
if (cchWideChar == -1)
{
cchWideChar = wcslen(lpWideCharStr);
}
//
// NOTENOTE YSLin:
// If you make fix in the following code, remember to make the appropriate fix
// in GetUnicodeToBytesCount() as well.
//
for (i = 0; i < cchWideChar; i++)
{
wch = lpWideCharStr[i];
if (wch <= 0x7f)
{
if (cchMBCount == cchMultiByte)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
lpMultiByteStr[cchMBCount++] = (BYTE)wch;
} else if (IS_HIGH_SURROGATE(wch))
{
//
// Look ahead one character to see if the next char is a low surrogate.
//
if (i + 1 < cchWideChar)
{
if (IS_LOW_SURROGATE(lpWideCharStr[ i+1 ]))
{
if (cchMBCount + 4 > cchMultiByte)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
i++;
//
// A surrogate pair will be converted to GB 18030 four-byte from
// 0x90308130 ~ 0xe339fe39.
//
dwSurrogateOffset = (wch - 0xd800) * 0x0400 + (lpWideCharStr[i] - 0xdc00);
lpMultiByteStr[cchMBCount+3] = (BYTE)(dwSurrogateOffset % GBK2K_BYTE4_RANGE) + GBK2K_BYTE4_MIN;
dwSurrogateOffset /= GBK2K_BYTE4_RANGE;
lpMultiByteStr[cchMBCount+2] = (BYTE)(dwSurrogateOffset % GBK2K_BYTE3_RANGE) + GBK2K_BYTE3_MIN;
dwSurrogateOffset /= GBK2K_BYTE3_RANGE;
lpMultiByteStr[cchMBCount+1] = (BYTE)(dwSurrogateOffset % GBK2K_BYTE2_RANGE) + GBK2K_BYTE2_MIN;
dwSurrogateOffset /= GBK2K_BYTE2_RANGE;
lpMultiByteStr[cchMBCount] = (BYTE)(dwSurrogateOffset % GBK2K_BYTE1_RANGE) + 0x90;
cchMBCount += 4;
} else
{
if (cchMBCount == cchMultiByte)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
//
// A High surrogate character is at the end of string.
// In this case, we will convert this character to a default character.
//
lpMultiByteStr[cchMBCount++] = GB18030_DEFAULT_CHAR;
}
}else
{
if (cchMBCount >= cchMultiByte)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
//
// A High surrogate character without a valid trailing low surrogate character.
// In this case, we will convert this character to a default character.
//
lpMultiByteStr[cchMBCount++] = GB18030_DEFAULT_CHAR;
}
} else if (IS_LOW_SURROGATE(wch))
{
if (cchMBCount == cchMultiByte)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
//
// Only a low surrogate character without a leading high surrogate.
// In this case, we will convert this character to a default character.
//
lpMultiByteStr[cchMBCount++] = GB18030_DEFAULT_CHAR;
} else
{
//
// This character is not below 0x7f, not a surrogate character.
// Check the table to see how this Unicode character should be
// converted. It could be:
// 1. Two-byte GB18030, which is compatible with GBK. (wOffset == 0xffff)
// 2. Two-byte GB18030, which is NOT compatible with GBK. (wOffset = 0xfffe and below)
// 3. Four-byte GB18030. (wOffset >= 0 && wOffset < g_wMax4BytesOffset)
//
wOffset = g_wUnicodeToGB[wch];
if (wOffset == 0xffff)
{
//
// This Unicode character will be converted to the same two-byte GBK code, so use GBK table.
//
if (cchMBCount + 2 > cchMultiByte)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
nResult = WideCharToMultiByte(CODEPAGE_GBK, 0, lpWideCharStr+i, 1, lpMultiByteStr+cchMBCount, 2, NULL, NULL);
if (nResult == 0)
{
return (0);
}
if (cchMBCount + nResult > cchMultiByte)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
cchMBCount += nResult;
} else if (wOffset <= g_wMax4BytesOffset)
{
if (cchMBCount + 4 > cchMultiByte)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
//
// This Unicode character will be converted to four-byte GB18030.
//
lpMultiByteStr[cchMBCount+3] = (wOffset % GBK2K_BYTE4_RANGE) + GBK2K_BYTE4_MIN;
wOffset /= GBK2K_BYTE4_RANGE;
lpMultiByteStr[cchMBCount+2] = (wOffset % GBK2K_BYTE3_RANGE) + GBK2K_BYTE3_MIN;
wOffset /= GBK2K_BYTE3_RANGE;
lpMultiByteStr[cchMBCount+1] = (wOffset % GBK2K_BYTE2_RANGE) + GBK2K_BYTE2_MIN;
wOffset /= GBK2K_BYTE2_RANGE;
lpMultiByteStr[cchMBCount] = (wOffset % GBK2K_BYTE1_RANGE) + GBK2K_BYTE1_MIN;
cchMBCount += 4;
} else
{
if (cchMBCount + 2 > cchMultiByte)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
//
// This Unicode character will be converted to two-byte GB18030, which is not compatible
// with GBK.
//
wOffset = 0xfffe - wOffset;
// We don't have to check the range of wOffset here, since the value of wOffset is coming from
// g_wUnicodeToGB.
CopyMemory(lpMultiByteStr+cchMBCount, &g_wUnicodeToGBTwoBytes[wOffset * 2], 2);
// Copy two bytes (a WORD) into lpMultiByteStr[cchMBCount].
// Instead od CompMemory(), This is probably faster:
// *((LPWORD)lpMultiByteStr[cchMBCount]) = *((LPWORD)g_wUnicodeToGBTwoBytes[wOffset * 2]);
cchMBCount += 2;
}
}
}
return (cchMBCount);
}