[PATCH] kernel32: Implement FormatMessage variable prefixes I, I32, and I64
Alex Henrie
alexhenrie24 at gmail.com
Tue Nov 20 00:58:10 CST 2018
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=33392
Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
dlls/kernel32/format_msg.c | 26 +++++++++++++++-
dlls/kernel32/tests/format_msg.c | 51 +++++++++++++++++++++++++-------
2 files changed, 66 insertions(+), 11 deletions(-)
diff --git a/dlls/kernel32/format_msg.c b/dlls/kernel32/format_msg.c
index 5741713d81..bd4b2df110 100644
--- a/dlls/kernel32/format_msg.c
+++ b/dlls/kernel32/format_msg.c
@@ -249,7 +249,31 @@ static LPCWSTR format_insert( BOOL unicode_caller, int insert, LPCWSTR format,
{
*p++ = 'c';
}
- /* FIXME: handle I64 etc. */
+ /* check for 32-bit integer format */
+ else if (format[0] == 'I' && format[1] == '3' && format[2] == '2' &&
+ (format[3] == 'd' || format[3] == 'i' || format[3] == 'u' ||
+ format[3] == 'o' || format[3] == 'x' || format[3] == 'X'))
+ {
+ *p++ = format[3];
+ }
+ /* check for 64-bit integer format */
+ else if (format[0] == 'I' && format[1] == '6' && format[2] == '4' &&
+ (format[3] == 'd' || format[3] == 'i' || format[3] == 'u' ||
+ format[3] == 'o' || format[3] == 'x' || format[3] == 'X'))
+ {
+ *p++ = 'l';
+ *p++ = format[3];
+ }
+ /* check for pointer-size integer format */
+ else if (format[0] == 'I' &&
+ (format[1] == 'd' || format[1] == 'i' || format[1] == 'u' ||
+ format[1] == 'o' || format[1] == 'x' || format[1] == 'x'))
+ {
+#ifdef _WIN64
+ *p++ = 'l';
+#endif
+ *p++ = format[1];
+ }
else while (*format && *format != '!') *p++ = *format++;
*p = 0;
diff --git a/dlls/kernel32/tests/format_msg.c b/dlls/kernel32/tests/format_msg.c
index 57ee78af9e..8aab9e7b43 100644
--- a/dlls/kernel32/tests/format_msg.c
+++ b/dlls/kernel32/tests/format_msg.c
@@ -26,6 +26,8 @@
#define ULL(a,b) (((ULONG64)(a) << 32) | (b))
+static const BOOL is_32bit = (sizeof(void *) == sizeof(int));
+
static DWORD WINAPIV doit(DWORD flags, LPCVOID src, DWORD msg_id, DWORD lang_id,
LPSTR out, DWORD outsize, ... )
{
@@ -98,6 +100,9 @@ static void test_message_from_string_wide(void)
static const WCHAR fmt_1oou1oou[] = {'%','1','!','*','.','*','u','!',',','%','1','!','*','.','*','u','!',0};
static const WCHAR fmt_1oou3oou[] = {'%','1','!','*','.','*','u','!',',','%','3','!','*','.','*','u','!',0};
static const WCHAR fmt_1oou4oou[] = {'%','1','!','*','.','*','u','!',',','%','4','!','*','.','*','u','!',0};
+ static const WCHAR fmt_1I32d[] = {'%','1','!','I','3','2','d','!',0};
+ static const WCHAR fmt_1I64d[] = {'%','1','!','I','6','4','d','!',0};
+ static const WCHAR fmt_1Id[] = {'%','1','!','I','d','!',0};
static const WCHAR s_123d[] = {'1','2','3',0};
static const WCHAR s_14d[] = {' ',' ',' ','1',0};
@@ -390,6 +395,20 @@ static void test_message_from_string_wide(void)
ok(r==12,"failed: r=%d\n",r);
}
+ /* prefixes not shared with standard printf */
+
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1I32d, 0, 0, out, ARRAY_SIZE(out), 123);
+ ok(!lstrcmpW(s_123d, out), "failed out=%s\n", wine_dbgstr_w(out));
+ ok(r==3,"failed: r=%d\n", r);
+
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1I64d, 0, 0, out, ARRAY_SIZE(out), 123);
+ ok(!lstrcmpW(s_123d, out), "failed out=%s\n", wine_dbgstr_w(out));
+ ok(r==3,"failed: r=%d\n", r);
+
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1Id, 0, 0, out, ARRAY_SIZE(out), 123);
+ ok(!lstrcmpW(s_123d, out), "failed out=%s\n", wine_dbgstr_w(out));
+ ok(r==3,"failed: r=%d\n", r);
+
/* change of pace... test the low byte of dwflags */
/* line feed */
@@ -688,6 +707,20 @@ static void test_message_from_string(void)
}
}
+ /* prefixes not shared with standard printf */
+
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!I32d!", 0, 0, out, ARRAY_SIZE(out), 123);
+ ok(!strcmp("123", out),"failed out=[%s]\n",out);
+ ok(r==3,"failed: r=%d\n",r);
+
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!I64d!", 0, 0, out, ARRAY_SIZE(out), 123);
+ ok(!strcmp("123", out),"failed out=[%s]\n",out);
+ ok(r==3,"failed: r=%d\n",r);
+
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!Id!", 0, 0, out, ARRAY_SIZE(out), 123);
+ ok(!strcmp("123", out),"failed out=[%s]\n",out);
+ ok(r==3,"failed: r=%d\n",r);
+
/* change of pace... test the low byte of dwflags */
/* line feed */
@@ -1718,26 +1751,28 @@ static void test_message_from_64bit_number(void)
UINT64 number;
const char expected[32];
int len;
+ BOOL todo32;
} unsigned_tests[] =
{
{ 0, "0", 1 },
{ 1234567890, "1234567890", 10},
- { ULL(0xFFFFFFFF,0xFFFFFFFF), "18446744073709551615", 20 },
- { ULL(0x7FFFFFFF,0xFFFFFFFF), "9223372036854775807", 19 },
+ { ULL(0xFFFFFFFF,0xFFFFFFFF), "18446744073709551615", 20, TRUE },
+ { ULL(0x7FFFFFFF,0xFFFFFFFF), "9223372036854775807", 19, TRUE },
};
static const struct
{
INT64 number;
const char expected[32];
int len;
+ BOOL todo32;
} signed_tests[] =
{
{ 0, "0" , 1},
{ 1234567890, "1234567890", 10 },
{ -1, "-1", 2},
{ ULL(0xFFFFFFFF,0xFFFFFFFF), "-1", 2},
- { ULL(0x7FFFFFFF,0xFFFFFFFF), "9223372036854775807", 19 },
- { -ULL(0x7FFFFFFF,0xFFFFFFFF), "-9223372036854775807", 20},
+ { ULL(0x7FFFFFFF,0xFFFFFFFF), "9223372036854775807", 19, TRUE },
+ { -ULL(0x7FFFFFFF,0xFFFFFFFF), "-9223372036854775807", 20, TRUE },
};
int i;
@@ -1746,14 +1781,12 @@ static void test_message_from_64bit_number(void)
r = doitW(FORMAT_MESSAGE_FROM_STRING, I64u, 0, 0, outW, ARRAY_SIZE(outW),
unsigned_tests[i].number);
MultiByteToWideChar(CP_ACP, 0, unsigned_tests[i].expected, -1, expW, ARRAY_SIZE(expW));
-todo_wine {
+todo_wine_if(is_32bit && unsigned_tests[i].todo32) {
ok(!lstrcmpW(outW, expW),"[%d] failed, expected %s, got %s\n", i,
unsigned_tests[i].expected, wine_dbgstr_w(outW));
ok(r == unsigned_tests[i].len,"[%d] failed: r=%d\n", i, r);
-}
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!I64u!",
0, 0, outA, sizeof(outA), unsigned_tests[i].number);
-todo_wine {
ok(!strcmp(outA, unsigned_tests[i].expected),"[%d] failed, expected %s, got %s\n", i,
unsigned_tests[i].expected, outA);
ok(r == unsigned_tests[i].len,"[%d] failed: r=%d\n", i, r);
@@ -1765,14 +1798,12 @@ todo_wine {
r = doitW(FORMAT_MESSAGE_FROM_STRING, I64d, 0, 0, outW, ARRAY_SIZE(outW),
signed_tests[i].number);
MultiByteToWideChar(CP_ACP, 0, signed_tests[i].expected, -1, expW, ARRAY_SIZE(expW));
-todo_wine {
+todo_wine_if(is_32bit && signed_tests[i].todo32) {
ok(!lstrcmpW(outW, expW),"[%d] failed, expected %s, got %s\n", i,
signed_tests[i].expected, wine_dbgstr_w(outW));
ok(r == signed_tests[i].len,"[%d] failed: r=%d\n", i, r);
-}
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!I64d!",
0, 0, outA, sizeof(outA), signed_tests[i].number);
-todo_wine {
ok(!strcmp(outA, signed_tests[i].expected),"[%d] failed, expected %s, got %s\n", i,
signed_tests[i].expected, outA);
ok(r == signed_tests[i].len,"[%d] failed: r=%d\n", i, r);
--
2.19.1
More information about the wine-devel
mailing list