当前位置 博文首页 > KOOKNUT的博客:RtlAnsiStringToUnicodeString源码实现
之前写代码过程中遇到过的单双字转换,很久不看内核方面的东西了,这是很早之前在草稿箱里面的内容,国庆中秋双节,闲来无事,更新一下。
BOOLEAN NlsMbCodePageTag = FALSE; /* exported *///全局导出
NTSTATUS
NTAPI
RtlAnsiStringToUnicodeString(
IN OUT PUNICODE_STRING UniDest,
IN PANSI_STRING AnsiSource,
IN BOOLEAN AllocateDestinationString)
{
NTSTATUS Status;
ULONG Length;
ULONG Index;
PAGED_CODE_RTL();
if (NlsMbCodePageTag == FALSE)
{
//计算ANSI到UNICODE的长度,这里的Length是有效长度+sizeof(WCHAR)
Length = AnsiSource->Length * 2 + sizeof(WCHAR);
}
else
{
//计算ANSI到UNICODE的长度,这里的Length是有效长度+sizeof(WCHAR)
Length = RtlxAnsiStringToUnicodeSize(AnsiSource);
}
if (Length > MAXUSHORT) //MAXUSHORT = 0xffff
return STATUS_INVALID_PARAMETER_2;
//有效长度
UniDest->Length = (USHORT)Length - sizeof(WCHAR);
if (AllocateDestinationString)
{
//如果需要申请内存,那么给目标对象申请
UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR);
UniDest->MaximumLength = (USHORT)Length;
if (!UniDest->Buffer) return STATUS_NO_MEMORY;
}
else if (UniDest->Length >= UniDest->MaximumLength)
{
return STATUS_BUFFER_OVERFLOW;
}
ASSERT(!(UniDest->MaximumLength & 1) && UniDest->Length <= UniDest->MaximumLength);
//进行转换赋值
Status = RtlMultiByteToUnicodeN(UniDest->Buffer,
UniDest->Length,
&Index,
AnsiSource->Buffer,
AnsiSource->Length);
if (!NT_SUCCESS(Status))
{
if (AllocateDestinationString)
{
RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
UniDest->Buffer = NULL;
}
return Status;
}
UniDest->Buffer[Index / sizeof(WCHAR)] = UNICODE_NULL;//字符串空字符结尾
return Status;
}
NTSTATUS NTAPI
RtlMultiByteToUnicodeN(OUT PWCHAR UnicodeString,
IN ULONG UnicodeSize,
OUT PULONG ResultSize,
IN PCSTR MbString,
IN ULONG MbSize)
{
ULONG Size = 0;
ULONG i;
PAGED_CODE_RTL();
if (!NlsMbCodePageTag)
{
if (MbSize > (UnicodeSize / sizeof(WCHAR)))
Size = UnicodeSize / sizeof(WCHAR);
else
Size = MbSize;
if (ResultSize)
*ResultSize = Size * sizeof(WCHAR);
for (i = 0; i < Size; i++)
UnicodeString[i] = NlsAnsiToUnicodeTable[(UCHAR)MbString[i]];
}
else
{
UCHAR Char;
USHORT LeadByteInfo;
PCSTR MbEnd = MbString + MbSize;
for (i = 0; i < UnicodeSize / sizeof(WCHAR) && MbString < MbEnd; i++)
{
Char = *(PUCHAR)MbString++;
//如果是ascii字符值小于128,则直接进行赋值
if (Char < 0x80)
{
*UnicodeString++ = Char;
continue;
}
//NlsLeadByteInfo NlsAnsiToUnicodeTable这些指针都是全局指针
//在源码中查看直接赋值为NULL,其实这些指针应该都是指向一张转换表
LeadByteInfo = NlsLeadByteInfo[Char];
if (!LeadByteInfo)
{
//进行查表转换
*UnicodeString++ = NlsAnsiToUnicodeTable[Char];
continue;
}
//如果以上两种情况都不存在,那么进行这种转换
if (MbString < MbEnd)
*UnicodeString++ = NlsLeadByteInfo[LeadByteInfo + *(PUCHAR)MbString++];
}
if (ResultSize)
*ResultSize = i * sizeof(WCHAR);//返回赋值的ascii字符个数
}
return STATUS_SUCCESS;
}
参考资料:Reactos
“在这条路上走,注定要忍受孤独。”—KookNut39