Last active
April 12, 2023 01:06
-
-
Save trueroad/46e9912cf3858bb01abe to your computer and use it in GitHub Desktop.
Unicode Filename Support for MinGW.org / MinGW-w64 Platform Software (hook)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Unicode Filename Support for MinGW.org / MinGW-w64 Platform Software (hook) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 *~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright (C) 2015 Masamichi Hosoda <[email protected]> | |
*/ | |
#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__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright (C) 2015 Masamichi Hosoda <[email protected]> | |
*/ | |
#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__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright (C) 2015 Masamichi Hosoda <[email protected]> | |
*/ | |
#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__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __MINGW_UTF8_HOOK_H__ | |
#define __MINGW_UTF8_HOOK_H__ | |
void mingw_utf8_hook(void); | |
#endif // __MINGW_UTF8_HOOK_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright (C) 2015 Masamichi Hosoda <[email protected]> | |
*/ | |
#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__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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