replace all wchar_t's with uint16_t's

This commit is contained in:
rjkiv 2025-08-09 13:54:47 -07:00
parent c78171755d
commit f6a2635e15
3 changed files with 200 additions and 133 deletions

View File

@ -13,7 +13,7 @@ typedef int (*_PIFV)();
namespace msvcrt {
int _commode;
int _fmode;
wchar_t** __winitenv;
uint16_t** __winitenv;
// Stub because we're only ever a console application
void WIN_ENTRY __set_app_type(int at) {
@ -62,7 +62,8 @@ namespace msvcrt {
// https://github.com/reactos/reactos/blob/fade0c3b8977d43f3a9e0b8887d18afcabd8e145/sdk/lib/crt/misc/getargs.c#L328
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/getmainargs-wgetmainargs?view=msvc-170
int WIN_ENTRY __wgetmainargs(int* wargc, wchar_t*** wargv, wchar_t*** wenv, int doWildcard, int* startInfo){
int WIN_ENTRY __wgetmainargs(int* wargc, uint16_t*** wargv, uint16_t*** wenv, int doWildcard, int* startInfo){
DEBUG_LOG("__wgetmainargs\n");
// get the regular, non-wide versions of argc/argv/env
// argc: the number of args in argv. always >= 1
// argv: array of null-terminated strings for command-line args.
@ -89,75 +90,28 @@ namespace msvcrt {
std::setlocale(LC_CTYPE, "");
if(wargv){
*wargv = new wchar_t*[argc + 1]; // allocate array of our future wstrings
*wargv = new uint16_t*[argc + 1]; // allocate array of our future wstrings
for(int i = 0; i < argc; i++){
const char* cur_arg = argv[i];
size_t wSize = std::mbstowcs(nullptr, cur_arg, 0);
if(wSize != (size_t)-1){
wSize++; // for null terminator
wchar_t* wStr = new wchar_t[wSize];
std::mbstowcs(wStr, cur_arg, wSize);
(*wargv)[i] = wStr;
}
else {
DEBUG_LOG("Bad argv[%d]: %s\n", i, cur_arg);
return -1;
}
std::vector<uint16_t> wStr = stringToWideString(cur_arg);
(*wargv)[i] = wStr.data();
}
(*wargv)[argc] = nullptr;
// sanity check
// for (int i = 0; i < argc; i++) {
// wchar_t* warg = (*wargv)[i];
// size_t len = std::wcstombs(nullptr, warg, 0);
// if (len != (size_t)-1) {
// char* converted = new char[len + 1];
// std::wcstombs(converted, warg, len + 1);
// DEBUG_LOG("Input argv[%d]: %s\n", i, argv[i]);
// DEBUG_LOG("Output wargv[%d]: %s\n", i, converted);
// delete[] converted;
// } else {
// DEBUG_LOG("Bad wide arg conversion for %d!\n", i);
// }
// }
}
if(wenv){
int count = 0;
for(; env[count] != nullptr; count++);
DEBUG_LOG("Found env count %d\n", count);
*wenv = new wchar_t*[count + 1]; // allocate array of our future wstrings
*wenv = new uint16_t*[count + 1]; // allocate array of our future wstrings
for(int i = 0; i < count; i++){
const char* cur_env = env[i];
size_t wSize = std::mbstowcs(nullptr, cur_env, 0);
if(wSize != (size_t)-1){
wSize++; // for null terminator
wchar_t* wStr = new wchar_t[wSize];
std::mbstowcs(wStr, cur_env, wSize);
(*wenv)[i] = wStr;
}
else {
DEBUG_LOG("Bad env[%d]: %s\n", i, cur_env);
return -1;
}
DEBUG_LOG("Adding env %s\n", cur_env);
std::vector<uint16_t> wStr = stringToWideString(cur_env);
(*wenv)[i] = wStr.data();
}
(*wenv)[count] = nullptr;
// sanity check
// for (int i = 0; i < count; i++) {
// wchar_t* warg = (*wenv)[i];
// size_t len = std::wcstombs(nullptr, warg, 0);
// if (len != (size_t)-1) {
// char* converted = new char[len + 1];
// std::wcstombs(converted, warg, len + 1);
// DEBUG_LOG("Input env[%d]: %s\n", i, env[i]);
// DEBUG_LOG("Output wenv[%d]: %s\n", i, converted);
// delete[] converted;
// } else {
// DEBUG_LOG("Bad wide arg conversion for %d!\n", i);
// }
// }
__winitenv = *wenv;
}
return 0;
@ -167,30 +121,28 @@ namespace msvcrt {
return std::setlocale(category, locale);
}
int WIN_ENTRY _wdupenv_s(wchar_t **buffer, size_t *numberOfElements, const wchar_t *varname){
std::string var_str = wideStringToString((const unsigned short*)varname, wcslen(varname));
DEBUG_LOG("_wdupenv_s: %s\n", var_str.c_str());
int WIN_ENTRY _wdupenv_s(uint16_t **buffer, size_t *numberOfElements, const uint16_t *varname){
std::string var_str = wideStringToString(varname);
DEBUG_LOG("_wdupenv_s: var name %s\n", var_str.c_str());
if(!buffer || !varname) return 22;
*buffer = nullptr;
if(numberOfElements) *numberOfElements = 0;
size_t varnamelen = wcslen(varname);
size_t varnamelen = wstrlen(varname);
for(wchar_t** env = __winitenv; env && *env; ++env){
wchar_t* cur = *env;
if(wcsncmp(cur, varname, varnamelen) == 0 && cur[varnamelen] == L'='){
wchar_t* value = cur + varnamelen + 1;
size_t value_len = wcslen(value);
for(uint16_t** env = __winitenv; env && *env; ++env){
uint16_t* cur = *env;
std::string cur_str = wideStringToString(cur);
if(wstrncmp(cur, varname, varnamelen) == 0 && cur[varnamelen] == L'='){
uint16_t* value = cur + varnamelen + 1;
size_t value_len = wstrlen(value);
wchar_t* copy = (wchar_t*)malloc((value_len + 1) * sizeof(wchar_t));
uint16_t* copy = (uint16_t*)malloc((value_len + 1) * sizeof(uint16_t));
if(!copy) return 12;
std::wmemcpy(copy, value, value_len + 1);
wstrncpy(copy, value, value_len + 1);
*buffer = copy;
std::string value_str = wideStringToString((const unsigned short*)copy, wcslen(copy));
DEBUG_LOG("Value: %s\n", value_str.c_str());
if(numberOfElements) *numberOfElements = value_len + 1;
return 0;
}
@ -207,30 +159,21 @@ namespace msvcrt {
std::free(ptr);
}
int WIN_ENTRY _get_wpgmptr(wchar_t** pValue){
int WIN_ENTRY _get_wpgmptr(uint16_t** pValue){
DEBUG_LOG("STUB: _get_wpgmptr(%p)\n", pValue);
return 0;
}
int WIN_ENTRY _wsplitpath_s(const wchar_t * path, wchar_t * drive, size_t driveNumberOfElements, wchar_t *dir, size_t dirNumberOfElements,
wchar_t * fname, size_t nameNumberOfElements, wchar_t * ext, size_t extNumberOfElements){
int WIN_ENTRY _wsplitpath_s(const uint16_t * path, uint16_t * drive, size_t driveNumberOfElements, uint16_t *dir, size_t dirNumberOfElements,
uint16_t * fname, size_t nameNumberOfElements, uint16_t * ext, size_t extNumberOfElements){
if(!path){
DEBUG_LOG("no path\n");
return -1;
}
{
size_t wlen = std::wcstombs(nullptr, path, 0);
if(wlen != (size_t)-1){
char* converted = new char[wlen + 1];
std::wcstombs(converted, path, wlen + 1);
DEBUG_LOG("Path: %s\n", converted);
delete [] converted;
}
else {
DEBUG_LOG("Bad wide arg conversion for path!\n");
}
else {
std::string path_str = wideStringToString(path);
DEBUG_LOG("path: %s\n", path_str.c_str());
}
if(drive && driveNumberOfElements) drive[0] = L'\0';
@ -238,29 +181,29 @@ namespace msvcrt {
if(fname && nameNumberOfElements) fname[0] = L'\0';
if(ext && extNumberOfElements) ext[0] = L'\0';
const wchar_t *slash = wcsrchr(path, L'/');
const wchar_t *dot = wcsrchr(path, L'.');
const wchar_t *filename_start = slash ? slash + 1 : path;
const uint16_t *slash = wstrrchr(path, L'/');
const uint16_t *dot = wstrrchr(path, L'.');
const uint16_t *filename_start = slash ? slash + 1 : path;
if (dot && dot < filename_start) dot = nullptr;
if (dir && dirNumberOfElements && slash) {
size_t dir_len = slash - path + 1;
if (dir_len >= dirNumberOfElements) return -1;
wcsncpy(dir, path, dir_len);
wstrncpy(dir, path, dir_len);
dir[dir_len] = L'\0';
}
if (fname && nameNumberOfElements) {
size_t fname_len = dot ? (size_t)(dot - filename_start) : wcslen(filename_start);
size_t fname_len = dot ? (size_t)(dot - filename_start) : wstrlen(filename_start);
if (fname_len >= nameNumberOfElements) return -1;
wcsncpy(fname, filename_start, fname_len);
wstrncpy(fname, filename_start, fname_len);
fname[fname_len] = L'\0';
}
if (ext && extNumberOfElements && dot) {
size_t ext_len = wcslen(dot);
size_t ext_len = wstrlen(dot);
if (ext_len >= extNumberOfElements) return -1;
wcsncpy(ext, dot, ext_len);
wstrncpy(ext, dot, ext_len);
ext[ext_len] = L'\0';
}
@ -274,41 +217,41 @@ namespace msvcrt {
return 0;
}
int WIN_ENTRY wcscat_s(wchar_t *strDestination, size_t numberOfElements, const wchar_t *strSource){
std::string dst_str = wideStringToString((const unsigned short*)strDestination, wcslen(strDestination));
std::string src_str = wideStringToString((const unsigned short*)strSource, wcslen(strSource));
int WIN_ENTRY wcscat_s(uint16_t *strDestination, size_t numberOfElements, const uint16_t *strSource){
std::string dst_str = wideStringToString(strDestination);
std::string src_str = wideStringToString(strSource);
DEBUG_LOG("wcscat_s %s %d %s", dst_str.c_str(), numberOfElements, src_str.c_str());
if(!strDestination || !strSource || numberOfElements == 0) return 22;
size_t dest_len = wcslen(strDestination);
size_t src_len = wcslen(strSource);
size_t dest_len = wstrlen(strDestination);
size_t src_len = wstrlen(strSource);
if(dest_len + src_len + 1 > numberOfElements){
if(strDestination && numberOfElements > 0) strDestination[0] = L'\0';
return 34;
}
std::wcscat(strDestination, strSource);
dst_str = wideStringToString((const unsigned short*)strDestination, wcslen(strDestination));
wstrcat(strDestination, strSource);
dst_str = wideStringToString(strDestination);
DEBUG_LOG(" --> %s\n", dst_str.c_str());
return 0;
}
wchar_t* WIN_ENTRY _wcsdup(const wchar_t *strSource){
std::string src_str = wideStringToString((const unsigned short*)strSource, wcslen(strSource));
uint16_t* WIN_ENTRY _wcsdup(const uint16_t *strSource){
std::string src_str = wideStringToString(strSource);
DEBUG_LOG("_wcsdup: %s", src_str.c_str());
if(!strSource) return nullptr;
size_t strLen = wcslen(strSource);
size_t strLen = wstrlen(strSource);
wchar_t* dup = (wchar_t*)malloc((strLen + 1) * sizeof(wchar_t));
uint16_t* dup = (uint16_t*)malloc((strLen + 1) * sizeof(uint16_t));
if(!dup) return nullptr;
for(int i = 0; i <= strLen; i++){
for(size_t i = 0; i <= strLen; i++){
dup[i] = strSource[i];
}
std::string dst_str = wideStringToString((const unsigned short*)dup, wcslen(dup));
std::string dst_str = wideStringToString(dup);
DEBUG_LOG(" --> %s\n", dst_str.c_str());
return dup;
}
@ -317,8 +260,8 @@ namespace msvcrt {
return std::memset(s, c, n);
}
int WIN_ENTRY wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count){
std::string src_str = wideStringToString((const unsigned short*)strSource, wcslen(strSource));
int WIN_ENTRY wcsncpy_s(uint16_t *strDest, size_t numberOfElements, const uint16_t *strSource, size_t count){
std::string src_str = wideStringToString(strSource);
DEBUG_LOG("wcsncpy_s dest size %d, src str %s, src size %d", numberOfElements, src_str.c_str(), count);
if(!strDest || !strSource || numberOfElements == 0){
@ -326,23 +269,23 @@ namespace msvcrt {
return 1;
}
if(count == (size_t)-1) count = std::wcslen(strSource);
if(count == (size_t)-1) count = wstrlen(strSource);
if(count >= numberOfElements){
strDest[0] = L'\0';
return 1;
}
std::wcsncpy(strDest, strSource, count);
wstrncpy(strDest, strSource, count);
strDest[count] = L'\0';
std::string dst_str = wideStringToString((const unsigned short*)strDest, wcslen(strDest));
std::string dst_str = wideStringToString(strDest);
DEBUG_LOG(" --> %s\n", dst_str.c_str());
return 0;
}
int WIN_ENTRY wcsncat_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count){
std::string dst_str = wideStringToString((const unsigned short*)strDest, wcslen(strDest));
std::string src_str = wideStringToString((const unsigned short*)strSource, wcslen(strSource));
int WIN_ENTRY wcsncat_s(uint16_t *strDest, size_t numberOfElements, const uint16_t *strSource, size_t count){
std::string dst_str = wideStringToString(strDest);
std::string src_str = wideStringToString(strSource);
DEBUG_LOG("wscncat_s dest str %s, dest size %d, src str %s, src size %d", dst_str.c_str(), numberOfElements, src_str.c_str(), count);
if(!strDest || !strSource || numberOfElements == 0){
@ -350,31 +293,31 @@ namespace msvcrt {
return 1;
}
size_t dest_len = std::wcslen(strDest);
size_t src_len = (count == (size_t)-1) ? std::wcslen(strSource) : wcsnlen(strSource, count);
size_t dest_len = wstrlen(strDest);
size_t src_len = (count == (size_t)-1) ? wstrlen(strSource) : wstrnlen(strSource, count);
if(dest_len + src_len + 1 > numberOfElements){
strDest[0] = L'\0';
return 1;
}
std::wcsncat(strDest, strSource, src_len);
dst_str = wideStringToString((const unsigned short*)strDest, wcslen(strDest));
wstrncat(strDest, strSource, src_len);
dst_str = wideStringToString(strDest);
DEBUG_LOG(" --> %s\n", dst_str.c_str());
return 0;
}
int WIN_ENTRY _itow_s(int value, wchar_t *buffer, size_t size, int radix){
int WIN_ENTRY _itow_s(int value, uint16_t *buffer, size_t size, int radix){
DEBUG_LOG("STUB: _itow_s\n");
return 0;
}
int WIN_ENTRY _wtoi(const wchar_t* str) {
int WIN_ENTRY _wtoi(const uint16_t* str) {
DEBUG_LOG("_wtoi\n");
return (int)wcstol(str, nullptr, 10);
return wstrtol(str, nullptr, 10);
}
int WIN_ENTRY wcscpy_s(wchar_t *dest, size_t dest_size, const wchar_t *src){
int WIN_ENTRY wcscpy_s(uint16_t *dest, size_t dest_size, const uint16_t *src){
DEBUG_LOG("STUB: wcscpy_s\n");
return 0;
}
@ -392,30 +335,32 @@ namespace msvcrt {
_Exit(status);
}
int WIN_ENTRY wcsncmp(const wchar_t *string1, const wchar_t *string2, size_t count){
return std::wcsncmp(string1, string2, count);
int WIN_ENTRY wcsncmp(const uint16_t *string1, const uint16_t *string2, size_t count){
return wstrncmp(string1, string2, count);
}
int WIN_ENTRY _vswprintf_c_l(wchar_t* buffer, size_t size, const wchar_t* format, va_list args) {
int WIN_ENTRY _vswprintf_c_l(uint16_t* buffer, size_t size, const uint16_t* format, va_list args) {
if (!buffer || !format || size == 0)
return -1;
return vswprintf(buffer, size, format, args);
DEBUG_LOG("STUB: _vswprintf_c_l\n");
return 0;
// return vswprintf(buffer, size, format, args); this doesn't work because on this architecture, wchar_t is size 4, instead of size 2
}
const wchar_t* WIN_ENTRY wcsstr( const wchar_t *dest, const wchar_t *src ){
return std::wcsstr(dest, src);
const uint16_t* WIN_ENTRY wcsstr( const uint16_t *dest, const uint16_t *src ){
return wstrstr(dest, src);
}
int WIN_ENTRY iswspace(wint_t w){
return std::iswspace(w);
}
const wchar_t* WIN_ENTRY wcsrchr(const wchar_t *str, wchar_t c){
return std::wcsrchr(str, c);
const uint16_t* WIN_ENTRY wcsrchr(const uint16_t *str, uint16_t c){
return wstrrchr(str, c);
}
unsigned long WIN_ENTRY wcstoul(const wchar_t *strSource, wchar_t **endptr, int base){
return std::wcstoul(strSource, endptr, base);
unsigned long WIN_ENTRY wcstoul(const uint16_t *strSource, uint16_t **endptr, int base){
return wstrtoul(strSource, endptr, base);
}
}

View File

@ -1,5 +1,6 @@
#include "common.h"
#include "strings.h"
#include <cstdint>
#include <vector>
size_t wstrlen(const uint16_t *str) {
@ -9,6 +10,73 @@ size_t wstrlen(const uint16_t *str) {
return len;
}
size_t wstrnlen(const uint16_t* str, size_t numberOfElements){
size_t len = 0;
while (str[len] != 0 && len < numberOfElements)
++len;
return len;
}
int wstrncmp(const uint16_t *string1, const uint16_t *string2, size_t count){
const uint16_t* ptr1 = string1;
const uint16_t* ptr2 = string2;
for(size_t i = 0; i < count; i++){
uint16_t c1 = *ptr1++;
uint16_t c2 = *ptr2++;
if (c1 != c2) {
return (c1 > c2) ? 1 : -1;
}
}
return 0;
}
const uint16_t* wstrstr(const uint16_t *dest, const uint16_t *src){
if (!*src) return dest;
for (; *dest != 0; dest++) {
const uint16_t* d = dest;
const uint16_t* s = src;
while (*d != 0 && *s != 0 && *d == *s) {
d++;
s++;
}
if (*s == 0) {
return dest;
}
}
return nullptr;
}
uint16_t* wstrrchr(const uint16_t* str, uint16_t c){
const uint16_t* last = nullptr;
for (; *str != 0; str++) {
if (*str == c) {
last = str;
}
}
return (uint16_t*)last;
}
uint16_t* wstrcat(uint16_t* dest, const uint16_t* src){
uint16_t* d = dest;
while (*d) d++;
while ((*d++ = *src++) != 0);
return dest;
}
uint16_t* wstrncat(uint16_t* dest, const uint16_t* src, size_t count){
uint16_t* d = dest;
while (*d) d++;
for(size_t i = 0; i < count && src[i] != 0; i++){
*d++ = src[i];
}
*d = 0;
return dest;
}
size_t wstrncpy(uint16_t *dst, const uint16_t *src, size_t n) {
size_t i = 0;
while (i < n && src[i] != 0) {
@ -40,5 +108,51 @@ std::vector<uint16_t> stringToWideString(const char *src) {
}
res[len] = 0; // NUL terminate
return res;
}
long wstrtol(const uint16_t* string, uint16_t** end_ptr, int base){
if(!string){
if(end_ptr) *end_ptr = nullptr;
return 0;
}
std::string normal_str = wideStringToString(string);
char* normal_end = nullptr;
long res = std::strtol(normal_str.c_str(), &normal_end, base);
if(end_ptr){
if(normal_end && *normal_end){
size_t offset = normal_end - normal_str.c_str();
*end_ptr = (uint16_t*)(string + offset);
}
else {
*end_ptr = (uint16_t*)(string + normal_str.size());
}
}
return res;
}
unsigned long wstrtoul(const uint16_t* string, uint16_t** end_ptr, int base){
if(!string){
if(end_ptr) *end_ptr = nullptr;
return 0;
}
std::string normal_str = wideStringToString(string);
char* normal_end = nullptr;
unsigned long res = std::strtoul(normal_str.c_str(), &normal_end, base);
if(end_ptr){
if(normal_end && *normal_end){
size_t offset = normal_end - normal_str.c_str();
*end_ptr = (uint16_t*)(string + offset);
}
else {
*end_ptr = (uint16_t*)(string + normal_str.size());
}
}
return res;
}

View File

@ -2,6 +2,14 @@
#include <vector>
size_t wstrlen(const uint16_t *str);
size_t wstrnlen(const uint16_t* str, size_t numberOfElements);
int wstrncmp(const uint16_t *string1, const uint16_t *string2, size_t count);
const uint16_t* wstrstr(const uint16_t *dest, const uint16_t *src);
uint16_t* wstrrchr(const uint16_t* str, uint16_t c);
uint16_t* wstrcat(uint16_t* dest, const uint16_t* src);
uint16_t* wstrncat(uint16_t* dest, const uint16_t* src, size_t count);
size_t wstrncpy(uint16_t *dst, const uint16_t *src, size_t n);
std::string wideStringToString(const uint16_t *src, int len = -1);
std::vector<uint16_t> stringToWideString(const char *src);
std::vector<uint16_t> stringToWideString(const char *src);
long wstrtol(const uint16_t* string, uint16_t** end_ptr, int base);
unsigned long wstrtoul(const uint16_t* strSource, uint16_t** end_ptr, int base);