How to display Japanese characters in a Linux Wine message box text? - winapi

<<If this question is better posted on Ubuntu or Superuser sites, please let me know.>>
I am building a Windows application on Debian Linux (stable) that runs with Wine.
To begin, I wrote a very simple "Hello, World!" application. It works very well for an English caption and text. However, if I add Japanese text to the caption and text, only the caption correctly displays the Japanese text. The text inside the Windows message box uses Unicode substitution characters (empty rectangles). I Google'd so hard, but I cannot find the answer to this issue. :(
My simple C source code:
/* Working with Strings: https://learn.microsoft.com/en-us/windows/win32/learnwin32/working-with-strings */
/* Ref: https://stackoverflow.com/questions/7424383/what-is-the-difference-between-the-a-and-w-functions-in-the-win32-api */
/* Ref: https://stackoverflow.com/questions/4143110/what-encoding-win32-api-functions-expect */
#define UNICODE 1
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
/* Ref: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox */
MessageBoxW(NULL, /* [in, optional] HWND hWnd */
TEXT("Hello, world! ようこそ東京!"), /* [in, optional] LPCTSTR lpText */
TEXT("ようこそ東京 | This is a MessageBox title"), /* [in, optional] LPCTSTR lpCaption */
MB_OK | MB_ICONINFORMATION); /* [in] UINT uType */
return 0;
}
I compile this code as: $ x86_64-w64-mingw32-gcc -o ./hello-world.exe ./hello-world.c
I run this code as: $ wine ./hello-world.exe
Output looks like this:
The caption displays correctly, but the message box text does not.
My locale looks like this:
$ locale
LANG=en_HK.UTF-8
LANGUAGE=en_HK:en
LC_CTYPE="en_HK.UTF-8"
LC_NUMERIC="en_HK.UTF-8"
LC_TIME="en_HK.UTF-8"
LC_COLLATE="en_HK.UTF-8"
LC_MONETARY="en_HK.UTF-8"
LC_MESSAGES="en_HK.UTF-8"
LC_PAPER="en_HK.UTF-8"
LC_NAME="en_HK.UTF-8"
LC_ADDRESS="en_HK.UTF-8"
LC_TELEPHONE="en_HK.UTF-8"
LC_MEASUREMENT="en_HK.UTF-8"
LC_IDENTIFICATION="en_HK.UTF-8"
LC_ALL=
I also tried this command, but no improvement: $ LC_ALL=ja_JP.UTF-8 wine ./hello-world.exe
What is the trick to make this work? I assume it is: (a) a missing #define, (b) a missing Debian package, (c) a missing environment variable.
Related question: Would my sample code work on native Win 7 or Win 10?
I also tried:
winetricks allfonts but no improvement.

