diff --git a/dlls/kernel32/console.c b/dlls/kernel32/console.c index 8ad0a39eca8..1762ee433b4 100644 --- a/dlls/kernel32/console.c +++ b/dlls/kernel32/console.c @@ -836,15 +836,26 @@ BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, LPSTR lpstr, DWOR { DWORD read; BOOL ret; - LPWSTR wptr = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR)); + LPWSTR wptr; - if (read_count) *read_count = 0; - if (!wptr) return FALSE; + if (!read_count) + { + SetLastError(ERROR_INVALID_ACCESS); + return FALSE; + } + + *read_count = 0; + + if (!(wptr = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR)))) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } if ((ret = ReadConsoleOutputCharacterW( hConsoleOutput, wptr, count, coord, &read ))) { read = WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr, read, lpstr, count, NULL, NULL); - if (read_count) *read_count = read; + *read_count = read; } HeapFree( GetProcessHeap(), 0, wptr ); return ret; diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index aa193b17a7d..9b53f485eb0 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -1855,6 +1855,90 @@ static void test_FillConsoleOutputAttribute(HANDLE output_handle) ok(count == 1, "Expected count to be 1, got %u\n", count); } +static void test_ReadConsoleOutputCharacterA(HANDLE output_handle) +{ + CHAR read; + COORD origin = {0, 0}; + DWORD count; + BOOL ret; + int i; + + const struct + { + HANDLE hConsoleOutput; + LPSTR lpstr; + DWORD length; + COORD coord; + LPDWORD read_count; + DWORD expected_count; + DWORD last_error; + int win7_crash; + } invalid_table[] = + { + {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE}, + {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {NULL, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1}, + {NULL, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {NULL, &read, 0, origin, &count, 0, ERROR_INVALID_HANDLE}, + {NULL, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {NULL, &read, 1, origin, &count, 0, ERROR_INVALID_HANDLE}, + {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE}, + {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1}, + {INVALID_HANDLE_VALUE, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {INVALID_HANDLE_VALUE, &read, 0, origin, &count, 0, ERROR_INVALID_HANDLE}, + {INVALID_HANDLE_VALUE, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {INVALID_HANDLE_VALUE, &read, 1, origin, &count, 0, ERROR_INVALID_HANDLE}, + {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {output_handle, NULL, 1, origin, &count, 1, ERROR_INVALID_ACCESS, 1}, + {output_handle, NULL, 10, origin, &count, 10, ERROR_INVALID_ACCESS, 1}, + {output_handle, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + {output_handle, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, + }; + + for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) + { + if (invalid_table[i].win7_crash) + continue; + + SetLastError(0xdeadbeef); + if (invalid_table[i].read_count) count = 0xdeadbeef; + ret = ReadConsoleOutputCharacterA(invalid_table[i].hConsoleOutput, + invalid_table[i].lpstr, + invalid_table[i].length, + invalid_table[i].coord, + invalid_table[i].read_count); + ok(!ret, "[%d] Expected ReadConsoleOutputCharacterA to return FALSE, got %d\n", i, ret); + if (invalid_table[i].read_count) + { + ok(count == invalid_table[i].expected_count, + "[%d] Expected count to be %u, got %u\n", + i, invalid_table[i].expected_count, count); + } + ok(GetLastError() == invalid_table[i].last_error, + "[%d] Expected last error to be %u, got %u\n", + i, invalid_table[i].last_error, GetLastError()); + } + + count = 0xdeadbeef; + ret = ReadConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count); + ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret); + ok(count == 0, "Expected count to be 0, got %u\n", count); + + count = 0xdeadbeef; + ret = ReadConsoleOutputCharacterA(output_handle, &read, 0, origin, &count); + ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret); + ok(count == 0, "Expected count to be 0, got %u\n", count); + + count = 0xdeadbeef; + ret = ReadConsoleOutputCharacterA(output_handle, &read, 1, origin, &count); + ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret); + ok(count == 1, "Expected count to be 1, got %u\n", count); +} + static void test_ReadConsoleOutputCharacterW(HANDLE output_handle) { WCHAR read; @@ -2053,5 +2137,6 @@ START_TEST(console) test_FillConsoleOutputCharacterA(hConOut); test_FillConsoleOutputCharacterW(hConOut); test_FillConsoleOutputAttribute(hConOut); + test_ReadConsoleOutputCharacterA(hConOut); test_ReadConsoleOutputCharacterW(hConOut); }