Abusing real event objects also doesn't seem nice. You could have an event_sync that would be a specialized struct sync with just a signaled flag, and use it for all event-like objects, including the events themselves.
This is my intention, but handling the sync users first and splitting the sync vtable was meant to make it easier to do it after, replacing the event objects with abstract sync objects, in a similar fashion to how struct fd is implemented.
Also, using a static sync struct doesn't seem to match the wineserver vtable based design, and keeping it static probably means ending up with an union at some point to store server/inproc sync?
I'll try to reorder things differently, and add allocation failure handling. I don't think it was so messy but as the sync objects were initially meant to be very small I assumed we could just assert that allocation succeeded.