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.
 
 
 
 
 
 

404 lines
12 KiB

/*++
Copyright (c) 1991-1999, Microsoft Corporation All rights reserved.
Module Name:
c_snadb.c
Abstract:
This file contains the main functions for this module.
External Routines in this file:
DllEntry
NlsDllCodePageTranslation
Revision History:
10-30-96 JulieB Created.
--*/
////////////////////////////////////////////////////////////////////////////
//
// IBM EBCDIC DBCS from/to Unicode conversions for SNA
//
// CP# = Single Byte + Double Byte
// ----- = ----------- + -----------
// 50930 = 290 (Katakana Extended) + 300 (Japanese) calls 20930
// 50931 = 037 (US/Canada) + 300 (Japanese) calls 20931
// 50933 = 833 (Korean Extended) + 834 (Korean) calls 20933
// 50935 = 836 (Simp-Chinese Ext.) + 837 (Simplified Chinese) calls 20935
// 50937 = 037 (US/Canada) + 835 (Traditional Chinese) calls 20937
// 50939 = 1027 (Latin Extended) + 300 (Japanese) calls 20939
//
////////////////////////////////////////////////////////////////////////////
//
// Include Files.
//
#include <share.h>
//
// Constant Declarations.
//
#define SHIFTOUT 0x0e // from SBCS to DBCS
#define SHIFTIN 0x0f // from DBCS to SBCS
#define BOGUSLEADBYTE 0x3f // prefix SBC to make it DBC
#define INTERNAL_CODEPAGE(cp) ((cp) - 30000)
//-------------------------------------------------------------------------//
// DLL ENTRY POINT //
//-------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////
//
// DllEntry
//
// DLL Entry initialization procedure.
//
// 10-30-96 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL DllEntry(
HANDLE hModule,
DWORD dwReason,
LPVOID lpRes)
{
switch (dwReason)
{
case ( DLL_THREAD_ATTACH ) :
{
return (TRUE);
}
case ( DLL_THREAD_DETACH ) :
{
return (TRUE);
}
case ( DLL_PROCESS_ATTACH ) :
{
return (TRUE);
}
case ( DLL_PROCESS_DETACH ) :
{
return (TRUE);
}
}
return (FALSE);
hModule;
lpRes;
}
//-------------------------------------------------------------------------//
// 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.
//
// 10-30-96 JulieB Created.
////////////////////////////////////////////////////////////////////////////
DWORD NlsDllCodePageTranslation(
DWORD CodePage,
DWORD dwFlags,
LPSTR lpMultiByteStr,
int cchMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar,
LPCPINFO lpCPInfo)
{
LPSTR lpMBNoEscStr;
int cchMBEscStr = 0;
int ctr, cchMBTemp, cchMBCount, cchWCCount;
BOOL IsDBCS = FALSE;
//
// Error out if internally needed c_*.nls file is not installed.
//
if (!IsValidCodePage(INTERNAL_CODEPAGE(CodePage)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
switch (dwFlags)
{
case ( NLS_CP_CPINFO ) :
{
memset(lpCPInfo, 0, sizeof(CPINFO));
lpCPInfo->MaxCharSize = 3;
lpCPInfo->DefaultChar[0] = 0x3f;
//
// Lead byte does not apply here, leave them all NULL.
//
return (TRUE);
}
case ( NLS_CP_MBTOWC ) :
{
if (cchMultiByte == -1)
{
cchMultiByte = strlen(lpMultiByteStr) + 1;
}
//
// Each single byte char becomes 2 bytes, so we need a
// temporary buffer twice as big.
//
if ((lpMBNoEscStr = (LPSTR)NLS_ALLOC_MEM(cchMultiByte << 1)) == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return (0);
}
//
// Remove all Shift-In & Shift-Out.
//
for (ctr = 0, cchMBTemp = 0; ctr < cchMultiByte; ctr++)
{
if (lpMultiByteStr[ctr] == SHIFTOUT)
{
IsDBCS = TRUE;
}
else if (lpMultiByteStr[ctr] == SHIFTIN)
{
IsDBCS = FALSE;
}
else
{
if (IsDBCS)
{
//
// Double byte char.
//
if (ctr < (cchMultiByte - 1))
{
lpMBNoEscStr[cchMBTemp++] = lpMultiByteStr[ctr++];
lpMBNoEscStr[cchMBTemp++] = lpMultiByteStr[ctr];
}
else
{
//
// Last char is a lead-byte with no trail-byte,
// so let MultiByteToWideChar take care of it.
//
break;
}
}
else
{
//
// Single byte char.
// Prefix it with a bogus lead byte to make it a
// double byte char. The internal table has been
// arranged accordingly.
//
lpMBNoEscStr[cchMBTemp++] = BOGUSLEADBYTE;
lpMBNoEscStr[cchMBTemp++] = lpMultiByteStr[ctr];
}
}
}
cchWCCount = MultiByteToWideChar( INTERNAL_CODEPAGE(CodePage),
0,
lpMBNoEscStr,
cchMBTemp,
lpWideCharStr,
cchWideChar );
if (cchWCCount == 0)
{
SetLastError(ERROR_NO_UNICODE_TRANSLATION);
}
NLS_FREE_MEM(lpMBNoEscStr);
return (cchWCCount);
}
case ( NLS_CP_WCTOMB ) :
{
if (cchWideChar == -1)
{
cchWideChar = wcslen(lpWideCharStr) + 1;
}
cchMBTemp = cchWideChar * sizeof(WCHAR);
lpMBNoEscStr = (LPSTR)NLS_ALLOC_MEM(cchMBTemp);
if (lpMBNoEscStr == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return (0);
}
//
// Convert to an MB string without Shift-In/Out first.
//
cchMBCount = WideCharToMultiByte( INTERNAL_CODEPAGE(CodePage),
WC_NO_BEST_FIT_CHARS,
lpWideCharStr,
cchWideChar,
lpMBNoEscStr,
cchMBTemp,
NULL,
NULL );
/*
what if (cchMBCount == 0) ?
might need to add error checking later
*/
//
// Insert Shift-In and Shift-Out as needed and
// remove BOGUSLEADBYTE.
//
ctr = 0;
while (ctr < cchMBCount)
{
//
// See if it's a single byte char.
//
if (lpMBNoEscStr[ctr] == BOGUSLEADBYTE)
{
//
// It's a single byte char.
//
ctr++;
if (IsDBCS)
{
if (cchMultiByte)
{
if (cchMBEscStr < cchMultiByte)
{
lpMultiByteStr[cchMBEscStr] = SHIFTIN;
}
else
{
//
// Output buffer is too small.
//
break;
}
}
cchMBEscStr++;
IsDBCS = FALSE;
}
if (cchMultiByte)
{
if (cchMBEscStr < cchMultiByte)
{
lpMultiByteStr[cchMBEscStr] = lpMBNoEscStr[ctr];
}
else
{
//
// Output buffer is too small.
//
break;
}
}
cchMBEscStr++;
ctr++;
}
else
{
//
// It's a double byte char.
//
if (!IsDBCS)
{
if (cchMultiByte)
{
if (cchMBEscStr < cchMultiByte)
{
lpMultiByteStr[cchMBEscStr] = SHIFTOUT;
}
else
{
//
// Output buffer is too small.
//
break;
}
}
cchMBEscStr++;
IsDBCS = TRUE;
}
if (ctr >= (cchMBCount - 1))
{
//
// Missing trail byte.
//
break;
}
if (cchMultiByte)
{
if (cchMBEscStr < (cchMultiByte - 1))
{
lpMultiByteStr[cchMBEscStr] = lpMBNoEscStr[ctr];
lpMultiByteStr[cchMBEscStr + 1] = lpMBNoEscStr[ctr + 1];
}
else
{
//
// Output buffer is too small.
//
break;
}
}
cchMBEscStr += 2;
ctr += 2;
}
}
NLS_FREE_MEM(lpMBNoEscStr);
//
// See if the output buffer is too small.
//
if ((cchMultiByte > 0) && (cchMBEscStr > cchMultiByte))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
return (cchMBEscStr);
}
}
//
// This shouldn't happen since this is called by the NLS APIs.
//
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}