Skip to content

Instantly share code, notes, and snippets.

@trueroad
Last active April 12, 2023 01:06
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trueroad/46e9912cf3858bb01abe to your computer and use it in GitHub Desktop.
Save trueroad/46e9912cf3858bb01abe to your computer and use it in GitHub Desktop.
Unicode Filename Support for MinGW.org / MinGW-w64 Platform Software (hook)
Unicode Filename Support for MinGW.org / MinGW-w64 Platform Software (hook)
CXX = i686-w64-mingw32-g++
testmain: testmain.cc mingw-utf8-main.cc mingw-utf8-hook.cc \
mingw-utf8-func.cc mingw-utf8-conv.cc
$(CXX) -static -o testmain testmain.cc \
mingw-utf8-main.cc mingw-utf8-hook.cc \
mingw-utf8-func.cc mingw-utf8-conv.cc \
-ldbghelp
clean:
-rm -fr *~
/*
Copyright (C) 2015 Masamichi Hosoda <trueroad@trueroad.jp>
*/
#ifdef __MINGW32__
#include <cwchar>
#include <vector>
#include <windows.h>
#include "mingw-utf8-conv.hh"
// Convert from UTF-16 to UTF-8
std::vector<char> mingw_utf8_16to8 (const wchar_t *wc)
{
int size = WideCharToMultiByte (CP_UTF8, 0, wc, -1, NULL, 0, NULL, NULL);
std::vector<char> retval (size);
if (size)
{
WideCharToMultiByte (CP_UTF8, 0, wc, -1,
retval.data(), retval.size(), NULL, NULL);
}
else
retval.push_back ('\0');
return retval;
}
// Convert from UTF-8 to UTF-16
std::vector<wchar_t> mingw_utf8_8to16 (const char *c)
{
int size = MultiByteToWideChar (CP_UTF8, 0, c, -1, NULL, 0);
std::vector<wchar_t> retval (size);
if (size)
{
MultiByteToWideChar (CP_UTF8, 0, c, -1,
retval.data(), retval.size());
}
else
retval.push_back (L'\0');
return retval;
}
#endif // __MINGW32__
#ifndef __MINGW_UTF8_CONV_H__
#define __MINGW_UTF8_CONV_H__
std::vector<char> mingw_utf8_16to8 (const wchar_t *wc);
std::vector<wchar_t> mingw_utf8_8to16 (const char *c);
#endif // __MINGW_UTF8_CONV_H__
/*
Copyright (C) 2015 Masamichi Hosoda <trueroad@trueroad.jp>
*/
#ifdef __MINGW32__
#include <cwchar>
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <vector>
#include <sys/stat.h>
#include <fcntl.h>
//#include <glib.h>
#include "mingw-utf8-func.hh"
#include "mingw-utf8-conv.hh"
// msvcrt fopen()
FILE *utf8_fopen (const char *path, const char *mode)
{
printf("hook!! fopen (\"%s\", \"%s\")\n", path, mode);
std::vector<wchar_t> wpath (mingw_utf8_8to16 (path));
std::vector<wchar_t> wmode (mingw_utf8_8to16 (mode));
return _wfopen (wpath.data(), wmode.data());
}
// msvcrt freopen()
FILE *utf8_freopen (const char *path, const char *mode, FILE *stream)
{
printf("hook!! freopen (\"%s\", \"%s\", stream)\n", path, mode);
std::vector<wchar_t> wpath (mingw_utf8_8to16 (path));
std::vector<wchar_t> wmode (mingw_utf8_8to16 (mode));
return _wfreopen (wpath.data(), wmode.data(), stream);
}
// msvcrt _stat() / stat()
int utf8__stat (const char *path, struct _stat *buff)
{
printf("hook!! _stat (\"%s\", buff)\n", path);
std::vector<wchar_t> wpath (mingw_utf8_8to16 (path));
return _wstat (wpath.data(), buff);
}
// msvcrt getcwd() / _getcwd()
char *utf8_getcwd(char *buff, int size)
{
printf("hook!! getcwd (0x%p, %d)\n", buff, size);
wchar_t *wp = _wgetcwd(NULL, 0);
std::vector<char> p (mingw_utf8_16to8 (wp));
free (wp);
if (buff == NULL)
buff = (char*) malloc (p.size());
strncpy(buff, p.data(), size);
buff[size]=0;
return buff;
}
// msvcrt getenv()
char *utf8_getenv(const char *var)
{
fputs("hook!! getenv (\"", stdout);
fputs(var, stdout);
fputs("\")\n", stdout);
static std::vector<char> env_ret;
std::vector<wchar_t> wvar (mingw_utf8_8to16 (var));
wchar_t *e = _wgetenv(wvar.data());
if (e == NULL)
return NULL;
env_ret = mingw_utf8_16to8 (e);
return env_ret.data();
}
// msvcrt open() / _open()
int utf8_open (const char *path, int flag, ...)
{
printf("hook!! open (\"%s\", flag, ...)\n", path);
int mode = 0777;
va_list list;
va_start (list, flag);
if ( flag & O_CREAT )
mode = va_arg (list, int);
va_end (list);
std::vector<wchar_t> wpath (mingw_utf8_8to16 (path));
return _wopen(wpath.data(), flag, mode);
}
// msvcrt system()
int utf8_system (const char *command)
{
printf("hook!! system (\"%s\")\n", command);
std::vector<wchar_t> wcommand (mingw_utf8_8to16 (command));
return _wsystem(wcommand.data());
}
#if 0
// glib g_locale_{to|from}_utf8()
// from gconvert.c g_locale_{to|from}_utf8() and strdup_len()
gchar *utf8_g_locale_to_from_utf8 (const gchar *string, gssize len,
gsize *bytes_read, gssize *bytes_written,
GError **error)
{
printf("hook!! g_locale_{to|from}_utf8\n");
gsize real_len;
if (len < 0)
real_len = strlen (string);
else
{
real_len = 0;
while (real_len < len && string[real_len])
real_len++;
}
if (bytes_read)
*bytes_read = real_len;
if (bytes_written)
*bytes_written = real_len;
return g_strndup (string, real_len);
}
#endif
#endif // __MINGW32__
#ifndef __MINGW_UTF8_FUNC_H__
#define __MINGW_UTF8_FUNC_H__
FILE *utf8_fopen(const char *path, const char *mode);
FILE *utf8_freopen (const char *path, const char *mode, FILE *stream);
int utf8__stat (const char *path, struct _stat *buff);
char *utf8_getcwd(char *buff, int size);
char *utf8_getenv(const char *var);
int utf8_open (const char *path, int flag, ...);
int utf8_system (const char *command);
//gchar *utf8_g_locale_to_from_utf8 (const gchar *string, gssize len,
// gsize *bytes_read, gssize *bytes_written,
// GError **error);
#endif // __MINGW_UTF8_FUNC_H__
/*
Copyright (C) 2015 Masamichi Hosoda <trueroad@trueroad.jp>
*/
#ifdef __MINGW32__
#include <cwchar>
#include <vector>
#include <windows.h>
#include <tlhelp32.h>
#include <dbghelp.h>
//#include <glib.h>
#include <cstdio>
#include "mingw-utf8-hook.hh"
#include "mingw-utf8-func.hh"
// Internal use
namespace
{
void hook_all (PROC func_old, PROC func_new);
void hook_one (PROC func_old, PROC func_new,
HMODULE hmod, LPBYTE pbase);
}
// Address of hook target functions.
extern "C"
{
extern PROC _imp__fopen;
extern PROC _imp__freopen;
extern PROC _imp___stat;
extern PROC _imp__stat;
extern PROC _imp__getcwd;
extern PROC _imp___getcwd;
extern PROC _imp__getenv;
extern PROC _imp__open;
extern PROC _imp___open;
extern PROC _imp__system;
extern PROC _imp__g_locale_to_utf8;
extern PROC _imp__g_locale_from_utf8;
}
// Hook filename related functions.
void mingw_utf8_hook (void)
{
printf("try to hook fopen\n");
hook_all (_imp__fopen, (PROC)utf8_fopen);
printf("try to hook freopen\n");
hook_all (_imp__freopen, (PROC)utf8_freopen);
printf("try to hook _stat\n");
hook_all (_imp___stat, (PROC)utf8__stat);
printf("try to hook stat\n");
hook_all (_imp__stat, (PROC)utf8__stat);
printf("try to hook getcwd\n");
hook_all (_imp__getcwd, (PROC)utf8_getcwd);
printf("try to hook _getcwd\n");
hook_all (_imp___getcwd, (PROC)utf8_getcwd);
printf("try to hook getenv\n");
hook_all (_imp__getenv, (PROC)utf8_getenv);
printf("try to hook open\n");
hook_all (_imp__open, (PROC)utf8_open);
printf("try to hook _open\n");
hook_all (_imp___open, (PROC)utf8_open);
printf("try to hook system\n");
hook_all (_imp__system, (PROC)utf8_system);
//printf("try to hook g_locale_to_utf8\n");
//hook_all (_imp__g_locale_to_utf8, (PROC)utf8_g_locale_to_from_utf8);
//printf("try to hook g_locale_from_utf8\n");
//hook_all (_imp__g_locale_from_utf8, (PROC)utf8_g_locale_to_from_utf8);
}
namespace
{
// Hook all loaded modules.
void hook_all (PROC func_old, PROC func_new)
{
printf ("hook_all enter old %p, new %p\n", func_old, func_new);
fflush (stdout);
// Take a snapshot of modules.
HANDLE hmod_snap =
CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, GetCurrentProcessId ());
if (hmod_snap == INVALID_HANDLE_VALUE)
return;
// Enumerate snapshotted modules.
MODULEENTRY32W me;
me.dwSize = sizeof (me);
BOOL bresult = Module32FirstW (hmod_snap, &me);
while (bresult)
{
printf (" Module %S...\n", me.szModule);
fflush (stdout);
// Hook one module.
hook_one(func_old, func_new, me.hModule, me.modBaseAddr);
bresult = Module32NextW (hmod_snap, &me);
}
printf("hook_all exit\n");
fflush(stdout);
}
// Hook one module.
void hook_one (PROC func_old, PROC func_new,
HMODULE hmod, LPBYTE pbase)
{
ULONG size;
// Get import descriptor.
PIMAGE_IMPORT_DESCRIPTOR pimp_desc = (PIMAGE_IMPORT_DESCRIPTOR)
ImageDirectoryEntryToData (hmod, TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT, &size);
if (pimp_desc == NULL)
return;
// Enumerate import modules.
while (pimp_desc->Name)
{
// Get import address table.
PIMAGE_THUNK_DATA pthunk = (PIMAGE_THUNK_DATA)
(pbase + pimp_desc->FirstThunk);
// Enumerate import address table.
while (pthunk->u1.Function)
{
// Get address of imported function.
PROC *p = (PROC*) &pthunk->u1.Function;
// Compare address of hook target.
if (*p == func_old)
{
printf (" Hit!! %p\n", *p);
fflush (stdout);
DWORD before;
// Change memory protection in order to write.
VirtualProtect(p, sizeof(p),
PAGE_EXECUTE_READWRITE, &before);
// Change hook target to new function.
WriteProcessMemory(GetCurrentProcess(),
p, &func_new, sizeof(func_new), NULL);
// Revert memory protection.
VirtualProtect(p, sizeof(p), before, &before);
printf (" Changed!!\n");
fflush (stdout);
}
pthunk++;
}
pimp_desc++;
}
}
}
#endif // __MINGW32__
#ifndef __MINGW_UTF8_HOOK_H__
#define __MINGW_UTF8_HOOK_H__
void mingw_utf8_hook(void);
#endif // __MINGW_UTF8_HOOK_H__
/*
Copyright (C) 2015 Masamichi Hosoda <trueroad@trueroad.jp>
*/
#ifdef __MINGW32__
#include <cwchar>
#include <vector>
#include "mingw-utf8.hh"
#include "mingw-utf8-hook.hh"
#include "mingw-utf8-conv.hh"
extern "C"
int __wgetmainargs (int*, wchar_t***, wchar_t***, int, int*);
#undef main
// Replaced main()
int main (int, char**, char**)
{
// Hook filename related functions.
mingw_utf8_hook();
// Get UTF-16 commandline arguments and environment variables.
int argc, si=0;
wchar_t **wargv;
wchar_t **wenvp;
__wgetmainargs (&argc, &wargv, &wenvp, 1, &si);
// Convert commandline arguments from UTF-16 to UTF-8.
std::vector<std::vector<char> > argv_vvc (argc);
std::vector<char*> argv_vc (argc);
for (int i = 0; i < argc; i++)
{
argv_vvc.at(i) = mingw_utf8_16to8 (wargv[i]);
argv_vc.at(i) = argv_vvc.at(i).data();
}
argv_vc.push_back (NULL);
// Count environment variables.
wchar_t **wenv_tmp=wenvp;
int env_count=0;
while(*wenv_tmp)
{
wenv_tmp++;
env_count++;
}
// Convert environment variables from UTF-16 to UTF-8.
std::vector<std::vector<char> > env_vvc (env_count);
std::vector<char*> env_vc (env_count);
for(int i = 0; i < env_count; i++)
{
env_vvc.at(i) = mingw_utf8_16to8 (wenvp[i]);
env_vc.at(i) = env_vvc.at(i).data();
}
env_vc.push_back (NULL);
// Call original main().
char **argv = argv_vc.data();
char **envp = env_vc.data();
return utf8_main (argc, argv, envp);
}
#endif // __MINGW32__
#ifdef __MINGW32__
#ifndef __MINGW_UTF8_H__
#define __MINGW_UTF8_H__
#define main(...) utf8_main(__VA_ARGS__)
int utf8_main(int argc, char **argv, char **envp);
#endif // __MINGW_UTF8_H__
#endif // __MINGW32__
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <direct.h>
#include <fcntl.h>
#include "mingw-utf8.hh"
int main(int argc, char **argv, char **envp)
{
std::cout << "argc " << argc << std::endl;
for(int i=0; i<argc; i++)
{
std::cout << "argv " << i << " " << argv[i] << std::endl;
}
std::cout << std::endl << "env" << std::endl;
char **e_tmp=envp;
while(*e_tmp)
{
std::cout << *e_tmp++ << std::endl;
}
if(argc>1)
{
std::cout << std::endl << "try to fopen \"" << argv[1] << "\"" << std::endl;
FILE *fp = fopen(argv[1], "wb");
fclose(fp);
}
char buff[1024];
getcwd(buff, sizeof(buff));
std::cout << std::endl << "getcwd \"" << buff << "\"" << std::endl;
std::cout << std::endl << "getenv path \"" << getenv("PATH") << "\"" << std::endl;
if(argc>2)
{
std::cout << std::endl << "try to open \"" << argv[2] << "\"" << std::endl;
int sd = open(argv[2], O_CREAT, 0644);
close(sd);
}
std::cout << std::endl << "try to system notepad" << std::endl;
system("notepad");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment