当前位置 博文首页 > KOOKNUT的博客:RtlAnsiStringToUnicodeString源码实现

    KOOKNUT的博客:RtlAnsiStringToUnicodeString源码实现

    作者:[db:作者] 时间:2021-07-02 18:35

    之前写代码过程中遇到过的单双字转换,很久不看内核方面的东西了,这是很早之前在草稿箱里面的内容,国庆中秋双节,闲来无事,更新一下。

    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

    cs
    下一篇:没有了