Skip to content

Commit

Permalink
win32_utf8: Add CreateDialogParam and DialogBoxParam.
Browse files Browse the repository at this point in the history
Bravo, Microsoft. What a great design.

If you just replaced lpTemplateName with an integer parameter (I mean, who references dialog box templates by name anyway), we wouldn't have needed the entire A and W distinction for these, because dialog box templates are guaranteed to be UTF-16 anyway.

And since everyone uses MAKEINTRESOURCE anyway, there is no reason to use the A version *at all*, even if you wouldn't code in Unicode otherwise (which, really, you should have done from the start, but oh well).
  • Loading branch information
nmlgc committed Aug 21, 2013
1 parent 71c1dca commit 609e844
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 78 deletions.
12 changes: 7 additions & 5 deletions thcrap/src/win32_patch.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,17 @@ void win32_patch(HMODULE hMod)
"GetTextExtentPoint32A", GetTextExtentPoint32U
);

iat_patch_funcs_var(hMod, "user32.dll", 7,
"RegisterClassA", RegisterClassU,
"RegisterClassExA", RegisterClassExU,
iat_patch_funcs_var(hMod, "user32.dll", 9,
"CharNextA", CharNextU,
"CreateDialogParamA", CreateDialogParamU,
"CreateWindowExA", CreateWindowExU,
"SetWindowTextA", SetWindowTextU,
// Yep, both original functions use the same parameters
"DefWindowProcA", DefWindowProcW,
"DialogBoxParamA", DialogBoxParamU,
"MessageBoxA", MessageBoxU,
"CharNextA", CharNextU
"RegisterClassA", RegisterClassU,
"RegisterClassExA", RegisterClassExU,
"SetWindowTextA", SetWindowTextU
);

iat_patch_funcs_var(hMod, "shlwapi.dll", 3,
Expand Down
183 changes: 110 additions & 73 deletions win32_utf8/src/user32_dll.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,58 @@

#include "win32_utf8.h"

#define RegisterClassBaseConvert(wcNew, lpwcOld) \
size_t lpszClassName_len = strlen(lpwcOld->lpszClassName) + 1; \
size_t lpszMenuName_len = strlen(lpwcOld->lpszMenuName) + 1; \
VLA(wchar_t, lpszClassName_w, lpszClassName_len); \
VLA(wchar_t, lpszMenuName_w, lpszMenuName_len); \
\
lpszClassName_w = StringToUTF16_VLA(lpszClassName_w, lpwcOld->lpszClassName, lpszClassName_len); \
lpszMenuName_w = StringToUTF16_VLA(lpszMenuName_w, lpwcOld->lpszMenuName, lpszMenuName_len); \
\
wcNew.style = lpwcOld->style; \
wcNew.lpfnWndProc = lpwcOld->lpfnWndProc; \
wcNew.cbClsExtra = lpwcOld->cbClsExtra; \
wcNew.cbWndExtra = lpwcOld->cbWndExtra; \
wcNew.hInstance = lpwcOld->hInstance; \
wcNew.hIcon = lpwcOld->hIcon; \
wcNew.hCursor = lpwcOld->hCursor; \
wcNew.hbrBackground = lpwcOld->hbrBackground; \
wcNew.lpszClassName = lpszClassName_w; \
wcNew.lpszMenuName = lpszMenuName_w;

#define RegisterClassBaseClean() \
VLA_FREE(lpszClassName_w); \
VLA_FREE(lpszMenuName_w)

ATOM WINAPI RegisterClassU(
__in CONST WNDCLASSA *lpWndClass
LPSTR WINAPI CharNextU(
__in LPSTR lpsz
)
{
ATOM ret;
WNDCLASSW WndClassW;
RegisterClassBaseConvert(WndClassW, lpWndClass);
ret = RegisterClassW(&WndClassW);
RegisterClassBaseClean();
LPSTR ret;
extern UINT fallback_codepage;

if(lpsz == NULL || *lpsz == '\0') {
ret = lpsz;
}
else if(IsDBCSLeadByteEx(fallback_codepage, lpsz[0])) {
int lpsz_len = strlen(lpsz);
if(lpsz_len < 2) {
ret = lpsz + 1;
} else {
ret = lpsz + 2;
}
}
else {
ret = lpsz + 1;
if(!IsDBCSLeadByteEx(fallback_codepage, ret[0])) {
// Get next UTF-8 char
while((*ret & 0xc0) == 0x80)
++ret;
}
}
return ret;
}

ATOM WINAPI RegisterClassExU(
__in CONST WNDCLASSEXA *lpWndClass
// Now, if Microsoft would have just used integer identifiers for resources
// instead of names plus the MAKEINTRESOURCE hack, we could just re-point
// all these calls to their wide versions and be done with it.
// Instead, there is some maintenance to do...
#define ResourceBaseConvert(lpTemplateName) \
LPCWSTR lptn_w; \
if(HIWORD(lpTemplateName) == 0) { \
lptn_w = (LPCWSTR)lpTemplateName; \
} else { \
WCHAR_T_DEC(lpTemplateName); \
lptn_w = StringToUTF16_VLA(lpTemplateName_w, lpTemplateName, lpTemplateName_len); \
}

HWND WINAPI CreateDialogParamU(
__in_opt HINSTANCE hInstance,
__in LPCSTR lpTemplateName,
__in_opt HWND hWndParent,
__in_opt DLGPROC lpDialogFunc,
__in LPARAM dwInitParam
)
{
ATOM ret;
WNDCLASSEXW WndClassW;
RegisterClassBaseConvert(WndClassW, lpWndClass);
WndClassW.cbSize = lpWndClass->cbSize;
WndClassW.hIconSm = lpWndClass->hIconSm;
ret = RegisterClassExW(&WndClassW);
RegisterClassBaseClean();
return ret;
ResourceBaseConvert(lpTemplateName);
return CreateDialogParamW(hInstance, lptn_w, hWndParent, lpDialogFunc, dwInitParam);
}

HWND WINAPI CreateWindowExU(
Expand Down Expand Up @@ -88,17 +92,16 @@ HWND WINAPI CreateWindowExU(
return ret;
}

BOOL WINAPI SetWindowTextU(
__in HWND hWnd,
__in_opt LPCSTR lpString
INT_PTR WINAPI DialogBoxParamU(
__in_opt HINSTANCE hInstance,
__in LPCSTR lpTemplateName,
__in_opt HWND hWndParent,
__in_opt DLGPROC lpDialogFunc,
__in LPARAM dwInitParam
)
{
BOOL ret;
WCHAR_T_DEC(lpString);
lpString_w = StringToUTF16_VLA(lpString_w, lpString, lpString_len);
ret = SetWindowTextW(hWnd, lpString_w);
VLA_FREE(lpString_w);
return ret;
ResourceBaseConvert(lpTemplateName);
return DialogBoxParamW(hInstance, lptn_w, hWndParent, lpDialogFunc, dwInitParam);
}

int WINAPI MessageBoxU(
Expand All @@ -119,31 +122,65 @@ int WINAPI MessageBoxU(
return ret;
}

LPSTR WINAPI CharNextU(
__in LPSTR lpsz
#define RegisterClassBaseConvert(wcNew, lpwcOld) \
size_t lpszClassName_len = strlen(lpwcOld->lpszClassName) + 1; \
size_t lpszMenuName_len = strlen(lpwcOld->lpszMenuName) + 1; \
VLA(wchar_t, lpszClassName_w, lpszClassName_len); \
VLA(wchar_t, lpszMenuName_w, lpszMenuName_len); \
\
lpszClassName_w = StringToUTF16_VLA(lpszClassName_w, lpwcOld->lpszClassName, lpszClassName_len); \
lpszMenuName_w = StringToUTF16_VLA(lpszMenuName_w, lpwcOld->lpszMenuName, lpszMenuName_len); \
\
wcNew.style = lpwcOld->style; \
wcNew.lpfnWndProc = lpwcOld->lpfnWndProc; \
wcNew.cbClsExtra = lpwcOld->cbClsExtra; \
wcNew.cbWndExtra = lpwcOld->cbWndExtra; \
wcNew.hInstance = lpwcOld->hInstance; \
wcNew.hIcon = lpwcOld->hIcon; \
wcNew.hCursor = lpwcOld->hCursor; \
wcNew.hbrBackground = lpwcOld->hbrBackground; \
wcNew.lpszClassName = lpszClassName_w; \
wcNew.lpszMenuName = lpszMenuName_w;

#define RegisterClassBaseClean() \
VLA_FREE(lpszClassName_w); \
VLA_FREE(lpszMenuName_w)

ATOM WINAPI RegisterClassU(
__in CONST WNDCLASSA *lpWndClass
)
{
LPSTR ret;
extern UINT fallback_codepage;
ATOM ret;
WNDCLASSW WndClassW;
RegisterClassBaseConvert(WndClassW, lpWndClass);
ret = RegisterClassW(&WndClassW);
RegisterClassBaseClean();
return ret;
}

if(lpsz == NULL || *lpsz == '\0') {
ret = lpsz;
}
else if(IsDBCSLeadByteEx(fallback_codepage, lpsz[0])) {
int lpsz_len = strlen(lpsz);
if(lpsz_len < 2) {
ret = lpsz + 1;
} else {
ret = lpsz + 2;
}
}
else {
ret = lpsz + 1;
if(!IsDBCSLeadByteEx(fallback_codepage, ret[0])) {
// Get next UTF-8 char
while((*ret & 0xc0) == 0x80)
++ret;
}
}
ATOM WINAPI RegisterClassExU(
__in CONST WNDCLASSEXA *lpWndClass
)
{
ATOM ret;
WNDCLASSEXW WndClassW;
RegisterClassBaseConvert(WndClassW, lpWndClass);
WndClassW.cbSize = lpWndClass->cbSize;
WndClassW.hIconSm = lpWndClass->hIconSm;
ret = RegisterClassExW(&WndClassW);
RegisterClassBaseClean();
return ret;
}

BOOL WINAPI SetWindowTextU(
__in HWND hWnd,
__in_opt LPCSTR lpString
)
{
BOOL ret;
WCHAR_T_DEC(lpString);
lpString_w = StringToUTF16_VLA(lpString_w, lpString, lpString_len);
ret = SetWindowTextW(hWnd, lpString_w);
VLA_FREE(lpString_w);
return ret;
}
20 changes: 20 additions & 0 deletions win32_utf8/src/user32_dll.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ LPSTR WINAPI CharNextU(
#undef CharNext
#define CharNext CharNextU

HWND WINAPI CreateDialogParamU(
__in_opt HINSTANCE hInstance,
__in LPCSTR lpTemplateName,
__in_opt HWND hWndParent,
__in_opt DLGPROC lpDialogFunc,
__in LPARAM dwInitParam
);
#undef CreateDialogParam
#define CreateDialogParam CreateDialogParamU

HWND WINAPI CreateWindowExU(
__in DWORD dwExStyle,
__in_opt LPCSTR lpClassName,
Expand All @@ -35,6 +45,16 @@ HWND WINAPI CreateWindowExU(
#undef DefWindowProc
#define DefWindowProc DefWindowProcW

INT_PTR WINAPI DialogBoxParamU(
__in_opt HINSTANCE hInstance,
__in LPCSTR lpTemplateName,
__in_opt HWND hWndParent,
__in_opt DLGPROC lpDialogFunc,
__in LPARAM dwInitParam
);
#undef DialogBoxParam
#define DialogBoxParam DialogBoxParamU

int WINAPI MessageBoxU(
__in_opt HWND hWnd,
__in_opt LPCSTR lpText,
Expand Down
2 changes: 2 additions & 0 deletions win32_utf8/win32_utf8.def
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ EXPORTS
; user32.dll
; ----------
CharNextU
CreateDialogParamU
CreateWindowExU
DialogBoxParamU
MessageBoxU
RegisterClassU
RegisterClassExU
Expand Down

0 comments on commit 609e844

Please sign in to comment.