This answer is the result of further research, so I am answering my own question.
The default font for Message Box Text is probably Tahoma. According to this font database (https://catalog.monotype.com/family/microsoft-corporation/tahoma), Tahoma does not support Japanese.
On recent versions of Microsoft Windows, the default Japanese font is now Meiryo: https://en.wikipedia.org/wiki/Meiryo
Run: winetricks allfonts
Run: winecfg
Select tab Desktop Integration
Select item Message Box Text
Click button Font
Select a Japanese font, e.g., Meiryo
Now, the message box can correctly display Japanese text.

Related

Is there a pre-existing WinAPI to check if some_app.exe can run w/o providing full-path and running it at any point

Is there a pre-existing WinAPI to check if some_app.exe can run w/o providing full-path and running it at any point?
For example, let's say I want to run cmd.exe or git.exe, but I don't provide with full path . Before I run it, is it possible of me to know prematurely if I can run it without knowing its full path?
One idea that comes to my mind is to emulate the way Windows does it, i.e. to check the current path, then to iterate through %PATH% variable and so on, but is there perhaps a Winapi for this exact purpose?
#RbMm has already pointed out the solution: Use SearchPath API.
The following is an example (a console application) of how to use that API, you can refer to.
#include <windows.h>
#define BUF_SIZE 260
int main()
{
WCHAR appFullPath[BUF_SIZE];
DWORD result = SearchPath(NULL, L"git.exe",NULL, BUF_SIZE, appFullPath, NULL);
if(result == 0)
wprintf(L"SearchPath call get an error: %d \n", GetLastError());
wprintf(L"App full path: %s \n", appFullPath);
getchar();
}
The output of above code:

the qt app shows Chinese in messy code on windows when using UTF-8 encoding-format

I developed a simple qt app on windows to test the qt Chinese UTF-8 encoding-format:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
QString strMessage = QString::fromLocal8Bit("我是UTF8编码的文件:");
qDebug() << strMessage;
return a.exec();
}
and my main.cpp file encoding format is UTF-8 without BOM, but when I run the app on windows, the app print string is "鎴戞槸UTF8缂栫爜鐨勬枃浠讹細" which I expect is "我是UTF8编码的文件:",it seems the string "我是UTF8编码的文件:" is converted to GB2312 encoding-format so shows the wrong string "鎴戞槸UTF8缂栫爜鐨勬枃浠讹細" in runtime,and the string "我是UTF8编码的文件:" shows right string "我是UTF8编码的文件:'' when the app runs on macos, I don't know why?
how to let the string "我是UTF8编码的文件:" show right on windows platform, thanks a lot!
On Windows, printing UTF-8 to the console is not automatic. You need to execute this command first in the console to change to codepage 65001 (which is the UTF-8 Windows codepage):
chcp 65001
You also need to set a font that offers Chinese characters. On Windows 10, that's the "NSimSun" font. However, the Windows console has a neat function where it automatically switches the font if you set a Chinese codepage (like 936). So you can actually programmatically run these commands using the standard library system() function. The chcp command produces output though. To hide it, redirect the output to nul.
#include <cstdlib>
// ...
int main(int argc, char *argv[])
{
#ifdef Q_OS_WIN
// Temporary codepage change so we get an automatic font change.
system("chcp 936 > nul");
// Change to UTF-8.
system("chcp 65001 > nul");
#endif
QApplication a(argc, argv);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
QString strMessage = QString::fromUtf8("我是UTF8编码的文件:");
qDebug() << strMessage;
return a.exec();
}
(As a side note, you should use QString::fromUtf8() since you know the text is in UTF-8.)

Where does bash prompt escape sequence \h get the hostname from?

