If wine dlls are built with frame pointers enabled, the frame pointer will be
used during unwinding.
If we don't restore frame pointer before calling the user mode callback, then
later when the unwinder encounters the user mode callback frame, it will set
the frame pointer to something unexpected (depends on what it was during
`call_user_mode_callback`). Then for the subsequent frame it adjusts the stack
pointer based on the frame pointer, thus derailing the unwinding process.
--
v5: ntdll: Also restore rbp before calling user mode callback.
https://gitlab.winehq.org/wine/wine/-/merge_requests/8466
eric pouech (@epo) commented about programs/conhost/conhost.c:
> while (ctx->history_index != start_pos);
> }
>
> +static void edit_line_copy_from_hist( struct console *console, int copycount )
> +{
> + if (console->edit_line.history_index)
> + {
> + unsigned int index = console->edit_line.history_index - 1;
> + struct edit_line *ctx = &console->edit_line;
> + WCHAR *line = edit_line_history(console, index);
> + unsigned int len = line ? lstrlenW(line) : 0;
> +
> + if (len > ctx->cursor)
it looks like native is doing stuff a bit more complicated:
* the MR implements the case where cursor is at the end of edit line
* if cursor is not at the end, it looks native just advance cursor by ccount
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/8467#note_108891
eric pouech (@epo) commented about programs/conhost/conhost.c:
> while (ctx->history_index != start_pos);
> }
>
> +static void edit_line_copy_from_hist( struct console *console, int copycount )
> +{
> + if (console->edit_line.history_index)
> + {
> + unsigned int index = console->edit_line.history_index - 1;
> + struct edit_line *ctx = &console->edit_line;
> + WCHAR *line = edit_line_history(console, index);
since you're not changing the `console->history` content, you could access `console->history[index]` directly (that would save recomputing the length, and one allocation)
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/8467#note_108890