On Tue Apr 29 15:04:19 2025 +0000, Rémi Bernon wrote:
But I would also rather do it like this, to reduce the scope of the pointer aliasing, and with some additional fixups:
{ unsigned int status, count = 8; HANDLE *handles; int i; do { if (!(handles = malloc( count * sizeof(*handles) ))) return STATUS_NO_MEMORY; SERVER_START_REQ( cancel_async ) { object_handle_t *server_handles = (object_handle_t *)handles; req->handle = wine_server_obj_handle( handle ); req->iosb = wine_server_client_ptr( io ); req->only_thread = only_thread; wine_server_set_reply( req, server_handles, count * sizeof(*server_handles) ); if (!(status = wine_server_call( req ))) { for (i = count - 1; i >= 0; i--) handles[i] = wine_server_ptr_handle( server_handles[i] ); io_status->Status = status; io_status->Information = 0; } else if (status == STATUS_BUFFER_OVERFLOW) { count = reply->handles_size / sizeof(*server_handles); free( handles ); } } SERVER_END_REQ; } while (status == STATUS_BUFFER_OVERFLOW); if (!status) NtWaitForMultipleObjects( count, handles, FALSE, TRUE, NULL ); free( handles ); return status; }
Thanks a lot, sorry that I messed up the two arrays in the current version...
There's a subtle issue with this: `count` needs to be updated on success as well, otherwise we wait on garbage handles.
There are a few alternatives to tackle that, unsure which one you'd prefer: - duplicate the `count` update in both `if` branches - move the `count` update back after the branch and the handle type conversion out of the loop (thus also moving back `server_handles` to the outer scope) - move the `count` update back after the branch and put both the handle conversion and the actual wait inside the loop, after the `SERVER_END_REQ` (i.e. `server_handles` goes inside the `do`)
The last option above is kinda an in-between and what I tried, it doesn't look too terrible but I don't know that it's particularly preferable.