\h is a bash prompt escape sequence that expands to the hostname. Where does it get the hostname from? On my system it shows a value that I cannot find anywhere, not in hostname -f or /etc/hosts or /etc/hostname or /etc/sysconfig/network or $HOSTNAME. So I'm wondering where it's getting it from. My system is Centos 7.4. I know there are hidden places where things such as UUIDs are stored, and I seem to recall that I've come across a similar hidden hostname type of issue in the past, but I can't remember the details.
If you look at the bash source code you'll see in shell.c that it calls gethostname(2), a POSIX system call that retrieves the hostname from the kernel.
/* It's highly unlikely that this will change. */
if (current_host_name == 0)
{
/* Initialize current_host_name. */
if (gethostname (hostname, 255) < 0)
current_host_name = "??host??";
else
current_host_name = savestring (hostname);
}
This is not necessarily a canonical string. The kernel doesn't actually know the machine's network hostname. It just reports back whatever was passed to sethostname(2). To quote from the uname(2) man page:
On the other hand, the [hostname] is meaningless: it gives the name of the present machine in some undefined network, but typically machines are in more than one network and have several names. Moreover, the kernel has no way of knowing about such things, so it has to be told what to answer here.
On non-Linux systems without gethostname(2), bash falls back to uname(2). If uname(2) isn't even available then it simply displays "unknown". You can see that logic in lib/sh/oslib.c:
#if !defined (HAVE_GETHOSTNAME)
# if defined (HAVE_UNAME)
# include <sys/utsname.h>
int
gethostname (name, namelen)
char *name;
int namelen;
{
int i;
struct utsname ut;
--namelen;
uname (&ut);
i = strlen (ut.nodename) + 1;
strncpy (name, ut.nodename, i < namelen ? i : namelen);
name[namelen] = '\0';
return (0);
}
# else /* !HAVE_UNAME */
int
gethostname (name, namelen)
char *name;
int namelen;
{
strncpy (name, "unknown", namelen);
name[namelen] = '\0';
return 0;
}
# endif /* !HAVE_UNAME */
#endif /* !HAVE_GETHOSTNAME */
\h isn't updated if the hostname changes. The value is cached at startup when the shell is initialized.
[jkugelman#malkovich]$ hostname
malkovich
[jkugelman#malkovich]$ sudo hostname kaufman
[jkugelman#malkovich]$ hostname
kaufman
[jkugelman#malkovich]$ bash
[jkugelman#kaufman]
It probably (just a guess) uses the gethostname(2) system call (which is handled by the kernel, as all syscalls(2) are...)
BTW, GNU bash is (as most packages of your Linux distributions are) free software; so please download its source code and study it; use the source, Luke! and open the source more, please.
A more interesting question is how that information is cached by bash. Does it call gethostname at every command? You might also use strace(1) to find out.
Of course, take the habit of studying the source code of free software every time you are curious. And use strace -and the gdb debugger- to understand their dynamic behavior.
A French singer, G.Bedos, told us "La liberté ne s'use que si on ne s'en sert pas", that is
Freedom wears out if you don't use it.
(translation is mine, I am French but not a native English speaker)
So next time, please dive into the source code of free software. It is important to exercise your freedom, and that is what free software is about.

Check if Windows file is redirected to itself

I'm trying to figure out how I can test if a file is being redirected to itself, e.g. .\command.exe file1 > file1
In the *nix world, I'd just use something like this:
// Language agnostic...
if (file_dev == out_dev && file_ino == out_ino) {
printf("%s\n", "same file!");
}
But in Windows, if I try to do this:
// This (language) is Go...
// create fileStat...
// now stat stdout
outStat, err := os.Stdout.Stat()
// error check
if os.SameFile(fileStat, outStat) {
fmt.Println("same file!")
}
...I get the IncorrectFunction error.
I read this (How to check if stdout has been redirected to NUL on Windows (a.k.a. /dev/null on Linux)?) question, and from what I gather you can't stat stdout?
This is a mostly language agnostic question -- I can translate whatever to Go (the language I'm using). I'm mostly concerned about how, using Windows' ABI (API?), I would find where stdout is being redirected to.
This answer is Windows-specific but as you've tagged windows I figure that's ok.
I can't help with Go, but in C/C++ you can do something like this:
#include <tchar.h>
#include <Windows.h>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t chPath[MAX_PATH];
if (GetFinalPathNameByHandle(GetStdHandle(STD_OUTPUT_HANDLE), chPath, MAX_PATH, 0))
std::wcout << L"stdout = " << chPath << std::endl;
else
std::cout << "stdout not redirected" << std::endl;
return 0;
}
GetFinalPathNameByHandle will fail if stdout is a console handle, but if it's been redirected to a file it will return the file path.
You can call HANDLE GetStdHandle( DWORD stdHandle ) with STD_INPUT_HANDLE and STD_OUTPUT_HANDLE to open the file handle.
Then call DWORD GetFileType( HANDLE hFile ) to check if the returned type is FILE_TYPE_DISK
Finally, call
DWORD WINAPI GetFinalPathNameByHandle( _In_ HANDLE hFile, _Out_ LPTSTR lpszFilePath, _In_ DWORD cchFilePath, _In_ DWORD dwFlags );
to obtain the file pathname and compare the names for equivalency.
Well, first up, I don't think your method in UNIX-land is actually going to protect you.
By the time your code gets to checking devices and inodes, the shell has already truncated the file. It is responsible for processing the output redirections and it does this before your program even starts, so that you're given a fresh file for your output.
I suspect you'd have the same problem in Windows in that cmd.exe will truncate your file before your script even started running.
Having said that, I believe at some point you're going to have to trust that the user knows what they're doing :-)
The other alternative is, of course, not to do output redirection but instead to require the input and output files as arguments:
cmd.exe myscipt myscript
That way, you could detect if the user was going to write to the input file (using canonicalised file names or inodes) and prevent it.
Although that still won't prevent the user from doing something silly like:
cmd.exe myscipt >myscript
blowing away your script before you get a chance to notify them they should have provided two arguments rather than one.
I think the bottom line is, if the user does output redirection, there's no way for your program to catch it before it's too late.

Is there a port of libfaketime to OSX?

Is there a port of libfaketime to OSX? http://www.code-wizards.com/projects/libfaketime/
Ok, so I ported it.
http://github.com/dbrashear/libfaketime/
On freshmeat libfaketime lists its platforms as Linux and POSIX. Since OSX is listed as fully POSIX compliant, it should be perfectly usable as-is.
EDIT
if clock_gettime is the only problematic function and you're feeling fool-hardy, you could try this little hack:
#if _POSIX_TIMERS > 0
clock_gettime(CLOCK_REALTIME, &tp);
#else
struct timeval tv;
gettimeofday(&tv, NULL);
tp.tv_sec = tv.tv_sec;
tp.tv_nsec = tv.tv_usec*1000;
#endif

Resources