diff --git a/dlls/kernel32/format_msg.c b/dlls/kernel32/format_msg.c index 302a78d928c..b1befb352b5 100644 --- a/dlls/kernel32/format_msg.c +++ b/dlls/kernel32/format_msg.c @@ -296,6 +296,13 @@ static LPWSTR format_message( BOOL unicode_caller, DWORD dwFlags, LPCWSTR fmtstr case '6':case '7':case '8':case '9': if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) goto ignore_inserts; + else if (((dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) && !format_args->args) || + (!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) && !format_args->list)) + { + SetLastError(ERROR_INVALID_PARAMETER); + HeapFree(GetProcessHeap(), 0, target); + return NULL; + } insertnr = *f-'0'; switch (f[1]) { case '0':case '1':case '2':case '3': diff --git a/dlls/kernel32/tests/format_msg.c b/dlls/kernel32/tests/format_msg.c index 25be3aceb1b..1c4dd76c5e0 100644 --- a/dlls/kernel32/tests/format_msg.c +++ b/dlls/kernel32/tests/format_msg.c @@ -180,6 +180,27 @@ static void test_message_from_string_wide(void) ok(r==0, "succeeded: r=%d\n", r); ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error); + /* insertion with no variadic arguments */ + SetLastError(0xdeadbeef); + memcpy(out, init_buf, sizeof(init_buf)); + r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_1, 0, + 0, out, sizeof(out)/sizeof(WCHAR), NULL); + error = GetLastError(); + ok(!memcmp(out, init_buf, sizeof(init_buf)), + "Expected the buffer to be unchanged\n"); + ok(r==0, "succeeded: r=%d\n", r); + ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error); + + SetLastError(0xdeadbeef); + memcpy(out, init_buf, sizeof(init_buf)); + r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, fmt_1, 0, + 0, out, sizeof(out)/sizeof(WCHAR), NULL); + error = GetLastError(); + ok(!memcmp(out, init_buf, sizeof(init_buf)), + "Expected the buffer to be unchanged\n"); + ok(r==0, "succeeded: r=%d\n", r); + ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error); + /* using the format feature */ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1s, 0, 0, out, sizeof(out)/sizeof(WCHAR), test); @@ -483,6 +504,35 @@ static void test_message_from_string(void) ok(GetLastError()==ERROR_INVALID_PARAMETER, "last error %u\n", GetLastError()); + /* insertion with no variadic arguments */ + SetLastError(0xdeadbeef); + memcpy(out, init_buf, sizeof(init_buf)); + r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "%1", 0, + 0, out, sizeof(out)/sizeof(CHAR), NULL); + ok(!memcmp(out, init_buf, sizeof(init_buf)) || + broken(!strcmp("%1", out)), /* Win9x */ + "Expected the buffer to be untouched\n"); + ok(r==0 || + broken(r==2), /* Win9x */ + "succeeded: r=%d\n", r); + ok(GetLastError()==ERROR_INVALID_PARAMETER || + broken(GetLastError()==0xdeadbeef), /* Win9x */ + "last error %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + memcpy(out, init_buf, sizeof(init_buf)); + r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, "%1", 0, + 0, out, sizeof(out)/sizeof(CHAR), NULL); + ok(!memcmp(out, init_buf, sizeof(init_buf)) || + broken(!strcmp("%1", out)), /* Win9x */ + "Expected the buffer to be untouched\n"); + ok(r==0 || + broken(r==2), /* Win9x */ + "succeeded: r=%d\n", r); + ok(GetLastError()==ERROR_INVALID_PARAMETER || + broken(GetLastError()==0xdeadbeef), /* Win9x */ + "last error %u\n", GetLastError()); + /* using the format feature */ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!s!", 0, 0, out, sizeof(out)/sizeof(CHAR), "test"); @@ -1340,6 +1390,20 @@ static void test_message_from_hmodule(void) MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL); ok(ret != 0, "FormatMessageA returned 0\n"); + /* Test a message string with an insertion without passing any variadic arguments. */ + ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 193 /* ERROR_BAD_EXE_FORMAT */, + MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL); + ok(ret == 0 || + broken(ret != 0), /* Win9x */ + "FormatMessageA returned non-zero\n"); + + ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_ARGUMENT_ARRAY, h, 193 /* ERROR_BAD_EXE_FORMAT */, + MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL); + ok(ret == 0 || + broken(ret != 0), /* Win9x */ + "FormatMessageA returned non-zero\n"); + /*Test nonexistent messageID with varying language ID's Note: FormatMessageW behaves the same*/ SetLastError(0xdeadbeef); ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,