|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
/* ntapi: Native API core library */
|
|
|
64e606 |
/* Copyright (C) 2013--2021 SysDeer Technologies, LLC */
|
|
|
dd89bb |
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
|
|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
#include <psxtypes/psxtypes.h>
|
|
|
dd89bb |
#include <ntapi/nt_status.h>
|
|
|
dd89bb |
#include <ntapi/nt_unicode.h>
|
|
|
dd89bb |
#include "ntapi_impl.h"
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
typedef struct ___two_bytes {
|
|
|
dd89bb |
unsigned char low;
|
|
|
dd89bb |
unsigned char high;
|
|
|
dd89bb |
} __two_bytes;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
typedef struct ___three_bytes {
|
|
|
dd89bb |
unsigned char low;
|
|
|
dd89bb |
unsigned char middle;
|
|
|
dd89bb |
unsigned char high;
|
|
|
dd89bb |
} __three_bytes;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __fastcall __utf8_to_utf16_handler_1byte_or_null_termination(nt_utf8_callback_args * args)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
/***************************/
|
|
|
dd89bb |
/* from: 0xxxxxxx */
|
|
|
dd89bb |
/* to: 00000000 0xxxxxxx */
|
|
|
dd89bb |
/***************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
wchar16_t * dst;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (args->dst >= args->dst_cap)
|
|
|
dd89bb |
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
|
dd89bb |
|
|
|
dd89bb |
dst = (wchar16_t *)args->dst;
|
|
|
dd89bb |
*dst = *(args->src);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* advance source and destination buffer */
|
|
|
dd89bb |
args->src++;
|
|
|
dd89bb |
args->dst = (void *)((uintptr_t)(args->dst) + sizeof(wchar16_t));
|
|
|
dd89bb |
|
|
|
dd89bb |
/* bytes_written */
|
|
|
dd89bb |
args->bytes_written += sizeof(wchar16_t);
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __fastcall __utf8_to_utf16_handler_2bytes(nt_utf8_callback_args * args)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
/***************************/
|
|
|
dd89bb |
/* from: 110yyyyy 10xxxxxx */
|
|
|
dd89bb |
/* to: 00000yyy yyxxxxxx */
|
|
|
dd89bb |
/***************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
__two_bytes * src; /* big endian */
|
|
|
dd89bb |
wchar16_t * dst;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (args->dst >= args->dst_cap)
|
|
|
dd89bb |
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
|
dd89bb |
|
|
|
dd89bb |
src = (__two_bytes *)args->src;
|
|
|
dd89bb |
dst = (wchar16_t *)args->dst;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* yyyyy */
|
|
|
dd89bb |
*dst = (src->low ^ 0xC0);
|
|
|
dd89bb |
*dst <<= 6;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* xxxxxx */
|
|
|
dd89bb |
*dst |= (src->high ^ 0x80);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* advance source and destination buffer */
|
|
|
dd89bb |
args->src += 2;
|
|
|
dd89bb |
args->dst = (void *)((uintptr_t)(args->dst) + sizeof(wchar16_t));
|
|
|
dd89bb |
|
|
|
dd89bb |
/* bytes_written */
|
|
|
dd89bb |
args->bytes_written += sizeof(wchar16_t);
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __fastcall __utf8_to_utf16_handler_3bytes(nt_utf8_callback_args * args)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
/************************************/
|
|
|
dd89bb |
/* from: 1110zzzz 10yyyyyy 10xxxxxx */
|
|
|
dd89bb |
/* to: zzzzyyyy yyxxxxxx */
|
|
|
dd89bb |
/************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
__three_bytes * src; /* big endian */
|
|
|
dd89bb |
wchar16_t * dst;
|
|
|
dd89bb |
wchar16_t yyyyy;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (args->dst >= args->dst_cap)
|
|
|
dd89bb |
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
|
dd89bb |
|
|
|
dd89bb |
src = (__three_bytes *)args->src;
|
|
|
dd89bb |
dst = (wchar16_t *)args->dst;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* zzzz */
|
|
|
dd89bb |
*dst = (src->low ^ 0xE0);
|
|
|
dd89bb |
*dst <<= 12;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* yyyyy */
|
|
|
dd89bb |
yyyyy = (src->middle ^ 0x80);
|
|
|
dd89bb |
yyyyy <<= 6;
|
|
|
dd89bb |
*dst |= yyyyy;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* xxxxxx */
|
|
|
dd89bb |
*dst |= (src->high ^ 0x80);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* advance source and destination buffer */
|
|
|
dd89bb |
args->src += 3;
|
|
|
dd89bb |
args->dst = (void *)((uintptr_t)(args->dst) + sizeof(wchar16_t));
|
|
|
dd89bb |
|
|
|
dd89bb |
/* bytes_written */
|
|
|
dd89bb |
args->bytes_written += sizeof(wchar16_t);
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __fastcall __utf8_to_utf16_handler_4bytes(nt_utf8_callback_args * args)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
/*************************************************/
|
|
|
dd89bb |
/* from: 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx */
|
|
|
dd89bb |
/* to: 110110ww wwzzzzyy 110111yy yyxxxxxx */
|
|
|
dd89bb |
/*************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
__two_bytes * src_low; /* big endian */
|
|
|
dd89bb |
__two_bytes * src_high; /* big endian */
|
|
|
dd89bb |
wchar16_t * dst_lead;
|
|
|
dd89bb |
wchar16_t * dst_trail;
|
|
|
dd89bb |
|
|
|
880eca |
wchar16_t wwww;
|
|
|
880eca |
wchar16_t lead;
|
|
|
880eca |
wchar16_t trail;
|
|
|
dd89bb |
unsigned char ulow;
|
|
|
dd89bb |
unsigned char uhigh;
|
|
|
880eca |
unsigned char yy;
|
|
|
dd89bb |
unsigned char yyyy;
|
|
|
880eca |
unsigned char zzzz;
|
|
|
dd89bb |
|
|
|
dd89bb |
dst_lead = dst_trail = (wchar16_t *)args->dst;
|
|
|
dd89bb |
dst_trail++;
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((uintptr_t)dst_trail >= (uintptr_t)args->dst_cap)
|
|
|
dd89bb |
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
|
dd89bb |
|
|
|
dd89bb |
src_low = src_high = (__two_bytes *)args->src;
|
|
|
dd89bb |
src_high++;
|
|
|
dd89bb |
|
|
|
880eca |
/* uuuuu */
|
|
|
dd89bb |
ulow = src_low->low ^ 0xF0;
|
|
|
dd89bb |
uhigh = src_low->high ^ 0x80;
|
|
|
dd89bb |
|
|
|
dd89bb |
ulow <<= 2;
|
|
|
dd89bb |
uhigh >>= 4;
|
|
|
dd89bb |
|
|
|
880eca |
/* wwww */
|
|
|
880eca |
wwww = (ulow | uhigh) - 1;
|
|
|
880eca |
wwww <<= 6;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* 110110ww wwzzzzyy */
|
|
|
880eca |
yy = src_high->low ^ 0x80;
|
|
|
880eca |
yy >>= 4;
|
|
|
880eca |
|
|
|
880eca |
zzzz = src_low->high;
|
|
|
880eca |
zzzz <<= 4;
|
|
|
880eca |
zzzz >>= 2;
|
|
|
880eca |
|
|
|
880eca |
lead = 0xD800;
|
|
|
880eca |
lead |= wwww;
|
|
|
880eca |
lead |= zzzz;
|
|
|
880eca |
lead |= yy;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* 110111yy yyxxxxxx */
|
|
|
880eca |
yyyy = src_high->low << 4;
|
|
|
880eca |
trail = yyyy << 2;
|
|
|
880eca |
trail |= src_high->high ^ 0x80;
|
|
|
880eca |
trail |= 0xDC00;
|
|
|
880eca |
|
|
|
880eca |
/* write */
|
|
|
880eca |
*dst_lead = lead;
|
|
|
880eca |
*dst_trail = trail;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* advance source and destination buffer */
|
|
|
dd89bb |
args->src += 4;
|
|
|
dd89bb |
args->dst = (void *)((uintptr_t)(args->dst) + (2 * sizeof(wchar16_t)));
|
|
|
dd89bb |
|
|
|
dd89bb |
/* bytes_written */
|
|
|
dd89bb |
args->bytes_written += 2 * sizeof(wchar16_t);
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __fastcall __update_stream_leftover_info_utf8(
|
|
|
dd89bb |
__in_out nt_unicode_conversion_params_utf8_to_utf16 * params)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
ptrdiff_t offset;
|
|
|
dd89bb |
unsigned char * utf8;
|
|
|
dd89bb |
|
|
|
dd89bb |
offset = (uintptr_t)params->src + (uintptr_t)params->src_size_in_bytes - (uintptr_t)params->addr_failed;
|
|
|
dd89bb |
utf8 = (unsigned char *)params->addr_failed;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* default status */
|
|
|
dd89bb |
status = NT_STATUS_ILLEGAL_CHARACTER;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (offset == 1) {
|
|
|
dd89bb |
if ((utf8[0] >= 0xC2) && (utf8[0] <= 0xF4)) {
|
|
|
dd89bb |
/* one leftover byte */
|
|
|
dd89bb |
params->leftover_count = 1;
|
|
|
dd89bb |
params->leftover_bytes = utf8[0];
|
|
|
dd89bb |
params->leftover_bytes <<= 24;
|
|
|
dd89bb |
status = NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
} else if (offset == 2) {
|
|
|
dd89bb |
if /* ------- */ (((utf8[0] == 0xE0) && (utf8[1] >= 0xA0) && (utf8[1] <= 0xBF))
|
|
|
dd89bb |
|| ((utf8[0] >= 0xE1) && (utf8[0] <= 0xEC) && (utf8[1] >= 0x80) && (utf8[1] <= 0xBF))
|
|
|
dd89bb |
|| ((utf8[0] == 0xED) && (utf8[1] >= 0x80) && (utf8[1] <= 0x9F))
|
|
|
dd89bb |
|| ((utf8[0] >= 0xEE) && (utf8[0] <= 0xEF) && (utf8[1] >= 0x80) && (utf8[1] <= 0xBF))
|
|
|
dd89bb |
|| ((utf8[0] == 0xF0) && (utf8[1] >= 0x90) && (utf8[1] <= 0xBF))
|
|
|
dd89bb |
|| ((utf8[0] >= 0xF1) && (utf8[0] <= 0xF3) && (utf8[1] >= 0x80) && (utf8[1] <= 0xBF))
|
|
|
dd89bb |
|| ((utf8[0] == 0xF4) && (utf8[1] >= 0x80) && (utf8[1] <= 0x8F))) {
|
|
|
dd89bb |
/* two leftover bytes */
|
|
|
dd89bb |
params->leftover_count = 2;
|
|
|
dd89bb |
params->leftover_bytes = utf8[0];
|
|
|
dd89bb |
params->leftover_bytes <<= 8;
|
|
|
dd89bb |
params->leftover_bytes += utf8[1];
|
|
|
dd89bb |
params->leftover_bytes <<= 16;
|
|
|
dd89bb |
status = NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
} else if (offset == 3) {
|
|
|
dd89bb |
if /* ------- */ (((utf8[0] == 0xF0) && (utf8[1] >= 0x90) && (utf8[1] <= 0xBF))
|
|
|
dd89bb |
|| ((utf8[0] >= 0xF1) && (utf8[0] <= 0xF3) && (utf8[1] >= 0x80) && (utf8[1] <= 0xBF))
|
|
|
dd89bb |
|| ((utf8[0] == 0xF4) && (utf8[1] >= 0x80) && (utf8[1] <= 0x8F))) {
|
|
|
dd89bb |
/* three leftover bytes */
|
|
|
dd89bb |
params->leftover_count = 3;
|
|
|
dd89bb |
params->leftover_bytes = utf8[0];
|
|
|
dd89bb |
params->leftover_bytes <<= 8;
|
|
|
dd89bb |
params->leftover_bytes += utf8[1];
|
|
|
dd89bb |
params->leftover_bytes <<= 8;
|
|
|
dd89bb |
params->leftover_bytes += utf8[2];
|
|
|
dd89bb |
params->leftover_bytes <<= 8;
|
|
|
dd89bb |
status = NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status != NT_STATUS_SUCCESS) {
|
|
|
dd89bb |
params->leftover_count = 0;
|
|
|
dd89bb |
params->leftover_bytes = 0;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_uc_convert_unicode_stream_utf8_to_utf16(
|
|
|
dd89bb |
__in_out nt_unicode_conversion_params_utf8_to_utf16 * params)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
nt_utf8_callback_args args;
|
|
|
dd89bb |
ntapi_uc_utf8_callback_fn * callback_fn[5];
|
|
|
dd89bb |
|
|
|
dd89bb |
callback_fn[0] = (ntapi_uc_utf8_callback_fn *)__utf8_to_utf16_handler_1byte_or_null_termination;
|
|
|
dd89bb |
callback_fn[1] = (ntapi_uc_utf8_callback_fn *)__utf8_to_utf16_handler_1byte_or_null_termination;
|
|
|
dd89bb |
callback_fn[2] = (ntapi_uc_utf8_callback_fn *)__utf8_to_utf16_handler_2bytes;
|
|
|
dd89bb |
callback_fn[3] = (ntapi_uc_utf8_callback_fn *)__utf8_to_utf16_handler_3bytes;
|
|
|
dd89bb |
callback_fn[4] = (ntapi_uc_utf8_callback_fn *)__utf8_to_utf16_handler_4bytes;
|
|
|
dd89bb |
|
|
|
dd89bb |
args.src = params->src;
|
|
|
dd89bb |
args.dst = params->dst;
|
|
|
dd89bb |
args.dst_cap = (void *)((uintptr_t)(params->dst) + (params->dst_size_in_bytes));
|
|
|
dd89bb |
args.bytes_written = params->bytes_written;
|
|
|
dd89bb |
|
|
|
dd89bb |
status = __ntapi_uc_validate_unicode_stream_utf8(
|
|
|
dd89bb |
params->src,
|
|
|
dd89bb |
params->src_size_in_bytes,
|
|
|
dd89bb |
¶ms->code_points,
|
|
|
dd89bb |
¶ms->addr_failed,
|
|
|
dd89bb |
callback_fn,
|
|
|
dd89bb |
&args);
|
|
|
dd89bb |
|
|
|
dd89bb |
params->bytes_written = args.bytes_written;
|
|
|
dd89bb |
|
|
|
56548d |
switch (status) {
|
|
|
56548d |
case NT_STATUS_SUCCESS:
|
|
|
0e7864 |
params->addr_failed = 0;
|
|
|
0e7864 |
params->leftover_bytes = 0;
|
|
|
0e7864 |
params->leftover_count = 0;
|
|
|
0e7864 |
return status;
|
|
|
0e7864 |
|
|
|
56548d |
case NT_STATUS_BUFFER_TOO_SMALL:
|
|
|
0e7864 |
params->addr_failed = args.src;
|
|
|
0e7864 |
params->leftover_bytes = 0;
|
|
|
0e7864 |
params->leftover_count = 0;
|
|
|
56548d |
return status;
|
|
|
56548d |
|
|
|
56548d |
default:
|
|
|
56548d |
status = __update_stream_leftover_info_utf8(params);
|
|
|
56548d |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* (optimized out on 32-bit architectures) */
|
|
|
dd89bb |
params->leftover_bytes <<= (8 * (sizeof(uintptr_t) - sizeof(uint32_t)));
|
|
|
dd89bb |
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_uc_convert_unicode_stream_utf8_to_utf32(
|
|
|
dd89bb |
__in_out nt_unicode_conversion_params_utf8_to_utf32 * params)
|
|
|
dd89bb |
{
|
|
|
c713d8 |
(void)params;
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|