📄 nls.c
字号:
/**
* @name GetNlsSectionName
*
* Construct a name of NLS section.
*
* @param CodePage
* Code page number.
* @param Base
* Integer base used for converting to string. Usually set to 10.
* @param Unknown
* As the name suggests the meaning of this parameter is unknown.
* The native version of Kernel32 passes it as the third parameter
* to NlsConvertIntegerToString function, which is used for the
* actual conversion of the code page number.
* @param BaseName
* Base name of the section. (ex. "\\Nls\\NlsSectionCP")
* @param Result
* Buffer that will hold the constructed name.
* @param ResultSize
* Size of the buffer for the result.
*
* @return TRUE if the buffer was large enough and was filled with
* the requested information, FALSE otherwise.
*
* @implemented
*/
BOOL STDCALL
GetNlsSectionName(UINT CodePage, UINT Base, ULONG Unknown,
LPSTR BaseName, LPSTR Result, ULONG ResultSize)
{
CHAR Integer[11];
if (!NT_SUCCESS(RtlIntegerToChar(CodePage, Base, sizeof(Integer), Integer)))
return FALSE;
/*
* If the name including the terminating NULL character doesn't
* fit in the output buffer then fail.
*/
if (strlen(Integer) + strlen(BaseName) >= ResultSize)
return FALSE;
lstrcpyA(Result, BaseName);
lstrcatA(Result, Integer);
return TRUE;
}
/**
* @name GetCPFileNameFromRegistry
*
* Get file name of code page definition file.
*
* @param CodePage
* Code page number to get file name of.
* @param FileName
* Buffer that is filled with file name of successful return. Can
* be set to NULL.
* @param FileNameSize
* Size of the buffer to hold file name in WCHARs.
*
* @return TRUE if the file name was retrieved, FALSE otherwise.
*
* @implemented
*/
BOOL STDCALL
GetCPFileNameFromRegistry(UINT CodePage, LPWSTR FileName, ULONG FileNameSize)
{
WCHAR ValueNameBuffer[11];
UNICODE_STRING KeyName, ValueName;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
HANDLE KeyHandle;
PKEY_VALUE_PARTIAL_INFORMATION Kvpi;
DWORD KvpiSize;
/* Convert the codepage number to string. */
ValueName.Buffer = ValueNameBuffer;
ValueName.MaximumLength = sizeof(ValueNameBuffer);
if (!NT_SUCCESS(RtlIntegerToUnicodeString(CodePage, 10, &ValueName)))
return FALSE;
/* Open the registry key containing file name mappings. */
RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System\\"
L"CurrentControlSet\\Control\\Nls\\CodePage");
InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE,
NULL, NULL);
Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
/* Allocate buffer that will be used to query the value data. */
KvpiSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
(MAX_PATH * sizeof(WCHAR));
Kvpi = HeapAlloc(GetProcessHeap(), 0, KvpiSize);
if (Kvpi == NULL)
{
NtClose(KeyHandle);
return FALSE;
}
/* Query the file name for our code page. */
Status = NtQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation,
Kvpi, KvpiSize, &KvpiSize);
NtClose(KeyHandle);
/* Check if we succeded and the value is non-empty string. */
if (NT_SUCCESS(Status) && Kvpi->Type == REG_SZ &&
Kvpi->DataLength > sizeof(WCHAR))
{
if (FileName != NULL)
{
lstrcpynW(FileName, (WCHAR*)Kvpi->Data,
min(Kvpi->DataLength / sizeof(WCHAR), FileNameSize));
}
return TRUE;
}
return FALSE;
}
/**
* @name IsValidCodePage
*
* Detect if specified code page is valid and present in the system.
*
* @param CodePage
* Code page number to query.
*
* @return TRUE if code page is present.
*/
BOOL STDCALL
IsValidCodePage(UINT CodePage)
{
if (CodePage == CP_UTF8 || CodePage == CP_UTF7)
return TRUE;
if (IntGetLoadedCodePageEntry(CodePage))
return TRUE;
return GetCPFileNameFromRegistry(CodePage, NULL, 0);
}
/**
* @name MultiByteToWideChar
*
* Convert a multi-byte string to wide-charater equivalent.
*
* @param CodePage
* Code page to be used to perform the conversion. It can be also
* one of the special values (CP_ACP for ANSI code page, CP_MACCP
* for Macintosh code page, CP_OEMCP for OEM code page, CP_THREAD_ACP
* for thread active code page, CP_UTF7 or CP_UTF8).
* @param Flags
* Additional conversion flags (MB_PRECOMPOSED, MB_COMPOSITE,
* MB_ERR_INVALID_CHARS, MB_USEGLYPHCHARS).
* @param MultiByteString
* Input buffer.
* @param MultiByteCount
* Size of MultiByteString, or -1 if MultiByteString is NULL
* terminated.
* @param WideCharString
* Output buffer.
* @param WideCharCount
* Size in WCHARs of WideCharString, or 0 if the caller just wants
* to know how large WideCharString should be for a successful
* conversion.
*
* @return Zero on error, otherwise the number of WCHARs written
* in the WideCharString buffer.
*
* @implemented
*/
INT STDCALL
MultiByteToWideChar(UINT CodePage, DWORD Flags,
LPCSTR MultiByteString, INT MultiByteCount,
LPWSTR WideCharString, INT WideCharCount)
{
/* Check the parameters. */
if (MultiByteString == NULL ||
(WideCharString == NULL && WideCharCount > 0) ||
(PVOID)MultiByteString == (PVOID)WideCharString)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
/* Determine the input string length. */
if (MultiByteCount < 0)
{
MultiByteCount = lstrlenA(MultiByteString) + 1;
}
switch (CodePage)
{
case CP_UTF8:
return IntMultiByteToWideCharUTF8(
Flags, MultiByteString, MultiByteCount,
WideCharString, WideCharCount);
case CP_UTF7:
DPRINT1("MultiByteToWideChar for CP_UTF7 is not implemented!\n");
return 0;
case CP_SYMBOL:
DPRINT1("MultiByteToWideChar for CP_SYMBOL is not implemented!\n");
return 0;
default:
return IntMultiByteToWideCharCP(
CodePage, Flags, MultiByteString, MultiByteCount,
WideCharString, WideCharCount);
}
}
/**
* @name WideCharToMultiByte
*
* Convert a wide-charater string to closest multi-byte equivalent.
*
* @param CodePage
* Code page to be used to perform the conversion. It can be also
* one of the special values (CP_ACP for ANSI code page, CP_MACCP
* for Macintosh code page, CP_OEMCP for OEM code page, CP_THREAD_ACP
* for thread active code page, CP_UTF7 or CP_UTF8).
* @param Flags
* Additional conversion flags (WC_NO_BEST_FIT_CHARS, WC_COMPOSITECHECK,
* WC_DISCARDNS, WC_SEPCHARS, WC_DEFAULTCHAR).
* @param WideCharString
* Points to the wide-character string to be converted.
* @param WideCharCount
* Size in WCHARs of WideCharStr, or 0 if the caller just wants to
* know how large WideCharString should be for a successful conversion.
* @param MultiByteString
* Points to the buffer to receive the translated string.
* @param MultiByteCount
* Specifies the size in bytes of the buffer pointed to by the
* MultiByteString parameter. If this value is zero, the function
* returns the number of bytes required for the buffer.
* @param DefaultChar
* Points to the character used if a wide character cannot be
* represented in the specified code page. If this parameter is
* NULL, a system default value is used.
* @param UsedDefaultChar
* Points to a flag that indicates whether a default character was
* used. This parameter can be NULL.
*
* @return Zero on error, otherwise the number of bytes written in the
* MultiByteString buffer. Or the number of bytes needed for
* the MultiByteString buffer if MultiByteCount is zero.
*
* @implemented
*/
INT STDCALL
WideCharToMultiByte(UINT CodePage, DWORD Flags,
LPCWSTR WideCharString, INT WideCharCount,
LPSTR MultiByteString, INT MultiByteCount,
LPCSTR DefaultChar, LPBOOL UsedDefaultChar)
{
/* Check the parameters. */
if (WideCharString == NULL ||
(MultiByteString == NULL && MultiByteCount > 0) ||
(PVOID)WideCharString == (PVOID)MultiByteString)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
/* Determine the input string length. */
if (WideCharCount < 0)
{
WideCharCount = lstrlenW(WideCharString) + 1;
}
switch (CodePage)
{
case CP_UTF8:
return IntWideCharToMultiByteUTF8(
CodePage, Flags, WideCharString, WideCharCount,
MultiByteString, MultiByteCount, DefaultChar,
UsedDefaultChar);
case CP_UTF7:
DPRINT1("WideCharToMultiByte for CP_UTF7 is not implemented!\n");
return 0;
case CP_SYMBOL:
DPRINT1("WideCharToMultiByte for CP_SYMBOL is not implemented!\n");
return 0;
default:
return IntWideCharToMultiByteCP(
CodePage, Flags, WideCharString, WideCharCount,
MultiByteString, MultiByteCount, DefaultChar,
UsedDefaultChar);
}
}
/**
* @name GetACP
*
* Get active ANSI code page number.
*
* @implemented
*/
UINT STDCALL
GetACP(VOID)
{
return AnsiCodePage.CodePageTable.CodePage;
}
/**
* @name GetOEMCP
*
* Get active OEM code page number.
*
* @implemented
*/
UINT STDCALL
GetOEMCP(VOID)
{
return OemCodePage.CodePageTable.CodePage;
}
/**
* @name IsDBCSLeadByteEx
*
* Determine if passed byte is lead byte in specified code page.
*
* @implemented
*/
BOOL STDCALL
IsDBCSLeadByteEx(UINT CodePage, BYTE TestByte)
{
PCODEPAGE_ENTRY CodePageEntry;
CodePageEntry = IntGetCodePageEntry(CodePage);
if (CodePageEntry != NULL)
return IntIsLeadByte(&CodePageEntry->CodePageTable, TestByte);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
/**
* @name IsDBCSLeadByteEx
*
* Determine if passed byte is lead byte in current ANSI code page.
*
* @implemented
*/
BOOL STDCALL
IsDBCSLeadByte(BYTE TestByte)
{
return IntIsLeadByte(&AnsiCodePage.CodePageTable, TestByte);
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -