Fixed Windows rawinput crash

RAWINPUT structures are variable size
main
Sam Lantinga 2024-03-26 14:11:38 -07:00
parent a7df28201b
commit d6fc629b5b
2 changed files with 25 additions and 24 deletions

View File

@ -667,7 +667,7 @@ void WIN_PollRawInput(SDL_VideoDevice *_this)
{ {
SDL_Window *window; SDL_Window *window;
SDL_WindowData *data; SDL_WindowData *data;
UINT size, count, i, total = 0; UINT size, i, count, total = 0;
RAWINPUT *input; RAWINPUT *input;
Uint64 now; Uint64 now;
@ -678,7 +678,7 @@ void WIN_PollRawInput(SDL_VideoDevice *_this)
} }
data = window->driverdata; data = window->driverdata;
if (data->rawinput_size == 0) { if (data->rawinput_offset == 0) {
BOOL isWow64; BOOL isWow64;
data->rawinput_offset = sizeof(RAWINPUTHEADER); data->rawinput_offset = sizeof(RAWINPUTHEADER);
@ -686,33 +686,34 @@ void WIN_PollRawInput(SDL_VideoDevice *_this)
/* We're going to get 64-bit data, so use the 64-bit RAWINPUTHEADER size */ /* We're going to get 64-bit data, so use the 64-bit RAWINPUTHEADER size */
data->rawinput_offset += 8; data->rawinput_offset += 8;
} }
if (GetRawInputBuffer(NULL, &data->rawinput_size, sizeof(RAWINPUTHEADER)) == (UINT)-1) {
return;
}
if (data->rawinput_size == 0) {
return;
}
} }
/* Get all available events */ /* Get all available events */
input = (RAWINPUT *)data->rawinput;
for (;;) { for (;;) {
if (total == data->rawinput_count) { size = data->rawinput_size - ((BYTE *)input - data->rawinput);
count = total + 8; count = GetRawInputBuffer(input, &size, sizeof(RAWINPUTHEADER));
input = (RAWINPUT *)SDL_realloc(data->rawinput, count * data->rawinput_size); if (count == 0 || count == (UINT)-1) {
if (!input) { if (!data->rawinput || (count == (UINT)-1 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
return; const size_t RAWINPUT_BUFFER_SIZE_INCREMENT = 96; // 2 64-bit raw mouse packets
BYTE *rawinput = (BYTE *)SDL_realloc(data->rawinput, data->rawinput_size + RAWINPUT_BUFFER_SIZE_INCREMENT);
if (!rawinput) {
break;
}
input = (RAWINPUT *)(rawinput + ((BYTE *)input - data->rawinput));
data->rawinput = rawinput;
data->rawinput_size += RAWINPUT_BUFFER_SIZE_INCREMENT;
} else {
break;
} }
data->rawinput = input; } else {
data->rawinput_count = count; total += count;
}
size = (data->rawinput_count - total) * data->rawinput_size; // Advance input to the end of the buffer
count = GetRawInputBuffer((RAWINPUT *)((BYTE *)data->rawinput + (total * data->rawinput_size)), &size, sizeof(RAWINPUTHEADER)); while (count--) {
if (count == (UINT)-1 || count == 0) { input = NEXTRAWINPUTBLOCK(input);
break; }
} }
total += count;
} }
now = SDL_GetTicksNS(); now = SDL_GetTicksNS();
@ -728,7 +729,7 @@ void WIN_PollRawInput(SDL_VideoDevice *_this)
timestamp = now; timestamp = now;
increment = 0; increment = 0;
} }
for (i = 0, input = data->rawinput; i < total; ++i, input = NEXTRAWINPUTBLOCK(input)) { for (i = 0, input = (RAWINPUT *)data->rawinput; i < total; ++i, input = NEXTRAWINPUTBLOCK(input)) {
timestamp += increment; timestamp += increment;
if (input->header.dwType == RIM_TYPEMOUSE) { if (input->header.dwType == RIM_TYPEMOUSE) {
RAWMOUSE *rawmouse = (RAWMOUSE *)((BYTE *)input + data->rawinput_offset); RAWMOUSE *rawmouse = (RAWMOUSE *)((BYTE *)input + data->rawinput_offset);

View File

@ -70,7 +70,7 @@ struct SDL_WindowData
UINT windowed_mode_corner_rounding; UINT windowed_mode_corner_rounding;
COLORREF dwma_border_color; COLORREF dwma_border_color;
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) #if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
RAWINPUT *rawinput; BYTE *rawinput;
UINT rawinput_offset; UINT rawinput_offset;
UINT rawinput_size; UINT rawinput_size;
UINT rawinput_count; UINT rawinput_count;